yukki.cn / writing / post-20260826-204123
邻接矩阵的基本概念
整理邻接矩阵的表示方法、性质、常见计算与复杂度。
一、基本定义
图的邻接矩阵存储由两部分组成:
- 一个一维数组,用于存放顶点;
- 一个二维数组,用于表示顶点之间的邻接关系。
设图为 G=(V,E),共有 n 个顶点:
V={v1,v2,…,vn}
其邻接矩阵记为 A=(aij)n×n。在无权图中:
aij={1,0,vi 与 vj 之间有边vi 与 vj 之间无边
在程序中,aij 对应数组元素 A[i][j]。
核心: 邻接矩阵就是用一个 n×n 的矩阵记录任意两个顶点之间是否有边。
二、不同类型图的邻接矩阵
1. 有向图
在有向图中,aij=1 表示存在从 vi 指向 vj 的有向边:
vi→vj
因此,矩阵中的行表示起点,列表示终点。
例如:
A=001100110
第一行 [0,1,1] 表示 v1→v2 和 v1→v3。
2. 无向图
无向图中,若 vi 与 vj 相邻,则必有 aij=aji。所以无向图的邻接矩阵是对称矩阵:
A=AT
同一条无向边会在矩阵中记录两次。因此,可以只存储上三角或下三角部分,但空间复杂度仍为 O(n2)。
3. 带权图(网)
带权图中,矩阵元素记录边的权值。在最短路径等问题中,通常规定:
aij={wij,∞,vi 与 vj 之间有边vi 与 vj 之间无边
通常还规定主对角线元素为 0。例如:
A=03∞305∞50
这表示边 (v1,v2) 的权值为 3,边 (v2,v3) 的权值为 5,而 v1 与 v3 之间无边。
当然是0是还是♾️都无所谓,看题目要求
三、存储结构
邻接矩阵常见的 C 语言存储结构如下:
typedef struct {
VertexType vex[MAXV];
int edge[MAXV][MAXV];
int vexnum;
int arcnum;
} MGraph;
| 成员 |
含义 |
| vex |
存储顶点信息 |
| edge |
存储边或弧的信息 |
| vexnum |
图的顶点数 |
| arcnum |
图的边数或弧数 |
四、常见性质与计算
以下结论默认讨论不含自环的简单无权图。
1. 无向图顶点的度
无向图中,顶点 vi 的度等于第 i 行元素之和,也等于该行非零元素的个数:
D(vi)=j=1∑naij
例如:
A=0110101111000100
第二行有三个 1,因此 D(v2)=3。
2. 有向图顶点的度
有向图中:
- 第 i 行元素之和是顶点 vi 的出度;
- 第 i 列元素之和是顶点 vi 的入度。
OD(vi)=j=1∑naij,ID(vi)=j=1∑naji
顶点的总度数为:
TD(vi)=OD(vi)+ID(vi)
重点: 行看出度,列看入度。
3. 图的边数
无向图中,每条边在矩阵中出现两次,因此:
∣E∣=21i=1∑nj=1∑naij
有向图中,每条弧只出现一次,因此:
∣E∣=i=1∑nj=1∑naij
五、复杂度与适用场景
| 操作 |
时间或空间复杂度 |
| 存储邻接矩阵 |
O(n2) |
| 判断两顶点之间是否有边 |
O(1) |
| 添加或删除一条边 |
O(1) |
| 查找一个顶点的所有邻接点 |
O(n) |
| 使用邻接矩阵进行 DFS 或 BFS |
O(n2) |
邻接矩阵的空间复杂度只与顶点数 n 有关,与实际边数无关。因此:
- 稠密图中边数较多,邻接矩阵结构简单且查询效率高,较为适用;
- 稀疏图中大量位置为 0,容易浪费空间,通常更适合邻接表。
作为对比,邻接表进行 DFS 或 BFS 的时间复杂度为 O(n+∣E∣)。
六、邻接矩阵的幂
设 A 为图的邻接矩阵,则矩阵幂中的元素 (Ak)ij 表示:
从顶点 vi 到 vj、长度为 k 的游走数量
矩阵A是有向图G的邻接矩阵,若矩阵A²的某元素(a2)ij=3,则说明
从顶点 i 到 j 存在 3 条长度为 2 的路径
看网课说比较重要,是往年真题考过的偏门知识点
七、速记
| 考点 |
结论 |
| 存储结构 |
顶点数组 + n×n 矩阵 |
| 无向图 |
A=AT |
| 无向图顶点度 |
第 i 行元素之和 |
| 有向图出度 |
第 i 行元素之和 |
| 有向图入度 |
第 i 列元素之和 |
| 无向图边数 |
矩阵中所有 1 的个数除以 2 |
| 有向图弧数 |
矩阵中所有 1 的个数 |
| 查询一条边 |
O(1) |
| 查找全部邻接点 |
O(n) |
| DFS、BFS |
O(n2) |
| (Ak)ij |
从 vi 到 vj 的长度为 k 的游走数量 |
记忆: 无向看对称,有向行出列入;查询一条边是 O(1),遍历邻接点是 O(n)。
接下来又要不更新一段时间了,我要开始勇闯二叉树和邻接矩阵的算法题部分,写代码去了。
现在数学的第一章节的练习题已经做完3/4了,到时候继续美美开第二章。
不过这有点太慢了,要不要考虑顺手把计算机组成原理也开了呢,大概了解下概念?
