图的遍历
含AI生成内容
图的遍历
图的遍历需要解决两个特殊问题:一是图中可能存在回路,需要标记已访问顶点防止重复访问;二是图可能不连通,需要遍历所有顶点,对每个未访问顶点启动一次遍历。
BFS(广度优先搜索)
核心思想
BFS 的核心是逐层扩展——从起始顶点出发,先访问其所有邻接顶点,再访问邻接顶点的邻接顶点,依此类推。过程类似于水波扩散。
- 数据结构:队列(FIFO),保证层次顺序
- visited 数组:标记已访问顶点,防止重复入队
- 每层距离相同:第 k 层的顶点距离源点恰好为 k
算法过程
层次 0: v0层次 1: v1 v2 v3 (v0 的邻接顶点)层次 2: v4 v5 (v1,v2,v3 的未访问邻接顶点)- 访问起始顶点 v,标记
visited[v] = true,v 入队 - 队列非空时循环:队头 u 出队,检查 u 的所有邻接顶点 w,若 w 未访问则标记并入队
- 队列为空时,从 v 出发可达的所有顶点均已访问
对于非连通图,需遍历所有顶点,对未访问的顶点再次调用 BFS(调用次数 = 连通分量个数)。
BFS 求无权图最短路径
BFS 的一个关键应用是求无权图(边权均为 1)的单源最短路径。由于逐层扩展的特性,某顶点首次被访问时的距离一定是最短距离。
维护两个数组:
d[v]:源点到 v 的最短距离(初始化为 -1 表示未访问)path[v]:v 的前驱顶点,用于回溯还原路径
路径还原:从目标顶点 t 沿 path[] 回溯到源点,逆序即为最短路径。
易错:BFS 求最短路径仅适用于无权图。如果边有不同的权值,BFS 的”最少边数”不等于”最小权值和”,此时必须使用 Dijkstra 算法。
BFS 生成树
对连通图从 v 进行 BFS 时,所有引起顶点首次被访问的边构成一棵BFS 生成树。树中从根到任意顶点的路径即为原图中从 v 到该顶点的最短路径(边数最少)。非连通图对应BFS 生成森林。
DFS(深度优先搜索)
核心思想
DFS 的核心策略是尽可能深地搜索图的分支,走到死胡同时再回溯。
- 数据结构:栈(递归调用栈自动完成回溯)
- visited 数组:标记已访问顶点
- 回溯:当前顶点的所有邻接点都已访问时,沿原路退回上一顶点
算法过程
- 从起始顶点 v 出发,标记 v 为已访问
- 依次检查 v 的所有邻接点 w:
- 若 w 未被访问,递归地对 w 执行 DFS
- 若 w 已被访问,跳过
- 当 v 的所有邻接点都已被访问,回溯到上一层
非连通图:DFSTraverse 中调用 DFS 的次数 = 连通分量个数。
DFS 生成树
对连通图进行 DFS,所有经过的边(递归调用时使用的边)构成一棵DFS 生成树。非连通图产生DFS 生成森林。
DFS 检测有向图环(三色标记法)
DFS 可以用三种状态标记顶点来检测有向图是否有环:
- 0(未访问):尚未遍历到
- 1(访问中):在当前递归栈上
- 2(已完成):该顶点的所有后继已遍历完毕
若 DFS 过程中遇到状态为 1 的顶点(即遇到了一条回边),则说明存在环。
BFS vs DFS 对比
| 对比项 | BFS | DFS |
|---|---|---|
| 数据结构 | 队列 | 栈(递归调用栈) |
| 思想 | 逐层扩展 | 尽可能深入,回溯 |
| 时间复杂度(邻接表) | O(V+E) | O(V+E) |
| 时间复杂度(邻接矩阵) | O(V2) | O(V2) |
| 空间复杂度 | O(V) | O(V) |
| 最短路径 | 可求无权图最短路径 | 不能 |
| 适用场景 | 最短路径、层次遍历 | 连通性、路径搜索、拓扑排序 |
| 生成树 | BFS 生成树/森林 | DFS 生成树/森林 |
| 连通分量 | BFS 调用次数 = 连通分量数 | DFS 调用次数 = 连通分量数 |
复杂度分析
| 存储方式 | BFS 时间复杂度 | DFS 时间复杂度 | 说明 |
|---|---|---|---|
| 邻接表 | O(V+E) | O(V+E) | 每个顶点入队/入栈一次,每条边检查一次 |
| 邻接矩阵 | O(V2) | O(V2) | 查找邻接顶点需扫描一整行 |
空间复杂度:O(V),主要为 visited 数组 O(V) 和辅助队列/递归栈 O(V)。
遍历序列的不唯一性
遍历序列不唯一——邻接表的链表顺序不同会产生不同的遍历序列。用邻接矩阵则结果唯一(按下标顺序访问邻接点)。408 选择题常给出一个图和一个遍历序列,问”这个序列可能是 DFS/BFS 的结果吗”。
考研高频考点
- 给定图结构,写出 BFS/DFS 遍历序列
- BFS 与 DFS 的对比:数据结构、适用场景、能否求最短路径
- BFS 调用次数 = 连通分量个数
- BFS 求无权图最短路径的 d[] 和 path[] 数组
- DFS 检测有向图中是否有环(三色标记法)
- 邻接表 vs 邻接矩阵对遍历时间复杂度的影响
- 遍历序列不唯一性的原因分析
关联页面
- 图的基本概念与存储结构 — 存储结构决定遍历的时间复杂度
- 栈(Stack) — DFS 的递归本质基于栈结构
- 队列(Queue) — BFS 的核心数据结构
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!










