题目描述
给定一棵二叉树的中序遍历和前序遍历,请你先将树做个镜面反转,再输出反转后的层序遍历的序列。所谓镜面反转,是指将所有非叶结点的左右孩子对换。这里假设键值都是互不相等的正整数。
输入格式:
输入第一行给出一个正整数N(<=30),是二叉树中结点的个数。第二行给出其中序遍历序列。第三行给出其前序遍历序列。数字间以空格分隔。
输出格式:
在一行中输出该树反转后的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。
输入样例:
7
1 2 3 4 5 6 7
4 1 3 2 6 5 7
输出样例:
4 6 1 7 5 3 2
分析:
给定一棵二叉树的前序和中序序列,可以唯一的确定一棵二叉树。
所谓的层次遍历的序列就是要按照从上到下从左到右的顺序输出来。但这里眼球镜面反转后在输出层次遍历的序列,我们一般在根据前序和中序确定一棵树的时候,先递归这棵树的左子树再递归右子树,但如果我们现在先递归右子树再递归左子树,这样每次递归的根节点的出现序列就是镜面反转后的序列。
代码:
#include <iostream>
#include<cstring>
#include<stdio.h>
using namespace std;
int post[35],in[35],pre[35],level[35];
int N=0;
//l1~r1前序的区间,l2~r2中序的区间
void postTranverse(int l1,int r1,int l2,int r2,int id)
{
if(l1>r1||l2>r2) return;
int i,len1,len2;
for(i=l2; i<=r2; i++)
{
if(pre[l1]==in[i])//从中序中找到当前的根节点
{
level[N]=id;
post[N++]=in[i];
len1=i-l2;//左子树的长度
len2=r2-i;//右子树的长度
break;
}
}
postTranverse(r1-len2+1,r1,i+1,r2,id+1);//递归右子树
postTranverse(l1+1,l1+len1,l2,i-1,id+1);//递归左子树
}
int main(int argc, char** argv)
{
int n,i,j;
cin>>n;
for(i=0; i<n; i++)
{
scanf("%d",&in[i]);//中序遍历序列
}
for(i=0; i<n; i++)
{
scanf("%d",&pre[i]);//前序遍历序列
}
memset(level,-1,sizeof(level));
postTranverse(0,n-1,0,n-1,0);
int t=1;
printf("%d",post[0]);
for(i=1; i<n; i++)
{
for(j=1; j<n; j++)
{
if(level[j]==t)
{
printf(" %d",post[j]);
}
}
++t;
}
return 0;
}