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


相关推荐
智者知已应修善业5 分钟前
【51单片机初始化D5-D8亮,每按键按下D1到D4全亮,再按下恢复,如此循环】2024-3-26
c++·经验分享·笔记·算法·51单片机
8Qi830 分钟前
LeetCode 4:寻找两个正序数组的中位数 —— 二分查找法
java·算法·leetcode·职场和发展·二分查找
8Qi834 分钟前
LeetCode 32:最长有效括号 —— 栈 + 标记法 题解
java·数据结构·算法·leetcode·职场和发展··括号匹配
机器学习之心37 分钟前
198种组合算法+优化CNN-LSTM+SHAP分析+新数据预测+多输出!深度学习可解释分析,强烈安利,粉丝必备
深度学习·算法·cnn-lstm·shap分析·198种组合算法
Tairitsu_H37 分钟前
[LC优选算法#3] 滑动窗口 | 将x减到0的最⼩操作数 | ⽔果成篮 | 字⺟异位词
c++·算法·leetcode·滑动窗口
bIo7lyA8v44 分钟前
算法复杂度与能耗关系的多变量分析研究的技术8
算法
洛水水1 小时前
【力扣100题】76.搜索插入位置
数据结构·算法·leetcode
Techblog of HaoWANG1 小时前
智巡守卫:多模态巡检智能体算法服务端设计与实现——基于Ollama+Qwen3.5的自动化巡检报告生成系统
运维·人工智能·算法·目标检测·自动化·边缘计算
小蒋学算法1 小时前
算法-灌溉花园的最少龙头数目-贪心
算法
满怀冰雪1 小时前
第07篇-差分算法-高效处理区间修改问题
数据结构·算法