L2-006 树的遍历
https://pintia.cn/problem-sets/994805046380707840/problems/994805069361299456
题意
给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。
输入
输入第一行给出一个正整数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
分析
使用后序遍历和中序遍历进行构造二叉树的模板题,递归创建树,由于结点键值不重复,因此可以使用映射map<int,int>L,R,来表示结点的连接关系,L[x]=y,表示键值为x的结点的左孩子为y,先通过后序遍历找到根,根据根的键值在中序遍历中找到它的位置,它之前的结点构成根的左子树,它之后的结点构成根的右子树,递归构建。构造成功后进行层次遍历即可。
C++程序
#include<iostream>
#include<queue>
#include<map>
using namespace std;
const int N=40;
map<int,int>L,R;
int post[N],in[N];
//l,r表示后序遍历post数组的区间,l2,r2表示中序遍历in数组的区间
int build(int l,int r,int l2,int r2)
{
if(l>r) return 0;
int root=post[r];
int mid;
for(mid=l2;mid<=r2&&in[mid]!=root;mid++);//在中序遍历中找到根结点的下标
L[root]=build(l,l-l2+mid-1,l2,mid-1);//将左子树分出来
R[root]=build(r-r2+mid,r-1,mid+1,r2);//将右子树分出来
return root;
}
//层次遍历
void bfs(int root)
{
queue<int>q;
q.push(root);
bool flag=false;
while(!q.empty())
{
int top=q.front();
if(flag) printf(" ");
printf("%d",top);
flag=true;
q.pop();
if(L[top]) q.push(L[top]);
if(R[top]) q.push(R[top]);
}
printf("\n");
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&post[i]);
for(int i=0;i<n;i++)
scanf("%d",&in[i]);
bfs(build(0,n-1,0,n-1));
return 0;
}