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


相关推荐
你撅嘴真丑10 小时前
第九章-数字三角形
算法
uesowys10 小时前
Apache Spark算法开发指导-One-vs-Rest classifier
人工智能·算法·spark
ValhallaCoder10 小时前
hot100-二叉树I
数据结构·python·算法·二叉树
董董灿是个攻城狮10 小时前
AI 视觉连载1:像素
算法
智驱力人工智能11 小时前
小区高空抛物AI实时预警方案 筑牢社区头顶安全的实践 高空抛物检测 高空抛物监控安装教程 高空抛物误报率优化方案 高空抛物监控案例分享
人工智能·深度学习·opencv·算法·安全·yolo·边缘计算
孞㐑¥11 小时前
算法——BFS
开发语言·c++·经验分享·笔记·算法
月挽清风11 小时前
代码随想录第十五天
数据结构·算法·leetcode
XX風12 小时前
8.1 PFH&&FPFH
图像处理·算法
NEXT0612 小时前
前端算法:从 O(n²) 到 O(n),列表转树的极致优化
前端·数据结构·算法
代码游侠12 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法