层序遍历必须用队列,关键在于通过每次循环前记录队列大小来区分层级边界;需用vector<vector<int>>存储每层节点值,而非仅计数;空树须特判返回空结果;C++17结构化绑定适用于结果遍历而非TreeNode本身。

层序遍历必须用队列,不能用递归或栈
递归天然适合深度优先,强行用它模拟层序会非常绕,且容易漏节点或重复访问。std::queue 是唯一合理选择:每轮处理当前队列中所有节点(即当前层),再把它们的子节点推入队列(下一层)。关键不是“进队出队”,而是**区分层级边界**——靠每次循环开始时记录队列大小来锁定本层节点数。
- 别用
std::stack或递归模拟,逻辑复杂且易错 - 避免在循环中直接调用
q.size()判断终止(因为push()会动态改变 size) - 正确做法:进入 while 循环前用
int levelSize = q.size();快照当前层节点数,然后 for 循环执行levelSize次
分级统计要提前存每层节点值,不能只计数
题目要求“按层分级统计节点”,意味着不仅要输出层数,还要保留每层的实际节点值(比如用于后续计算均值、最大值等)。如果只用一个整数累加 count,信息就丢了。实际场景中,更常见的是返回 std::vector<:vector>></:vector> ——外层 vector 的每个元素对应一层,内层 vector 存该层所有节点值。
- 不要只声明
int count = 0;然后 ++,这无法还原原始结构 - 每层用临时
std::vector<int> levelNodes;</int>收集,处理完 push 进结果result - 若只需统计数量(如求最宽层宽度),可只存
levelNodes.size(),但原始需求明确要“统计节点”,即节点本身
空树和单节点树必须显式处理
很多实现一上来就 q.push(root),但如果 root == nullptr,就会对空指针解引用或 push 空指针导致未定义行为。C++ 中 TreeNode* 是裸指针,不做判空就是埋雷。
- 开头必须检查
if (!root) return {};(返回空 vector) - 单节点树(
root有值但左右子为nullptr)是合法输入,q.push(root)后第一轮 for 循环执行一次,levelNodes只含一个值,这是正确行为 - 别依赖“测试用例没给空树”——生产代码必须覆盖
nullptr路径
C++17 结构化绑定简化遍历,但注意兼容性
如果用 C++17 或更高版本,可以用结构化绑定快速展开每层数据,比如 for (const auto& [val, left, right] : levelNodes) ——但这仅适用于自定义结构体;标准 TreeNode 是指针类型,不支持。真正能用结构化绑定的地方是结果处理阶段:
立即学习“C++免费学习笔记(深入)”;
for (const auto& level : result) {
std::cout << "Level " << levelIdx++ << ": ";
for (const auto& nodeVal : level) { // 这里用范围 for 最自然
std::cout << nodeVal << " ";
}
std::cout << "\n";
}
- 别试图对
TreeNode*做结构化绑定,编译失败 -
auto& level比auto level更高效,避免拷贝 vector - 如果项目限制 C++14,就老实用下标或迭代器,别硬套新语法
levelNodes.clear() 不需要手动调,因为它是 for 循环内定义的局部变量,每次迭代自动重建。很多人习惯性在循环末尾加 clear,反而引入冗余操作。


















