数据结构复习 ---- 邻接矩阵

一、邻接矩阵的定义

这里要总结的邻接矩阵时关于图的邻接矩阵;图的邻接矩阵(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;
}

在这里插入图片描述
根据生成的邻接矩阵,就可以完整的还原这个图,所以我故意找了一个相对比较复杂的图来测试~

五、总结

邻接矩阵存储图确实不错,但是它也有不好的地方,就是当图的边很少的时候,会存在空间浪费的情况,通过上面测试的邻接矩阵也能看出来,二位数组其实还有很多空白位置;能够消除空间浪费的结构自然而然就会想到链表,下一篇就总结邻接表;不过邻接矩阵还是很易于理解的,这种顺序存储结构总是会浪费一些空间的,但是其好处就是,他的遍历很方便,也算是空间换时间吧;
对于图来说,我没有总结其定义相关的一些内容,因为太多了,并且没什么意义,因为当你熟悉了邻接矩阵,邻接表,十字链表这些结构之后,自然就对图的基础定义有一定认识了;而且关于图的深度优先广度优先算法似乎也很有用,至少我在做很多算法题的时候都会看到,不过我还不是很熟悉,慢慢来吧~

发布了15 篇原创文章 · 获赞 5 · 访问量 1267

猜你喜欢

转载自blog.csdn.net/weixin_44816732/article/details/104125410