给出二叉树的中序遍历序列和后序遍历序列,编程还原该二叉树。
输入
第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;
}