关于二叉树层序遍历代码的部分解析

部署运行你感兴趣的模型镜像

CPP:

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        queue<TreeNode*> que;
        if (root != NULL) que.push(root);
        vector<vector<int>> result;
        while (!que.empty()) {
            int size = que.size();
            vector<int> vec;
            // 这里一定要使用固定大小size,不要使用que.size(),因为que.size是不断变化的
            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();
                vec.push_back(node->val);
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
            result.push_back(vec);
        }
        return result;
    }

类定义

class Solution { 
public: 
vector<vector<int>> levelOrder(TreeNode* root); 
};

这里定义了一个名为Solution的类,其中包含一个公开的成员函数levelOrder,该函数接收一个指向二叉树根节点的指针root,并返回一个二维向量,该向量包含了二叉树层序遍历的结果。

成员函数实现

vector<vector<int>> levelOrder(TreeNode* root) { 
// 使用队列进行层序遍历 
queue<TreeNode*> que; 
// 如果根节点不为空,则将其加入队列 
if (root != NULL) que.push(root); 
// 初始化结果向量 
vector<vector<int>> result; 


// 当队列不为空时,继续遍历 
while (!que.empty()) { 
// 获取当前层的节点数量 
int size = que.size(); 
// 初始化一个向量,用于存储当前层的节点值 
vector<int> vec; 


// 遍历当前层的所有节点 
// 注意:这里使用size而不是que.size(),因为que.size()在循环中会变化 
for (int i = 0; i < size; i++) { 
// 从队列中取出一个节点 
TreeNode* node = que.front(); 
que.pop(); 
// 将节点值加入当前层的向量 
vec.push_back(node->val); 
// 如果节点有左子节点,则将其加入队列 
if (node->left) que.push(node->left); 
// 如果节点有右子节点,则将其加入队列 
if (node->right) que.push(node->right); 
} 
// 将当前层的节点值向量加入结果向量 
result.push_back(vec); 
} 


// 返回结果 
return result; 

 

关键点

  1. 队列的使用:队列是一种先进先出(FIFO)的数据结构,非常适合用于层序遍历。在遍历过程中,我们首先将根节点(如果非空)加入队列,然后不断从队列中取出节点,并访问其左右子节点(如果存在),将子节点加入队列。

  2. 当前层节点数量的确定:在遍历每一层之前,我们首先获取队列的大小(即当前层的节点数量),然后基于这个大小进行遍历。这是因为在遍历过程中,队列的大小会随着子节点的加入而增加,如果我们在循环中直接使用que.size(),那么可能会导致同一层的节点被遍历多次。

  3. 结果向量的构建:我们使用一个二维向量result来存储层序遍历的结果。对于每一层,我们都先初始化一个一维向量vec,用于存储当前层的节点值,然后将这个向量加入result

  4. 空节点的处理:在代码中,我们没有显式地处理空节点的情况,因为空节点不会被加入队列。只有当节点存在时,我们才会将其加入队列,并访问其左右子节点。

  5. 返回值:函数最终返回result,即包含了二叉树层序遍历结果的二维向量。

C代码:

public IList<IList<int>> LevelOrder(TreeNode root)
{
    var res = new List<IList<int>>();
    var que = new Queue<TreeNode>();
    if (root == null) return res;
    que.Enqueue(root);
    while (que.Count != 0)
    {
        var size = que.Count;
        var vec = new List<int>();
        for (int i = 0; i < size; i++)
        {
            var cur = que.Dequeue();
            vec.Add(cur.val);
            if (cur.left != null) que.Enqueue(cur.left);
            if (cur.right != null) que.Enqueue(cur.right);
        }
        res.Add(vec);


    }
    return res;
}

以下是逐帧扣的解析

该方法实现了二叉树的层序遍历,即广度优先遍历,并返回一个二维列,其中每个内部列表代表树的一层节点的值。

方法签名

public IList<IList<int>> LevelOrder(TreeNode root)
  1. 返回类型-->一个嵌套列表,外层列表代表不同的层,内层列表包含该层所有节点的值。
  2. 参数-->TreeNode root,表示二叉树的根节点。

方法体

  1. 初始化结果列表和队列
    • 创建一个空列表res,用于存储每层的节点值(每层的节点值本身也会作为一个列表存储)。
      var res = new List<IList<int>>();
    • 创建一个队列que,用于存储待处理的节点。队列元素先入先出,适合实现层序遍历。
      var que = new Queue<TreeNode>();
  2. 处理空树情况:如果根节点root为空,则直接返回空的res列表,因为空树没有节点可以遍历。
  3. 将根节点加入队列
    • 将根节点加入队列,准备开始遍历。
      que.Enqueue(root);

  4. 层序遍历循环:使用while循环,只要队列不为空就继续遍历。队列不为空意味着还有节点没有处理。
  5. 处理当前层的节点
    • 在遍历每一层之前,首先获取队列的当前大小size,这是因为我们需要在不添加新节点到队列的情况下遍历当前层的所有节点。队列的大小在遍历过程中会因为新节点的加入而改变,但size保持了当前层的节点数。
    • 创建一个新列表vec,用于存储当前层的节点值。
    • 使用for循环遍历当前层的所有节点(循环次数为size)。在每次迭代中:
      • 从队列中取出当前节点curque.Dequeue())。
      • 将当前节点的值添加到vec列表中。
      • 如果当前节点有左子节点,则将左子节点加入队列。
      • 如果当前节点有右子节点,则将右子节点加入队列。
  6. 将当前层的节点值列表添加到结果列表中:将vec(包含当前层所有节点值的列表)添加到res列表中。
  7. 返回结果:当队列为空时,表示所有节点都已遍历完毕,返回res列表作为层序遍历的结果。

