洛谷_UVA548_树Tree

1 UVA_树 Tree

1.1 题目描述

PDF

1.2 输入格式

1.3 输出格式

1.4 题面翻译

输入一个二叉树的中序和后序遍历,请你输出一个叶子节点,该叶子节点到根的数值总和最小,且这个叶子是编号最小的那个。

  • 输入

    ​ 您的程序将从输入文件中读取两行(直到文件结尾)。第一行是树的中序遍历值序列,第二行是树的后序遍历值序列。所有值将不同,大于零且小于或等于10000.二叉树的节1<=N<=10000。

  • 输出

    ​ 对于每个树描述,您应该输出最小值路径的叶节点的值。存在多路径最小的情况下,您应该选择终端叶子节点上具有最小值的那条路径,且输出那个最小值的终端叶子。

1.5 样例

1.5.1 样例输入

3 2 1 4 5 7 6
3 1 2 5 6 7 4
7 8 11 3 5 16 12 18
8 3 11 7 16 18 12 5
255
255

1.5.2 样例输出

1
3
255

1.5.3 示例

如第一个样例

3 2 1 4 5 7 6
3 1 2 5 6 7 4

构建出树

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

将一条路上的结点分别相加

  • 4+2+3=9
  • 4+2+1=7
  • 4+7+5=16
  • 4+7+6=17

由此可见,当最后叶子结点为1时,结果最小

因此输出1

1.6 思路

分为3步

  • 读取数据
  • 构建树
  • 查找最小值

1.6.1 读取数据

测试样例中,第一行是树的中序遍历值序列,第二行是树的后序遍历值序列。

  • 传入后序或中序数组
  • 直接读取每一行
  • 而每行数据的每个数字,中间都有一个空格,这里我们不再使用string来存储,而使用stringstream字符串流将读取到的一整行存入缓冲区中
  • 然后重定向缓冲区,每次读取一个整型int的数据,将读取到的一个整型按下标存入原数组
实现
bool ReadLine(int* val)
{
	string line;
	if (!getline(cin, line))	return false;
	stringstream str(line);	//将读取到的line一个字符串流的缓冲区str中
	num = 0;
	int _int;
	while (str >> _int)	//从str缓冲区中读数,每次读一个int
		val[num++] = _int;	//将读取到的int存入val数组中
	return num > 0;
}

1.6.2 构建树

和前序同样的方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

实现
int CreateTree(int len1, int len2, int _num)
{
	if (_num <= 0)	return 0;
	int root = postorder[len2 + _num - 1];
	int len = 0;
	while (inorder[len1 + len] != root)	//计算左子树长度
		len++;
	left_child[root] = CreateTree(len1, len2, len);
	right_child[root] = CreateTree(len1 + len + 1, len2 + len, _num - len - 1);
	return root;
}

1.6.3 找最小值

  • 遍历树,结点数值一直往下加
  • 如果有左右节点,不断往下遍历
  • 如果某个值的左右子树都为空,说明是叶子节点,即最下面的结点,此时可以将该最小值min_val和这条路总和min_sum保存
  • 如果某条路上的总和和其他路相同,则输出这两个最小值中的较小值
实现
void FindMin(int _val, int _sum)
{
	_sum += _val;
	if (!left_child[_val] && !right_child[_val])	//下面没有数据,说明是叶子节点
	{
		if (_sum < min_sum || (_sum == min_sum && _val < min_val))
		{
			min_val = _val;
			min_sum = _sum;
		}
	}
	if (left_child[_val])	FindMin(left_child[_val], _sum);	//结点有左子树
	if (right_child[_val])	FindMin(right_child[_val], _sum);	//结点有右子树
}

1.6.4 main

#include<iostream>
#include<fstream>
#include<sstream>

using namespace std;

const int maxn = 1000 ;
int inorder[maxn], postorder[maxn], left_child[maxn], right_child[maxn];
int num, min_val, min_sum;

int main()
{
	while (ReadLine(inorder))//读取中序
	{
		ReadLine(postorder); //读取后序
		CreateTree(0, 0, num);

		min_sum = 0x7fffffff;
		FindMin(postorder[num - 1], 0);
		cout << min_val << endl;
	} 
	return 0;
}

取中序
{
ReadLine(postorder); //读取后序
CreateTree(0, 0, num);

	min_sum = 0x7fffffff;
	FindMin(postorder[num - 1], 0);
	cout << min_val << endl;
} 
return 0;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值