洛谷题单指南-二叉树-P1827 [USACO3.4] 美国血统 American Heritage

原题链接:https://www.luogu.com.cn/problem/P1827

题意解读:已知二叉树的中序、前序遍历结果,求后序遍历结果。

解题思路:

已知中序、前序(或后序)遍历的结果,要求后序(或前序)遍历的结果,本质上就是借助于已知的前序(或后序)遍历结果寻找二叉树的根,

再根据根节点将中序序列划分成两部分,左边是左子树的中序序列,右边是右子树的中序序列,

同样,前序(或后序)序列除去根节点,也可以划分成两部分,前一部分对应左子树的前序(或后序)序列,后一部分对应右子树的前序(或后序)序列。

再递归的去处理左子树序列、右子树序列

输出每次找到的根的值即可实现遍历,输出的位置如在递归之前,则为前序遍历,输出的位置如在递归之后,则为后序遍历。

注意:此类题,必须知道中序遍历的结果,如果仅仅有前序、后序是无法计算中序的,因为无法确定左、右子树序列的范围。

下面介绍二叉树还原的过程:

中序:ABEDFCHG

前序:CBADEFGH

 

第一步:根据前序找到根C

二叉树形如:

  C

           /        \

ABEDF(中)     HG(中)

BADEF(前)     GH(前)

 

第二步:根据前序找BADEF的根B, GH的根G

二叉树形如:

            C

    /               \

   B                 G

 /   \             /

A  EDF(中)  H

    DEF(前)

 

第三步:根据前序找到DEF里的根D

二叉树形如:

        C

     /     \

   B        G

 /   \      /

A    D  H

     /  \

    E   F

100分代码:

#include <bits/stdc++.h>
using namespace std;

string in, pre;

//in_l:中序序列的起点,in_r:中序序列的终点,pre_l:前序序列的起点,pre_r:前序序列的终点
void postorder(int in_l, int in_r, int pre_l, int pre_r)
{
    if(in_l > in_r) return; //没有节点
    //先通过前序序列找根节点
    int root = pre_l; //根节点位置为前序序列起点

    //在中序序列中找到根节点的位置
    int i = in_l;
    while(in[i] != pre[root]) i++;

    // in_l ~ i-1即左子树的中序序列, 一共有i-in_l个元素
    // i+1 ~ in_r即右子树的中序序列, 一共有in_r-i个元素
    // pre_l+1 ~ pre_l+i-in_l即左子树的前序序列
    // pre_l+i-in_l+1 ~ pre_r即右子树的前序序列
    postorder(in_l, i - 1, pre_l + 1, pre_l + i - in_l); //对左子树递归调用找根
    postorder(i + 1, in_r, pre_l + i - in_l + 1, pre_r); //对右子树递归调用找根
    cout << pre[root]; //递归之后输出根即后序遍历
}

int main()
{
    cin >> in >> pre;
    postorder(0, in.size() - 1, 0, pre.size() - 1);
    return 0;
}

 

posted @ 2024-03-14 10:43  五月江城  阅读(39)  评论(0编辑  收藏  举报