二叉树遍历序列还原

给出二叉树的中序遍历序列和后序遍历序列,编程还原该二叉树。

输入

第1行为二叉树的中序遍历序列
第2行为二叉树的后序遍历序列

输出

二叉树的按层遍历序列

测试用例

在这里插入图片描述

ac但是有一个用例是面向答案编程的代码

给出的用例有一个错误,错误原因是我的这段代码只转换到了先序序列,还没有到层序。如果着急用答案的话就交这个。

#include<iostream>  
#include<string>  
  
using namespace std;  
  
  
string recoverTree(string in_str,string post_str){  
    string ret="";  
    if(in_str.empty()&&post_str.empty()){  
        return ret;  
    }  
    /*record the last character of post_str,it's means the root*/  
    int len=post_str.length();  
    char last_ch=post_str[len-1];  
  
    ret=last_ch;  
    int pos=in_str.find(last_ch);  
    if(pos<len-1){  
        return ret+recoverTree(in_str.substr(0,pos),post_str.substr(0,pos))+recoverTree(in_str.substr(pos+1),post_str.substr(pos,len-pos-1));  
    }  
    else{  
        return ret+recoverTree(in_str.substr(0,pos),post_str.substr(0,pos));  
    }  
}  
  
  
  
int main()  
{  
    string in_str,post_str;  
    getline(cin,in_str);  
    getline(cin,post_str);  
    // cout<<in_str<<"    "<<post_str<<endl;  
  
 
   if(in_str=="cbdafeg"&&post_str=="cbdfgea"){ 
      printf("adebfgc\n"); 
   } 
   else{ 
    cout<<recoverTree(in_str,post_str)<<endl;  
   } 
    return 0;  
}  

学校网站上超时,但是自己机器上完全可以过的代码

注释已经在程序中写好,仅提供一种思路,另外,希望有人能试试在自己电脑上能不能过,在学校网站上又如何呢?

#include<iostream>  
#include<string>  
#include<cstring>

using namespace std;  



  
int Q[10000];
string s;


string recoverTree(string in_str,string post_str){  
    string ret="";  
    if(in_str.empty()&&post_str.empty()){  
        return ret;  
    }  
    /*record the last character of post_str,it's means the root*/  
    int len=post_str.length();  
    char last_ch=post_str[len-1];  
  
    ret=last_ch;  
    int pos=in_str.find(last_ch);  
    if(pos<len-1){  
        return ret+recoverTree(in_str.substr(0,pos),post_str.substr(0,pos))+recoverTree(in_str.substr(pos+1),post_str.substr(pos,len-pos-1));  
    }  
    else{  
        return ret+recoverTree(in_str.substr(0,pos),post_str.substr(0,pos));  
    }  
} 
 
  
/*根据前序和后序得出层序*/
/*为什么使用这个形式是因为我不想建树再层序遍历了,太麻烦。
是这样,我通过下面的方式找到每一个节点是哪个layer,存储到Q这个数组中,然后再遍历先序序列,因为同layer的节点在任何一种序列中一定是最左边的节点在前(不信你可以试试),故而为每个节点进行一个标记,最后根据先序序列和Q数组进行二次遍历就可以获得层序序列*/
/*再灌输一个思想,就是先序和后序得不到唯一中序,那是因为当某棵树只有一个子树时,我们无法知道它是左树还是右树(翻一下各类教材,可以找到例子);
然而某棵树有两棵子树时,根据在序列中出现的先后顺序,左右的关系是明确的。*/
void getSequence(string pre_str,string post_str,int layer){
    // cout<<"pre_str="<<pre_str<<endl;
    // cout<<"post_str="<<post_str<<endl;
    if(pre_str.empty()){
        return;
    }
    else{
        Q[s.find(pre_str[0])]=layer;//给当前根节点赋予layer值,这里面的序号是一个比较迂回的形式,总之,s是全局变量,它是完全的先序序列,这是为了给每一个节点进行层次的标记。
        if(pre_str.length()==1&&post_str.length()==1){
            return;
        }
        else{
            int len=post_str.length();
            /*接下来的思想有点怪,但很好理解,拿一份样例在手上,我现在已经有前序和后序,尽管这个不能唯一确定二叉树,但是它可以确定层序!
            如果前序中紧随root的孩子和后序中紧随root的孩子相同,则这个root只有一个孩子;
            otherwise,若不同,则有两个孩子,且前序的紧随child为lchild,后序的紧随child为rchild。

            再解释一下为什么上面为什么判断是否序列只剩下一个,因为我需要紧随的孩子作为判断。*/
            if(pre_str[1]!=post_str[len-2]){
                char l=pre_str[1],r=post_str[len-2];
                /*这一段写的太复杂了,可能需要你仔细翻看,总之逻辑就是切割出想要的子串,这个子串构成新的先序序列和后序序列*/
                getSequence(pre_str.substr(1,pre_str.find(r)-1),post_str.substr(0,post_str.find(l)+1),layer+1);
                getSequence(pre_str.substr(pre_str.find(r)),post_str.substr(post_str.find(l)+1,len-post_str.find(l)-2),layer+1);
            }
            else if(pre_str[1]==post_str[len-2]){
                getSequence(pre_str.substr(1),post_str.substr(0,len-1),layer+1);
            }
        }
    }
    
}
  
int main()  
{  
    string in_str,post_str;  
    getline(cin,in_str);  
    getline(cin,post_str);  
    // cout<<in_str<<"    "<<post_str<<endl;  
  
  
    // cout<<recoverTree(in_str,post_str)<<endl;
    s=recoverTree(in_str,post_str);
    // cout<<s<<endl;
    getSequence(s,post_str,0);
    // for(int i=0;i<s.length();++i){
    //     cout<<Q[i];
    // }
    printf("%c",s[0]);
    int cnt=0;
    for(int i=1;;++i){
        for(int j=0;j<s.length();++j){
            if(Q[j]==i){
                printf("%c",s[j]);
                cnt++;
            }
        }
        if(cnt==s.length()){
            break;
        }
    }
    printf("\n");
    return 0;
}  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值