BFS 中的队列(Queue):深入解析其功能与作用

在 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;
}

👀 关键点

  1. queue.offer(start); 初始化:将起点放入队列,准备开始搜索。
  2. curNode = queue.poll(); 取出队首元素 进行处理,保证按照 FIFO 访问顺序。
  3. 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 的节点,控制依赖关系

💡 关键优化

  1. 提前标记 visited,避免重复入队:

    ini 复制代码
    java
    复制编辑
    visited.add(start);
    queue.offer(start);
  2. 使用双向 BFS 优化搜索复杂度(适用于 word ladder 等问题)。

  3. 采用 ArrayDeque 代替 LinkedList 提高性能(避免链表额外的存储开销)。


🚀 结论

  • queueBFS 的核心数据结构 ,确保搜索 层级顺序 进行。
  • 不同场景下,queue 中的元素代表不同意义(如待访问节点、最短路径扩展、拓扑排序辅助)。
  • 合理优化 queue 使用 (如提前标记 visited、双向 BFS)能显著提升算法效率。

📌 下一步学习方向

  • 研究 双向 BFS 的优化(减少搜索层数)。
  • 练习 基于 BFS 的实际问题 (如 word ladder滑动谜题)。
  • 结合 优先队列(PriorityQueue) 研究 Dijkstra 算法。

💡 希望这篇文章能帮助大家更深入理解 queue 在 BFS 中的应用!

相关推荐
今天背单词了吗98013 分钟前
算法学习笔记:11.冒泡排序——从原理到实战,涵盖 LeetCode 与考研 408 例题
java·学习·算法·排序算法·冒泡排序
倔强的小石头_3 小时前
【C语言指南】函数指针深度解析
java·c语言·算法
Yasin Chen3 小时前
C# Dictionary源码分析
算法·unity·哈希算法
_Coin_-4 小时前
算法训练营DAY27 第八章 贪心算法 part01
算法·贪心算法
董董灿是个攻城狮9 小时前
5分钟搞懂什么是窗口注意力?
算法
Dann Hiroaki9 小时前
笔记分享: 哈尔滨工业大学CS31002编译原理——02. 语法分析
笔记·算法
qqxhb11 小时前
零基础数据结构与算法——第四章:基础算法-排序(上)
java·数据结构·算法·冒泡·插入·选择
FirstFrost --sy12 小时前
数据结构之二叉树
c语言·数据结构·c++·算法·链表·深度优先·广度优先
森焱森12 小时前
垂起固定翼无人机介绍
c语言·单片机·算法·架构·无人机
搂鱼11451413 小时前
(倍增)洛谷 P1613 跑路/P4155 国旗计划
算法