图是数据结构中一种重要的非线性结构,用于表示对象之间的多对多关系。以下是对你提供内容的系统化梳理与补充说明:
一、图的核心概念
1. 连通图与连通分量
- 连通图:在无向图中,若任意两个顶点之间都存在路径,则称该图为连通图。
- 连通分量:无向图中的极大连通子图称为连通分量。
- “极大”意味着不能再加入更多顶点和边而保持连通性。
- 对于非连通图,它有多个连通分量。
✅ 示例:一个由三个互不相连的三角形组成的无向图,共有3个连通分量。
2. 强连通图与强连通分量
- 强连通图:在有向图中,若任意两顶点 viv_ivi 和 vjv_jvj 之间都互相可达(即存在 vi→vjv_i \to v_jvi→vj 和 vj→viv_j \to v_ivj→vi 的路径),则称为强连通图。
- 强连通分量:有向图中的极大连通子图,其中每对顶点都互相可达。
- 注意:不是所有有向图都是强连通的,但每个顶点本身至少属于一个强连通分量。
🔍 应用:Kosaraju算法、Tarjan算法可用于求解有向图的强连通分量。
3. 网(网络图)
- 指边或弧上带有权值的图,通常表示距离、成本、时间等。
- 权可以为正数、负数(需注意负权环)、零。
- 常见于最短路径问题(如Dijkstra、Floyd-Warshall)和最小生成树(如Prim、Kruskal)。
4. 有向树
- 一种特殊的有向图:
- 恰有一个顶点入度为0(称为根节点);
- 其余顶点入度均为1;
- 忽略方向后形成一棵树。
- 特点:从根出发可到达所有其他节点,且无环。
📌 应用:常用于表示组织结构、文件系统、语法树等层次结构。
二、图的存储结构 —— 邻接矩阵表示法
基本定义
- 使用一个 n×nn \times nn×n 的二维数组
A表示具有 nnn 个顶点的图。 - 元素定义如下:
A[i][j]={1若 (vi,vj) 或 ⟨vi,vj⟩ 是边0否则 A[i][j] = \begin{cases} 1 & \text{若 } (v_i, v_j) \text{ 或 } \langle v_i, v_j \rangle \text{ 是边} \\ 0 & \text{否则} \end{cases} A[i][j]={10若 (vi,vj) 或 ⟨vi,vj⟩ 是边否则
特性分析
| 图类型 | 邻接矩阵性质 | 度的计算方式 |
|---|---|---|
| 无向图 | 对称矩阵(A[i][j]=A[j][i]A[i][j] = A[j][i]A[i][j]=A[j][i]) | 顶点 viv_ivi 的度 = 第 iii 行(或列)中非0元素个数 |
| 有向图 | 不一定对称 | 出度 = 第 iii 行非0个数;入度 = 第 iii 列非0个数 |
网的邻接矩阵
对于带权图(网),邻接矩阵定义为:
A[i][j]={Wij若存在边 (vi,vj)∞否则(或用特殊值如 -1、INF 表示无穷大)
A[i][j] =
\begin{cases}
W_{ij} & \text{若存在边 } (v_i, v_j) \\
\infty & \text{否则(或用特殊值如 -1、INF 表示无穷大)}
\end{cases}
A[i][j]={Wij∞若存在边 (vi,vj)否则(或用特殊值如 -1、INF 表示无穷大)
- 实现时常用
float('inf')或一个极大值代替 ∞\infty∞。 - 主对角线一般设为 0(自身到自身的距离为0)。
优缺点总结
| 优点 | 缺点 |
|---|---|
| 边的存在性查询快(O(1)O(1)O(1)) | 空间复杂度高:O(n2)O(n^2)O(n2),稀疏图浪费严重 |
| 易实现图算法(如Floyd) | 插入/删除顶点代价高(需重新分配矩阵) |
| 支持快速计算度、路径判断 | 不适合顶点数极多但边很少的情况(稀疏图) |
✅ 适用场景建议:
- 顶点数量较少且图较稠密时,优先使用邻接矩阵;
- 若图稀疏,推荐使用邻接表以节省空间。
判断一个有向图是否为强连通图,可以基于邻接矩阵使用以下方法:
✅ 方法:利用深度优先搜索(DFS)或可达性矩阵
由于邻接矩阵本身只表示直接边的关系,要判断强连通性,需要知道任意两个顶点之间是否互相可达。具体步骤如下:
🔧 步骤一:从任一顶点出发进行 DFS(基于邻接矩阵)
- 选择任意一个顶点 v0v_0v0;
- 使用邻接矩阵实现 DFS,记录能访问到的所有顶点;
- 如果不能访问所有 nnn 个顶点 → 不是强连通图。
🔧 步骤二:将邻接矩阵转置(即边反向),再做一次 DFS
- 转置矩阵 ATA^TAT 表示原图中所有边的方向反转;
- 在转置图上从同一个顶点 v0v_0v0 开始 DFS;
- 若仍不能访问全部顶点 → 也不是强连通图。
💡 原理:若在原图和反图中都能从 v0v_0v0 到达所有其他点,则说明任意两点间双向可达。
✅ 判定条件:
只有当 原图的 DFS 访问了所有顶点,且 反图的 DFS 也访问了所有顶点 时,该有向图才是强连通图。
🧮 示例代码(Python 风格伪代码)
def is_strongly_connected(adj_matrix):
n = len(adj_matrix)
def dfs(start, graph):
visited = [False] * n
stack = [start]
while stack:
u = stack.pop()
if not visited[u]:
visited[u] = True
for v in range(n):
if graph[u][v] and not visited[v]:
stack.append(v)
return visited
# 第一步:原图 DFS
visited1 = dfs(0, adj_matrix)
if not all(visited1):
return False
# 第二步:转置图 DFS(边反向)
transpose = [[adj_matrix[j][i] for j in range(n)] for i in range(n)]
visited2 = dfs(0, transpose)
if not all(visited2):
return False
return True
⏱️ 时间复杂度
- 每次 DFS:O(n2)O(n^2)O(n2)(因为遍历整个矩阵的行);
- 总时间复杂度:O(n2)O(n^2)O(n2);
- 空间复杂度:O(n)O(n)O(n)(用于
visited数组和栈)。
✅ 补充说明:
- 对于更大的图或频繁查询,可构造可达性矩阵(如用 Floyd-Warshall 算法传递闭包),然后检查是否所有点对 (i,j)(i,j)(i,j) 和 (j,i)(j,i)(j,i) 均可达。
- Floyd-Warshall 后判断:对所有 i,ji,ji,j,都有
reach[i][j] == True且reach[j][i] == True。


17万+

被折叠的 条评论
为什么被折叠?



