算法与数据结构(六)

一、图

一、临接表

表示方法如下:
在这里插入图片描述
带权值的无向图的构建:

#define MaxInt 32767     // 极大值
#define MVNum 100        // 最大定点数
typedef int ArcType;     // 边的权值类型
typedef char VerTexType; // 顶点数据类型//弧(边)的结点结构
struct ArcNode
{int adjvex;              // 该边指向顶点的下标struct ArcNode *nextarc; // 下一条边指针ArcType info;            // 边的权值
};// 顶点的结点结构
typedef struct VNode
{VerTexType data;          // 顶点信息struct ArcNode *firstarc; // 指向第一条边关联该点的边
} VNode, AdjList[MVNum];// 图的结构定义
typedef struct
{AdjList vertices;int vexnum, arcnum; // 图的顶点数和边数
} ALGraph;

创建图:

// 采用邻接表表示法创建无向网
Status CreateUDG(ALGraph &G)
{cin >> G.vexnum >> G.arcnum; // 输入总顶点数与总边数for (int i = 0; i < G.vexnum; ++i){cin >> G.vertices[i].data;G.vertices[i].firstarc = NULL;}for (int k = 0; k < G.arcnum; ++k){char v1, v2;cin >> v1 >> v2;int i = LocateVex(G, v1);int j = LocateVex(G, v2);ArcNode *p1 = new ArcNode;p1->adjvex = j;p1->nextarc = G.vertices[i].firstarc;G.vertices[i].firstarc = p1;ArcNode *p2 = new ArcNode;p2->adjvex = i;p2->nextarc = G.vertices[j].firstarc;G.vertices[j].firstarc = p2;}return 0;
}//顶点在顶点表中的下标
int LocateVex(ALGraph G, VerTexType u)
{int i;for (int i = 0; i < G.vexnum; ++i)if (u == G.vertices[i].data) return i;return -1;
}

二、临接矩阵

表示如下:
在这里插入图片描述
带权值的有向图的构建:

#include <bits/stdc++.h>
using namespace std;
#define MaxVertices 100	//假设包含的最大结点数
#define MaxWeight -1	//假设两点不邻接的正无穷值//定义结点
struct AdjMarix {int Vertices[MaxVertices];	//存储结点信息int Edge[MaxVertices][MaxVertices] = { 0 };	//存储每条边的权值int numV;	//当前顶点的个数int numE;	//当前边的个数
};void CreatGraph(AdjMarix *G) {int vi, vj, w;cout << "请输入顶点数量:" << endl;cin >> G->numV;cout << "请输入顶点信息:" << endl;//输入结点的编号并初始化for (int i = 0; i < G->numV; i++) {cin >> vi;G->Vertices[i] = vi;G->Edge[i][i] = MaxWeight; //初始化过程先默认权值为无穷大}cout << "请输入边的数量:" << endl;cin >> G->numE;cout << "请输入边的信息:" << endl;for (int i = 0; i < G->numE; i++) {cin >> vi >> vj >> w; //vi、vj为邻接矩阵对应点的坐标,w为边的权值G->Edge[vi - 1][vj - 1] = w;//G->Edge[vj-1][vi-1]=w; 无向图需要再加上这一句}
}//遍历图,展示邻接表矩阵
void ShowGraph(AdjMarix *G) {for (int i = 0; i < G->numV; i++) {for (int j = 0; j < G->numV; j++) {cout << G->Edge[i][j] << " ";}cout << endl;}
}int main() {AdjMarix AM;CreatGraph(&AM);ShowGraph(&AM);
}

输入输出的结果为:
在这里插入图片描述

三、图的宽度优先遍历

1,利用队列实现
2,从源节点开始依次按照宽度进队列,然后弹出
3,每弹出一个点,把该节点所有没有进过队列的邻接点放入队列
4,直到队列变空
邻接矩阵版:

