输入先序遍历和中序遍历,输出后序遍历。
易错点:1.在build函数里面没有判断left>right的条件
2.递归区间的选择。
优化点:1.直接在每个build函数里面输出root,因为后序遍历,是先输出左边,在输出右边,在输出结点。所以利用这个特性,build函数做成“先建左边的树,再建右边的树,再打印出自身”。
用left>right来判断非法,其他的不用管。
#include<cstring>
#include<cstdio>
using namespace std;
int preord[30],inord[30];
char preord_2[30],inord_2[30],l;
int left[30],right[30];
bool init(){
memset(preord_2,0,sizeof(preord_2));
memset(inord_2,0,sizeof(inord_2));
// scanf("%s",preord);
// scanf("%s",inord);
if(scanf("%s %s",preord_2,inord_2)==EOF){
return false;
}
l=strlen(preord_2);
for(int i=0;i<l;i++){
preord[i]=preord_2[i]-'A';
inord[i]=inord_2[i]-'A';
}
memset(left,-1,sizeof(left));
memset(right,-1,sizeof(right));
return true;
}
int build(int prelt,int prert,int inlt,int inrt){
int root=preord[prelt];
// printf("%d %d %d %d %d\n",prelt,prert,inlt,inrt,root);
if(prelt==prert) return preord[prert];
int pos;
for(pos=inlt;pos<=inrt;pos++){
if(inord[pos]==root)
break;
}
if(pos>inlt)
left[root]=build(prelt+1,prelt+pos-inlt,inlt,pos-1);
if(pos<inrt)
right[root]=build(prert-inrt+pos+1,prert,pos+1,inrt);
// printf("%c",root+'A');
return root;
}
void build2(int prelt,int prert,int inlt,int inrt){
int root=preord[prelt];
// printf("%d %d %d %d %d\n",prelt,prert,inlt,inrt,root);
if(prelt>prert||inlt>inrt) return;
int pos;
for(pos=inlt;pos<=inrt;pos++){
if(inord[pos]==root)
break;
}
build2(prelt+1,prelt+pos-inlt,inlt,pos-1);
build2(prert-inrt+pos+1,prert,pos+1,inrt);
printf("%c",root+'A');
}
void print(int u){
if(left[u]!=-1){
print(left[u]);
}
if(right[u]!=-1){
print(right[u]);
}
printf("%c",u+'A');
}
int main(void){
while(init()){
// printf("%d",left[1]);
// print(build(0,l-1,0,l-1));
// printf("\n");
build2(0,l-1,0,l-1);
printf("\n");
}
return 0;
}