算法与数据结构

图的表示与 BFS/DFS 遍历

04-图与网络核心预计 25 分钟图BFSDFS邻接表
学习状态:

一句话定义

图(Graph)G=(V,E) 由顶点集与边集构成(有向/无向、带权/无权);邻接表/邻接矩阵是两种基本表示,广度优先搜索(BFS)按层扩展、深度优先搜索(DFS)一探到底,二者都在 O(V+E) 内遍历全图,是所有图算法的骨架。

为什么重要

图是「任意二元关系」的通用模型:社交网络、依赖关系、路网、状态机。本模块的其余算法(最短路、MST、拓扑、二分图、网络流)全部构建在「表示 + BFS/DFS」这块地基上;BFS 求无权最短路、DFS 求连通性与环,本身就是高频面试与工程题。visited 标记、队列/栈的选择这些肌肉记忆,从这里开始建立。

前置知识

kp-008(队列/栈);kp-011(树遍历——图遍历是它的带环推广)。

核心概念

  • 术语:度(无向)/入度出度(有向)、路径、环、连通、子图;稀疏图 E≈O(V),稠密图 E≈O(V²)。
  • 邻接表:每顶点一个邻居列表(数组 of 列表),空间 O(V+E),遍历邻居快,适合稀疏图——工程默认。
  • 邻接矩阵:n×n 0/1(或权值)矩阵,空间 O(V²),查「u,v 是否相邻」O(1),适合稠密图或频繁邻接查询。
  • BFS:队列 + visited;从源点分层扩展,首次到达某点的层数即无权最短距离。
  • DFS:递归或显式栈 + visited;产生深度优先森林,进入/离开时间戳(括号结构)支持拓扑序、割点桥等推导。
  • 复杂度:两者均 Θ(V+E)(邻接表);矩阵表示则 Θ(V²)。

直观类比

BFS 是往池塘里丢石头看波纹,一圈圈往外扩,第一次碰到即最短距离;DFS 是走迷宫时「贴一面墙一直走到底再回头」,把一条支路彻底探索完才换下一条。

原理与机制

BFS 伪代码(无权最短距离):

函数 BFS(s):
    dist[全部] ← ∞ ; dist[s] ← 0 ; 队列 ← [s]
    当 队列非空:
        u ← 出队
        对于 v ∈ adj[u]:
            若 dist[v] == ∞:
                dist[v] ← dist[u] + 1 ; v 入队

正确性核心:队列单调(距离值只增不减、至多两种相邻值),顶点按距离非降序出队,故首次入队的 dist 即最短跳数——证明要点是「归纳于层」。DFS 的时间戳性质:u 是 v 的祖先 ⇔ [in(u), out(u)] ⊇ [in(v), out(v)](括号定理),它直接导出拓扑排序与 kp-019 的 SCC 算法。

图示

图:  A ─ B ─ C          邻接表:
     |   |                  A: [B, D]
     D ─ E                  B: [A, C, E]
                            C: [B]
从 A 出发:                  D: [A, E]
BFS 层次: A → {B,D} → {C,E}   E: [B, D]
dist: A=0, B=D=1, C=E=2
DFS(先访字母序): A→B→C 回溯→E→D(栈序)

实例或案例

  • 社交网络「几度人脉」:BFS 层数即度数;LinkedIn 的二度连接。
  • 迷宫最短步数、棋盘马走日最少步数:格子图上 BFS。
  • 爬虫与垃圾回收(可达性标记):DFS/BFS 遍历引用图。
  • 编译依赖、课程先修:有向图判环(DFS 回边)或拓扑排序(kp-018)。

常见误区

  • 忘记 visited 标记:有环图无限循环;标记时机应在「入队/入栈时」而非出队后(否则同一节点重复入队,复杂度劣化)。
  • 无向图只加单向边:邻接表必须 u→v、v→u 双向注册,这是最高频的实现 bug。
  • 递归 DFS 在深图上栈溢出:V 可达 10⁵~10⁶ 时应显式栈化。
  • 用 BFS 去解带权最短路:层数 ≠ 权和,带权必须换 Dijkstra(kp-017)。

自测题

  1. 对上图从 E 出发写 BFS 序与各点最短跳数。

答案要点:E=0;B=1, D=1;A=2(经 D 或 B), C=2(经 B)。

  1. 无向图邻接表与邻接矩阵的空间各是多少?何时选矩阵?

答案要点:O(V+2E)=O(V+E) 与 O(V²);E≈V² 的稠密图或需要 O(1) 邻接判定时选矩阵。

  1. 如何用 DFS 判断有向图是否有环?

答案要点:三色标记,遇到「灰色」回边(当前递归栈中的节点被再次访问)即有环。

与其他知识点的关系

kp-017 在 BFS 的分层思想上加权升级;kp-018 拓扑排序直接用 DFS 完成时间;kp-030 并查集是「只要连通性不要遍历路径」时的省力替代;kp-027 回溯与 DFS 的关系是「图遍历求可达 vs 决策树遍历求全部解」。

延伸阅读

《算法导论》第 20 章(20.2/20.3 BFS 与 DFS);《算法(第 4 版)》第 4.1–4.2 节(无向/有向图)。