leetcode 102二叉树的层序遍历

cpp 复制代码
class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        if (root == nullptr) {
            return {};
        }

        vector<vector<int>> ans;
        queue<TreeNode*> q;

        q.push(root);

        // 外层 while:一层一层处理
        while (q.empty() == false) {

            // 当前这一层节点数量
            int n = q.size();

            // 每一层都重新创建一个 layer
            vector<int> layer;

            // 内层 while:处理当前这一层的 n 个节点
            while (n != 0) {

                // 取出队头节点
                TreeNode* node = q.front();
                q.pop();

                // 当前节点加入当前层
                layer.push_back(node->val);

                // 当前层还剩一个节点少处理
                n--;

                // 把下一层节点加入队列
                if (node->left != nullptr) {
                    q.push(node->left);
                }

                if (node->right != nullptr) {
                    q.push(node->right);
                }
            }

            // 当前层处理完毕
            ans.push_back(layer);
        }

        return ans;
    }
};

这段代码的整体思路就是:

用一个队列 queue 做层序遍历,每次先记住"当前层有多少个节点",然后把这一层的节点全部取出来,同时把它们的左右孩子放进队列。这样下一轮处理的就是下一层。

假设二叉树是:

复制代码
        3
       / \
      9   20
         /  \
        15   7

最终希望得到:

复制代码
[
    [3],
    [9, 20],
    [15, 7]
]

先看代码:

复制代码
vector<vector<int>> ans;
queue<TreeNode*> q;
q.push(root);

这里:

复制代码
ans

负责保存最终答案。

复制代码
q

负责保存"接下来要处理的节点"。

最开始:

复制代码
q = [3]
ans = []

然后进入外层循环:

复制代码
while(q.empty() == false)

意思是:

只要队列里面还有节点,就继续处理。

第一次进入外层循环时:

复制代码
q = [3]

创建当前层:

复制代码
vector<int> layer;

所以:

复制代码
layer = []

然后:

复制代码
int n = q.size();

此时:

复制代码
n = 1

这个 n 非常关键。

它表示:

当前这一层有 1 个节点。

所以接下来:

复制代码
while(n != 0)

就是把当前这一层的 1 个节点全部处理掉。


第一层

当前:

复制代码
q = [3]
n = 1
layer = []

执行:

复制代码
TreeNode* node = q.front();

那么:

复制代码
node -> 3

然后:

复制代码
layer.push_back(node->val);

得到:

复制代码
layer = [3]

然后:

复制代码
q.pop();

3 从队列删除:

复制代码
q = []

然后:

复制代码
n--;

得到:

复制代码
n = 0

接着检查 3 的左右孩子:

复制代码
if(node->left != nullptr){
    q.push(node->left);
}

if(node->right != nullptr){
    q.push(node->right);
}

3 的左右孩子是:

复制代码
9
20

所以放入队列:

复制代码
q = [9, 20]

注意这里非常重要。

虽然现在:

复制代码
q = [9,20]

但是:

复制代码
n = 0

所以:

复制代码
while(n != 0)

结束。

这意味着:

9、20 虽然已经进入队列,但是它们属于下一层,所以这一轮先不处理。

然后:

复制代码
ans.push_back(layer);

得到:

复制代码
ans = [
    [3]
]

第二层

又回到:

复制代码
while(q.empty() == false)

现在:

复制代码
q = [9,20]

队列不为空,所以继续。

重新创建:

复制代码
vector<int> layer;

所以:

复制代码
layer = []

然后:

复制代码
int n = q.size();

现在:

复制代码
n = 2

代表:

当前第二层有两个节点:9 和 20。

开始内层循环。

先处理 9

复制代码
TreeNode* node = q.front();

得到:

复制代码
node = 9

加入:

复制代码
layer = [9]

弹出:

复制代码
q = [20]

然后:

复制代码
n = 1

9 没有左右孩子,所以没有新节点入队。


接着因为:

复制代码
n = 1

继续内层循环。

现在:

复制代码
node = q.front();

得到:

复制代码
node = 20

加入:

复制代码
layer = [9,20]

弹出:

复制代码
q = []

然后:

复制代码
n = 0

但是 20 有两个孩子:

复制代码
15
7

所以:

复制代码
q = [15,7]

内层循环结束,因为:

复制代码
n = 0

然后:

复制代码
ans.push_back(layer);

得到:

复制代码
ans = [
    [3],
    [9,20]
]

第三层

现在:

复制代码
q = [15,7]

进入下一轮。

复制代码
int n = q.size();

所以:

复制代码
n = 2

处理 15

复制代码
layer = [15]
q = [7]
n = 1

处理 7

复制代码
layer = [15,7]
q = []
n = 0

两个节点都没有孩子。

所以:

复制代码
ans = [
    [3],
    [9,20],
    [15,7]
]

此时:

复制代码
q = []

所以外层:

复制代码
while(q.empty() == false)

不成立,整个遍历结束。


你可以把整个执行过程压缩成这样:

复制代码
开始:
q = [3]

第一层:
n = 1
处理 3
q = [9,20]

ans = [[3]]

----------------

第二层:
n = 2
处理 9
处理 20
q = [15,7]

ans = [[3], [9,20]]

----------------

第三层:
n = 2
处理 15
处理 7
q = []

ans = [[3], [9,20], [15,7]]

这段代码最核心其实就是这四个变量:

复制代码
queue<TreeNode*> q;

表示:

等待处理的节点。

复制代码
int n = q.size();

表示:

当前这一层有几个节点。

复制代码
vector<int> layer;

表示:

当前这一层的答案。

复制代码
vector<vector<int>> ans;

表示:

所有层的最终答案。

你尤其要理解:

复制代码
int n = q.size();

为什么必须提前保存。

因为处理当前层的时候,会不断执行:

复制代码
q.push(node->left);
q.push(node->right);

下一层的节点加入队列。

例如第二层刚开始:

复制代码
q = [9,20]
n = 2

处理 20 后:

复制代码
q = [15,7]

但是我们不能继续处理 15、7,因为它们已经是第三层了。

所以使用:

复制代码
n

把当前层节点数量固定下来。

一句话记忆这道题:

外层 while 控制一层一层地走,内层 while 控制把当前这一层的所有节点处理完;处理当前节点时,把它的左右孩子加入队列,留给下一层处理。

相关推荐
遥感知识服务2 小时前
从局部阈值、双极化到暗地表剔除:NASA OPERA DSWx-S1全球动态水体算法拆解
大数据·人工智能·深度学习·神经网络·算法·机器学习
晚风醉蝶2 小时前
1-13-TimSort
算法
ZJU_统一阿萨姆2 小时前
【算子开发】算子融合与Softmax_LayerNorm实现
人工智能·算法·语言模型·硬件架构
叩码以求索4 小时前
浅谈:前序遍历反转法求解N叉树的后序遍历
算法
官乐5 小时前
AI面试指南(多agent开发流程)
人工智能·面试·职场和发展
北风toto6 小时前
中缀、前缀、后缀表达式
算法·软件设计师
程序员三藏6 小时前
自动化测试用例编写详解
自动化测试·软件测试·python·功能测试·测试工具·职场和发展·测试用例
听取WA声一片(无恶意)6 小时前
CSP-J/CSP-S 深度优先搜索(DFS)完全讲义
c++·算法·深度优先
跟我一起学测试呀6 小时前
软件测试面试总结,备战金九银十
面试·职场和发展
码流怪侠6 小时前
2026年8月GitHub热榜深度拆解:Agent Skills席卷开源圈,一个“技能包“收割5万星
算法·程序员·github