C# 广度优先搜索方法 C#如何用队列实现BFS

来源:这里教程网 时间:2026-02-21 17:43:18 作者:

为什么用
Queue<t></t>
而不是其他集合

因为 BFS 的核心是“先进先出”,必须按层顺序访问节点,

Queue<t></t>
是 .NET 中唯一原生支持 O(1) 入队/出队且语义明确的集合。用
List<t></t>
模拟(比如
RemoveAt(0)
)会导致每次出队都 O(n) 移动元素,树稍深就明显卡顿;用
Stack<t></t>
则直接变成 DFS,逻辑错位。

Queue<t></t>
实现 BFS 的关键三步

以二叉树为例,实际写法极简,但每步都有明确意图:

初始化:把根节点入队 ——
queue.Enqueue(root)
循环处理:只要队列非空,就
Dequeue()
取出当前层第一个节点,访问它,再把它的子节点(左、右)依次
Enqueue()
终止条件:队列为空,说明所有可达节点已遍历完毕

示例片段(无异常处理,聚焦主干):

var queue = new Queue<TreeNode>();
if (root != null) queue.Enqueue(root);
while (queue.Count > 0)
{
    var node = queue.Dequeue();
    Console.WriteLine(node.val); // 访问
    if (node.left != null) queue.Enqueue(node.left);
    if (node.right != null) queue.Enqueue(node.right);
}

图结构中 BFS 必须加 visited 集合

树天然无环,但图可能有环或重复边,不判重会导致死循环。常见错误是只靠队列去重 ——

Queue
不提供
Contains
高效查询,且入队前未检查是否已入过队。

正确做法:用
HashSet<t></t>
记录已访问节点,每次入队前先查
visited.Contains(neighbor)
注意:
HashSet
Add()
返回
bool
,可直接用于跳过已访问节点:
if (visited.Add(neighbor)) queue.Enqueue(neighbor);
不要用
List<t>.Contains()</t>
替代,大数据量下性能断崖式下跌

BFS 中记录层数或距离的惯用写法

很多题目要求返回最短路径长度、最小操作步数等,不能只靠节点值,得知道当前在第几层。

方法一(推荐):每轮 while 循环代表一层,用内层 for 循环固定处理当前队列长度个节点 ——
int size = queue.Count; for (int i = 0; i 
方法二:在入队时同时存节点和对应层数,用元组或自定义类,如
Queue
避免在节点类里加临时字段存 level,污染数据结构,且多线程不安全

层级计数容易漏掉初始层判断,比如从起点出发算第 0 层还是第 1 层,需严格对照题意。

相关推荐

热文推荐