真正的原创在这里
我不过是照着这位博主打的代码
题意:给出一一棵二叉树的前序和中序,输出后序
举例:
前序:1 2 4 7 3 5 8 9 6
中序:4 7 2 1 8 5 9 3 6
后序:7 4 2 8 9 5 6 3 1
函数OUTPUT的奥妙:
一个奇妙的特性:当我们将前序和后序对比时,发现一个节点的子树总是在前序里该节点的后面,后序里该节点的前面(这当然不难理解),所以同时满足这两个条件的就是该节点的子树。我们只需要逐步缩小子树,就能最终找到树的末端。而先找左子树,就能先输出左节点
图中蓝色箭头表示前序,紫色表示中序,这幅图说明当左节点缺失时前序和中序相同,n==0,事实上前序和中序相同时左节点缺失,n==0,子程序直接返回,继续执行OUTPUT的右节点程序。
右节点程序中,如果该节点是叶节点,n==0子程序不做任何事直接返回,flag==0,输出该叶节点。当该点不是叶节点时,将继续递归。所有的左节点在前面输出,右节点在后面输出,根节点最后输出。
另外举一例:
程序的执行过程:
AC代码
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
int N;
void OUTPUT(int*Import1,int*Import2,int a,int b,int N,int flag)
{
if(N==1)
{
printf("%d ",Import1[a]);
return;
}
else if(N==0) return;
int i=0;
for(;Import1[a]!=Import2[b+i];i++);
OUTPUT(Import1,Import2,a+1,b,i,0);//如果i=0,将不执行任何程序
OUTPUT(Import1,Import2,a+i+1,b+i+1,N-i-1,0);//如果n=2,i=0,说明前中序相同,没有左节点,那么直接输出右节点;如果有左节点,那么n-i-1=0,不执行任何程序;
if(flag==1) printf("%d\n", Import1[a]);
else printf("%d ",Import1[a]);
}
int main()
{
while(scanf("%d",&N)!=EOF && N)
{
int*Import1=(int*)malloc(sizeof(int)*(N+2));
int*Import2=(int*)malloc(sizeof(int)*(N+2));
for(int i=1;i<=N;i++) scanf("%d",&Import1[i]);
for(int i=1;i<=N; i++) scanf("%d",&Import2[i]);
OUTPUT(Import1,Import2,1,1,N,1);
}
return 0;
}