SWUST OJ#983 利用中序和后序遍历求先序遍历

目录

题目

思路

代码


题目

题目描述

已知二叉树的中序和先序遍历可以唯一确定后序遍历、已知中序和后序遍历可以唯一确定先序遍历,但已知先序和后序,却不一定能唯一确定中序遍历。现要求根据输入的中序遍历结果及后序遍历结果,要求输出其先序遍历结果。

输入

第一行为中序序列 第二行为后续序列

输出

输出为遍历二叉树得到的先序序列 

样例输入

BFDAEGC
FDBGECA

样例输出

ABDFCEG

思路

首先先要把三种遍历弄明白

前序遍历:★根->左孩子->右孩子

中序遍历:左孩子->★根->右孩子

后序遍历:左孩子->右孩子->★根

关键突破点就是遍历时根节点的位置

根据定义,后序遍历的最后一个节点即是根节点

找到根节点,再确定根节点中序序列中的位置,就可以分出左右两棵子树。

然后再在已知的左右子树中,故技重施,再次按照上述步骤,再次

找到左右孩子的根节点,再确定左右孩子的根节点中序序列中的位置,就可以再次分出左右两棵子树。

下面假设某棵树的中序遍历:CBEDFAHG。后序遍历:CEFDBHGA。

分界线标准:

中序:已经判断根节点的左右两边以 | 分开。左边是左子树,右边是右子树。

后序:左右子树以 | 分开。左边是左子树,右边是右子树。zho

[ ]表示当前搜索的区间

红色表示当前步骤的判断,蓝色表示已经搜过的节点。

(注意想明白分界线 | 和 [] ,这对之后代码的理解有极大帮助)

第①步:

中序:[CBEDF | A | HG 后序:[CEFDB | HG A]

可知:第一层就是A,也就是根节点,同时可以得知 A的左孩子(左子树)的元素有:BCDEF,右孩子(右子树)的元素有:GH 。

第②步:

中序:[C | B | EDF]A[HG 后序:[C | EFD B][G] A

可知:第二层是B和G。也就是左右孩子的根节点,同时可以得知 B的左孩子(左子树)的元素只有C,右孩子(右子树)的元素有:DEF。G的左孩子(左子树)只有H,且不存在右孩子。

第③步:

中序:[C]B[E | D | F]A[H]G  后序:[C][E | F D[H] GA

可知:第三层是C,D和H。并且C和H是叶子节点,同时可以得知 D的左孩子是E,右孩子是F。

第④步:

中序:CB[E]D[F]AHG  后序:[E][FDBHGA

可知:第四层是E和F,并且他们都是叶子节点。

所以根据以上分析,按照每一步的步骤,已经可以画出这棵树了

​               A
             / \
        B  G
       / \ /
        C  D H
        / \
       E   F

然而说了这么多,题目是要求我们求出前续遍历呀,但我们只是有能力求出这棵树。

由于暴力建树确实过于复杂,所以直接深搜

//建树
string ord,post;
//so,eo表示搜索ord,也就是搜索中序遍历每一个元素
//so表示从前往后搜,eo表示从后往前搜
//sp,ep表示搜索post,也就是搜索后序遍历每一个元素
//sp表示从前往后搜,ep表示从后往前搜
void dfs(int so,int eo,int sp,int ep) {
    if(so>eo||sp>ep) return;
    for(int i=so,j=sp;i<=eo;i++,j++) {
        if(ord[i]==post[ep]) { //找到相同了,那么他就是根节点
            cout<<post[ep];
            dfs(so,i-1,sp,j-1);//搜索左孩子
            dfs(i+1,eo,j,ep-1);//搜索右孩子
            //为什么这样搜索子区间?想想之前解析过程的分界线。
        }
    }
}

代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;
string ord,post;
void dfs(int so,int eo,int sp,int ep) {
    if(so>eo||sp>ep) return;
    for(int i=so,j=sp;i<=eo;i++,j++) {
        if(ord[i]==post[ep]) {
            cout<<post[ep];
            dfs(so,i-1,sp,j-1);
            dfs(i+1,eo,j,ep-1);
        }
    }
}
int main() {
    cin>>ord>>post;
    dfs(0,ord.size()-1,0,post.size()-1);
    return 0;
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是孤衾呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值