uva536-Tree Recovery-二叉树遍历

与算法入门经典中的例题6-8,uva548类似。本题是已知先序和中序遍历求后序遍历。
先序中序后序遍历都是根据递归定义的深度优先(DFS)遍历。如下所示:

PreOrder(T) = T 的根节点 + PreOrder(T 的左子树) + PreOrder(T 的右子树)
InOrder(T) = InOrder(T 的左子树) + T 的根节点 + InOrder(T 的右子树)
PostOrder(T) = PostOrder(T 的左子树) + PostOrder(T 的右子树) + T 的根节点

样例:先序:DBACEGF 中序: ABCDEFG
因为在先序遍历中的第一个字母就是根,所以在中序遍历中找到根,然后在中序遍历中
根的左右两边就是左右子树,然后根据左子树字母的个数在先序遍历(从左边开始数)中切分,
并且切分后第一个还是左子树的根,然后再在中序遍历的左子树中找根,继续反复。右子树类似。

例如:先序遍历中第一个字母‘D’肯定为整棵树的根, 在中序遍历中找到‘D’,切分,左子树剩下”ABC”, 右子树剩下“EFG”, 然后(先右子树)右子树有三个,在先序遍历中切分,把’D’去掉。先序中的右子树为“EGF”, 左子树“BAC”。 先序右子树的第一个字母‘E’为右子树的根,在中序遍历中找到, 切分 右子树的右子树剩下“FG”左子树“”, 这样子树有两个字母, 继续在先序中看根,为‘G’,在中序中找,最后的左子树为“F”,右子树“”, 同样的方法遍历左子树(“BAC”), 这样整个树就建立起来了。

将每次找的根按顺序存在一个数组里,就成了“D->E->G->F->B->C->A”。
将此序列倒过来即是后序遍历。注意: 这里是先递归右子树才会有后序遍历的倒序。
以下是别人的代码,我给简化注释了一下。

#include <iostream>
#include <vector>
#include <string>
using namespace std;

vector <char > post;
string pre, mid;

void solve(int l1, int r1, int l2, int r2)
{
//当遍历到最后一个时,l1 = r1;l2= r2;
//这时候cnt = 0;再进行右序遍历时就该退出了,并且,这时候l1传过来的值会+1比r1大 
    if(r1 < l1)
        return ;
    post.push_back(pre[l1]);//将根按顺序存在数组里
    int q = l2;
    while(pre[l1] != mid[q]) q++;//在中序中找到根
    int cnt = q - l2;//遍历的个数
    //首先遍历右子树
    //右子树先序开始位置,结束位置,中序开始位置,结束的位置
    solve(l1 + cnt+1, r1, q+1, r2);
    //遍历左子树
    //左子树先序开始位置,结束位置,中序开始位置,结束的位置
    solve(l1+1, l1+cnt, l2, q-1);
}

int main()
{
    while(cin >> pre >> mid)
    {
        post.clear();
        solve(0, pre.size()-1, 0, mid.size()-1);
        //倒序输出
        for(int i = post.size() - 1; i >= 0; i--)
        {
            cout << post[i];
        }
        cout << endl;
    }
    return 0;
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值