在 BFS(广度优先搜索)中,queue
(队列)扮演着核心角色,它控制着 节点的访问顺序 ,确保搜索按 层级顺序 进行。队列的 FIFO(先进先出) 特性,保证了 BFS 适用于 最短路径搜索 、连通性检查 、拓扑排序 等场景。
🔍 Queue 在 BFS 代码中的应用
在 BFS 代码中,我们通常使用 queue
进行以下操作:
ini
java
复制编辑
public List<GraphNode> BFS(GraphNode start){
List<GraphNode> result = new ArrayList<>();
Set<GraphNode> visited = new HashSet<>();
Deque<GraphNode> queue = new ArrayDeque<>();
queue.offer(start);
while(!queue.isEmpty()){
GraphNode curNode = queue.poll();
if(visited.contains(curNode)){
continue;
}
result.add(curNode);
visited.add(curNode);
for(GraphNode nei: curNode.neighbors){
queue.offer(nei);
}
}
return result;
}
👀 关键点
queue.offer(start);
初始化:将起点放入队列,准备开始搜索。curNode = queue.poll();
取出队首元素 进行处理,保证按照 FIFO 访问顺序。queue.offer(nei);
将当前节点的所有邻居入队,确保逐层遍历。
🔄 Queue 中元素的功能解析
在 BFS 过程中,queue
中存储的 每个元素 都有其特定的功能,我们可以从多个角度进行解析。
1️⃣ 作为「待访问节点」
- 队列存储的是即将访问的节点,即「当前层的邻居 + 下一层的起点」。
- 保证广度优先,确保每一层的节点都被访问完后,才进入下一层。
示例:
ini
mathematica
复制编辑
图结构:
A
/ \
B C
/ \
D E
BFS 过程:
1. queue = [A] (初始)
2. queue = [B, C] (访问 A,加入 B 和 C)
3. queue = [C, D, E] (访问 B,加入 D 和 E)
4. queue = [D, E] (访问 C)
5. queue = [E] (访问 D)
6. queue = [] (访问 E)
2️⃣ 作为「层级标记」
queue
通过 FIFO 规则 让同一层的节点按照顺序访问,确保每一层处理完后,才进入下一层。- 适用于 层次遍历(如二叉树层次遍历、最短路径)。
示例:求二叉树的最大深度
arduino
java
复制编辑
while (!queue.isEmpty()) {
int size = queue.size(); // 记录当前层的元素数量
for (int i = 0; i < size; i++) {
TreeNode cur = queue.poll();
if (cur.left != null) queue.offer(cur.left);
if (cur.right != null) queue.offer(cur.right);
}
depth++; // 进入下一层
}
3️⃣ 作为「最短路径搜索工具」
- BFS 在 无权图中 计算最短路径时,队列中每个元素都代表「路径中下一步的节点」。
- 例如,在迷宫问题或最短单词接龙问题中,
queue
维护 当前路径的前进方向。
示例:最短路径问题(单源最短路径)
scss
java
复制编辑
while (!queue.isEmpty()) {
GraphNode curNode = queue.poll();
for (GraphNode nei : curNode.neighbors) {
if (!visited.contains(nei)) {
distance.put(nei, distance.get(curNode) + 1); // 计算最短路径
queue.offer(nei);
}
}
}
4️⃣ 作为「拓扑排序的辅助结构」
- 在 拓扑排序 (Topological Sorting)中,
queue
主要存储 入度为 0 的节点,用于逐步移除依赖关系。 - 例如,在 课程表问题(Course Schedule) 里,队列负责维护当前可以选的课程。
示例:拓扑排序(Kahn's Algorithm)
ini
java
复制编辑
Queue<Integer> queue = new LinkedList<>();
for (int i = 0; i < numCourses; i++) {
if (inDegree[i] == 0) {
queue.offer(i); // 入度为 0 的课程入队
}
}
while (!queue.isEmpty()) {
int course = queue.poll();
for (int neighbor : graph.get(course)) {
inDegree[neighbor]--;
if (inDegree[neighbor] == 0) {
queue.offer(neighbor);
}
}
}
✅ 总结
🎯 Queue 的核心作用
角度 | 功能 |
---|---|
存储待访问节点 | 记录当前搜索范围,保证 FIFO 顺序 |
层级标记 | 维护 BFS 的逐层扩展特性 |
最短路径搜索 | 计算无权图的最短路径 |
拓扑排序 | 记录入度为 0 的节点,控制依赖关系 |
💡 关键优化
-
提前标记
visited
,避免重复入队:inijava 复制编辑 visited.add(start); queue.offer(start);
-
使用双向 BFS 优化搜索复杂度(适用于
word ladder
等问题)。 -
采用
ArrayDeque
代替LinkedList
提高性能(避免链表额外的存储开销)。
🚀 结论
queue
是 BFS 的核心数据结构 ,确保搜索 层级顺序 进行。- 不同场景下,queue 中的元素代表不同意义(如待访问节点、最短路径扩展、拓扑排序辅助)。
- 合理优化
queue
使用 (如提前标记visited
、双向 BFS)能显著提升算法效率。
📌 下一步学习方向
- 研究 双向 BFS 的优化(减少搜索层数)。
- 练习 基于 BFS 的实际问题 (如
word ladder
、滑动谜题
)。 - 结合 优先队列(PriorityQueue) 研究 Dijkstra 算法。
💡 希望这篇文章能帮助大家更深入理解 queue
在 BFS 中的应用!