一、邻接矩阵的定义
这里要总结的邻接矩阵时关于图的邻接矩阵;图的邻接矩阵(Adjacency Matrix)存储方式是用两个数组来表示图;一个一维数组存储图中顶点信息,一个二维数组(称为邻接矩阵)存储图中的边或弧的信息;
图分为有向图和无向图,其对应的邻接矩阵也不相同,无向图的邻接矩阵是一个对称矩阵,就是一个对称的二位数组,a[i][j] = a[j][i];
邻接矩阵可以清楚的知道图的任意两个顶点是否有边;方便计算任意顶点的度(包括有向图的出度和入度);可以直观的看出任意顶点的邻接点;
二、邻接矩阵的存储结构
vexs[MAXVEX]这是顶点表;arc[MAXVEX][MAXVEX]这是邻接矩阵,也是存储每条边信息的二位数组,索引是边的两个顶点,数组的数据是边的权值;numVertexes, numEdges分别为图的顶点数和边数;
#define MAXVEX 20
#define INFINITY 0 //用于初始化时填充邻接矩阵
typedef struct Graph {
char vexs[MAXVEX];
int arc[MAXVEX][MAXVEX];
int numVertexes, numEdges;
}*pGraph;
三、建立邻接矩阵
先建立顶点表,然后初始化邻接矩阵,最后将每条边的信息写入邻接矩阵;这个创建的是无向网图的邻接矩阵,所以有graph.arc[x][y] = w;graph.arc[y][x] = w;因为无向,所以二位数组是对称的;
void CreateGraph(Graph &graph) {
cout << "输入顶点数和边数:";
cin >> graph.numVertexes >> graph.numEdges;
//建立顶点表
for(int i = 0; i < graph.numVertexes; ++i) {
cout << "请输入第" << i + 1 << "个顶点名:";
cin >> graph.vexs[i];
}
//初始化邻接矩阵
for(int i = 0; i < graph.numVertexes; ++i) {
for(int j = 0; j < graph.numVertexes; ++j) {
graph.arc[i][j] = INFINITY;
}
}
//建立邻接矩阵
int x, y, w;
for(int i = 0; i < graph.numEdges; ++i) {
cout << "输入边的下标x,y和权值w:";
cin >> x >> y >> w;
graph.arc[x][y] = w;
graph.arc[y][x] = w;
}
}
四、测试
#include<iostream>
using namespace std;
#define MAXVEX 20
#define INFINITY 0 //用于初始化时填充邻接矩阵
typedef struct Graph {
char vexs[MAXVEX];
int arc[MAXVEX][MAXVEX];
int numVertexes, numEdges;
}*pGraph;
void CreateGraph(Graph &graph) {
cout << "输入顶点数和边数:";
cin >> graph.numVertexes >> graph.numEdges;
//建立顶点表
for(int i = 0; i < graph.numVertexes; ++i) {
cout << "请输入第" << i + 1 << "个顶点名:";
cin >> graph.vexs[i];
}
//初始化邻接矩阵
for(int i = 0; i < graph.numVertexes; ++i) {
for(int j = 0; j < graph.numVertexes; ++j) {
graph.arc[i][j] = INFINITY;
}
}
//建立邻接矩阵
int x, y, w;
for(int i = 0; i < graph.numEdges; ++i) {
cout << "输入边的下标x,y和权值w:";
cin >> x >> y >> w;
graph.arc[x][y] = w;
graph.arc[y][x] = w;
}
}
int main() {
Graph graph;
CreateGraph(graph);
for(int i = 0; i < graph.numVertexes; ++i) {
cout << "\t" << graph.vexs[i];
}
cout << "\n\n";
for(int i = 0; i < graph.numVertexes; ++i) {
cout << graph.vexs[i] << "\t";
for(int j = 0; j < graph.numVertexes; ++j) {
cout << graph.arc[i][j] << "\t";
}
cout << "\n\n";
}
getchar();
return 0;
}
根据生成的邻接矩阵,就可以完整的还原这个图,所以我故意找了一个相对比较复杂的图来测试~
五、总结
邻接矩阵存储图确实不错,但是它也有不好的地方,就是当图的边很少的时候,会存在空间浪费的情况,通过上面测试的邻接矩阵也能看出来,二位数组其实还有很多空白位置;能够消除空间浪费的结构自然而然就会想到链表,下一篇就总结邻接表;不过邻接矩阵还是很易于理解的,这种顺序存储结构总是会浪费一些空间的,但是其好处就是,他的遍历很方便,也算是空间换时间吧;
对于图来说,我没有总结其定义相关的一些内容,因为太多了,并且没什么意义,因为当你熟悉了邻接矩阵,邻接表,十字链表这些结构之后,自然就对图的基础定义有一定认识了;而且关于图的深度优先广度优先算法似乎也很有用,至少我在做很多算法题的时候都会看到,不过我还不是很熟悉,慢慢来吧~
来源:CSDN
作者:长安某~
链接:https://blog.csdn.net/weixin_44816732/article/details/104125410