#include <iostream>
#include <queue>using namespace std;#define MaxVertexNum 100 //顶点数目的最大值// VertexType,顶点的数据类型
template<typename VertexType>
class MGraph {
private:VertexType Vex[MaxVertexNum];   //顶点表int Edge[MaxVertexNum][MaxVertexNum];  //邻接矩阵,边表int vexnum, arcnum;  //图的当前顶点数和弧数bool inq[MaxVertexNum]; //如果顶点i已入过,inq[i]==true。初值为falsevoid BFS(int u) {   //遍历u所在的连通块queue<int> q;   //定义队列qq.push(u);   //初始顶点u入队inq[u] = true;  //设置u已入过队while (!q.empty()) {    //只要队列非空u = q.front();  //取出队首元素并访问cout << Vex[u] << "\t";q.pop();    //队首元素出队for (int v = 0; v < vexnum; v++)//如果u的邻接点v未曾加入过队列if (Edge[u][v] == 1 && inq[v] == false) {//将v入队并标记已入队q.push(v);inq[v] = true;}}}public:MGraph() {for (int i = 0; i < MaxVertexNum; i++) {inq[i] = false;for (int k = 0; k < MaxVertexNum; k++)Edge[i][k] = 0;}}void create() {int row, col;cin >> vexnum >> arcnum;    //输入实际图的顶点数和边数for (int i = 0; i < vexnum; i++)   //输入顶点信息cin >> Vex[i];for (int i = 0; i < arcnum; i++) {  //输入边信息cin >> row >> col;Edge[row][col] = 1;}}void BFSTrave() {  //遍历图Gfor (int u = 0; u < vexnum; u++) //枚举所有顶点if (inq[u] == false)BFS(u); //遍历u所在的连通块}
};int main() {MGraph<string> G;G.create();G.BFSTrave();return 0;
}

邻接表版:

#include <iostream>
#include <queue>using namespace std;#define MaxVertexNum 100 //顶点数目的最大值struct ArcNode {    //边表结点int adjvex;     //该弧所指向的顶点的位置ArcNode *next;  //指向下一条弧的指针
};template<typename VertexType>
struct VNode {        //顶点表结点VertexType data;  //顶点信息ArcNode *first;   //指向第一条依附该顶点的弧的指针
};template<typename VertexType>
class ALGraph { //ALGraph是以邻接表存储的图类型
private:VNode<VertexType> vertices[MaxVertexNum]; //邻接表int vexnum, arcnum; //图的顶点数和弧数bool inq[MaxVertexNum]; //如果顶点i已入过,inq[i]==true。初值为falsevoid BFS(int u) {   //遍历u所在的连通块queue<int> q;   //定义队列qq.push(u);   	//初始顶点u入队inq[u] = true;  //设置u已入过队while (!q.empty()) {u = q.front();  //取出队首元素并访问cout << vertices[u].data << "\t";q.pop();    //队首元素出队ArcNode *p = vertices[u].first;while (p) {if (inq[p->adjvex] == false) {q.push(p->adjvex);inq[p->adjvex] = true;}p = p->next;}}}public:ALGraph() {for (int i = 0; i < MaxVertexNum; i++) {inq[i] = false;vertices[i].first = NULL;}}void create() {int row, col;cin >> vexnum >> arcnum;    //输入实际图的顶点数和边数for (int i = 0; i < vexnum; i++)   //输入顶点信息cin >> vertices[i].data;for (int i = 0; i < arcnum; i++) {  //输入边信息cin >> row >> col;ArcNode *p = new ArcNode;p->adjvex = col;p->next = vertices[row].first;vertices[row].first = p;}}void BFSTrave() {  //遍历图Gfor (int u = 0; u < vexnum; u++) //枚举所有顶点if (inq[u] == false)BFS(u); //遍历u所在的连通块}
};int main() {ALGraph<string> G;G.create();G.BFSTrave();return 0;
}

四、广度优先遍历

深度优先搜索以“深度”作为第一关键词,每次都是沿着路径到不能再前进时才退回到最近的岔道口。以一个有向图(见下图)进行 DFS 遍历来举例(从V0 开始进行遍历,黑色表示结点未访问,白色表示结点已访问,虚线边表示当前遍历路径):
在这里插入图片描述

