• 数据结构


     

     

    • 写在前面

    昨天有同学问到我一题关于重构二叉树的问题(link),做了一下,也做个记录吧!

    所谓二叉树的重构,就是给你前序和中序,或者中序和后序,让你还原这棵二叉树.

    注意:给出前序和后序是不能唯一确定一棵二叉树的,证明请看这儿.

     

    一.给出前序和中序,重构二叉树

    一个递归的过程:

    当前结点的value:每一轮根据前序的第一个元素确定当前结点值.

    左子树的中序遍历数组:以当前结点的value为分界点,将中序分为左部分和右部分,左部分即为左子树的中序遍历数组.

    右子树的中序遍历数组:以当前结点的value为分界点,将中序分为左部分和右部分,右部分即为右子树的中序遍历数组.

    左子树的前序遍历数组:pre[1 ... i] (i为左子树的中序遍历数组的个数).

    右子树的前序遍历数组:pre[i+1 ... end](i为左子树的中序遍历数组的个数).

    构造出这5个值,继续递归求左右子树即可.

    题目1:重建二叉树(剑指offer)

    给出前序和中序,要你重建二叉树.

    按照上面所说递归即可,详见代码:

    /**
    * -----------------------------------------------------------------
    * Copyright (c) 2016 crazyacking.All rights reserved.
    * -----------------------------------------------------------------
    *       Author: crazyacking
    *       Date  : 2016-01-03-21.09
    */
    #include <queue>
    #include <cstdio>
    #include <set>
    #include <string>
    #include <stack>
    #include <cmath>
    #include <climits>
    #include <map>
    #include <cstdlib>
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    typedef long long(LL);
    typedef unsigned long long(ULL);
    const double eps(1e-8);

    /**
    * Definition for binary tree
    * struct TreeNode {
    *     int val;
    *     TreeNode *left;
    *     TreeNode *right;
    *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
    * };
    */

    struct TreeNode
    {
       int val;
       TreeNode *left;
       TreeNode *right;
       TreeNode(int x) : val(x),left(NULL),right(NULL) {}
    };


    class Solution
    {
    public:
       vector<int> tpr;
       vector<int> tin;
       void reBuild(int a,int b,int n,TreeNode *treeNode)
       {
           if(n==1) // leaf node
           {
               treeNode = new TreeNode(tpr[a]);
               return ;
           }
           else if(n<=0) // null node
               return ;
           int i=0;
           for(; tpr[a]!=tin[b+i]; ++i);
           TreeNode *lson,*rson;
           reBuild(a+1,b,i,lson);
           reBuild(a+1+i,b+1+i,n-i-1,rson);
           treeNode = new TreeNode(tpr[a]);
           treeNode->left=lson;
           treeNode->right=rson;
       }
       struct TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> in)
       {
           tpr.clear();
           tin.clear();

           for(int i=0; i<pre.size(); ++i)
               tpr.push_back(pre[i]);
           for(int i=0; i<in.size(); ++i)
               tin.push_back(in[i]);

           TreeNode *root;
           int n=pre.size();
           reBuild(0,0,n,root);
           return root;
       }
    };

    void DFS(TreeNode *root)
    {
       if(root)
       {
           cout<<(root->val)<< " ";
       }
       else return ;
       if(root->left)
           DFS(root->left);
       if(root->right)
           DFS(root->right);
    }

    int main()
    {
       freopen("D:\Desktop\in.txt","r",stdin);
       int n;
       vector<int>pre;
       vector<int>in;
       while(cin>>n)
       {
           pre.clear();
           in.clear();
           for(int i=0; i<n; ++i)
           {
               int tmp;
               cin>>tmp;
               pre.push_back(tmp);
           }
           for(int i=0; i<n; ++i)
           {
               int tmp;
               cin>>tmp;
               in.push_back(tmp);
           }
           Solution a;
           TreeNode *root=a.reConstructBinaryTree(pre,in);
           DFS(root);
       }
       return 0;
    }

    题目2:HDU 1710 Binary Tree Traversals

    方法一:也很简单,根据上面说的方法递归建树,然后按照后序访问输出即可.

    /**
    * -----------------------------------------------------------------
    * Copyright (c) 2016 crazyacking.All rights reserved.
    * -----------------------------------------------------------------
    *       Author: crazyacking
    *       Date  : 2016-01-04-18.01
    */
    #include <queue>
    #include <cstdio>
    #include <set>
    #include <string>
    #include <stack>
    #include <cmath>
    #include <climits>
    #include <map>
    #include <cstdlib>
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    typedef long long(LL);
    typedef unsigned long long(ULL);
    const double eps(1e-8);

    int n;
    vector<int> pr;
    vector<int> in;

    struct TreeNode
    {
         int val;
         TreeNode *left,*right;
         TreeNode(int v):val(v),left(NULL),right(NULL){}
    };

    TreeNode* reBuildBinaryTree(vector<int> pr,vector<int> in)
    {
         if(pr.size()==0 || in.size()==0)
               return NULL;
         int root=pr[0];
         TreeNode *node=new TreeNode(root);
         vector<int> prLeft,prRight,inLeft,inRight;
         int i=0;
         for(;pr[0]!=in[i];++i);

         for(int j=0;j!=i;++j)
               inLeft.push_back(in[j]);
         for(int j=i+1;j<in.size();++j)
               inRight.push_back(in[j]);
         for(int j=1;j<i+1;++j)
               prLeft.push_back(pr[j]);
         for(int j=i+1;j<pr.size();++j)
               prRight.push_back(pr[j]);

         node->left=reBuildBinaryTree(prLeft,inLeft);
         node->right=reBuildBinaryTree(prRight,inRight);
         return node;
    }


    vector<int>po;
    void getPostOrder(TreeNode *root,bool flag)
    {
         if(root->left)
               getPostOrder(root->left,0);
         if(root->right)
               getPostOrder(root->right,0);
         po.push_back(root->val);
    }
    int main()
    {
         while(cin>>n)
         {
               int tmp;
               pr.clear();
               in.clear();
               po.clear();
               for(int i=0;i<n;++i)
               {
                     cin>>tmp;
                     pr.push_back(tmp);
               }
               for(int i=0;i<n;++i)
               {
                     cin>>tmp;
                     in.push_back(tmp);
               }
               TreeNode *root=reBuildBinaryTree(pr,in);
               getPostOrder(root,1);
               for(int i=0;i<n;++i)
               {
                     if(i<n-1) cout<<po[i]<<" ";
                     else cout<<po[i]<<endl;
               }
         }
         return 0;
    }

    方法二:由于题目没让重构二叉树,只让输出后序访问的顺序,因此可直接访问输出.

    /**
    * -----------------------------------------------------------------
    * Copyright (c) 2016 crazyacking.All rights reserved.
    * -----------------------------------------------------------------
    *       Author: crazyacking
    *       Date  : 2016-01-04-20.09
    */
    #include <queue>
    #include <cstdio>
    #include <set>
    #include <string>
    #include <stack>
    #include <cmath>
    #include <climits>
    #include <map>
    #include <cstdlib>
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    typedef long long(LL);
    typedef unsigned long long(ULL);
    const double eps(1e-8);

    int n;
    vector<int> pr; // pre Order
    vector<int> in; // in Order
    vector<int> po; // post Order

    void getPostOrder(int a,int b,int n,bool flag)
    {
         if(n==1)
         {
               po.push_back(pr[a]);
               return;
         }
         else if(n<=0)
               return;
         int i=0;
         for(;pr[a]!=in[b+i];++i);
         getPostOrder(a+1,b,i,false);
         getPostOrder(a+i+1,b+i+1,n-i-1,false);
         po.push_back(pr[a]);
    }

    int main()
    {
         while(cin>>n)
         {
               pr.clear();
               in.clear();
               po.clear();
               for(int i=0;i<n;++i)
               {
                     int tmp;
                     cin>>tmp;
                     pr.push_back(tmp);
               }
               for(int i=0;i<n;++i)
               {
                     int tmp;
                     cin>>tmp;
                     in.push_back(tmp);
               }

               getPostOrder(0,0,n,true);
               for(int i=0;i<n;++i)
               {
                     if(i<n-1)
                           cout<<po[i]<<" ";
                     else cout<<po[i]<<endl;
               }
         }
         return 0;
    }

    二.给出后序和中序,重构二叉树

    一个递归的过程:

    当前结点的value:每一轮根据前序的最后一个元素确定当前结点值.

    左子树的中序遍历数组:以当前结点的value为分界点,将中序分为左部分和右部分,左部分即为左子树的中序遍历数组.

    右子树的中序遍历数组:以当前结点的value为分界点,将中序分为左部分和右部分,右部分即为右子树的中序遍历数组.

    左子树的前序遍历数组:pre[0 ... i-1] (i为左子树的中序遍历数组的个数).

    右子树的前序遍历数组:pre[i ... end-1](i为左子树的中序遍历数组的个数).

    构造出这5个值,继续递归求左右子树即可.

    红色部分标出的是和上面的不同点,其余都相同.

    /**
    * -----------------------------------------------------------------
    * Copyright (c) 2016 crazyacking.All rights reserved.
    * -----------------------------------------------------------------
    *       Author: crazyacking
    *       Date  : 2016-01-04-22.07
    */
    #include <queue>
    #include <cstdio>
    #include <set>
    #include <string>
    #include <stack>
    #include <cmath>
    #include <climits>
    #include <map>
    #include <cstdlib>
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    typedef long long(LL);
    typedef unsigned long long(ULL);
    const double eps(1e-8);

    int n;
    vector<int> po;
    vector<int> in;

    struct TreeNode
    {
         int val;
         TreeNode *left,*right;
         TreeNode(int v):val(v),left(NULL),right(NULL){}
    };

    TreeNode* reBuildBinaryTree(vector<int> po,vector<int> in)
    {
         if(po.size()==0 || in.size()==0)
               return NULL;

         int root=po[po.size()-1];
         TreeNode* node=new TreeNode(root);
         vector<int> poLeft,poRight,inLeft,inRight;
         int i=0;
         for(;in[i]!=root;++i);

         for(int j=0;j<i;++j)
               inLeft.push_back(in[j]);
         for(int j=i+1;j<in.size();++j)
               inRight.push_back(in[j]);
         for(int j=0;j<i;++j)
               poLeft.push_back(po[j]);
         for(int j=i;j<po.size()-1;++j)
               poRight.push_back(po[j]);
         node->left=reBuildBinaryTree(poLeft,inLeft);
         node->right=reBuildBinaryTree(poRight,inRight);
         return node;

    }

    void print_BFS(TreeNode* root)
    {
         queue<TreeNode*> q;
         q.push(root);
         while(!q.empty())
         {
               TreeNode *now=q.front();
               q.pop();
               cout<<(now->val)<<" ";
               if(now->left) q.push(now->left);
               if(now->right) q.push(now->right);
         }
    }

    int main()
    {
        // test demo
         int a[]={7,4,2,5,8,6,3,1};
         int b[]={4,7,2,1,5,3,8,6};
         po.clear();
         in.clear();
         for(int i=0;i<8;++i)
         {
               po.push_back(a[i]);
               in.push_back(b[i]);
         }
         TreeNode *root=reBuildBinaryTree(po,in);
         print_BFS(root);
         return 0;
    }
  • 相关阅读:
    celery的使用
    DOM操作
    js动画
    列表案例
    背景案例
    背景属性连写
    背景属性
    链接导航案例
    链接伪类
    优先权之权重会叠加
  • 原文地址:https://www.cnblogs.com/crazyacking/p/5100277.html
Copyright © 2020-2023  润新知