NYOJ221二叉树重建(已知先序和中序求后序)

来源:互联网 发布:慕容安cos淘宝 编辑:程序博客网 时间:2024/06/06 19:02

题意:大概意思就是给你一个二叉树的先序遍历和中序遍历,然后需要你求出后序遍历并输出到屏幕上面

 

思路分析: 首先明确三种遍历的特点:

先序遍历:先访问根节点,接着访问左子树,再访问右子树,由此可以明确先序遍历的第一个节点一定是根节点

中序遍历:先访问左子树,接着访问根节点,然后访问右子树,由此可以知道如果知道根节点,那么中序遍历根节点左边为左子树,右边有右子树

后序遍历:先访问左子树,接着访问右子树,最后访问根节点,由此可以知道后序遍历最后一个一定是根节点。

 

根据以上三种遍历的特点,我们可以分析,已知先序遍历和中序遍历的情况下,我们可以由先序遍历知道根节点,然后在中序遍历中找出根节点的位置,那么中序序列根节点左边为左子树,右边为右子树,接下来关键:我们思考一下,对于一个只有两层,左右树存在,那么根节点确定吧,那么,在我们这个给出的遍历中,抛开根节点,每一个这样的父节点我们都可以当做隔离开来的这个两层树的根节点,不知道懂了没,意思就是,我们在去掉根节点的先序中,把遍历的下一个节点(当然根节点下面的左右子树分开)当做新的根节点并在中序序列中查找位置,不断如此递归,把中序不断分开,当递归完左子树之后,同样如此递归右子树,当然,在每次这样的过程中,我们需要同时保存数据,建立二叉树。

如果有树:前序为ABDGHCEIF ,中序为:GDHBAEICF。

按照以上意思,A为第一次递归根节点,中序分为:GDHB  AEICF;

第二次递归   B为在中序中查找的节点  分为:GDH

第三次递归 D为在中序中查找的节点 分为:G H

接着G,后面没了,左边递归完成,G为左子树最后一个叶子节点,然后回溯。。。。

右子树是同样的道理,注意,每次我们递归的时候在中间建立了二叉树,并且进行了赋值

 代码:

#include<stdio.h>#include<stdlib.h>#include<string.h>typedef struct tree{char value;struct tree *lchild;struct tree *rchild;}Tree;void search(char *preorder, char *pinorder,Tree **first ,int treelen){int nleftlen,nrightlen;char *pleftend;Tree *p;if(preorder==NULL||pinorder==NULL||first==NULL)return;p=(Tree *)malloc(sizeof(Tree));p->value=*preorder;    //对建立的节点赋值p->lchild=p->rchild=NULL;    //初始化节点左右指针*first=p;              //记录此时根节点if(treelen==1)return ;pleftend=pinorder;            //pletfend得到先序遍历中根节点的值,下面在中序遍历中查找该点的位置while(*pleftend!=*preorder)pleftend++;nleftlen=(int)(pleftend-pinorder);nrightlen=treelen-nleftlen-1;if(nleftlen>0)    //左边递归search(preorder+1,pinorder,&(p->lchild),nleftlen);if(nrightlen>0)   //右边递归 注意指针位置的变化search(preorder+nleftlen+1,pinorder+nleftlen+1,&(p->rchild),nrightlen);}void Postorder(Tree *p)   //树建立完了之后进行后序遍历{if(p!=NULL){Postorder(p->lchild);Postorder(p->rchild);printf("%c",p->value);}}int main(){char a[100],b[100];Tree *p;while(scanf("%s%s",a,b)!=EOF){search(a,b,&p,strlen(a));Postorder(p);printf("\n");}return 0;}