例题6-8 树 UVa 548 Tree

来源:互联网 发布:ug8.钻孔怎么编程 编辑:程序博客网 时间:2024/06/07 22:48

1.      题目描述:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=489

 

 

2.      对于二叉树T,可以递归定义它的先序遍历、中序遍历和后序遍历:

a)        PreOrder(T)=T的根结点+ PreOrder(T的左子树)+ PreOrder(T的右子树)

b)        InOrder(T)= InOrder(T的左子树)+T的根结点+InOrder(T的右子树)

c)        PostOrder(T)= PostOrder(T的左子树)+ PostOrder(T的右子书)+T的根结点

d)        这三种遍历都属于递归遍历,或者说深度优先遍历(DFS),因为它总是优先往深处访问

 

 

3.      解题思路:

a)        后序遍历的最后一个字符是根,且各个结点的权值各不相同且都是整数,因此只需在中序遍历中找到它,从而得知左右子树的中序和后序遍历。然而,将二叉树构造出来,再执行一次递归遍历,以找到最优解

b)        建立read_list函数,用来读入中序遍历和后序遍历的二叉树并存储到对应的数组中

c)        用DFS找最优解

 

 

4.       

#include <iostream>#include <cstdio>#include <cstring>#include <sstream>#include <algorithm>using namespace std;const int maxn=10000+10;//因为各个结点的权值各不相同且都是正整数,因此直接用权值作为结点编号 int in_order[maxn],post_order[maxn],lch[maxn],rch[maxn];int n;//n为全局变量,记录结点个数 int best,best_sum;//目前为止的最优解和对应的权和 bool read_list(int *a){string line;if(!getline(cin,line))return false;//输入错误stringstream ss(line);//从string类型的变量line中读取n=0;int x;while(ss>>x)a[n++]=x;//n为结点个数return n>0;//true }//把in_order[L1...R1]和post_order[L2...R2]建成二叉树,并返回树根int build(int L1,int R1,int L2,int R2){if(R1<L1)//判断是否为空树 return 0; int root=post_order[R2];int p=L1;while(in_order[p]!=root)//如果没有找到根结点就继续找 p++;int cnt=p-L1;//左子树的节点个数lch[root]=build(L1,p-1,L2,L2+cnt-1);rch[root]=build(p+1,R1,L2+cnt,R2-1);return root;} void dfs(int u,int sum){sum+=u;if(!lch[u]&&!rch[u]){//叶子if(sum<best_sum || (sum==best_sum && u<best)){best=u;best_sum=sum;} }if(lch[u])dfs(lch[u],sum);if(rch[u])dfs(rch[u],sum);}int main(){while(read_list(in_order)){//将中序遍历存入in_order中 read_list(post_order);//将第二行的后续遍历存入post_order中build(0,n-1,0,n-1); best_sum=10000000000;dfs(post_order[n-1],0);cout<<best<<endl;}return 0;}