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 解决问题!🚀


相关推荐
新新学长搞科研7 分钟前
【CCF主办 | 高认可度会议】第六届人工智能、大数据与算法国际学术会议(CAIBDA 2026)
大数据·开发语言·网络·人工智能·算法·r语言·中国计算机学会
近津薪荼8 分钟前
优选算法——前缀和(1):一维前缀和
c++·学习·算法
多恩Stone8 分钟前
【3D-AICG 系列-2】Trellis 2 的O-voxel (上) Shape: Flexible Dual Grid
人工智能·python·算法·3d·aigc
梵刹古音2 小时前
【C语言】 字符数组相关库函数
c语言·开发语言·算法
wfeqhfxz25887829 小时前
YOLO13-C3k2-GhostDynamicConv烟雾检测算法实现与优化
人工智能·算法·计算机视觉
Aaron15889 小时前
基于RFSOC的数字射频存储技术应用分析
c语言·人工智能·驱动开发·算法·fpga开发·硬件工程·信号处理
_不会dp不改名_11 小时前
leetcode_3010 将数组分成最小总代价的子数组 I
算法·leetcode·职场和发展
你撅嘴真丑13 小时前
字符环 与 变换的矩阵
算法
早点睡觉好了13 小时前
重排序 (Re-ranking) 算法详解
算法·ai·rag
gihigo199813 小时前
基于全局自适应动态规划(GADP)的MATLAB实现方案
算法