std::queue 是 C++ 中实现 BFS 最常用方式,需配合访问标记数组避免重复入队,且标记必须在入队时设置;图可用邻接表或邻接矩阵表示,稀疏图推荐邻接表。
std::queue 实现标准 BFS 遍历广度优先搜索在 C++ 中最常用、最直观的实现方式是借助 std::queue,配合访问标记数组(或 std::set/std::unordered_set)避免重复入队。核心逻辑是:从起点入队 → 循环取队首 → 访问所有未访问邻接点并入队。
关键点:
std::queue 是 FIFO 容器适配器,不支持随机访问或遍历,但完全满足 BFS 层序需求vector> )或邻接矩阵(vector> )表示;稀疏图强烈推荐邻接表vector> graph = {{1,2}, {0,3}, {0,3}, {1,2}}; vector visited(graph.size(), false); queue q; q.push(0); visited[0] = true; while (!q.empty()) { int u = q.front(); q.pop(); cout << u << " "; for (int v : graph[u]) { if (!visited[v]) { vi sited[v] = true; q.push(v); } } }
pair 或结构体纯 BFS 仅适用于无权图或所有边权相等的情形。若需在 BFS 过程中同步维护节点距离(如求最短路径长度),常见做法是把 node 和 dist 绑定为 pair 入队。
注意:
queue 配合外部数组“延迟更新”距离——这会导致距离值与实际出队顺序错位queue> q; // {node, dist} q.push({0, 0}); vector dist(graph.size(), -1); // -1 表示未访问 dist[0] = 0; while (!q.empty()) { auto [u, d] = q.front(); q.pop(); for (int v : graph[u]) { if (dist[v] == -1) { dist[v] = d + 1; q.push({v, d + 1}); } } }
当问题要求“从任意一个起点出发的最短距离”(如矩阵中多个 '0' 扩散到 '1'),可将所有起点一次性压入队列,并初始化对应距离为 0。这本质上仍是标准 BFS,只是初始队列非单元素。
典型场景包括:
陷阱:
BFS 在 C++ 中容易因容器误用或边界疏忽引发崩溃或死循环:
graph.size() 可能小于最大节点 ID —— 若输入含孤立大编号点(如节点 100 但只有 5 条边),需用 max_node_id + 1 初始化 visited 或 dist
queue::front() 和 queue::pop() 是两个独立操作,不能省略 pop(),否则无限循环vector> 存图时,确保每行都已 resize 或用 push_back 正确构建,空行会导致范围访问越界queue 时,记得每次调用前 queue = queue() 清空(C++11 后可直接赋值空队列)图论 BFS 看似简单,真正难的是根据题意准确建模——节点定义、边是否存在、是否允许回头、距离含义是否随层变化,这些细节一旦错,整个 BFS 就偏离目标。