• 二叉树的遍历与创建


    前序遍历

    前序遍历伪代码:

    void prevorderTraverse(TreeNode* root) 
    {
        if (root == NULL) 
            return;
    
        // 前序遍历代码
    
        prevorderTraverse(root->left);//递归左子树
        prevorderTraverse(root->right);//递归右子树
    }    

    LeetCode297-二叉树的序列化与反序列化:输入一棵二叉树的根节点 root,要求你实现一个类,用serialize方法将二叉树序列化成字符串,用deserialize方法将序列化的字符串反序列化成二叉树

    class Codec {
    public:
        int index=0;
    
        //序列化
        string serialize(TreeNode* root) 
        {
            string str;
            PreOrderTraverse(root,str);//前序遍历
            return str;
        }
    
        //前序遍历
        //将二叉树序列化为字符串,val之间用,隔开
        //空节点用#表示
        void PreOrderTraverse(TreeNode* root,string& str)
        {
            if(!root)
            {
                str+="#,";
                return;
            }
    
            str=str+to_string(root->val)+",";//整型转换为字符串
    
            PreOrderTraverse(root->left,str);//遍历左子树
            PreOrderTraverse(root->right,str);//遍历右子树
        }
    
    
        //反序列化
        TreeNode* deserialize(string str) 
        {
            vector<string> vec;
            split(str,vec);//按,进行字符串切分
            return createTree(vec);//创建二叉树
        }
    
        //根据前序遍历结果创建一棵二叉树
        TreeNode* createTree(vector<string> vec)
        {
            if(index==vec.size())
                return NULL;
    
            TreeNode* root=NULL;
            string str=vec[index++];
    
            if (str != "#")
            {
                int val=atoi(str.c_str());//字符串转为整型
                root = new TreeNode(val);
    
                root->left = createTree(vec);//创建左子树
                root->right = createTree(vec);//创建右子树
            }
    
            return root;
        }
    
        //切分字符串
        void split(string str,vector<string>& vec)
        {
            int nPos = str.find( "," );
            string strTmp;
    
            while( nPos > 0 )
            {
                strTmp = str.substr( 0, nPos );//字串
                vec.push_back( strTmp );
                                
                str.erase( 0, nPos+1 );//删除子串
                nPos = str.find( "," );
            }
    
            return;
        }
    };
    

      

    中序遍历

    中序遍历伪代码:

    void inorderTraverse(TreeNode* root) 
    {
        if (root == NULL) 
            return;
    
        inorderTraverse(root->left);//递归左子树
    
        // 中序遍历代码
    
        inorderTraverse(root->right);//递归右子树
    }    
    
    //中序遍历
    //扩展的中序遍历结果不能唯一确定一棵二叉树
    //        1          2
    //       /          / 
    //      2          3   1
    //     /
    //    3
    //扩展的中序遍历均为#3#2#1#

    后序遍历

    后序遍历伪代码:

    void postorderTraverse(TreeNode* root) 
    {
        if (root == NULL) 
            return;
    
        postorderTraverse(root->left);//递归左子树
        postorderTraverse(root->right);//递归右子树
    
        // 后序遍历代码
    }    

     LeetCode297-二叉树的序列化与反序列化:输入一棵二叉树的根节点 root,要求你实现一个类,用serialize方法将二叉树序列化成字符串,用deserialize方法将序列化的字符串反序列化成二叉树

    //后序遍历
    class Codec 
    {
    public:
        int index=0;
    
        //序列化
        string serialize(TreeNode* root) 
        {
            string str;
            PostOrderTraverse(str,root);//后序遍历
            return str;
        }
    
        //后序遍历
        void PostOrderTraverse(string& str,TreeNode* root)
        {
            if(!root)
            {
                str+="#,";
                return;
            }
    
            PostOrderTraverse(str,root->left);//遍历左子树
            PostOrderTraverse(str,root->right);//遍历右子树
            str=str+to_string(root->val)+",";
        }
    
    
        //反序列化
        TreeNode* deserialize(string str) 
        {
            vector<string> vec;
            split(vec,str);
            index=vec.size()-1;
            return CreateTree(vec);
        }
    
        //根据扩展的后序遍历结果创建二叉树
        //后序遍历的特点:生成树的字符串的最后一个字符,代表的就是它的根结点,倒数第二个就是它的右孩子
        //从字符串后面开始推,按照根结点 -> 右结点 ->左节点 的顺序就能通过递归构造出一棵二叉树了
        TreeNode* CreateTree(vector<string> vec)
        {
            if(index<0)
                return NULL;
    
            TreeNode* root=NULL;
            string str=vec[index--];
    
            if(str!="#")
            {
                int val=atoi(str.c_str());
                root=new TreeNode(val);
                root->right=CreateTree(vec);//创建右子树
                root->left=CreateTree(vec);//创建左子树
            }
    
            return root;
        }
    
        //切分字符串
        void split(vector<string>& vec,string str)
        {
            int pos=str.find(",");
            string strTemp;
    
            while(pos>0)
            {
                strTemp=str.substr(0,pos);
                vec.push_back(strTemp);
                str.erase(0,pos+1);
                pos=str.find(",");
            }
    
            return;
        }
    };
    

    层序遍历

    层序遍历伪代码:

    void traverse(TreeNode* root) 
    {
        if (root == NULL) 
            return;
    
        // 初始化队列,将 root 加入队列
        queue<TreeNode*> queue;
        queue.push(root);
    
        while (!q.empty()) 
        {
            TreeNode* cur = queue.front();
         queue.pop(); //层级遍历代码 if (cur->left != NULL) q.push(cur->left); if (cur->right != NULL) q.push(cur->right); } }

    LeetCode297-二叉树的序列化与反序列化:输入一棵二叉树的根节点 root,要求你实现一个类,用serialize方法将二叉树序列化成字符串,用deserialize方法将序列化的字符串反序列化成二叉树(仅仅适用于完全二叉树)

    //层序遍历,只适用于完全二叉树
    class Codec 
    {
    public:
    
        //序列化
        string serialize(TreeNode* root) 
        {
            string str;
            LevelOrderTraverse(str,root);//层序遍历
            cout<<str<<endl;
            return str;
        }
    
        void LevelOrderTraverse(string& str,TreeNode* root)
        {
            if(!root)
                return;
    
            queue<TreeNode*> que;
            que.push(root);
    
            while(!que.empty())
            {
                TreeNode* current=que.front();
                que.pop();
                str=str+to_string(current->val)+",";
    
                if(current->left!=NULL)
                    que.push(current->left);
    
                if(current->right!=NULL)
                    que.push(current->right);
            }
        }
    
        //反序列化
        TreeNode* deserialize(string str) 
        {
            vector<string> vec;
            split(vec,str);
            int index=0;
            return CreateTree(vec,index);
        }
    
        //根据扩展的层序遍历结果创建二叉树
        TreeNode* CreateTree(vector<string> vec,int index)
        {
            if(index>=vec.size())
                return NULL;
    
            TreeNode* root=NULL;
            string str=vec[index];
    
            int val=atoi(str.c_str());
            root=new TreeNode(val);
    
            root->left=CreateTree(vec,2*index+1);
            root->right=CreateTree(vec,2*index+2);
    
            return root;
        }
    
        //切分字符串
        void split(vector<string>& vec,string str)
        {
            int pos=str.find(",");
            string strTemp;
    
            while(pos>0)
            {
                strTemp=str.substr(0,pos);
                vec.push_back(strTemp);
                str.erase(0,pos+1);
                pos=str.find(",");
            }
    
            return;
        }
    };
    

    根据两种遍历结果确定二叉树  

    伪代码:

    TreeNode* CreateTree(遍历结果1,遍历结果2)
    {
        if(遍历结果为空)
            return NULL;
    
        TreeNode* root=new TreeNode(根节点值);
        if(遍历结果大小为1)
            return root;
        else
        {
            //根据根节点将遍历结果划分为
            //左子树的遍历结果1,左子树的遍历结果2
            //右子树的遍历结果1,右子树的遍历结果2
            root->left=CreateTree(左子树的遍历结果1,左子树的遍历结果2);
            root->right=CreateTree(右子树的遍历结果1,右子树的遍历结果2);
        }
    
        return root;      
    }
    

    LeetCode105-前序遍历+中序遍历确定一棵二叉树

    /**
     * Definition for a binary tree node.
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
     *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
     *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
     * };
     */
    class Solution {
    public:
        TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) 
        {
            if(preorder.empty()||inorder.empty()||preorder.size()!=inorder.size())
                return NULL;
    
            return CreateTree(preorder,inorder);
        }
    
        TreeNode* CreateTree(vector<int> preorder,vector<int> inorder)
        {
            if(preorder.empty())
                return NULL;
    
            TreeNode* root=new TreeNode(preorder[0]);
            if(preorder.size()==1)
                return root;
            else
            {
                int valTemp=preorder[0];
                auto pos=find(inorder.begin(),inorder.end(),valTemp);
                int i=pos-inorder.begin();
    
                vector<int> prevLeft{preorder.begin()+1,preorder.begin()+1+i};//左子树的前序遍历
                vector<int> prevRight{preorder.begin()+1+i,preorder.end()};//右子树的前序遍历
                vector<int> inLeft{inorder.begin(),inorder.begin()+i};//左子树的中序遍历
                vector<int> inRight{inorder.begin()+i+1,inorder.end()};//右子树的中序遍历
    
                root->left=CreateTree(prevLeft,inLeft);//创建左子树
                root->right=CreateTree(prevRight,inRight);//创建右子树
            }
    
            return root;
        }
    };
    

    LeetCode889-前序遍历+后序遍历确定一棵二叉树的任意一种情况

    /**
     * Definition for a binary tree node.
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
     *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
     *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
     * };
     */
    class Solution {
    public:
        TreeNode* constructFromPrePost(vector<int>& pre, vector<int>& post) 
        {
            if(pre.empty()||post.empty()||pre.size()!=post.size())
                return NULL;
    
            return CreatTree(pre,post);
        }
    
        //前序遍历的第一个元素和后序遍历的最后一个元素为根节点
        //前序遍历的第二个元素为左子树的根节点
        //后序遍历的倒数第二个元素为右子树的根节点
        //根据左右子树根结点的值可以将整个遍历结果切分为左/右子树的前/后序遍历
        TreeNode* CreatTree(vector<int>& pre,vector<int>& post)
        {
            TreeNode* root=NULL;
    
            if(pre.empty())
                return NULL;
            
            root=new TreeNode(pre[0]);
            if(pre.size()==1)
                return root;
            else
            {  
                //valLeft左子树根结点的值
                int valLeft=pre[1];
                auto pos=find(post.begin(),post.end(),valLeft);
                int i=pos-post.begin()+1;//左子树有i个元素
    
                vector<int> preLeft{pre.begin()+1,pre.begin()+1+i};//左子树的前序遍历
                vector<int> postLeft{post.begin(),post.begin()+i};//左子树的后序遍历
    
                vector<int> preRight{pre.begin()+1+i,pre.end()};//右子树的前序遍历
                vector<int> postRight{post.begin()+i,post.end()-1};//右子树的后序遍历
    
                //递归创建左右子树
                root->left=CreatTree(preLeft,postLeft);
                root->right=CreatTree(preRight,postRight);
            }
    
            return root;
        }
    };
    

    LeetCode106-中序遍历+后序遍历确定一棵二叉树

    /**
     * Definition for a binary tree node.
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
     *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
     *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
     * };
     */
    class Solution {
    public:
        TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) 
        {
            if(inorder.empty()||postorder.empty()||inorder.size()!=postorder.size())
                return NULL;
    
            return CreateTree(inorder,postorder);
        }
    
        TreeNode* CreateTree(vector<int> inorder,vector<int> postorder)
        {
            if(inorder.empty())
                return NULL;
    
            TreeNode* root=new TreeNode(postorder[postorder.size()-1]);
            if(inorder.size()==1)
                return root;
            else
            {
                int valTemp=postorder[postorder.size()-1];
                auto pos=find(inorder.begin(),inorder.end(),valTemp);
                int i=pos-inorder.begin();
    
                vector<int> inLeft{inorder.begin(),inorder.begin()+i};
                vector<int> inRight{inorder.begin()+i+1,inorder.end()};
                vector<int> postLeft{postorder.begin(),postorder.begin()+i};
                vector<int> postRight{postorder.begin()+i,postorder.end()-1};
    
                root->left=CreateTree(inLeft,postLeft);
                root->right=CreateTree(inRight,postRight);
            }
    
            return root;
        }
    };
  • 相关阅读:
    Ubuntu下基于u-boot搭建qemu的vexpress环境
    linux从head.s到start_kernelstart_kernel之---内核重定位后分析
    linux从head.s到start_kernelstart_kernel之---内核解压到重定位分析
    Jupyter Notebook介绍、安装及使用教程
    python基于SMTP发送邮件(qq邮箱)
    python正则表达式多次提取数据(一个规则提取多组数据)
    python正则表达式提取中文
    找到任务栏图标广告的源头
    1. Visio Web 形状
    Python GUI之tkinter窗口视窗教程大集合(看这篇就够了)
  • 原文地址:https://www.cnblogs.com/yongjin-hou/p/15023534.html
Copyright © 2020-2023  润新知