给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。
输入格式:
输入第一行给出一个正整数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
因为树中每个节点的权值不同,所以可以知道每个值在后序遍历和中序遍历中的位置
后序遍历中,所有子节点都在父节点的左边(在左边的节点不一定都是该点的子节点)
中序遍历中,左叶子节点在父节点的左边,右叶子节点在父节点的右边
可以知道,后序遍历的最后一个点为二叉树的根节点,以其为父节点,其范围为[L,R],找到其在中序遍历中的位置p,然后从后序遍历中第一个数开始找,找出最后一个在中序遍历中在p前面的数,其为该点的左节点,可以得到后序遍历左子树的范围为[L,x] x为左节点后序遍历的位置,如果后序遍历父节点前一点不为左节点,则右节点为后序遍历根节点前一点,否则不存在右节点,右子树范围为[x+1,R-1],然后分别以左右节点为父节点继续递推下去,可以建成二叉树。
最后bfs得到二叉树的层序遍历序列
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
const int N = 1e2 + 10;
typedef long long LL;
int n,a[N],b[N],ida[N],idb[N];
int l[N],r[N];
void build(int fa,int L,int R){
if(L>R) return;
int nt = 0;
for(int i=L;i<=R;i++){
if(idb[a[i]]<idb[fa]) nt = a[i];
}
if(nt){
l[fa] = nt;
build(nt,L,ida[nt]-1);
}
if(ida[nt]!=ida[fa]-1&&ida[fa]!=1){
r[fa] = a[ida[fa]-1];
if(nt) build(r[fa],ida[nt]+1,R-1);
else build(r[fa], L, R-1);
}
}
void bfs(){
queue<int>q; q.push(a[n]);
int flag = 0;
while(!q.empty()){
int now = q.front(); q.pop();
if(flag) printf(" "); printf("%d",now); flag = 1;
if(l[now]) q.push(l[now]);
if(r[now]) q.push(r[now]);
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
ida[a[i]] = i;
}
for(int i=1;i<=n;i++){
scanf("%d",&b[i]);
idb[b[i]] = i;
}
build(a[n],1,n-1);
bfs();
return 0;
}