2255:重建二叉树

来源:互联网 发布:在线ppi计算器软件 编辑:程序博客网 时间:2024/05/22 07:41

2255:重建二叉树

总时间限制: 1000ms 内存限制: 65536kB
描述
给定一棵二叉树的前序遍历和中序遍历的结果,求其后序遍历。

输入
输入可能有多组,以EOF结束。
每组输入包含两个字符串,分别为树的前序遍历和中序遍历。每个字符串中只包含大写字母且互不重复。
输出
对于每组输入,用一行来输出它后序遍历结果。
样例输入
DBACEGF ABCDEFG
BCAD CBAD
样例输出
ACBFGED
CDAB

解析:巨难过,感觉自己写的没有错,但是一直runtime error,为什么!哪位大神给解释一下,感激不尽~第一个代码是自己写的,朴素的构造树来求的,第二个是某大神写的,巨简洁,膜拜一下

#include<iostream>#include<string.h>#include<stdio.h>using namespace std;//http://bailian.openjudge.cn/practice/2255///Runtime Error  为什么!!! struct node{    char val;    node *l,*r;};char a[1000000],b[1000000];int len1,len2;node *f(node *x,int l1,int l2,int r2){    //l1是前序左端点,l2,r2是后序左右端点    if(r2==l2)return x;//子树为空     char k=a[l1];// 根节点是前序第一个字符    x=new node;    x->val=k;    x->l=NULL;x->r=NULL;    if(r2-l2==1)return x;    int ll2,lr2,rl2,rr2;    for(int i=l2;i<r2;i++){        //从中序中找根节点,分出左右子树        if(b[i]==k){            ll2=l2;//左子树左端点             lr2=i;            rl2=i+1;//右子树左端点            rr2=r2;            break;         }     }     x->l=f(x->l,l1+1,ll2,lr2);    x->r=f(x->r,l1+1+(lr2-ll2),rl2,rr2);}void post(node *x){    if(x->l!=NULL)post(x->l);    if(x->r!=NULL)post(x->r);    cout<<x->val;}int main(){    while(scanf("%s %s",a,b)!=EOF){        len1=strlen(a);        len2=strlen(b);        node *root=NULL;        root=f(root,0,0,len2);         post(root);        cout<<endl;    }}

http://www.cnbolgs.com/Peper/p/7241955.html

#include<stdio.h>#include<string.h>void bulid(int n,char s1[],char s2[])//n是树的节点数,s1是记录先序遍历,s2中序遍历 {    if(n<=0)  return;//没有节点了,找到边界return     int p=strchr(s2,s1[0])-s2;    // strchr(s2,s1[0])是s2的地址+s1[0]第一次出现的位置i。s2是s2的地址     //所以p是 s1[0]第一次出现在s2中的位置    bulid(p,s1+1,s2);    //数的节点数为s1[0]在s2中之前的所有节点。s1+1是把s1数组整体向前移动一位(s1[0]是以前的s1[1],s1[1]改为以前s1[2]...    //以前s1[0]是根,现在不需要,所以删除。要它左子树的根节点     //s2不变(假设中序遍历中根节点的位置是a,那么后序遍历中0~a个点是树的左子树节点)     bulid(n-p-1,s1+p+1,s2+p+1);    //数的节点数为s1[0]在s2中之后的所有节点(因为数组从0开始,所以-1)    //以前s1[0]是根,现在不需要,左子树也不需要,所以都删除。要它右子树的根节点    //s2+p+1(假设中序遍历中根节点的位置是a,a~n-2(数组从0开始)个点是树的右子树节点 )     printf("%c",s1[0]);//输出 }int main(){    char s1[10007],s2[10007];//s1是树的前序遍历,s2是树的中序遍历     while(scanf("%s %s",s1,s2)!=EOF)//多组数据     {        bulid(strlen(s1),s1,s2);         printf("\n");//记得输出\n     }    return 0;}/*先序遍历第一个节点一定是根节点。中序遍历根节点左侧就是树的左子树,右侧就是树的右子树。后序遍历最后一个节点一定是根节点,而假设中序序列里根节点位置是m,那么后序序列里0至m-1个节点是树的左子树节点,m至倒数第二个点是树的右子树节点。*/

今天又做这个题,又写了一个程序,AC了

#include<iostream>#include<string.h>using namespace std;//http://bailian.openjudge.cn/practice/2255///第一次忘记返回的判断了,想明白了就是对两个数组分段进行递归处理//每次根据前序中找到根节点,然后对中序左右分别处理直到空 char a[10000],b[10000];int len1,len2;void f(int l,int l2,int r2){    if(l2==r2)return;    char k=a[l];//前序中的第一个值是根节点    int rr;    for(int i=l2;i<r2;i++){        if(b[i]==k){            rr=i;            break;//rr左边是左子树,右边是右子树         }    }     f(l+1,l2,rr);    f(l+(rr-l2+1),rr+1,r2);    cout<<k;}int main(){    while(cin>>a>>b){        len1=strlen(a);        len2=strlen(b);        f(0,0,len2);        cout<<endl;    }} 
原创粉丝点击