序列构建二叉树 - 树的遍历 - 天梯赛 L2-006

序列构建二叉树 - 树的遍历 - 天梯赛 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 n30

时间限制: 400 ms


分析:

主要思考一下建数:

无 论 是 先 序 + 中 序 , 还 是 后 序 + 中 序 , 无论是先序+中序,还是后序+中序, ++

我 们 首 先 要 从 先 序 / 后 序 序 列 中 , 找 到 根 结 点 u , 然 后 在 中 序 序 列 中 找 到 u 结 点 , 将 中 序 序 列 一 分 为 二 。 我们首先要从先序/后序序列中,找到根结点u,然后在中序序列中找到u结点,将中序序列一分为二。 /uu

然 后 递 归 建 立 左 右 子 树 。 然后递归建立左右子树。

有两个需要注意的地方:

① 、 因 为 我 们 是 递 归 对 两 个 子 区 间 [ 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]mm+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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值