Queue 在 BFS 中的 Expansion 和 Generation 的区别

在 BFS 代码中,queueExpansion(扩展)Generation(生成) 是两个关键概念,决定了节点何时被标记为 visited,以及搜索顺序如何进行。这两种策略在不同场景下有不同的适用性,理解它们的区别对于正确使用 BFS 以及避免冗余计算至关重要。

🔍 1. Expansion(扩展)

概念

  • 节点在出队(poll)时才标记为 visited
  • 这意味着该节点在 queue 中可能会出现多次,但只有在真正访问它时才会检查是否已经访问过。
  • 适用于无环图或某些特定场景,如无权图的最短路径问题。

特点

保证访问顺序 :所有的相邻节点都会先入队,但只有在出队时才被确认访问。

BFS 仍然按层级遍历 ,但 queue 可能包含重复节点。

可能导致冗余入队 ,但 visited.contains(curNode) 可以防止重复处理。

代码示例

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); // 在出队时标记 visited

        for(GraphNode nei: curNode.neighbors){
            queue.offer(nei);
        }
    }
    return result;
}

适用场景

  • 搜索整个图的连通性问题(如遍历所有可达节点)。
  • 无权图的最短路径搜索(虽然 Dijkstra 更高效)。
  • 适用于不连通的图 ,因为可以在 queue.poll() 时检查 visited

🔄 2. Generation(生成)

概念

  • 节点在入队(offer)时就被标记为 visited
  • 这样可以防止一个节点被多次入队,减少 queue 中的冗余数据。
  • 适用于所有 BFS 相关问题,尤其适用于有环图和连通性检查。

特点

防止冗余入队 ,提高效率。

BFS 仍然按层级遍历 ,但每个节点只会在 queue 中出现一次。

在某些场景下可能不适用,例如多次访问同一节点是必须的情况。

代码示例

scss 复制代码
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);
    visited.add(start); // 在入队时标记 visited

    while(!queue.isEmpty()){
        GraphNode curNode = queue.poll();

        result.add(curNode);

        for(GraphNode nei: curNode.neighbors){
            if(!visited.contains(nei)){
                visited.add(nei); // 在入队时标记 visited
                queue.offer(nei);
            }
        }
    }
    return result;
}

适用场景

  • 连通性检查:所有相连的节点只会被访问一次,不会重复入队。
  • 防止环的重复访问:避免无限循环。
  • 更高效的 BFS,适用于大多数图遍历问题。

📊 3. Expansion vs. Generation 总结对比

策略 何时标记 visited 是否可能重复入队 优缺点 适用场景
Expansion(扩展) 出队 (poll()) 时 ✅ 可能 ✅ 适用于遍历所有路径,但可能冗余入队 ❌ 需要额外检查 visited.contains(curNode) 无权图最短路径问题、连通性检查
Generation(生成) 入队 (offer()) 时 ❌ 不会 ✅ 更高效,防止重复入队 ❌ 不能处理需要多次访问的情况 有环图遍历、连通性检查、一般 BFS 问题

🔥 4. 如何选择?

如果问题涉及连通性检查、一般 BFS 遍历,推荐使用 Generation (入队时标记 visited)。

如果问题允许重复入队(例如计算路径数),可以使用 Expansion (出队时检查 visited)。

最短路径问题 中,通常建议使用 Generation 以减少冗余计算


🚀 5. 结论

  • queue 在 BFS 中有 两种不同的使用方式

    • Expansion (出队时标记 visited,可能重复入队)
    • Generation (入队时标记 visited,避免重复入队)
  • 大多数情况下,Generation 更优 ,但 Expansion 在某些特殊情况下更合适。

  • 了解 Expansion vs. Generation 的区别,可以帮助我们更高效地使用 BFS 解决问题!🚀


相关推荐
熬了夜的程序员17 分钟前
【LeetCode】74. 搜索二维矩阵
线性代数·算法·leetcode·职场和发展·矩阵·深度优先·动态规划
蓝色汪洋18 分钟前
oj字符矩阵
算法
点云SLAM18 分钟前
矩阵奇异值分解算法(SVD)的导数 / 灵敏度分析
人工智能·线性代数·算法·机器学习·矩阵·数据压缩·svd算法
坚持编程的菜鸟18 分钟前
LeetCode每日一题——矩阵置0
c语言·算法·leetcode·矩阵
零基础的修炼24 分钟前
Linux---线程封装
linux·c++·算法
chao1898441 小时前
基于MATLAB的双摆系统阻抗控制实现
算法
龙腾AI白云2 小时前
大模型-AIGC技术在文本生成与音频生成领域的应用
算法
坚持编程的菜鸟6 小时前
LeetCode每日一题——困于环中的机器人
c语言·算法·leetcode·机器人
Aurorar0rua7 小时前
C Primer Plus Notes 09
java·c语言·算法
我不是QI10 小时前
DES 加密算法:核心组件、加解密流程与安全特性
经验分享·算法·安全·网络安全·密码学