题面
给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。
输入格式:
输入第一行给出一个正整数N(≤30),是二叉树中结点的个数。第二行给出其后序遍历序列。第三行给出其中序遍历序列。数字间以空格分隔。
输出格式:
在一行中输出该树的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。
输入样例:
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
输出样例:
4 1 6 3 5 7 2
相关知识
1.中序遍历:左子树->结点->右子树
2.后序遍历:左子树->右子树->结点
分析
由以上可知,后序遍历的最后一个数即为根结点,即样例中的 “4”,对应到中序遍历中,“4”左边的数组即为左子树,右边的数组即为右子树,左边数组中后序遍历下标最大的数即为左子树的子树根结点,同理右边也是一样。因此我们只要对中序遍历不断递归寻找每一个结点,并按层次记录结点键值,最后依次输出即可。
代码实现
#include<stdio.h>
#include <string.h>
struct tree{
int arr[30];
int num;//记录同层次结点数量
};//用于记录不同层次结点键值
int* max(int*,int*,int*);//用于寻找后序遍历中下标最大的值,并返回地址
void creat(int*,int,struct tree*,int*,int*);//用于递归查找结点
int main()
{
int b,c=0;//b为结点数,c用于输出
struct tree a[30];//定义每一层
memset(a,0,sizeof(struct tree));//初始化结构体
scanf("%d",&b);
int lat[b];//后序遍历
int hash[1000]={0};//用于记录后序遍历中键值对应的下标,便于查找比较
int mid[b];//前序遍历
for(int i=0; i<b; i++){
scanf("%d",&lat[i]);
hash[lat[i]]=i;//记录下标
}
for(int i=0; i<b; i++){
scanf("%d",&mid[i]);
}
creat(hash,0,a,&mid[0],&mid[b-1]);
while(1){//输出
if(a[c].arr[0]==0) break;
if(c==0) printf("%d",a[c++].arr[0]);
else {
for(int i=0; i<a[c].num; i++){
printf(" %d",a[c].arr[i]);
}
c++;
}
}
return 0;
}
void creat(int* hash,int b,struct tree* a,int* l,int* r){//用左右指针限制数组
int* root=max(hash,l,r);//找结点
int *p=root,*q=root;
a[b].arr[ a[b].num++ ]=*root;//记录结点键值且计数加一
if(l!=q){
q--;
creat(hash,b+1,a,l,q);//进入左子树
}
if(p!=r){
p++;
creat(hash,b+1,a,p,r);//进入右子树
}
return;
}
int* max(int* hash,int* p, int* q){
int* p1=p;//用指针进行遍历
int* p2;
int maxi=-1;
while(p1<=q){
if(hash[*p1]>maxi){
maxi=hash[*p1];
p2=p1;//记录最大下标数的地址
}
p1++;
}
return p2;
}