如果要遍历整个图,就需要对所有连通块(连通分量和强连通分量)分别进行遍历。所以 DFS 遍历图的基本思路就是将经过的顶点设置为已访问,在下次递归碰到这个顶点时就不再去处理,直到整个图的顶点都被标记为已访问。

#include <iostream>using namespace std;#define MaxVertexNum 100 //顶点数目的最大值struct ArcNode {    //边表结点int adjvex;     //该弧所指向的顶点的位置ArcNode *next;  //指向下一条弧的指针
};template<typename VertexType>
struct VNode {        //顶点表结点VertexType data;  //顶点信息ArcNode *first;   //指向第一条依附该顶点的弧的指针
};template<typename VertexType>
class ALGraph { //ALGraph是以邻接表存储的图类型
private:VNode<VertexType> vertices[MaxVertexNum]; //邻接表int vexnum, arcnum; //图的顶点数和弧数bool visited[MaxVertexNum]; //如果顶点i已被访问,则visited[i]==true。初值为falsevoid DFS(int u) {   //u为当前访问的顶点索引cout << vertices[u].data << "\t";visited[u] = true;   //设置u已被访问ArcNode *p = vertices[u].first;while (p) {if (visited[p->adjvex] == false)DFS(p->adjvex);p = p->next;}}public:ALGraph() {for (int i = 0; i < MaxVertexNum; i++) {visited[i] = false;vertices[i].first = NULL;}}void create() {int row, col;cin >> vexnum >> arcnum;    //输入实际图的顶点数和边数for (int i = 0; i < vexnum; i++)   //输入顶点信息cin >> vertices[i].data;for (int i = 0; i < arcnum; i++) {  //输入边信息cin >> row >> col;ArcNode *p = new ArcNode;p->adjvex = col;p->next = vertices[row].first;vertices[row].first = p;}}void DFSTrave() {  //遍历图Gfor (int u = 0; u < vexnum; u++)  //对每个顶点uif (visited[u] == false)  //如果u未被访问DFS(u); //访问u和u所在的连通块}
};int main() {ALGraph<string> G;G.create();G.DFSTrave();return 0;
}

邻接矩阵版:

#include <iostream>using namespace std;#define MaxVertexNum 100 //顶点数目的最大值// VertexType,顶点的数据类型
template<typename VertexType>
class MGraph {
private:VertexType Vex[MaxVertexNum];   //顶点表int Edge[MaxVertexNum][MaxVertexNum];  //邻接矩阵,边表int vexnum, arcnum;  //图的当前顶点数和弧数bool visited[MaxVertexNum]; //如果顶点i已被访问,则visited[i]==true。初值为falsevoid DFS(int u) {   //u为当前访问的顶点索引cout << Vex[u] << "\t";visited[u] = true;   //设置u已被访问for (int i = 0; i < vexnum; i++)if (Edge[u][i] == 1 && visited[i] == false)DFS(i);}public:MGraph() {for (int i = 0; i < MaxVertexNum; i++) {visited[i] = false;for (int k = 0; k < MaxVertexNum; k++)Edge[i][k] = 0;}}void create() {int row, col;cin >> vexnum >> arcnum;    //输入实际图的顶点数和边数for (int i = 0; i < vexnum; i++)   //输入顶点信息cin >> Vex[i];for (int i = 0; i < arcnum; i++) {  //输入边信息cin >> row >> col;Edge[row][col] = 1;}}void DFSTrave() {  //遍历图Gfor (int u = 0; u < vexnum; u++)  //对每个顶点uif (visited[u] == false)  //如果u未被访问DFS(u); //访问u和u所在的连通块}
};int main() {MGraph<string> G;G.create();G.DFSTrave();return 0;
}

二、拓扑排序

拓扑排序就是对一个有向无环图构造拓扑序列的过程:
1、在有向图中选一个没有前驱的顶点并输出。
2、从图中删除该顶点和所有以它为尾的弧。
代码如下:

