数据结构 uva 548-Tree

本文介绍了解决UVA在线裁判489号问题的方法。通过中序和后序遍历构建二叉树,并使用深度优先搜索找出从根到叶子节点路径上值最小的叶子节点。

 

题目链接:

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=489

 

题目意思:

一颗二叉树用中序和后序遍历给出,让你求出从根到叶子节点的总和最小的叶子节点的值。

 

解题思路:

根据中序遍历序列和后序遍历序列,构建二叉树,然后用dfs求总和最小的那个叶子节点的值。

后序遍历的最后一个节点一定是根节点,根节点在中序中的位置之前的节点一定在这个根的左树上,根节点在中序的位置之后的节点一定在这个根的右树上。

据此可以用递归来建这个树,注意有的节点没有左孩子或右孩子。

 

代码:

#include<iostream>
#include<cstdio>
#define INF (1<<20)
using namespace std;

int inorder[11000],suborder[11000];


struct Node
{
	int value,left,right;
}tree[11000];

int num,Min,ans;

int build(int start1,int end1,int start2,int end2)  //建立一颗二叉树
{
	if(end1<start1||end2<start2)  //没有左孩子或右孩子
		return 0;
	tree[++num].value=suborder[end2]; //将值存入树节点中
	int temp=num;
	

	if(start1==end1)   //到达叶子节点
	{
		tree[num].left=-1;
		return num;
	}

	int i;
	for(i=start1;i<=end1;i++)  //遍历中序,找到当前节点的位置
		if(inorder[i]==suborder[end2])
			break;

	tree[temp].left=build(start1,i-1,start2,i-start1+start2-1); //建立当前节点的左树,注意不能用tree[num].left,应为num为全局变量,会改变直至最后,wa了好多次
	tree[temp].right=build(i+1,end1,i-start1+start2,end2-1);  //建立当前节点的右树


	return temp; //注意是return 当前的节点编号,wa了好几次

}

void DFS(int cur,int sum) //dfs求和
{
	sum+=tree[cur].value;  

	if(tree[cur].left==-1)  //如果到达了叶子节点,则返回
	{

		if(sum<Min)
		{
			Min=sum;
			ans=tree[cur].value;
		}
		return ;
	}
	if(tree[cur].left==0&&tree[cur].right!=0)  //遇到没有孩子的情况,不能全盘不做,要考虑还有另一个孩子
	{
		DFS(tree[cur].right,sum);
		return ;
	}
	if(tree[cur].right==0&&tree[cur].left!=0)
	{
		DFS(tree[cur].left,sum);
		return ;
	}
	if(tree[cur].right==0&&tree[cur].left==0) //既没有做孩子又没有右孩子
		return;

	

	DFS(tree[cur].left,sum);  //从左孩子dfs
	DFS(tree[cur].right,sum); //从右孩子dfs

	return ;
}



int main()
{
	char c;
	int len1=0,len2=0;

	while(scanf("%d%c",&inorder[++len1],&c)!=EOF)  //注意读入的方式
	{
		while(c!='\n')
			scanf("%d%c",&inorder[++len1],&c);

		do
		{
			scanf("%d%c",&suborder[++len2],&c);
		}while(c!='\n');

		num=0;
		build(1,len1,1,len2); //建树

		Min=INF;
		DFS(1,0);  //求最大的总和的叶子节点的值

		printf("%d\n",ans); 
		len1=len2=0;   //注意每次清零
	}
	
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值