层序遍历必须用队列实现,因其实质是广度优先,需fifo保证层级顺序;递归或栈会破坏层次结构。关键点包括:每轮先记录队列大小以隔离当前层、入队前判空防nullptr解引用、按层分组需在内层循环结束后将临时vector加入结果。

层序遍历必须用队列,不能用递归
递归天然适合深度优先(前/中/后序),但层序是广度优先,必须靠 FIFO 的队列来维持“先进先出”的访问顺序。用栈或递归模拟只会打乱层级顺序,甚至陷入死循环。
关键点:
-
std::queue是最直接的选择;std::deque也可,但没必要 - 每轮循环处理当前层所有节点:先记录队列大小
size,再循环size次出队,避免把下一层节点混进来 - 空指针必须跳过,否则
nullptr->left会崩溃
如何按层分组输出(比如返回 vector>)
很多题目要求“每层一个子数组”,这就不能只用一个扁平的 vector<int></int> 收集全部值。核心在于每次内层循环结束时,把当前层的临时容器推入结果。
示例逻辑片段:
vector<vector>> result;
queue<treenode> q;
if (root) q.push(root);
while (!q.empty()) {
int size = 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);
}
result.push_back(level); // ← 关键:每层结束后才 push
}
</int></treenode></vector>
遇到 nullptr 节点时的常见错误
错误写法:q.push(node->left) 不加判断,导致队列中存入大量 nullptr。后续取 q.front() 后直接解引用就会段错误。
正确做法始终是:
- 入队前判空:
if (node->left) q.push(node->left); - 出队后立刻检查:
if (!node) continue;(仅在允许队列含 nullptr 时作为兜底,不推荐) - 初始化时也要判
root是否为空,否则q.push(nullptr)会埋雷
性能与边界注意点
层序遍历时间复杂度固定为 O(n),但空间取决于最宽层的节点数——不是树高。极端情况(完全二叉树最后一层)队列可能暂存 n/2 个指针。
几个容易被忽略的细节:
- 用
int size = q.size()必须在 for 循环外获取,否则每次q.size()动态变化,导致漏节点或死循环 - 不要用
auto& node接q.front(),因为q.pop()后引用立即失效 - LeetCode 上输入为
vector<int></int>的数组形式(如[3,9,20,null,null,15,7]),那是建树逻辑,和遍历无关
真正卡住人的往往不是算法思路,而是队列 size 的快照时机和空指针的防御性检查。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











