必须用std::queue实现层序遍历,因其fifo特性严格保证“从上到下、从左到右”层级顺序;需在每轮循环初用q.size()快照当前层节点数,过滤nullptr入队,并以临时vector收集每层结果。

用 std::queue 实现层序遍历是最直接的方式
宽度优先搜索(BFS)在二叉树中就是层序遍历,核心是借助队列按“当前层节点→子节点”顺序推进。C++ 标准库的 std::queue 天然适配这个逻辑:先进先出,每次取队首、压入左右子节点即可。
关键点在于节点指针的管理——必须确保不访问空指针,且不把 nullptr 推入队列,否则后续解引用会崩溃。
- 定义队列类型为
std::queue<treenode></treenode>,避免拷贝整棵树节点 - 入队前判空:
if (node->left)而不是if (node->left != nullptr)(更简洁且等价) - 循环条件始终是
!q.empty(),每次迭代只处理当前队列长度对应的节点数(用于分层输出)
分层处理时用 q.size() 控制本层边界
如果需要区分每层(比如返回二维 vector、计算最大宽度、打印换行),不能靠单次 q.pop() 拆分层次——因为子节点会不断入队,队列长度动态变化。正确做法是在每轮外层循环开始时记录当前队列大小,作为本层节点总数。
常见错误是把 for (int i = 0; i 写成 <code>while 或漏掉该限制,导致跨层混读。
vector<vector>> levelOrder(TreeNode* root) {
if (!root) return {};
vector<vector>> res;
queue<treenode> q;
q.push(root);
while (!q.empty()) {
int n = q.size(); // ← 关键:固定本层宽度
vector<int> level;
for (int i = 0; i val);
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);
}
res.push_back(level);
}
return res;
}
</int></treenode></vector></vector>
遇到空节点要跳过,但别提前终止整个 BFS
二叉树的 BFS 不因某一层出现空节点而结束;空节点只是不入队,不代表树到此为止。典型误区是把 if (!node) 当作退出条件,实际上 root 为空才应直接返回,其余节点由入队逻辑自然过滤。
-
nullptr永远不该出现在队列中——构造队列时只推非空指针 - 若题目要求输出包含
null的完整层(如 LeetCode 二叉树序列化),需改用标记法或额外存 size,但标准 BFS 不需要 - 内存安全:所有
node->left和node->right访问前都已确认node非空(因来自非空队列)
迭代写法比递归更自然,也避免栈溢出风险
虽然 BFS 可强行用递归模拟(维护一个全局队列+深度计数),但既违背递归直觉,又增加状态管理复杂度。C++ 中纯迭代 + std::queue 是唯一推荐路径。
注意:不要用 std::stack 替代,那是 DFS 的节奏;也不要手写链表队列——std::queue 默认基于 deque,均摊 O(1) 操作,足够高效。
- 头文件只需
#include <queue></queue>和<vector></vector>,无额外依赖 - 时间复杂度 O(n),每个节点进出队各一次;空间复杂度最坏 O(w),w 是最大层宽(非树高)
- 若需反向层序(从底向上),可在主循环结束后对结果
reverse(res.begin(), res.end()),无需改 BFS 主干
实际写的时候最容易卡在空指针检查位置和层边界计数时机——这两个地方少一个判断,运行时就崩,或者输出错层。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











