二叉树遍历

题目描述

二叉树的前序、中序、后序遍历的定义: 前序遍历:对任一子树,先访问跟,然后遍历其左子树,最后遍历其右子树; 中序遍历:对任一子树,先遍历其左子树,然后访问根,最后遍历其右子树; 后序遍历:对任一子树,先遍历其左子树,然后遍历其右子树,最后访问根。 给定一棵二叉树的前序遍历和中序遍历,求其后序遍历(提示:给定前序遍历与中序遍历能够唯一确定后序遍历)。

输入描述:

两个字符串,其长度n均小于等于26。
第一行为前序遍历,第二行为中序遍历。
二叉树中的结点名称以大写字母表示:A,B,C....最多26个结点。

输出描述:

输入样例可能有多组,对于每组测试样例,
输出一行,为后序遍历的字符串。
示例1

输入

ABC
BAC
FDXEAG
XDEFAG

输出

BCA
XEDGAF

这道题的结局思路(我觉得)采用了分治的策略。

已知二叉树的前序序列和中序序列,求后序序列。对于一串前序序列,可知第一个结点是根节点,那么将该结点放置在后序序列的最后。

然后在中序序列里寻找该根结点的位置k,那么k之前的序列即为左孩子,k之后的即为右孩子,并且可以求得左右孩子的长度,也就知道了在前序序列里左右孩子的位置。

对左右孩子依旧采取这种策略,直到后序序列被填满,即可得到后序序列。


在求后序序列时是递归求解,其终结递归条件需要注意。一开始我以为是前序序列首位置等于前序序列末位置时即停止。后来发现不对,如果一个序列没有左孩子,那么放置根节点后,其左孩子长度为0,新的前序序列首位置加1,末位置不变,导致首位置直接大于末位置。

所以终结递归条件应是,如果首位置大于末位置即停止。

代码:

#include <iostream>
#include <string>
#include <stdio.h>

using namespace std;
string pre;
string in;
char post[26];

  /*
   *  low_pre  表示前序序列首位置
   *  high_pre 表示前序序列末位置
   *  其余类似
   */


void postSearch(int low_pre,int high_pre,int low_in, int high_in,int low_post,int high_post)
{
    if(low_pre > high_pre)
        return ;
    char c = pre[low_pre];
    post[high_post] = c;          //把先序序列第一个字符(也就是树根)赋值给后序序列的最后一个位置

    int k=0;
    while(in[low_in+k] != c )    //寻找先序序列树根在中序序列中的位置
        k++;                     // 由此可以知道,该位置前面的序列是树根的左孩子,后面是树根的右孩子
                                 // 可以知道 左孩子的长度为k,把整个序列分成两部分
    //此时后序序列为 (low_post,low_post+k-1) (low_post+k,high_post-1)
    //中序序列 (low_in,low_in+k-1),(low_in+k+1,high_in)
    //前序序列变成了 (low_pre+1,low_pre+k),(low_pre+k+1,high_pre)
    postSearch(low_pre+1,low_pre+k,low_in,low_in+k-1,low_post,low_post+k-1);
    postSearch(low_pre+k+1,high_pre,low_in+k+1,high_in,low_post+k,high_post-1);
}

int main()
{
    while(cin>>pre)
    {
        int i;
        cin>>in;
        int length = pre.size();
        postSearch(0,length-1,0,length-1,0,length-1);
        printf("%s",post);
        cout<<endl;
    }

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值