uva 548 利用中序与后序遍历还原二叉树

uva 548

给出一棵树的中序与后序遍历结果,其中每个节点的值不重复,求根节点到叶子节点的最短权和(路径上所有节点的权相加)对应的叶子节点。如果存在多个,则输出叶子权值最小的那个。

  • 后序遍历:左子树后序遍历-右子树后序遍历-树的根节点,直接得到根节点
  • 中序遍历:左子树中序遍历-根节点-右子树中序遍历,在掌握根节点的位置和树的中序遍历结果时,可以求出左右子树的节点数
  • 同时利用notleaf做标记:已经判断有子树的,标true。这个数组的首尾封住,可以避免单独判断出界问题
  • 遍历一个树的步骤:
    1. 给出其后序遍历,得到根节点
    2. 在中序遍历中得到左右子树的节点数,就可以确定左右子树的后序遍历,形成递归
#include <iostream>
#include <cstring>

using namespace std;

#define MAXSIZE 10000

bool notleaf[MAXSIZE + 2];
int inoder[MAXSIZE], postorder[MAXSIZE];

int cnt;
int smallest, with;

int whichRoot(int k)
{
    int ret = 0;
    for (; inoder[ret] != k; ++ret)
        ;
    return ret;
}
int left_cnt(int cur)
{
    int ret = 0;
    while (!notleaf[cur--])
        ++ret;
    return ret;
}

void explore(int total, int b, int e)
{
    //这个子树不存在
    if (b > e)
        return;

    int root = postorder[e];
    total += root;

    //叶子节点
    if (b == e)
    {
        if (smallest >= total)
        {
            smallest = total;
            with = min(smallest, root);
        }
        return;
    }
    int pos = whichRoot(root);
    notleaf[pos + 1] = true; //至少存在一个子树
    int lcnt = left_cnt(pos);
    explore(total, b, b + lcnt - 1); //左子树
    explore(total, b + lcnt, e - 1); //右子树
}

int main()
{
    while (1)
    {
        cnt = 0;
        smallest = MAXSIZE * MAXSIZE;
        with = MAXSIZE;
        while (1)	//输入
        {
            if (!(cin >> inoder[cnt++]))
                return 0;
            if (getchar() == '\n')
                break;
        }
        for (int i = 0; i != cnt; ++i)
            cin >> postorder[i];
        memset(notleaf, 0, (cnt + 2) * sizeof(bool));
        notleaf[0] = notleaf[cnt + 1] = true;
        explore(0, 0, cnt - 1);
        cout << with << '\n';
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值