首页/数据结构/05-graph/广度优先遍历(BFS) 🔗 在 Obsidian 中打开
数据结构 · 05-graph

广度优先遍历(BFS)

重要度 ⭐⭐ 广度优先图遍历队列最短路径408
速查
BFS 用队列逐层扩展(像水波扩散)。无权图中 BFS 求得最短路径(最重要性质)。邻接矩阵 O(|V|²)、邻接表 O(|V|+|E|)。生成 BFS 生成树。

核心概念

从起始顶点出发,先访问所有直接相邻顶点,再依次访问这些邻接点的未访问邻接点,逐层扩展。
  • 队列管理待访问顶点(FIFO,保证按层次访问)。
  • 连通图调一次 BFS;非连通图对每个连通分量各调一次。
  • BFS 循环结束的判据:使用辅助数组 visited[];每访问一个顶点就把它从「未访问」集合中删除。
BFS 的重要性质无权图中 BFS 求出的路径是最短路径(按边数计);过程产生 BFS 生成树;层次对应顶点到起点的距离。

BFS vs DFS

特性BFSDFS
数据结构队列栈(递归栈)
策略逐层扩展尽可能深
无权最短路径
空间O(|V|)O(|V|)

存储影响:邻接矩阵实现 BFS O(|V|²);邻接表实现 O(|V| + |E|)。

算法步骤

BFS_Visit(G, v):
1. 访问 v,visited[v]=true,v 入队 Q
2. 当 Q 非空:
   2.1 队头 u 出队
   2.2 对 u 的每个邻接点 w:
        若 w 未被访问:访问 w、标记、w 入队

层次性:第 0 层起始点,第 1 层其所有邻接点……第 k 层为距离起点恰好 k 条边的顶点。BFS 生成树:w 首次被访问时使之入队的边 (u,w) 即树边。

代码实现(C)

邻接表版 BFS(主流程 + 求最短路径只需把 dist 赋值替代 visit):

void BFS_AL(ALGraph G, int v){
    Queue Q; InitQueue(&Q);
    visit(v); visited[v]=true; EnQueue(&Q, v);
    while(!IsEmpty(&Q)){
        int u=DeQueue(&Q);
        for(ArcNode *p=G.vertices[u].firstarc; p; p=p->nextarc)
            if(!visited[p->adjvex]){
                visit(p->adjvex);
                visited[p->adjvex]=true;
                EnQueue(&Q, p->adjvex);
            }
    }
}

广度优先求无权图最短路径:dist[] 初值 -1(不可达),起点的 dist=0;访问邻接点时 dist[w]=dist[u]+1BFS 生成树第 k 层的顶点恰是 dist=k 的顶点。

手算示例

顶点集 $V=\{0,1,2,3,4,5\}$,边集 $E=\{(0,1),(0,2),(1,3),(1,4),(2,4),(3,5),(4,5)\}$,从顶点 0 开始:

队列演进: [0] → [1,2] → [2,3,4] → [3,4] → [4,5] → [5] → []
BFS 序:   0 → 1 → 2 → 3 → 4 → 5
层次:    第 0 层 {0}、第 1 层 {1,2}、第 2 层 {3,4}、第 3 层 {5}
dist:    dist[0]=0, dist[1]=1, dist[2]=1, dist[3]=2, dist[4]=2, dist[5]=3

易错点

易错清单
  • BFS 用队列、DFS 用,别混。
  • 访问过的顶点必须立即标记 visited,否则会重复入队。
  • 非连通图要对每个连通分量分别 BFS。
  • 有权图不能用 BFS 求最短路径(只保证无权图)。

核心结论

  1. BFS 从起点出发逐层扩展,队列实现,思想是「先进先出」。时间复杂度:邻接表 O(|V|+|E|),邻接矩阵 O(|V|²)。
  2. 在无权图上 BFS 可以求最短路径(边数最少)。
  3. BFS 生成的树叫 BFS 生成树(森林),用于理解层次结构。
  4. 空间复杂度 O(|V|),极端情况(一个连通分量)最多同时排队 |V|-1 个顶点。

记忆卡片

BFS 用什么数据结构?
队列(FIFO),保证按层次(距离)逐层访问。
BFS 能求什么?
无权图的最短路径(按边数),生成 BFS 树。
BFS 的时间复杂度?
邻接表 O(|V|+|E|),邻接矩阵 O(|V|²)。
BFS 与 DFS 遍历序一样吗?
通常不同:BFS 先近后远,DFS 深入优先。

交互动画 · BFS 逐层扩展

队列:(空) 0 1 2 3 4 5
从顶点 0 开始 BFS:逐层访问、队列先行
点「下一步」走队列入出队过程;可查看最短路径或生成树
BFS 序 0→1→2→3→4→5;dist 即层号,dist[5]=3 是 0 到 5 的最短路长。

相关知识点

depth-first-search-dfs graph-traversal-and-applications graph-traversal

↑ 以上为站内 HTML 相对链接(纯网页可浏览);本页右上「在 Obsidian 中打开」跳回源笔记。