【C语言\数据结构】图之邻接矩阵(无向、有权)代码简单实现

图的邻接矩阵表示法

假设一个图的顶点数是V,则用 V*V大小的二维数组来表示这个图边的信息,例如矩阵arcs[i][j],数值为1表示从下标为i的顶点到下标为j的顶点有边,数值为0表示从下标为i的顶点到下标为j的顶点没有边。矩阵的对角线上数值默认是0,因为没有自己顶点到自己顶点的边。

编写结构体

#include 
#include 
#include 

#define MAX 100
#define INFINITY 9999
enum graphType {DG, UG, DN, UN}; //图的类型定义:有向图,无向图,有向网,无项网
typedef char vertexType;
typedef struct {
	vertexType vexs[MAX];
	int arcs[MAX][MAX];
	int vexnum, arcnum;
	graphType kind;
} graph;

预定义MAX的值为100,表示二维数组最多能够存储100个顶点之间边的关系,同时也表示这个图最多能够存储100个节点。

预定义INFINITY的值为9999,表示边长权值为无无限,即边关系为不存在。

enum是一个枚举数据类型,花括号括起来的是枚举的元素,“DG, UG, DN, UN”分别表示有向图,无向图,有向网,无向网。

vertexType vexs[MAX]定义一个MAX大小的一维数组,存放的是顶点的名称数据vexs是vertex的复数缩写,vertex的意思是顶点,例如vexs数组可以存放不同的城市的名称,不同城市之间的距离可以用边长的权值表示。

arcs[MAX][MAX]定义一个MAX大小的方阵,即二维数组,长和宽都是MAX大小,arcs[i][j]表示下标i对应的顶点到下标j对应的顶点的权值,arcs是弧长的意思。

vexnum, arcnum分别是顶点的个数,边的个数。

kind是这个图的类型定义。


编写初始化函数

void initGraph(graph &g) {
	
	g.kind = UN;
	printf("输入顶点数和边数:\n");
	scanf("%d%d", &g.vexnum, &g.arcnum);
	for (int i = 1; i <= g.vexnum; i++) {
		g.vexs[i] = i;
	}
	for (int i = 1; i <= g.vexnum; i++) {
		for (int j = 1; j < g.vexnum; j++) {
			if (i == j) g.arcs[i][j] = 0;
			else g.arcs[i][j] = INFINITY;
		}
	}
}

initGraph(graph &g)语句中,运用了C++中引用的技巧,在参数的前面添加“&”这个符号表示引用,引用的意思是,函数内变量g与外界传入进来的g是一个共同体,函数内g的任何改变都会影响外界传入的g,也就是函数中的参数g是外界传入的g的不同展现形式,本质上是相同的变量,这样我们就不用传入地址,根据地址去寻找本体了。

g.kind = UN把这个图的类型定义为无向图。

分别输入图的顶点个数和边的个数。

for (int i = 1; i <= g.vexnum; i++) { g.vexs[i] = i; }语句,定义每一个顶点的名称,我们这里就直接用1、2、3...这样的数字去定义,注意我们在代码实现过程中,舍弃了数组中第一个元素,所以我们数组能够存储的数据的最大值变成了99,这样做可以使代码变得更清晰一点。

for (int i = 1; i <= g.vexnum; i++) { for (int j = 1; j < g.vexnum; j++) { if (i == j) g.arcs[i][j] = 0; else g.arcs[i][j] = INFINITY; } }语句,把存储边长的数组对角线元素全部置0,对角线的含义是每一个顶点,自己到自己的权值,当然,这个值应该为0,因为没有意义。如果不是对角线,置为无穷,表示目前还没有这条边存在的关系。


编写建图函数

void createGraph(graph &g) {
	int start_index, end_index, weight;
	
	printf("输入每条边的起点终点下标和边的权重:\n");
	for (int i = 1; i <= g.arcnum; i++) {
		scanf("%d%d%d", &start_index, &end_index, &weight);
		g.arcs[start_index][end_index] = weight;
		g.arcs[end_index][start_index] = weight;
	}
}

因为我们在初始化函数中,存储了图顶点的信息,建图函数中只要实现边信息的存储就可以了。

start_index, end_index, weight分别表示起始顶点下标,终点下标,和这条边的权重。

我们表示不同的顶点,都是通过它的下标。