#include <bits/stdc++.h>
using namespace std;
#define MAXVERTIES 20
#define OK 1
#define ERROR 0int indegree[MAXVERTIES] = { 0 };	//用于存储入度信息/*
5
1 2 3 4 5
6
1 2
1 4
1 3
2 4
3 5
4 5
*///定义结点
struct VexNode {int data;VexNode *next;
};//定义弧
struct ArcNode {int data;VexNode *firstacr = NULL;
};//定义邻接表
struct GraphList {ArcNode arclist[MAXVERTIES];int vexnum, arcnum;
};//定义栈
struct Stack {int Sacklist[MAXVERTIES] = { 0 };int top = -1;
};//入栈操作
void Push(Stack &S, int key) {if (S.top == MAXVERTIES) {cout << "栈已满!" << endl;return;}S.top++;S.Sacklist[S.top] = key;
}//出栈操作
int Pop(Stack &S) {if (S.top == -1) {cout << "栈为空!" << endl;return -1;}int temp = S.Sacklist[S.top];S.top--;return temp;
}//返回结点在结点数组中的下标
int Location(GraphList &G, int key) {for (int i = 0; i < G.vexnum; i++) {if (G.arclist[i].data == key) {return i;}}return -1;
}//创建图
void CreatGraph(GraphList &G) {cout << "请输入顶点数:" << endl;cin >> G.vexnum;cout << "请输入顶点信息:" << endl;for (int i = 0; i < G.vexnum; i++) {cin >> G.arclist[i].data;}cout << "请输入弧数:" << endl;cin >> G.arcnum;cout << "请输入弧端点信息:" << endl;for (int i = 0; i < G.arcnum; i++) {int v1, v2;cin >> v1 >> v2;int Location1 = Location(G, v1);int Location2 = Location(G, v2);VexNode *new_node = new VexNode;new_node->data = Location2;new_node->next = G.arclist[Location1].firstacr;G.arclist[Location1].firstacr = new_node;indegree[Location2]++;}
}//拓扑排序
int TopoSort(GraphList &G, int *topolist) {Stack S;int topo = 0;//先将所有入度为0的结点入栈for (int i = 0; i < G.vexnum; i++) {if (indegree[i] == 0) {Push(S, i);}}//依次出栈入度为0的结点while (S.top != -1) {int vx = Pop(S);topolist[topo++] = G.arclist[vx].data;	//输出结点VexNode *temp = G.arclist[vx].firstacr;//删除以该结点为尾的弧while (temp != NULL) {int index = temp->data;indegree[index]--;	//将该弧的弧头结点入度减1//如果入度为0,则入栈if (indegree[index] == 0) {Push(S, index);}temp = temp->next;}}topolist[topo] = -1;//如果拓扑序列中的元素个数等于所有元素个数,则该图无环,否则该图有环if (topo == G.vexnum) {return OK;} else {return ERROR;}
}int main() {GraphList GL;CreatGraph(GL);int topolist[MAXVERTIES] = { 0 };int vx = TopoSort(GL, topolist);if (!vx) {cout << "有环!" << endl;} else {cout << "有向无环!" << endl;cout << "拓扑序列如下:" << endl;for (int i = 0; topolist[i] != -1; i++) {cout << topolist[i] << " ";}}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/5358.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

当金融风控遇上人工智能,众安金融的实时特征平台实践

导读&#xff1a;随着企业数字化转型升级&#xff0c;线上业务呈现多场景、多渠道、多元化的特征。数据要素价值的挖掘可谓分秒必争&#xff0c;业务也对数据的时效性和灵活性提出了更高的要求。在庞大分散、高并发的数据来源背景下&#xff0c;数据的实时处理能力成为企业提升…

Maven中依赖使用范围

IDEA中help中show Log in Explorer可以查看idea日志 依赖使用范围 构建包含的流程&#xff1a;编译 &#xff0c;测试 &#xff0c;运行 &#xff0c;打包 &#xff0c;安装 &#xff0c;部署 comile test package install deploy 使用标签 1&#xff1a;compile 缺省值 伴随者…

VRP基础操作

目录 一、华为VRP 1.1、VRP介绍 1.2、设备管理接口 1.3、Console口登录 1.4、参数配置 二、华为VRP命令行基础 2.1、真机设备初始化启动 2.2、命令行视图 2.3、命令行功能 2.4、命令行在线帮助 2.5、配置系统时钟 2.6、配置标题消息 2.7、命令等级 2.8、用户界面…

突破性5G NTN技术,美格智能携手高通发布卫星物联网连接方案

通信技术的快速发展&#xff0c;使得万物互联成为现实&#xff0c;物联网深刻影响我们的生活方式。目前&#xff0c;全球物联网连接主要由WiFi、蓝牙和蜂窝网络等几类技术支撑。数据显示&#xff0c;蜂窝基站的陆地覆盖率约为20%&#xff0c;而海洋覆盖率则不到5%。 这意味着陆…

Docker数据卷与容器的挂载

什么是Docker数据卷: 数据卷&#xff08;Volumes&#xff09;是宿主机中的一个目录或文件&#xff0c;当容器目录和数据卷目录绑定后&#xff0c;对方的修改会立即同步。一个数据卷可以被多个容器同时挂载&#xff0c;一个容器也可以被挂载多个数据卷。简单来说数据卷本质其实是…

FPGA的软核、硬核、固核

“核” 现在的FPGA设计&#xff0c;规模巨大而且功能复杂&#xff0c;因此设计的每一个部分都从头开始是不切实际的。一种解决的办法是&#xff1a;对于较为通用的部分可以重用现有的功能模块&#xff0c;而把主要的时间和资源用在设计中的那些全新的、独特的部分。这就像是你在…

20kV高精度可调高压稳压测试电源的学习与使用

一&#xff1a;应用范围 A: 二极管反向耐压测试 B: 二极管反向漏电流测试 C: 高压电容耐压测试 D: 玻璃釉电阻非线性性能测试 E:氙灯击穿电压测试 F: 材料耐压测试 二、特点 高精度恒流恒压高压输出源 它拥有0~20kV的电压输出能力, 0.005%的电压分辨率精度, 0.1uA的电 …

mysql——存储过程

目录 存储过程存储过程的优点创建存储过程调用存储过程查看存储过程查看存储过程的详细信息查看存储过程的属性 存储过程的参数删除存储过程存储过程控制语句 存储过程 存储过程是一组为了完成特定功能的SQL语句集合存储过程在使用过程中是将常用或者复杂的工作预先使用SQL语句…

Android通过连接USB读写SD卡(libaums方案)

Android通过连接USB读写SD卡 最近有一个需求是要求通过Usb扩展读取到SD卡的内容。可以从Usb存储设备拷贝文件到内置卡&#xff0c;也可以从内置卡文件拷贝到Usb存储。 1. 相关的引入包 implementation androidx.core:core-ktx:1.7.0implementation androidx.appcompat:appcompa…

02-基础入门-数据包拓展

基础入门-数据包拓展 基础入门-数据包拓展1、http/https数据包&#xff08;1&#xff09;HTTP协议是什么&#xff1f;&#xff08;2&#xff09;HTTP原理&#xff08;3&#xff09;HTTP特点&#xff08;4&#xff09;URI和URL的区别&#xff08;5&#xff09;HTTP报文组成&…

数据安全服务,美创科技为“数字国贸” 筑牢安全防线

在数字经济蓬勃发展的当下&#xff0c;国有企业作为国民经济的“中流砥柱”&#xff0c;正以主力军和先行者之姿&#xff0c;以数字化转型创新作为引擎&#xff0c;驱动高质量发展。数字化进程持续深入&#xff0c;伴随数据要素多样流动&#xff0c;降低数据安全风险&#xff0…

【ES三周年】| 基于国产化操作系统搭建ELK日志分析平台

引入 鲲鹏认证-Kylin麒麟操作系统-ELK日志分析平台 开篇 何为ELK Stack&#xff1f;它又能够给我们带来什么&#xff1f; 综述 ELK为三个开源项目的首字母缩写&#xff0c;分别对应是&#xff1a;Elasticsearch、Logstash、Kibana&#xff0c;由这三个软件及其相关的组件可…