给定一颗满二叉树的中序遍历序列和前/后序遍历序列。请尝试还原该二叉树并给出其层次遍历序列。
输入格式:
输入仅有一组样例。
第一行给出该满二叉树的高度H(3≤H≤20)(只有根节点的树的高度记为1)。
随后2行中,其中一行给出中序遍历的序列,另外一行可能给出的是前序遍历的序列、也可能给出的是后序遍历的序列。序列元素保证在整型范围内且互不相同。
注:输入的2组序列,中序遍历序列可能是第1组,也可能是第2组。
输出格式:
输出该满二叉树的层次遍历序列。
输入样例1:
3
1 2 4 5 3 6 7
4 2 5 1 6 3 7
输出样例1:
1 2 3 4 5 6 7
输入样例2:
3
4 2 5 1 6 3 7
4 5 2 6 7 3 1
输出样例2:
1 2 3 4 5 6 7
此题的难点在于未告知:给出的数组顺序(1.前序遍历,中序遍历)(2.中序遍历,前序遍历)(3.后序遍历,中序遍历)(4.中序遍历,后序遍历)这四种排列组合中的哪一种。
但是好在其是一个满二叉树,因此中序遍历数组的中间值为根节点,就此展开讨论进行假设,前序遍历数组第一个值也是根节点,后序遍历数组最后一个值也是根节点
#include <iostream>
#include <math.h>
#include<queue>
#define maxn 10000000
using namespace std;
int b1[maxn],b2[maxn];
int pre[maxn],in[maxn],post[maxn]; //存放先序,中序,后续的数组
struct node{ //定义结构体建立树节点
int data;
node* lchild;
node* rchild;
};
node* creaprein(int prel,int prer,int inl,int inr) //先序和中序建立树
{
if(prel>prer) return NULL; //递归边界,长度小于等于0,直接返回
node* root=new node; //建立新节点,存放根节点
root->data=pre[prel]; //根节点的数据域是根节点的值
int i;
for(i=inl;i<=inr;i++)
{
if(in[i]==pre[prel]) //找到该节点,并记录下标值
break;
}
int num=i-inl;
root->lchild=creaprein(prel+1,prel+num,inl,i-1); //递归其左子树
root->rchild=creaprein(prel+num+1,prer,i+1,inr); //递归其右子树
return root; //递归终点,返回根节点
}
node* creainpost(int postl,int postr,int inl,int inr) //中序和后序建立树
{
if(postl>postr) return NULL; //递归边界
node* root=new node;
root->data=post[postr]; //先序和后序不同的就在于这里
int i;
for(i=inl;i<=inr;i++)
{
if(in[i]==post[postr])
break;
}
int num=i-inl;
root->lchild=creainpost(postl,postl+num-1,inl,i-1);//递归其左子树
root->rchild=creainpost(postl+num,postr-1,i+1,inr);//递归其右子树
return root;
}
void prin(node* root,int num) //层序遍历输出
{
queue<node*> q; //建立队列,并且这是node型指针
q.push(root); //压入根节点
while(!q.empty()) //判断队列是否为空,从而结束循环
{
node* now=new node;
now=q.front(); //建立新节点并且取出队列首元素,取出不是删除,类似一个把队首元素赋值的意思
cout<<now->data; //输出队首元素的值
num--;
if(num != 0)
cout<< " ";
q.pop(); //输出完之后就可以pop掉队首元素
if(now->lchild!=NULL) //但是此时的now依旧存在 判断他是否有左孩子
q.push(now->lchild); //递归左孩子
if(now->rchild!=NULL)
q.push(now->rchild); //递归右孩子
}
}
int main()
{
int H;
cin >> H ;
int num = pow(2,H) - 1;
int q = 0,h = 0;
for(int i = 1;i <= num;i++)
{
cin >> b1[i];
}
for(int i = 1;i <= num;i++)
{
cin >> b2[i];
}
if(b1[(num+1)/2] == b2[1])
{
for(int i = 1;i <= num;i++)
{
in[i] = b1[i];
pre[i] = b2[i];
}
q++;
}
if(b1[(num+1)/2] == b2[num])
{
for(int i = 1;i <= num;i++)
{
in[i] = b1[i];
post[i] = b2[i];
}
h++;
} //假设数组b1为中序遍历
if(b2[(num+1)/2] == b1[1])
{
for(int i = 1;i <= num;i++)
{
in[i] = b2[i];
pre[i] = b1[i];
}
q++;
}
if(b2[(num+1)/2] == b1[num])
{
for(int i = 1;i <= num;i++)
{
in[i] = b2[i];
post[i] = b1[i];
}
h++;
}
if(q != 0)
{
node* root = creaprein(1,num,1,num);
prin(root,num);
}
if(h != 0)
{
node* root=creainpost(1,num,1,num);
prin(root,num);
}
}