根据前序遍历,中序遍历求后序遍历

来源:互联网 发布:电动车 知乎 编辑:程序博客网 时间:2024/06/07 13:06


                                                Binary Tree Traversals

                                                     Time Limit: 1000/1000 MS     Memory Limit: 32768/32768 K
A binary tree is a finite set of vertices that is either empty or consists of a root r and two disjoint binary trees called the left and right subtrees. There are three most important ways in which the vertices of a binary tree can be systematically traversed or ordered. They are preorder, inorder and postorder. Let T be a binary tree with root r and subtrees T1,T2. 

In a preorder traversal of the vertices of T, we visit the root r followed by visiting the vertices of T1 in preorder, then the vertices of T2 in preorder. 

In an inorder traversal of the vertices of T, we visit the vertices of T1 in inorder, then the root r, followed by the vertices of T2 in inorder. 

In a postorder traversal of the vertices of T, we visit the vertices of T1 in postorder, then the vertices of T2 in postorder and finally we visit r. 

Now you are given the preorder sequence and inorder sequence of a certain binary tree. Try to find out its postorder sequence. 
Input
The input contains several test cases. The first line of each test case contains a single integer n (1<=n<=1000), the number of vertices of the binary tree. Followed by two lines, respectively indicating the preorder sequence and inorder sequence. You can assume they are always correspond to a exclusive binary tree. 
Output
For each test case print a single line specifying the corresponding postorder sequence. 
Sample Input
91 2 4 7 3 5 8 9 64 7 2 1 8 5 9 3 6
Sample Output
7 4 2 8 9 5 6 3 1
解题报告:
已知二叉树的前序遍历和中序遍历,求它的后序遍历,我们可以通过前序遍历知道第一个点就是它的根结点,然后再看中序遍历,找出根结点在中序遍历中的位置,然后在这个位置的左边为左子树,右边为右子树。然后左子树和右子树再用上面的方法递归,即可求出它的后序遍历。
刚开始接触数据结构一脸懵逼,啥也不会,硬着头皮写,推了好久才稍微弄明白了一点,没学过数据结构的做二叉树的题真的难啊!
以下代码的注释仅仅是用来增加个人的理解,自己瞎写的,看不懂就算了,哈哈!
#include<iostream>using namespace std;const int maxn=1001;int a[maxn],b[maxn];int m,flag;//通过前序遍历第一个数确定结点,然后通过结点在中序遍历的位置判断哪些元素为左右子树//再在找到的左右子树中,通序遍历的第二个数找确定结点,依此类题,类似于递归; void createtree(int preleft,int preright,int inleft,int inright){int i,lsize,rsize;if(preleft<=preright&&inleft<=inright)              {for(i=inleft;i<inright;i++)              //通过前序遍历的第一个值为根节点,找出其在中序遍历的位置 {if(a[preleft]==b[i]){break;}} lsize=i-inleft;     //在第i个数据为根节点的情况下求左子树的个数 rsize=inright-i;     //同理,求右子树的个数 if(lsize > 0)         {              createtree(preleft+1, preleft + lsize,inleft,i-1);    //以左子树为一个二叉树继续查找         }          //preleft+1从前序遍历中第二个开始确定结点,preleft+lsize表示将第一次找到的左子树定为新的二叉树,继续查找 ;//preleft+1为左子树的结点         //inleft,i-1表示左子树                         if(rsize > 0)          {              createtree(preleft+lsize+1,preright,i+1,inright);    //以右子树为一个二叉树继续查找         }        //preleft+lsize+1表示将第一次的右子树定位新的二叉树,继续查找;//preleft+lsize+1为右子树的结点         //i+1,inright表示右子树                 if(flag)          {              cout<<a[preleft];              flag = 0;          }          else          {              cout<<" "<<a[preleft];          } } }    int main()  {      int i;      while(cin>>m)      {          flag = 1;          for(i=0; i<m; i++)          {              cin>>a[i];          }          for(i=0; i<m; i++)          {              cin>>b[i];          }          createtree(0,m-1,0,m-1);          cout<<endl;      }      return 0;} 
/////////////////////////////////////////////////////////////////////
以下是队里学长学姐的代码,参考参考,学习下
数组建树的代码:
#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int maxn = 1e6 + 100;int pr[maxn], in[maxn], n;          /*pr储存前序遍历,in储存中序遍历*/ int Left[maxn], Right[maxn], root;  //二叉树相关bool ok;//根据前序和中序建树int build(int L1, int R1, int L2, int R2) {    if(L1 > R1)     return 0;    int rt = pr[L1];    int p = 1;    while(in[p] != rt)     ++p;                                          //在中序中找到根结点    Left[rt] = build(L1+1, L1 + p-L2, L2, p-1);      //递归建立左子树    Right[rt] = build(L1+ p-L2 + 1, R1, p+1, R2);    //递归建立右子树    return rt;                                       //返回根结点}//后序遍历void poOrder(int rt) {    if(Left[rt] != 0)     poOrder(Left[rt]);    if(Right[rt] != 0)     poOrder(Right[rt]);    if(ok)     cout << " "; if(!ok) ok = 1;        cout << rt;}int main() {    while(scanf("%d", &n) == 1) {        //初始化+输入        memset(Left, 0, sizeof(Left)); memset(Right, 0, sizeof(Right));        for(int i = 1; i <= n; ++i)     scanf("%d", &pr[i]);        for(int i = 1; i <= n; ++i)     scanf("%d", &in[i]);        root = build(1,n,1,n);  //建树        ok = 0;        poOrder(root);          //后序遍历输出结果        cout << endl;    }    return 0;}
////////////////////////////////////////////////////////////////////////////////////////
指针建树的代码(/*...*/为自己的注释,增加自己的理解,指针建树弄不清白,没有数组建树简单)
#include <iostream>#include <cstring>#include <algorithm>#include <cstdio>#include <cmath>using namespace std;const int maxn = 1e3+5;int pre_order[maxn],in_order[maxn];    /*pre_order前序遍历,in_order中序遍历*/ struct node//结点{    int v;    node *left,*right;    node(){        v=0;        left=NULL,right=NULL;    }};node *root;//头结点node *buildtree(int p1,int p2,int i1,int i2)//由前序中序序列来建二叉树{    if(p1>p2)     return NULL;    int g=pre_order[p1];        /*将前序遍历确定的头结点赋给g*/     node *temp;                 /*建立新的结点*/     temp=new node();    temp->v=g;                   /*将值赋给temp->v,然后输出*/     int cnt;    for(int i=i1;i<=i2;i++)     /*确定头结点在中序遍历的位置*/     {        if(in_order[i]==g)        {            cnt=i;            break;        }    }    temp->left=buildtree(p1+1,p1+1+(cnt-1-i1),i1,cnt-1);      /*递归建立左子树*/    temp->right=buildtree(p1+1+cnt-i1,p2,cnt+1,i2);           /*递归建立右子树*/     return temp;}int num=0;void postorder(node *t)//后序遍历{    if(t->left)       postorder(t->left);    if(t->right)        postorder(t->right);    if(!num){        printf("%d",t->v);        num++;    }    else     printf(" %d",t->v);}int main(){    int n;    while(scanf("%d",&n)!=EOF)    {        root=new node();          /*建立头结点*/         memset(pre_order,0,sizeof(pre_order));        memset(in_order,0,sizeof(in_order));        for(int i=0;i<n;i++)                scanf("%d",&pre_order[i]);        for(int i=0;i<n;i++)            scanf("%d",&in_order[i]);        root=buildtree(0,n-1,0,n-1);        num=0;        postorder(root);        printf("\n");    }    return 0;}

 


 
阅读全文
0 0
原创粉丝点击