给定某二叉树的前序序列和中序序列,输出该二叉树的后序序列。(输入的前序遍历和中序遍历的结果中都不含重复的数字)
第一行是n 接下来一行有n个数表示前序序列 最后一行是中序序列 对于30%的数据,n<=20 对于60%的数据,n<=1000 对于100%的数据,n<=100000
输出树的后序序列
输入:
5
3 9 20 15 7
9 3 15 20 7
输出:
9 15 7 20 3 注意最后一位数字后没有空格
因为通过一棵树的前序遍历,我们可以确定它的根结点,那么有了根结点以后,我们联系之前正常遍历一棵树:其实很简单,就是打印出当前的根结点,根据前中后的顺序,在递归中把打印动作放到适当的位置。那么现在我们有了前序和中序,其实不用构建一棵树再打印,而是通过前序遍历,可以知道根结点在哪里,然后我们去中序里面找这个根结点的位置,根据根结点的位置将中序遍历得到的序列分成左右两棵树,同理前序序列也要分成左右子树与中序的对应进行递归,再对分出的左右子树继续遍历,在两次递归后最后打印根结点,这样就得到了这棵树的后序遍历。
那么如何找这个前序中序中左右子树的位置呢?其实也很简单,随便举一个例子,找出对应的等式关系就好了!
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/90059932888fe41045075c266b674d16.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/9a7c83d2805229155ab69e8b87f50f1b.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/4cb59bb0a21e3d79fdfc981d6aafcd08.png)
有了上述关系 代码就很好写了!!
#include<bits/stdc++.h>
const int N = 1e5;
int n;
int pre[N];
int in[N];
int cnt;
void post(int pre[],int in[],int len){
if(len<=0)
{return;}
int root = pre[0];
int k=0;
while(in[k]!=root)k++;
int inleft[N],preleft[N],inright[N],preright[N];
for(int i=0;i<=k-1;i++)
inleft[i]=in[i];
for(int i=1;i<=k;i++)
preleft[i-1]=pre[i];
for(int i=k+1;i<=len-1;i++)
inright[i-k-1]=in[i];
for(int i=k+1;i<=len-1;i++)
preright[i-k-1]=pre[i];
int leftlen = k;
int rightlen = len-k-1;
post(preleft,inleft,leftlen);
post(preright,inright,rightlen);
if(cnt==0)
printf("%d",root);
else
printf(" %d",root);
cnt++;
}
int main(){
scanf("%d",&n);
for(int i = 0;i<n;i++)
scanf("%d",&pre[i]);
for(int i = 0;i<n;i++)
scanf("%d",&in[i]);
post(pre,in,n);
return 0;
}