图的存储结构——邻接矩阵

邻接矩阵表示法

若有n个顶点,就是n*n的方阵,与边数无关

对称矩阵:从矩阵的左上角到右上角的主对角线为轴,右上角的元与左下角对应的元全都是相等的

有向图、无向图的邻接矩阵表示法

在这里插入图片描述
如:
无向图在这里插入图片描述
总结:

  1. 无向图的邻接矩阵是对称的
  2. 顶点i的度=第i行(列)中1的个数;
  3. 特别的:完全图的邻接矩阵中,对角元素为0,其余为1;

有向图
在这里插入图片描述

总结:

  1. 第i行含义:以结点vi为尾的弧(即出度边)
  2. 第i列含义:以结点vi为头的弧(即入度边)
  3. 有向图的邻接矩阵可能是不对称的
  4. 顶点的出度=第i行元素之和
  5. 顶点的入度=第i列元素之和
  6. 顶点的度=第i行元素之和+第i列元素之和

网的邻接矩阵表示法

定义为:
在这里插入图片描述
如:
在这里插入图片描述

存储表示

顶点表用一维数组存储、邻接矩阵用二维数组存储

两个数组分别存储顶点表邻接矩阵(也叫边表)

#define MaxInt 32767 //表示极大值,即无穷
#define MVNum 100	//最大顶点数
typedef char VerTexType;	//设顶点的数据类型为字符型
typedef int ArcType;	//假设边的权值类型为整形

typedef struct{
	VerTexType vexs[MVNum];	//顶点表
	ArcType arcs[MVNum][MVNum];	//邻接矩阵,可以看作边表
	int vexnum,arcnum;	//图的当前点数和边数
}AMGraph;//Adjacency Matrix Graph

采用邻接矩阵表示法创建无向网

已知一个图的点和边,使用邻接矩阵表示法来创建此图的方法比较简单,以无向网为例

【算法思想】

  1. 输入总顶点数和边数
  2. 依次输入点的信息存入顶点表中。
  3. 初始化邻接矩阵,使得每个权值初始化为极大值
  4. 构造邻接矩阵

依次输入每条边依附的顶点和其权值

确定两个顶点在图中的位置之后,使相应边赋予相应的权值

同时使其对称边赋予相同的权值

补充一下顶点表
在这里插入图片描述
【算法描述】

bool CreateUDN(AMGraph &G) 
{
 	char v1,v2;
 	int w,i,j,k;
 	cin>>G.vexnum>>G.arcnum; //输入总顶点数,总边数 
	for(i=0;i<G.vexnum;i++)//依次输入点的信息
		cin>>G.vexs[i];
 	for(i=0;i<G.vexnum;i++)
  	 for(j=0;j<G.vexnum;j++)
   		G.arcs[i][j]=MAXInt;//初始化邻接矩阵,边的权值均置为极大值MAXInt
	for(k=0;k<G.arcnum;k++){//构造邻接矩阵 
  		cin>>v1>>v2>>w;//输入一条边所依附的顶点及边的权值 
  	i=LocateVex(G,v1);
  	j=LocateVex(G,v2);//确定v1和v2在G中的位置,即顶点数组的下标
  	G.arcs[i][j]=w; //边<v1,v2>权值置为w 
  	G.arcs[j][i]=G.arcs[i][j];  //边<v1,v2>的对称边<v2,v1>的权值为w 
 }//for  
  return true; 
}//CreateUDN

注:从代码中可以得到,n个顶点和e条边的无向网图的创建,时间复杂度度为O(n+ n ^2 + e ), 其中对邻接矩阵G.arc的初始化耗费了O(n ^ 2)的时间。

【查找顶点的算法】

int LocateVex(AMGraph G,VertexType u){
 //在图G中查找顶点u,存在则返回顶点表中的下标;否则返回-1
 	int i;
 	for(i=0;i<G.vexnum;i++)
  		if(u==G.vexs[i])
   		return i;
  	return -1;  
}

建立无向网后,想要建立无向图,有向网和有向图时只需要稍稍改动即可
在这里插入图片描述

用代码实现无向网

#include<iostream>
using namespace std;
#define MaxInt 32767 //表示极大值,即无穷
#define MVNum 100 //最大顶点数
typedef char VerTexType; //设顶点的数据类型为字符型
typedef int ArcType; //假设边的权值类型为整形

typedef struct{
 VerTexType vexs[MVNum]; //顶点表
 ArcType arcs[MVNum][MVNum]; //邻接矩阵
 int vexnum,arcnum; //图的当前点数和边数
}AMGraph;//Adjacency Matrix Graph

//在图中查找顶点
int LocateVex(AMGraph G,VerTexType u){
 //在图G中查找顶点u,存在则返回顶点表中的下标;否则返回-1
 	int i;
 	for(i=0;i<G.vexnum;i++)
  	if(u==G.vexs[i])
   		return i;
  	return -1;
} 
//采用邻接矩阵表示法,创建无向网G
bool CreateUDN(AMGraph &G) 
{
 	char v1,v2;
 	int w,i,j,k;
 	cout<<"分别输入总顶点数、总边数:";
 	cin>>G.vexnum>>G.arcnum; //输入总顶点数,总边数 
 	cout<<"输入点的信息:";
 	for(i=0;i<G.vexnum;i++)//依次输入点的信息 
  		cin>>G.vexs[i];
 	for(i=0;i<G.vexnum;i++)
 	 for(j=0;j<G.vexnum;j++)
	   G.arcs[i][j]=MaxInt;//初始化邻接矩阵,边的权值均置为极大值MAXInt
	   cout<<"请输入一条边所依附的两个顶点、权值:";
 	for(k=0;k<G.arcnum;k++){//构造邻接矩阵 
  	cin>>v1>>v2>>w;//输入一条边所依附的顶点及边的权值 
  	int i=LocateVex(G,v1);
  	int j=LocateVex(G,v2);//确定v1和v2在G中的位置,即顶点数组的下标
  	G.arcs[i][j]=w; //边<v1,v2>权值置为w 
  	G.arcs[j][i]=G.arcs[i][j];
  //边<v1,v2>的对称边<v2,v1>的权值为w 
 }//for  
  	return true; 
}//CreateUDN  


int main()
{
 	AMGraph G;
 	CreateUDN(G);
 	cout<<"无向网为:";
 	for(int i=0;i<G.vexnum;i++)
 	{
  
	  for(int j=0;j<G.vexnum;j++){
	   cout<<G.arcs[i][j]<<" ";
  	}
 	 cout<<endl;
	}//for
	return 0;
}

实现结果为:
在这里插入图片描述

优点

  1. 直观、简洁,便于判断两个顶点是否有边。
  2. 便于计算各顶点的度
  3. 方便找任意顶点的邻接点

缺点

  1. 不便于增加和删除顶点
  2. 浪费空间——存稀疏图(点多边少)有大量无效元素,空间复杂度为O(n^2),存稠密图还是很合算。
  3. 浪费时间——统计稀疏图中一共有多少条边,时间复杂度为O(n^2).
发布了67 篇原创文章 · 获赞 216 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_45895026/article/details/104098718