【C++】根据二叉树的前序遍历和中序遍历重建二叉树并输出后续遍历

/*
现在有一个问题,已知二叉树的前序遍历和中序遍历:
PreOrder:GDAFEMHZ
InOrder:ADEFGHMZ
我们如何还原这颗二叉树,并求出他的后序遍历

我们基于一个事实:中序遍历一定是 { 左子树中的节点集合 },root,{ 右子树中的节点集合 },前序遍历的作用就是找到每颗子树的root位置。

算法1
输入:前序遍历,中序遍历
1、寻找树的root,前序遍历的第一节点G就是root。
2、观察前序遍历GDAFEMHZ,知道了G是root,剩下的节点必然在root的左或右子树中的节点。
3、观察中序遍历ADEFGHMZ。其中root节点G左侧的ADEF必然是root的左子树中的节点,G右侧的HMZ必然是root的右子树中的节点,root不在中序遍历的末尾或开始就说明根节点的两颗子树都不为空。
4、观察左子树ADEF,按照前序遍历的顺序来排序为DAFE,因此左子树的根节点为D,并且A是左子树的左子树中的节点,EF是左子树的右子树中的节点。
5、同样的道理,观察右子树节点HMZ,前序为MHZ,因此右子树的根节点为M,左子节点H,右子节点Z。

观察发现,上面的过程是递归的。先找到当前树的根节点,然后划分为左子树,右子树,然后进入左子树重复上面的过程,然后进入右子树重复上面的过程。最后就可以还原一棵树了:

PreOrder:GDAFEMHZ
InOrder:ADEFGHMZ
从而得到PostOrder:       
AEFDHZMG
*/


#include<iostream>
#include<cstring>
using namespace std;
const int M=1024;
char pr[M];
char in[M];

struct node
{
    char data;
    node *l;
    node *r;
};
/*
void build(node * & t,int prl,int prr,int inl,int inr)
{
    char m=pr[prl];
    //printf("%c\n",m);
    if(prl>prr||inl>inr)
    {
        t=NULL;
        return ;
    }
    int i1=0;// -> middle num in the pr
    int i2=0;// -> middle num in the in
    while(in[i2]!=m)
        i2++;
    i1=i2;
    t=new node();
    t->data=m;
    
    if(prl==prr||inl==inr)
    {
        t->l=NULL;
        t->r=NULL;
        return ;
    }
    else
    {
        build(t->l,prl+1,i1,inl,i2-1);//go build left part
        build(t->r,i1+1,prr,i2+1,inr);//go build right part
    }
}
*/
void create(node * &t, int preL, int preR, int inL,int inR) {
    if ( preL > preR )
    {
        t=NULL;
        return ;
    }
    t = new node();
    t->data = pr[preL];
    int index;
    for ( index = inL; index <= inR; index++ ) {
        if ( in[index] == pr[preL] )break;
    }
    int numLeft = index - inL;
    create(t->l, preL+1, preL+numLeft, inL, index-1);
    create(t->r, preL+numLeft+1, preR, index+1, inR);
}

void post_display(const node *t)
{
    if(t==NULL)
        return ;
    post_display(t->l);
    post_display(t->r);
    printf("%c ",t->data);
}

int main()
{
    
    memset(pr,'\0',sizeof(pr));
    memset(in,'\0',sizeof(in));
    
    while(cin>>pr&&cin>>in)
    {
        node *tree=NULL;
        if(strlen(pr)==strlen(in))
        {
            create(tree,0,strlen(pr)-1,0,strlen(pr)-1);
            cout<<"build tree ok"<<endl;
        }
        //cout<<tree<<endl<<tree->l<<endl<<tree->r<<endl;
        post_display(tree);
        cout<<endl;
        memset(pr,'\0',sizeof(pr));
        memset(in,'\0',sizeof(in));
    }
    
    return 0;
}


/*
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 35;
char in[maxn];
char pre[maxn];
struct node {
    char data;
    node *lchild;
    node *rchild;
};

node *Create(int preL, int preR, int inL,int inR) {
    if ( preL > preR ) return NULL;
    node *root = new node();
    root->data = pre[preL];
    int index;
    for ( index = inL; index <= inR; index++ ) {
        if ( in[index] == pre[preL] )break;
    }
    int numLeft = index - inL;
    root->lchild = Create(preL+1, preL+numLeft, inL, index-1);
    root->rchild = Create(preL+numLeft+1, preR, index+1, inR);
    return root;
}


void PostOrderTraversal(node *root) {
    if ( root != NULL ) {
        PostOrderTraversal(root->lchild);
        PostOrderTraversal(root->rchild);
        cout << root->data << " ";
    }
}
int main() {
    int n;
    cin >> n;

    for ( int i = 0; i < n; i++ )
        cin >> pre[i];
    for ( int i = 0; i < n; i++ )
        cin >> in[i];
    node *root=NULL;
    root = Create(0,n-1,0,n-1);

    PostOrderTraversal(root);

    return 0;
}
*/

 

 

 

tz@HZAU

2019/3/16

posted on 2019-03-16 22:52  tuzhuo  阅读(651)  评论(0编辑  收藏  举报