uva548

题目描述:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=19105

/* 1:从中序以及后序恢复二叉树 2:注意getline与sstream用法,容易出错 3:利用getline与sstream读入 */
#include <iostream>
#include <cstdio>
#include <sstream>
#include <string>

using namespace std;
const int maxn = 10000 + 1;

int in_order[maxn], post_order[maxn], lchild[maxn], rchild[maxn];   //lchild[i]代表i节点的左孩子
int n;  //有几个节点
int best, best_sum;     //所求的叶子节点以及最优路径

bool read_input(int * a) {
    string str;
    if(!getline(cin, str))  return false;   //getline与stringstream
    stringstream ss(str);   n = 0;
    int val;
    while(ss >> val)    a[n++] = val;
    return n > 0;
}

int make_tree(int start1, int end1, int start2, int end2) {
    if(start1 > end1)   return 0;

    int root = post_order[end2];

    int p = start1;
    while(in_order[p] != root)  p++;
    int lchild_num = p - start1;    //根节点左孩子的数量

    lchild[root] = make_tree(start1, p-1, start2, start2 + lchild_num - 1);
    rchild[root] = make_tree(p+1, end1, start2 + lchild_num, end2-1);   //递归求出二叉树
    return root;
}

void dfs(int node, int sum) {   //从节点node开始深度遍历每一个叶子,每计算出一个叶子到根节点的权和就将其保存在sum中
    sum += node;    //将起始节点本身的权值也算在里面
    if(!lchild[node] && !rchild[node]) {
        if((sum < best_sum) || (sum == best_sum && node < best)) {  //如果权和相等的话选择节点小的
            best_sum = sum;
            best = node;
        }
    }
    if(lchild[node])    dfs(lchild[node], sum);
    if(rchild[node])    dfs(rchild[node], sum);
}

int main()
{
    while(read_input(in_order)) {
        read_input(post_order);     //依次读入前序跟中序遍历
        make_tree(0, n-1, 0, n-1);      //根据前序跟中序的数组建立二叉树
        best_sum = 100000;
        dfs(post_order[n-1], 0);    //从根节点开始遍历,一开始最优权和设置为0
        printf("%d\n", best);
    }
    return 0;
}

你可能感兴趣的:(二叉树,uva)