Python代码:

class Solution:
    def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
        if not root:
            return []
        queue = collections.deque([root])
        result = []
        while queue:
            level = []
            for _ in range(len(queue)):
                cur = queue.popleft()
                level.append(cur.val)
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
            result.append(level)
        return result

类定义

首先,定义了一个名为Solution的类,其中包含一个名为levelOrder的方法。这个方法接收一个二叉树的根节点root(类型为Optional[TreeNode],表示根节点可以是TreeNode类型或者None),并返回一个二维列表(List[List[int]]),其中包含了二叉树层序遍历的结果。

方法实现

  1. 边界条件处理
    • 如果根节点root为空,那么直接返回一个空列表[],因为空树没有节点可以遍历。
  2. 初始化队列和结果列表
    • 使用collections.deque创建一个双端队列queue,并将根节点root加入队列中。这里虽然使用了双端队列,但只使用了它作为队列的功能(即只从一端添加和移除元素)。
    • 初始化一个空列表result,用于存储层序遍历的结果,每一层的结果将是一个包含节点值的列表。
  3. 层序遍历
    • 使用一个while循环来遍历队列,直到队列为空。
    • 在循环内部,首先初始化一个空列表level,用于存储当前层的节点值。
    • 使用一个for循环,循环次数为当前队列的长度(即当前层的节点数)。在每次循环中:
      • 从队列的左端弹出一个节点cur(这是当前层的一个节点)。
      • cur的节点值添加到level列表中。
      • 如果cur有左子节点,则将左子节点加入队列中。
      • 如果cur有右子节点,则将右子节点加入队列中。
    • 当完成当前层的所有节点处理后,将level列表(即当前层的节点值列表)添加到result列表中。
  4. 返回结果
    • 当队列为空时,所有层的节点都已经遍历完成,此时result列表中包含了所有层的节点值列表。函数返回result列表作为层序遍历的结果。

关键点

  • 队列的使用:队列是实现层序遍历的关键数据结构,它保证了节点按照层次顺序被访问。
  • 长度法:在遍历每一层时,通过range(len(queue))来确定当前层的节点数,这种方法被称为“长度法”。它避免了在遍历过程中由于子节点的加入而导致的队列长度变化问题。
  • 双端队列与队列:虽然这里使用了collections.deque,但主要利用了其作为队列的功能。双端队列的特点是可以在两端进行添加和移除操作,但在这里只使用了其一端。

这段代码有效地实现了二叉树的层序遍历,并清晰地展示了队列在层序遍历中的应用。

总结

该方法通过队列实现了二叉树的层序遍历。在遍历过程中,首先处理当前层的所有节点,然后将它们的子节点加入队列以供后续处理。通过这种方式,能够按照从上到下、从左到右的顺序遍历二叉树的所有节点,并将每层的节点值作为一个列表存储在结果列表中。

您可能感兴趣的与本文相关的镜像

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值