编程导航算法通关村第六关 | 二叉树的层次遍历

本文讲解了如何通过队列实现二叉树的层序遍历,包括常规遍历、自底向上遍历以及右侧视图,适合学习数据结构和算法基础。

二叉树的基本层次遍历

二叉树最简单的情况,仅仅遍历输出全部元素
	  3    
	 / \   
	9  20
      /  \    
     15   7

上面的二叉树层次遍历结果输出为[3, 9, 20, 15, 7 ]

如 LeetCode102这道题

给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
示例 1:
输入:root = [3,9,20,null,null,15,7]
输出:[[3],[9,20],[15,7]]

示例 2:
输入:root = [1]
输出:[[1]]

示例 3:
输入:root = []
输出:[]

基本思想是:
从根节点开始,一层一层的访问,先访问3,然后访问3的左右孩子9和20,接着访问9的左右孩子,再访问20的左右孩子15,7
算法基本思想是:

  1. 首先 3 入队
  2. 然后取队头元素(这里也就是3),然后该节点出队,接着将其左右孩子入队
  3. 循环步骤 2,直到队列中的元素全是叶子结点,随后全部出队

代码如下:

vector<vector<int>> levelOrder(TreeNode* root) {
	// 定义一个二维数组用来存储每一层的元素
    vector<vector<int>> ret;
    // 判空
    if(!root) {
        return ret;
    }

	// 初始化队列
    queue<TreeNode*> q;
    // 根节点入队
    q.push(root);
    // 循环步骤2
    while(!q.empty()) {
    	// 先获取当前队列的大小,保证每次只遍历当前层次
        int nsize = q.size();
        // 当前层遍历完后,将当前层的结果数组添加到ret的末尾
        ret.push_back(vector<int>());
        // 遍历当前层
        for(int i = 0; i < nsize; i++) {
        	// 取队头
            auto node = q.front();
            q.pop();
            // cout << node->val << ' ';
            // 遍历当前层,每取出一个节点就把当前节点的值添加到数组末尾
            ret.back().push_back(node->val);
            if(node->left) q.push(node->left);
            if(node->right) q.push(node->right);
        }
    }
    return ret;
}

接下来看一道这道题的变体:

LeetCode 107

给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
示例 1:
输入:root = [3,9,20,null,null,15,7]
输出:[[15,7],[9,20],[3]]

示例 2:
输入:root = [1]
输出:[[1]]

示例 3:
输入:root = []
输出:[]

这道题要求自底向上的层序遍历,无非就最后返回的时候把这个二维数组翻转一下就行了,调用库函数reverse(it1, it2),需要了解的是两个参数都是迭代器,即iterator,而vector的begin()和end()正是起止迭代器

vector<vector<int>> levelOrderBottom(TreeNode* root) {
        vector<vector<int>> ret;
        if(!root) {
            return ret;
        }
        queue<TreeNode*> q;
        q.push(root);

        while(!q.empty()) {
            int nsize = q.size();
            ret.push_back(vector<int>());
            for(int i = 0; i < nsize; i++) {
                auto node = q.front();
                q.pop();
                ret.back().push_back(node->val);
                if(node->left) q.push(node->left);
                if(node->right) q.push(node->right);
            }
        }
        reverse(ret.begin(), ret.end());
        return ret;
    }

再来一道变体:

LeetCode 199

给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
示例 1:
输入: [1,2,3,null,5,null,4]
输出: [1,3,4]

示例 2:
输入: [1,null,3]
输出: [1,3]

示例 3:
输入: []
输出: []

这道变体只需要输出每一层的最后一个结点元素,也就是在第一道题的基础上,把二维数组的每一行的最后一个元素输出出来就行了,我们可以把他们取出来存在一维数组中

vector<int> rightSideView(TreeNode* root) {
    vector<vector<int>> ret;
    if(!root) {
        return vector<int>();
    }
    queue<TreeNode*> q;
    q.push(root);
    vector<int> ans;
    while(!q.empty()) {
        int nsize = q.size();
        ret.push_back(vector<int>());
        for(int i = 0; i < nsize; i++) {
            auto node = q.front();
            q.pop();
            ret.back().push_back(node->val);
            if(node->left) q.push(node->left);
            if(node->right) q.push(node->right);
            // 取每一行最后一个元素
            if(i == nsize - 1) {
                ans.push_back(ret.back().back());
            }
        }
    }
    return ans;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值