例题6-8 树 UVa 548 Tree

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;
}

posted @ 2017-08-02 18:32  ChuningGao  阅读(203)  评论(0编辑  收藏  举报