数据结构之图(二)——邻接矩阵

图的逻辑结构为多对多,图没有顺序存储结构,但可以借助二维数组来表示元素间的关系,即数组表示法(邻接矩阵)。图的链式存储结构可以用多重链表来描述,如邻接表,邻接多重表以及十字链表等。

邻接矩阵

  • 数组(邻接矩阵)表示法:
    建立一个邻接表(记录各个顶点信息)和一个邻接矩阵(表示各个顶点间的关系)。
    1.设图A=(V,E)有n个顶点,则有顶点表Vexs[n]如下,
i 0 1 2 ⋯ \cdots n-1
Vexs[i] v 1 v_1 v1 v 2 v_2 v2 v 3 v_3 v3 ⋯ \cdots v n v_n vn

2.图的邻接矩阵是一个二维数组A.arcs[n][n],定义为:
A . a r c s [ i ] [ j ] = { 1              如 果 < i , j > ∈ E 或 者 ( i , j ) ∈ E 0              否 则 A.arcs[i][j] = \left\{ {\begin{array}{l} {1\;\;\;\;\;\; 如果< i,j > \in E或者(i,j) \in E}\\ {0\;\;\;\;\;\;否则} \end{array}} \right. A.arcs[i][j]={1<i,j>E(i,j)E0



无向图的邻接矩阵

  • 例子:
    数据结构之图(二)——邻接矩阵_第1张图片
  • 特点:
    1.无向图的邻接矩阵是对称的,且主对角线元素全为0(因为自己到自己没有边)。
    2.顶点i的度=第i行(列)中1的个数。
    3.完全图的邻接矩阵中,主对角元素为0,其余全为1。


有向图的邻接矩阵

  • 例子:
    数据结构之图(二)——邻接矩阵_第2张图片
    在有向图的邻接矩阵中,
    第i行的含义:以结点 v i v_i vi为尾的弧(出度边);
    第i列的含义:以结点 v i v_i vi为头的弧(入度边);

  • 特点:
    1.有向图的邻接矩阵可能不是对称的。
    2.顶点的出度=第i行元素之和;
       顶点的入度=第i列元素之和;
       顶点的=第i行元素之和+第i列元素之和。



网的邻接矩阵

  • 网的邻接矩阵表示法:
    A . a r c s [ i ] [ j ] = { W i j              < v i , v j > 或 ( v i , v j ) ∈ V R ∞                    无 边 ( 弧 ) A.arcs[i][j] = \left\{ {\begin{array}{l} {{W_{ij}}\;\;\;\;\;\; < {v_i},{v_j} > 或({v_i},{v_j}) \in VR}\\ {\infty \;\;\;\;\;\;\;\;\;无边(弧)} \end{array}} \right. A.arcs[i][j]={Wij<vi,vj>(vi,vj)VR()

  • 例子:
    数据结构之图(二)——邻接矩阵_第3张图片



邻接矩阵的具体实现

  • 邻接矩阵的存储表示:用两个数组分别存储顶点表邻接矩阵
#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.输入总顶点数和总边数(为vexnum和arcnum赋值)
      • 2.依次输入点的信息存入顶点表中(为vexs[i]赋值)。
      • 3.初始化邻接矩阵,使每个权值初始化为极大值。
      • 4.构造邻接矩阵
    • 算法描述:
Status CreateUDN(AMGraph &G)
{
	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;            //边的权值均置为极大值(无穷大)
	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;                     //边的权值为w
		G.arcs[j][i] = G.arcs[i][j];          //置地对称边的权值为w
	}
	return OK;
}

其中的LocateVex函数表示查找某顶点在顶点表中的位置,具体如下,

//在图G中查找顶点u,存在则返回其在顶点表中的下标,否则返回-1
int LocateVex(AMGraph G, VerTexType u)
{
	int i;
	for (i = 0; i < G.vexnum; ++i)
		if (u == G.vexs[i])
			return i;
	return -1;
}
  • 采用邻接矩阵表示法创建其它图
    在前面创建无向网的基础上,只需经过一点修改,就可以创建无向图,有向网和有向图,操作如下图,
    数据结构之图(二)——邻接矩阵_第4张图片


邻接矩阵表示法的优缺点

  • 优点:

    • 直观、简单、好理解
    • 方便检查任意一对顶点间是否存在边
    • 方便找任一顶点的所有“邻接点”(有边直接相连的顶点)
    • 方便计算任一顶点的“度”。
  • 缺点:

    • 不便于增加和删除顶点
    • 浪费空间——存稀疏图(点很多而边很少)有大量无效元素
      • 对稠密图(特别是完全图)还是很合算的
    • 浪费时间——统计稀疏图中一共有多少条边

你可能感兴趣的:(数据结构)