g.arcs[start_index][end_index] = weight; g.arcs[end_index][start_index] = weight;

因为我们表示的是无向图,所以起点到终点有权重,终点到起点同样有权重。


编写展示邻接矩阵函数

void showGraph(graph &g) {
	printf("邻接矩阵:\n");
	for (int i = 1; i <= g.vexnum; i++) {
		for (int j = 1; j <= g.vexnum; j++) {
			printf("%d ", g.arcs[i][j]);
		}
		printf("\n");
	}
}

遍历二维数组,把二维数组中的每一个值都打印出来。


编写主函数

int main() {
	graph g;
	initGraph(g);
	createGraph(g);
	showGraph(g);
	
	
}
/*测试用例:
5 7
1 3 2
2 3 1
1 4 4
1 5 6
2 4 5
3 4 1
5 2 8
*/

首先我们创建了一个数据类型为图的变量g,对g进行初始化,然后创建图的边信息,打印图的邻接矩阵。主函数下面有一个测试用例,让我们检测一下代码的正确性吧!


完整代码

#include 
#include 
#include 

#define MAX 100
#define INFINITY 9999
enum graphType {DG, UG, DN, UN}; //图的类型定义:有向图,无向图,有向网,无项网
typedef char vertexType;
typedef struct {
	vertexType vexs[MAX];
	int arcs[MAX][MAX];
	int vexnum, arcnum;
	graphType kind;
} graph;

void initGraph(graph &g) {
	
	g.kind = UN;
	printf("输入顶点数和边数:\n");
	scanf("%d%d", &g.vexnum, &g.arcnum);
	for (int i = 1; i <= g.vexnum; i++) {
		g.vexs[i] = i;
	}
	for (int i = 1; i <= g.vexnum; i++) {
		for (int j = 1; j < g.vexnum; j++) {
			if (i == j) g.arcs[i][j] = 0;
			else g.arcs[i][j] = INFINITY;
		}
	}
}

void createGraph(graph &g) {
	int start_index, end_index, weight;
	
	printf("输入每条边的起点终点下标和边的权重:\n");
	for (int i = 1; i <= g.arcnum; i++) {
		scanf("%d%d%d", &start_index, &end_index, &weight);
		g.arcs[start_index][end_index] = weight;
		g.arcs[end_index][start_index] = weight;
	}
}

void showGraph(graph &g) {
	printf("邻接矩阵:\n");
	for (int i = 1; i <= g.vexnum; i++) {
		for (int j = 1; j <= g.vexnum; j++) {
			printf("%d ", g.arcs[i][j]);
		}
		printf("\n");
	}
}

int main() {
	graph g;
	initGraph(g);
	createGraph(g);
	showGraph(g);
	
	
}
/*测试用例:
5 7
1 3 2
2 3 1
1 4 4
1 5 6
2 4 5
3 4 1
5 2 8
*/

代码运行截图:

【C语言\数据结构】图之邻接矩阵(无向、有权)代码简单实现_第1张图片

我们一共创建了五个定点,分别是1、2、3、4、5,一共有7条边存在,邻接矩阵第一行表示顶点1与其他顶点的边的信息,对照我们的输入信息,顶点1与顶点3边权值为2,顶点1与顶点4权值为4,顶点1与顶点5权值为6,第一行正确,依次比较剩下四行,都正确,说明我们的代码基本上没有问题。

结尾

我们今天学习了邻接矩阵(无图有权)的简单实现,你还记得代码的实现步骤吗?图结构体中包括图的顶点数量和边数量,一个一维数组存储顶点的信息,一个二维数组存储存储边的信息,一个变量存储图的类型。接下来维护图的边的信息,arcs[i][j]表示i顶点到j顶点的边权值,无向图不要忘记起点到终点,终点到起点的权值都需要维护,展示邻接矩阵就是遍历二维数组,打印每个元素的值。

最后,感谢您阅读我的文章,希望这些内容能够对您有所启发和帮助。如果您有任何问题或想要分享您的观点,请随时在评论区留言。

同时,不要忘记订阅我的博客以获取更多有趣的内容。在未来的文章中,我将继续探讨这个话题的不同方面,为您呈现更多深度和见解。

谢谢您的支持,期待与您在下一篇文章中再次相遇!

你可能感兴趣的:(C语言,数据结构,c语言,数据结构,开发语言)