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 中的应用!

相关推荐
Inverse1622 分钟前
C语言_自定义类型:结构体
c语言·开发语言·算法
Musennn17 分钟前
102. 二叉树的层序遍历详解:队列操作与层级分组的核心逻辑
java·数据结构·算法·leetcode
越来越无动于衷23 分钟前
java数组题(5)
java·算法
理论最高的吻25 分钟前
77. 组合【 力扣(LeetCode) 】
c++·算法·leetcode·深度优先·剪枝·回溯法
强盛小灵通专卖员3 小时前
分类分割详细指标说明
人工智能·深度学习·算法·机器学习
IT猿手7 小时前
基于强化学习 Q-learning 算法求解城市场景下无人机三维路径规划研究,提供完整MATLAB代码
神经网络·算法·matlab·人机交互·无人机·强化学习·无人机三维路径规划
万能程序员-传康Kk10 小时前
旅游推荐数据分析可视化系统算法
算法·数据分析·旅游
PXM的算法星球10 小时前
【并发编程基石】CAS无锁算法详解:原理、实现与应用场景
算法
ll77881110 小时前
C++学习之路,从0到精通的征途:继承
开发语言·数据结构·c++·学习·算法
烨然若神人~10 小时前
算法第十七天|654. 最大二叉树、617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树
算法