🔥 本文由 程序喵正在路上 原创,CSDN首发!
💖 系列专栏:数据结构与算法
🌠 首发时间:2022年11月13日
🦋 欢迎关注🖱点赞👍收藏🌟留言🐾
🌟 一以贯之的努力 不得懈怠的人生
阅读指南
邻接矩阵法(顺序存储)
图中点和点之间是否有连接,我们可以用一个表来表示,其中 “1” 表示两点之间有边,反之
上图很容易用代码表示出来
#define MaxVertexNum 100 //顶点数目的最大值
typedef struct{
char Vex[MaxVertexNum]; //顶点表
int Edge[MaxVertexNum][MaxVertexNum]; //邻接矩阵,边表
int vexnum, arcnum; //图的当前顶点数和边数/弧数
} MGraph;
顶点的数组中我们可以存储更复杂的信息,比如一个结构体
结点数为 n n n 的图 G = ( V , E ) G = (V, E) G=(V,E) 的邻接矩阵 A A A 是 n × n n \times n n×n 的,将 G G G 的顶点编号为 v 1 , v 2 , … , v n v_1, v_2, \dots, v_n v1,v2,…,vn, 则
KaTeX parse error: No such environment: align* at position 8: \begin{̲a̲l̲i̲g̲n̲*̲}̲ \begin{split} …
在这种情况下,我们怎么求顶点的度、入度和出度呢?
- 对于无向图,第 i i i 个结点的度 = = = 第 i i i 行(或第 i i i 列)的非零元素个数
- 对于有向图,第 i i i 个结点的出度 = = = 第 i i i 行的非零元素个数,第 i i i 个结点的入度 = = = 第 i i i 列的非零元素个数,,第 i i i 个结点的度 = = = 第 i i i 行、第 i i i 列的非零元素个数之和
邻接矩阵法求顶点的度 / 出度 / 入度的时间复杂度均为 O ( ∣ V ∣ ) O(|V|) O(∣V∣)
邻接矩阵法存储带权图(网)
#define MaxVertexNum 100 //顶点数目的最大值
#define INFINITY 最大的int值 //宏定义常量 “无穷”
typedef char VertexType; //顶点的数据类型
typedef int EdgeType; //带权图中边上权值的数据类型
typedef struct{
VertexType Vex[MaxVertexNum]; //顶点
EdgeType Edge[MaxVertexNum][MaxVertexNum]; //边的权
int vexnum, arcnum; //图的当前顶点数和弧数
} MGraph;
邻接矩阵法的性能分析
空间复杂度: O ( ∣ V ∣ ) O(|V|) O(∣V∣) —— 只和顶点数相关,和实际的边数无关,邻接矩阵法采用数组顺序存储的形式,适合用于存储稠密图
无向图的邻接矩阵是对称矩阵,我们可以压缩存储,也就是只存储上三角区或者下三角区
邻接矩阵法的性质
设图 G G G 的邻接矩阵为 A A A(矩阵元素为 0 / 1 0/1 0/1),则 A n A^n An 的元素 A n [ i ] [ j ] A^n[i][j] An[i][j] 等于由顶点 i i i 到顶点 j j j 的长度为 n n n 的路径的数目
假设 A A A 如下表所示
现在要计算 A 2 [ 1 ] [ 4 ] , A 2 [ 2 ] [ 2 ] A^2[1][4], A^2[2][2] A2[1][4],A2[2][2],该怎么做呢?
A 2 [ 1 ] [ 4 ] = a 11 × a 14 + a 12 × a 24 + a 13 × a 34 + a 14 × a 44 = 1 A 2 [ 2 ] [ 2 ] = a 21 × a 12 + a 22 × a 22 + a 23 × a 32 + a 24 × a 42 = 3 A^2[1][4] = a_{11} \times a_{14} + a_{12} \times a_{24} + a_{13} \times a_{34} + a_{14} \times a_{44} = 1 \\ A^2[2][2] = a_{21} \times a_{12} + a_{22} \times a_{22} + a_{23} \times a_{32} + a_{24} \times a_{42} = 3 A2[1][4]=a11×a14+a12×a24+a13×a34+a14×a44=1A2[2][2]=a21×a12+a22×a22+a23×a32+a24×a42=3
其中 a 11 a_{11} a11 表示矩阵的第 1 1 1 行第 1 1 1 个元素,其他依此类推
我们画出 A 2 A^2 A2 的表,如下
可以发现,我们计算出来的值就是这个表中对应位置的值
如果让你计算 A 3 [ 1 ] [ 4 ] A^3[1][4] A3[1][4] 呢?
邻接表法(顺序+链式存储)
// “边/弧”
typedef struct ArcNode{
int adjvex; //边/弧指向哪个结点
struct ArcNode *next; //指向下一条弧的指针
InfoType info; //边权值(没有可不加)
}ArcNode;
// “顶点”
typedef struct VNode{
VertexType data; //顶点信息
ArcNode *first; //第一条边/弧
}VNode, AdjList[MaxVertexNum];
//用邻接表存储的图
typedef struct{
AdjList vertices;
int vexnum, arcnum;
}ALGraph;
当然,有向图也可以用邻接表法来表示
空间复杂度分析
对于无向图,由于每一条边都会有一个指向的结点占空间,而且是双向的,比如 A A A 和 B B B 之间有一条边,那么
A A A 到 B B B 这条边就会有一个指向 B B B 的结点,同理 B B B 到 A A A 这条边就会有一个指向 A A A 的结点,由于边结点的数量是 2 ∣ E ∣ 2|E| 2∣E∣ ,所以整体的空间复杂度为 O ( ∣ V ∣ + 2 ∣ E ∣ ) O(|V| + 2|E|) O(∣V∣+2∣E∣)
对于有向图,由于每条边都是有方向的,所以只会有一个指向结点,整体的空间复杂度即为 O ( ∣ V ∣ + ∣ E ∣ ) O(|V| + |E|) O(∣V∣+∣E∣)
度、入度和出度
那么,下面我们思考一下怎么求顶点的度、入度和出度呢?
- 对于无向图,我们只要遍历边结点的链表就能求出对应顶点的度
- 对于有向图,通过遍历边结点的链表我们就能求出对应顶点的出度;但是要得到某个顶点的入度,就很麻烦了,我们需要遍历所有顶点相应的边结点的链表,这也是邻接表法的一个缺点
邻接矩阵和邻接表的对比
图的邻接表表示方式并不唯一,与一个顶点有关系的边的顺序是可以颠倒排列的;但是对于前面的邻接矩阵来说,只要确定了顶点编号,那图的邻接矩阵就是唯一的
对比角度 | 邻接矩阵 | 邻接表 |
---|---|---|
空间复杂度 | O ( ∣ V ∣ 2 ) O(|V|^2) O(∣V∣2) | 无向图 O ( ∣ V ∣ + 2 ∣ E ∣ ) O(|V| + 2|E|) O(∣V∣+2∣E∣);有向图 O ( ∣ V ∣ + ∣ E ∣ ) O(|V| + |E|) O(∣V∣+∣E∣) |
适合用于 | 存储稠密图 | 存储稀疏图 |
表示方式 | 唯一 | 不唯一 |
计算度 / 出度 / 入度 | 必须遍历对应行或列 | 计算有向图的度、入度不方便,其余很方便 |
找相邻的边 | 必须遍历对应行或列 | 找有向图的入边不方便,其余很方便 |
十字链表
我们需要定义两个结构:弧结点和顶点结点
空间复杂度为: O ( ∣ V ∣ + ∣ E ∣ ) O(|V| + |E|) O(∣V∣+∣E∣)
如何找到指定顶点的所有出边? —— 顺着绿色线路找
如何找到指定顶点的所有入边? —— 顺着橙色线路找
注意:十字链表只用于存储有向图
邻接多重表
空间复杂度为: O ( ∣ V ∣ + ∣ E ∣ ) O(|V| + |E|) O(∣V∣+∣E∣)
删除边、删除节点等操作很方便
注意:邻接多重表只用于存储无向图
总结
角度 | 邻接矩阵 | 邻接表 | 十字链表 | 邻接多重表 |
---|---|---|---|---|
空间复杂度 | O ( ∣ V ∣ 2 ) O(|V|^2) O(∣V∣2) | 无向图 O ( ∣ V ∣ + 2 ∣ E ∣ ) O(|V| + 2|E|) O(∣V∣+2∣E∣);有向图 O ( ∣ V ∣ + ∣ E ∣ ) O(|V| + |E|) O(∣V∣+∣E∣) | O ( ∣ V ∣ + ∣ E ∣ ) O(|V| + |E|) O(∣V∣+∣E∣) | O ( ∣ V ∣ + ∣ E ∣ ) O(|V| + |E|) O(∣V∣+∣E∣) |
找相邻边 | 遍历对应行或列,时间复杂度为 O ( ∣ V ∣ ) O(|V|) O(∣V∣) | 找有向图的入边必须遍历整个邻接表 | 很方便 | 很方便 |
删除边或顶点 | 删除边很方便,删除顶点需要移动大量数据 | 无向图中删除边或顶点都不方便 | 很方便 | 很方便 |
适用于 | 存储稠密图 | 存储稀疏图或其他 | 只能存储有向图 | 只能存储无向图 |
表示方式 | 唯一 | 不唯一 | 不唯一 | 不唯一 |