zoukankan      html  css  js  c++  java
  • 队列 102 Binary Tree Level Order Traversal

    队列的基本应用 - 广度优先遍历

    1)树 : 层序遍历;

    2)图:无权图的最短路径。

    使用队列来实现二叉树的层序遍历,需要多关注一个层数的信息

    /**
     * Definition for a binary tree node.
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     * };
     */
    class Solution {
    public:
        vector<vector<int>> levelOrder(TreeNode* root) {
            vector<vector<int> > res;   //存储最终输出的二维列表
            if(root == NULL)
                return res;
            queue< pair<TreeNode*, int> > q;    //将当前结点与它在第几层成对
            q.push(make_pair(root, 0));
            while(!q.empty()){
                TreeNode* node = q.front().first;
                int level = q.front().second;
                q.pop();
                
                if(level == res.size())  //若相等则说明res中还不存在这一层,因为level从0开始计数,res从1开始
                    //这个结点在一个新的层中,在res中新加一层
                    res.push_back(vector<int>());
                
                res[level].push_back(node->val);
                
                if(node->left)
                    q.push(make_pair(node->left, level+1));
                if(node->right)
                    q.push(make_pair(node->right, level+1));
            }
            return res;
        }
    };

    解法二:<推荐> 比解法一通用,更方便。

    /**
     * Definition for a binary tree node.
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     * };
     */
    class Solution {
    public:
        vector<vector<int>> levelOrder(TreeNode* root) {
            if(!root) 
                return {};
            vector<vector<int>> res;
            queue<TreeNode* > q{{root}};
            while(!q.empty()){
                vector<int> oneLevel;
                for(int i = q.size(); i>0; i--){
                    //因为q的大小是会变的,所以i要从q.size()开始从大往小减
                    TreeNode* t = q.front();
                    q.pop();
                    oneLevel.push_back(t->val);
                    if(t->left) q.push(t->left);
                    if(t->right) q.push(t->right);
                }
                res.push_back(oneLevel);
            }
            return res;
        }
    };

    /**
     * Definition for a binary tree node.
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     * };
     */
    class Solution {
    public:
        vector<vector<int>> levelOrderBottom(TreeNode* root) {
            if(!root) 
                return {};
            vector<vector<int>> res;
            queue<TreeNode* > q{{root}};
            while(!q.empty()){
                vector<int> oneLevel;
                for(int i = q.size(); i>0; i--){
                    TreeNode* t = q.front();
                    q.pop();
                    oneLevel.push_back(t->val);
                    if(t->left) q.push(t->left);
                    if(t->right) q.push(t->right);
                }
                res.insert(res.begin(), oneLevel);    //倒序插入
            }
            return res;
        }
    };

    之形的意思是:第0行是从左到右遍历,第1行是从右到左遍历,以此类推,交叉往返的之字形的层序遍历。

    这里需要注意的一点是:不能将某一层的左子树和右子树逆序插入,这样会导致下一层的顺序出错。而是应该在奇数层时将各个结点反向插入

    /**
     * Definition for a binary tree node.
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     * };
     */
    class Solution {
    public:
        vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
            vector<vector<int> > res;
            if(!root)
                return {};
            queue<TreeNode* > q{{root}};
            int j = 0;   //层数从0开始计数
            while(!q.empty()){
                vector<int> oneLevel;
                for(int i=q.size(); i>0; i--){
                    TreeNode* t = q.front();
                    q.pop();
                    
                    if(j%2 == 0){
                        oneLevel.push_back(t->val);     //偶数层正向插入
                    }
                    else{
                        oneLevel.insert(oneLevel.begin(), t->val);   //奇数层时反向插入
                    }  
                    if(t->left) q.push(t->left);
                    if(t->right) q.push(t->right);
                }
                j++;
                res.push_back(oneLevel);
            }
            return res;
        }
    };

    即打印出二叉树每一行最右边的一个结点。使用队列来实现,遍历每层的结点时,把下一层的结点都存入队列中,则每当开始新一层结点的遍历之前,先把新一层最后一个结点值存到res中。

    /**
     * Definition for a binary tree node.
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     * };
     */
    class Solution {
    public:
        vector<int> rightSideView(TreeNode* root) {
            vector<int> res;
            if(!root) return {};
            queue<TreeNode*> q{{root}};
            while(!q.empty()){
                res.push_back(q.back()->val);   //将每层的最后一个结点保存到res中
                for(int i=q.size(); i>0; i--){
                    TreeNode* t = q.front();
                    q.pop();
                    if(t->left) q.push(t->left);
                    if(t->right) q.push(t->right);
                }
            }
            
            return res;
        }
    };
  • 相关阅读:
    ES6 一些新特性的总结
    前端模块化开发的规范:AMD与CDM
    webpack与grunt/glub 的比较
    前端总结(一)
    前端性能的优化
    Typescript 常见写法
    显示模式------行内元素、块元素,行内块元素
    浏览器前缀及内核
    BFC规范
    数据库习题练习
  • 原文地址:https://www.cnblogs.com/Bella2017/p/10284540.html
Copyright © 2011-2022 走看看