序列构建二叉树 - 树的遍历 - 天梯赛 L2-006
题意:
给 定 一 个 n 个 结 点 的 二 叉 树 , 给定一个n个结点的二叉树, 给定一个n个结点的二叉树,
根 据 后 序 遍 历 序 列 和 中 序 遍 历 序 列 , 输 出 层 次 遍 历 的 序 列 。 根据后序遍历序列和中序遍历序列,输出层次遍历的序列。 根据后序遍历序列和中序遍历序列,输出层次遍历的序列。
输入:
首 行 一 个 正 整 数 n , 表 示 结 点 的 数 量 首行一个正整数n,表示结点的数量 首行一个正整数n,表示结点的数量
接 着 一 行 为 树 的 后 序 遍 历 序 列 。 接着一行为树的后序遍历序列。 接着一行为树的后序遍历序列。
最 后 一 行 为 树 的 中 序 遍 历 序 列 。 最后一行为树的中序遍历序列。 最后一行为树的中序遍历序列。
输出:
一 行 数 据 , 表 示 层 次 遍 历 序 列 。 一行数据,表示层次遍历序列。 一行数据,表示层次遍历序列。
输入样例:
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
输出样例:
4 1 6 3 5 7 2
数据范围:
n ≤ 30 n\le 30 n≤30
时间限制: 400 ms
分析:
主要思考一下建数:
无 论 是 先 序 + 中 序 , 还 是 后 序 + 中 序 , 无论是先序+中序,还是后序+中序, 无论是先序+中序,还是后序+中序,
我 们 首 先 要 从 先 序 / 后 序 序 列 中 , 找 到 根 结 点 u , 然 后 在 中 序 序 列 中 找 到 u 结 点 , 将 中 序 序 列 一 分 为 二 。 我们首先要从先序/后序序列中,找到根结点u,然后在中序序列中找到u结点,将中序序列一分为二。 我们首先要从先序/后序序列中,找到根结点u,然后在中序序列中找到u结点,将中序序列一分为二。
然 后 递 归 建 立 左 右 子 树 。 然后递归建立左右子树。 然后递归建立左右子树。
有两个需要注意的地方:
① 、 因 为 我 们 是 递 归 对 两 个 子 区 间 [ l , m ] 和 [ m + 1 , r ] 进 行 操 作 , 边 界 情 况 当 m 是 中 序 序 列 中 的 倒 数 第 二 个 结 点 的 时 候 , m + 1 = r , 此 时 会 返 回 空 结 点 。 但 事 实 上 它 是 叶 子 结 点 , 因 此 , 我 们 建 树 的 区 间 写 成 [ 1 , n + 1 ] 。 ①、因为我们是递归对两个子区间[l,m]和[m+1,r]进行操作,\\\qquad边界情况当m是中序序列中的倒数第二个结点的时候,m+1=r,此时会返回空结点。\\\qquad但事实上它是叶子结点,因此,我们建树的区间写成[1,n+1]。 ①、因为我们是递归对两个子区间[l,m]和[m+1,r]进行操作,边界情况当m是中序序列中的倒数第二个结点的时候,m+1=r,此时会返回空结点。但事实上它是叶子结点,因此,我们建树的区间写成[1,n+1]。
② 、 因 为 本 题 是 后 序 + 中 序 , 后 序 的 遍 历 顺 序 为 : 左 右 根 , 而 我 们 是 从 后 往 前 遍 历 后 序 序 列 来 找 根 的 , 所 以 , 反 过 来 我 们 应 该 优 先 递 归 建 立 好 右 子 树 , 再 递 归 建 立 左 子 树 。 否 则 会 导 致 左 右 孩 子 错 位 。 ②、因为本题是后序+中序,后序的遍历顺序为:左右根,而我们是从后往前遍历后序序列来找根的,\\\qquad所以,反过来我们应该优先递归建立好右子树,再递归建立左子树。\\\qquad否则会导致左右孩子错位。 ②、因为本题是后序+中序,后序的遍历顺序为:左右根,而我们是从后往前遍历后序序列来找根的,所以,反过来我们应该优先递归建立好右子树,再递归建立左子树。否则会导致左右孩子错位。
层次遍历:
非 常 容 易 地 应 当 选 择 b f s 来 输 出 。 非常容易地应当选择bfs来输出。 非常容易地应当选择bfs来输出。
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int N = 40;
int n;
int suf[N], mid[N];
struct node
{
int l, r;
}tr[N*4];
int root;
int ans[N], idx;
int build(int l,int r)
{
if(l>=r) return -1;
int m;
int u=suf[root--];
for(int i=1;i<=n;i++)
if(mid[i]==u)
{
m=i;
break;
}
tr[u].r=build(m+1,r);
tr[u].l=build(l,m);
return u;
}
void bfs(int S)
{
queue<int>Q;
Q.push(S);
while(Q.size())
{
int u=Q.front();
Q.pop();
if(u==-1) continue ;
ans[idx++] = u;
Q.push(tr[u].l), Q.push(tr[u].r);
}
}
int main()
{
cin>>n;root=n;
for(int i=1;i<=n;i++) cin>>suf[i];
for(int i=1;i<=n;i++) cin>>mid[i];
int start=build(1,n+1);
bfs(start);
for(int i=0;i<idx;i++)
printf("%d%c",ans[i],(i==idx-1?'\n':' '));
return 0;
}