用 std::queue 配合 levelsize 快照实现分层 bfs 是最直观可靠的写法,关键在于每次循环前记录队列当前长度以精确切分层级,避免使用 nullptr 分隔导致的空指针风险与逻辑复杂性。

用 queue 实现 BFS 分层遍历的核心逻辑
直接用 std::queue 配合每层节点计数,是 C++ 中最直观、最不易出错的分层 BFS 写法。关键不是“能不能遍历”,而是“怎么把层边界清晰切开”——靠每次循环前记录队列当前长度,即本层节点数。
- 初始化时把根节点入队,若为空则直接返回空结果
- 进入 while 循环前,先用
int levelSize = q.size()快照当前层宽度 - 内层 for 循环只执行
levelSize次,确保只处理本层节点,子节点全留到下一轮 - 每轮 for 结束后,当前层数据(如 vector)即可 push 到最终结果中
为什么不能只用一个 queue + nullptr 做层分隔
用 nullptr 当作层间标记看似简洁,但在 C++ 里容易引发空指针解引用或逻辑错位,尤其当树结构不规则或插入顺序稍有偏差时。
- 插入
nullptr的时机必须严格:每层末尾插一次,且不能漏、不能多 - 遇到
nullptr后需立刻判断队列是否非空,再决定是否插入下一个nullptr,分支多、易漏判 - 若树为空或只有根节点,
nullptr插入/弹出顺序极易混乱,调试时看到segmentation fault或无限循环很常见 - 相比
levelSize方案,它没带来任何性能优势,反而增加维护成本
完整可跑的分层 BFS 示例(含 TreeNode 定义)
下面这段代码能直接编译运行,返回 vector<vector>></vector>,每层元素按从左到右顺序排列:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
<p>vector<vector>> levelOrder(TreeNode* root) {
vector<vector>> result;
if (!root) return result;</vector></vector></p><pre class="brush:php;toolbar:false;">queue<TreeNode*> q;
q.push(root);
while (!q.empty()) {
int levelSize = q.size();
vector<int> level;
for (int i = 0; i < levelSize; ++i) {
TreeNode* node = q.front(); q.pop();
level.push_back(node->val);
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);
}
result.push_back(level);
}
return result;}
注意 left/right 指针判空和移动语义的影响
实际项目中如果 TreeNode 成员是 unique_ptr<treenode></treenode>,就不能再用 node->left 直接判空——得写成 if (node->left),因为 unique_ptr 重载了 operator bool;但若误写成 if (node->left != nullptr) 也能过编译,只是冗余且掩盖意图。
- 用裸指针时,
if (node->left)和if (node->left != nullptr)等价,但前者更符合 C++ 惯例 - 若用智能指针,
q.push(node->left.get())是常见错误:会丢失所有权,导致提前析构或 double free - 正确做法是用
q.push(node->left.release())(转移所有权)或改用queue<unique_ptr>></unique_ptr>并配合move - 层级遍历本身不修改树结构,所以大多数场景用裸指针就够了,不必过度引入智能指针复杂度
BFS 分层的关键不在“遍历”,而在“切层”——levelSize 这一行代码决定了你是在做真分层,还是在模拟分层。很多人卡在输出格式不对,其实问题就出在没在 for 循环前冻结队列长度。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










