Tree UVA - 548 (二叉树的遍历互求)

题意:给一棵点带权(权值各不相同,都是小于10000的正整数)的二叉树的中序和后序遍历,找一个叶子使得它到跟的路径上的权和最小。如果有多解,该叶子本身的权应该尽量小。输入中每两行表示一棵树,其中第一行为中序遍历,第二行为后序遍历。

【分析】

后序遍历的第一个字符就是根,因此只需要在中序遍历中找到它,就知道左右子树的中序和后序遍历了。这样就可以先把二叉树构造出来,然后在执行一次递归遍历,找到最优解。

提示6-19:给定二叉树的中序遍历和后序遍历,可以构造出这棵二叉树。方法是根据后序遍历找到树根,然后在中序遍历中国找到树根,从而找出左右子树的结点列表,然后递归构造左右子树。


数组模拟:

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 10005;
const int INF = 100000010;
int n, best, best_num, in_order[MAXN], post_order[MAXN];
int root, cnt;
struct Node
{
    int Left, Right;
    Node(): Left(0), Right(0) {}
}tree[MAXN];
bool read_list(int *a)//读取输入
{
    string line;
    if (!getline(cin, line)) return false;
    stringstream ss(line);
    n = 0; int x;
    while (ss >> x) a[n++] = x;
    return n > 0;
}
//把in_order[L1..R1]和post_order[L2..R2]建成一棵二叉树,返回树根
int build(int L1, int R1, int L2, int R2)
{
    if (L1 > R1) return 0;//空树
    int u = post_order[R2];
    int p = L1;
    while (in_order[p] != u) p++;
    int cnt = p - L1;//左子树结点个数
    tree[u].Left  = build(L1, p - 1, L2, L2 + cnt - 1);//左
    tree[u].Right = build(p + 1, R1, L2 + cnt, R2 - 1);//右
    return u;
}
void dfs(int u, int sum)
{
    sum += u;
    if (!tree[u].Left && !tree[u].Right)//叶子结点
    {
        if (best_num > sum || best_num == sum && best < u)
            best = u, best_num = sum;
    }
    if (tree[u].Left) dfs(tree[u].Left, sum);
    if (tree[u].Right) dfs(tree[u].Right, sum);

}
int main()
{
    while(read_list(in_order) && read_list(post_order))
    {
        cnt = 1;
        root = build(0, n-1, 0, n-1);
        best_num = INF;
        dfs(root, 0);
        cout << best << "\n";
    }
    return 0;
}
/*
3 2 1 4 5 7 6
3 1 2 5 6 7 4
7 8 11 3 5 16 12 18
8 3 11 7 16 18 12 5
255
255
*/


动态创建:

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 10005;
const int INF = 100000010;
int n, best, best_num, in_order[MAXN], post_order[MAXN];
struct Node
{
    int v;
    Node *Left, *Right;
    Node(): v(0), Left(nullptr), Right(nullptr) {}
};
bool read_list(int *a)//读取输入
{
    string line;
    if (!getline(cin, line)) return false;
    stringstream ss(line);
    n = 0; int x;
    while (ss >> x) a[n++] = x;
    return n > 0;
}
Node* root;
//把in_order[L1..R1]和post_order[L2..R2]建成一棵二叉树,返回树根
Node* build(int L1, int R1, int L2, int R2)
{
    if (L1 > R1) return nullptr;//空树
    Node* u = new Node();
    u->v = post_order[R2];
    int p = L1;
    while (in_order[p] != u->v) p++;
    int cnt = p - L1;//左子树结点个数
    u->Left  = build(L1, p - 1, L2, L2 + cnt - 1);//左
    u->Right = build(p + 1, R1, L2 + cnt, R2 - 1);//右
    return u;
}
void dfs(Node* u, int sum)
{
    sum += u->v;
    if (u->Left == nullptr && u->Right == nullptr)//叶子结点
    {
        if (best_num > sum || best_num == sum && best < u->v)
            best = u->v, best_num = sum;
    }
    if (u->Left != nullptr) dfs(u->Left, sum);
    if (u->Right != nullptr) dfs(u->Right, sum);

}
void remove_tree(Node* u)
{
    if (u == nullptr) return ;
    remove_tree(u->Left);
    remove_tree(u->Right);
    delete u;
}
int main()
{
    while(read_list(in_order) && read_list(post_order))
    {
        remove_tree(root);
        root = build(0, n-1, 0, n-1);
        best_num = INF;
        dfs(root, 0);
        cout << best << "\n";
    }
    return 0;
}
/*
3 2 1 4 5 7 6
3 1 2 5 6 7 4
7 8 11 3 5 16 12 18
8 3 11 7 16 18 12 5
255
255
*/



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值