剑指offer---从上往下打印二叉树

题目23:从上往下打印二叉树(leetcode链接:https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-lcof/

题目分析

方法1:

建立队列,利用队列的先进先出特点,将二叉树的节点入队,当每一个父节点出队​时将其左右孩子节点入队,这样队列中的节点顺序就是按照从上向下从左向右的顺序打印的。

​​​​​​

方法2:题目改进,使用二维数组返回结果,二叉树的每一层保存在二维数组的一项中(leetcode链接:https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-ii-lcof/submissions/)。

基本思路还是建立队列,让父节点出队时子节点入队。但是,这里需要建立一个临时数组保存每一层的节点,当每一层节点遍历完后在放入ret数组中,而确定每一层节点是否遍历完需要两个整型变量,一个保存当前层节点个数一个保存下一层节点个数,每当一个节点存入临时数组时,当前节点就-1,当当前节点为0表示这一层已经打印完径临时数组加入ret中,同时进行下一层遍历。

方法3:题目改进,当是奇数层按照从左向右打印偶数层按照从右向左打印。

基本思路和方法2相同,只是将临时数组加入到ret中时需要判断当前层时奇数层还是偶数层,如果是偶数层逆置数组在加入ret.

代码描述

方法2

class Solution {
public:
    vector<int> levelOrder(TreeNode* root) {
        vector<int> ret;
        if(root == NULL)
            return ret;
        //创建队列对象
        queue<TreeNode*> myQueue;
        //根节点入队
        myQueue.push(root);
        while(!myQueue.empty())
        {
            //队头节点的左右孩子节点入队
            if(myQueue.front()->left)
                myQueue.push(myQueue.front()->left);
            if(myQueue.front()->right)
                myQueue.push(myQueue.front()->right);
            //队头节点出队
            ret.push_back(myQueue.front()->val);
            myQueue.pop();
        }
        return ret;
    }
};

方法2

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> ret;
        //如果二叉树为空,返回空数组
        if(root == NULL)
            return ret;
        queue<TreeNode*> myQueue;
        //根节点入队
        myQueue.push(root);
        //初始化临时变量和临时数组
        int count1 = 1;//当前层节点个数
        int count2 = 0;//下一层节点个数
        int row = 0;//当前层数
        vector<int> ret1;
        while(!myQueue.empty())
        {
            //如果当前层数已经遍历完,count1就为0
            if(count1 == 0)
            {
                //将临时数组加入ret中
                ret.push_back(ret1);
                //清空临时数组
                while(!ret1.empty())
                    ret1.pop_back();
                //更新当前层节点数,进入下一层
                count1 = count2;
                //更新下一层节点数
                count2 = 0;
                //更新层数
                row++;
            }
            //获取队头节点存入临时数组中
            ret1.push_back(myQueue.front()->val);
            //每存入一个,当前层节点数-1
            count1--;
            //将队头节点的左右孩子节点入队
            if(myQueue.front()->left)
            {
                myQueue.push(myQueue.front()->left);
                //每箱队列中加入一个节点,下一层节点数+1
                count2++;
            }
            if(myQueue.front()->right)
            {
                myQueue.push(myQueue.front()->right);
                count2++;
            }
            //队头节点已经存入到临时数组中,将队头节点出队
            myQueue.pop();
        }
        //如果临时数组中有还没有加入到ret中的,就要加入
        if(!ret1.empty())
            ret.push_back(ret1);
        return ret;
    }
};

方法3

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> ret;
        //如果二叉树为空,返回空数组
        if(root == NULL)
            return ret;
        queue<TreeNode*> myQueue;
        //根节点入队
        myQueue.push(root);
        //初始化临时变量和临时数组
        int count1 = 1;//当前层节点个数
        int count2 = 0;//下一层节点个数
        int row = 0;//当前层数
        vector<int> ret1;
        while(!myQueue.empty())
        {
            //如果当前层数已经遍历完,count1就为0
            if(count1 == 0)
            {
                //偶数行要反转数组从右向左打印
                if(row%2 != 0)
                {
                    vector<int>::iterator begin = ret1.begin();
                    vector<int>::iterator end = ret1.end()-1;
                    while(begin < end)
                    {
                        int tmp = *begin;
                        *begin = *end;
                        *end = tmp;
                        begin++;
                        end--;
                    }
                }
                //将临时数组加入ret中
                ret.push_back(ret1);
                //清空临时数组
                while(!ret1.empty())
                    ret1.pop_back();
                //清空临时数组
                while(!ret1.empty())
                    ret1.pop_back();
                //更新当前层节点数,进入下一层
                count1 = count2;
                //更新下一层节点数
                count2 = 0;
                //更新层数
                row++;
            }
            //获取队头节点存入临时数组中
            ret1.push_back(myQueue.front()->val);
            //每存入一个,当前层节点数-1
            count1--;
            //将队头节点的左右孩子节点入队
            if(myQueue.front()->left)
            {
                myQueue.push(myQueue.front()->left);
                //每箱队列中加入一个节点,下一层节点数+1
                count2++;
            }
            if(myQueue.front()->right)
            {
                myQueue.push(myQueue.front()->right);
                count2++;
            }
            //队头节点已经存入到临时数组中,将队头节点出队
            myQueue.pop();
        }
        //如果临时数组中有还没有加入到ret中的,就要加入
        if(!ret1.empty())
        {
            if(row%2 != 0)
            {
                vector<int>::iterator begin = ret1.begin();
                vector<int>::iterator end = ret1.end()-1;
                while(begin < end)
                {
                    int tmp = *begin;
                    *begin = *end;
                    *end = tmp;
                    begin++;
                    end--;
                }
            }
            ret.push_back(ret1);
        }
        return ret;
    }
};

 

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值