例题6-8 树(Tree, UVa 548)

欢迎访问我的Uva题解目录哦 https://blog.****.net/ri*qi/article/details/81149109

题目描述

例题6-8 树(Tree, UVa 548)

题意解析

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

算法设计

关于通过中根序列和后根序列重建一棵树的算法可以参考我的博客pat甲级1020. Tree Traversals (25),在此不再赘述。本题与pat甲级1020. Tree Traversals (25)类似,只是需要处理一下输入数据,在重建树的过程中顺便求解符合要求的叶子结点即可。具体实现可见代码。

C++代码

#include<bits/stdc++.h>
using namespace std;
struct Node{
    int data=0,left=-1,right=-1,pathValue=0;//数据域
};
Node inOrder[10005];
int postOrder[10005];
int ans=0,MINpath=INT_MAX;
int split(string&s,bool in){//分割字符串
    int size=0;
    string t="";
    for(int i=0;i<=s.size();++i)
        if(i==s.size()||s[i]==' '){
            if(in){
                inOrder[size].left=inOrder[size].right=-1;
                inOrder[size++].data=stoi(t);
            }else
                postOrder[size++]=stoi(t);
            t="";
        }else
            t+=s[i];
    return size;
}
int createTree(int left,int right,int root,int index){//根据中序序列、后序序列重建树
    if(left>right)
        return -1;
    int i=left;
    while(inOrder[i].data!=postOrder[root])//查找根在中根序列中的位置
        ++i;
    //更新从根结点到该结点的路径权值
    inOrder[i].pathValue=(index!=-1)?inOrder[index].pathValue+inOrder[i].data:inOrder[i].data;
    inOrder[i].left=createTree(left,i-1,root-1+i-right,i);//递归重建左子树
    inOrder[i].right=createTree(i+1,right,root-1,i);//递归重建右子树
    if(inOrder[i].left==-1&&inOrder[i].right==-1//是叶结点
        &&(inOrder[i].pathValue<MINpath//从根结点到该结点的路径权值小于当前最大路径权值
           ||(inOrder[i].pathValue==MINpath&&inOrder[i].data<inOrder[ans].data))){
            ans=i;//更新最小路径权值的叶子结点
            MINpath=inOrder[i].pathValue;//更新最小路径权值
        }
    return i;
}
int main(){
    string line;
    while(getline(cin,line)){
        int n=split(line,true);
        getline(cin,line);
        n=split(line,false);
        MINpath=INT_MAX;
        createTree(0,n-1,n-1,-1);
        printf("%d\n",inOrder[ans].data);
    }
    return 0;
}