uva548解题报告

简单描述下原题意,题目给出二叉树按照中序遍历和后序遍历得到的序列, 需要求出从根节点到叶子节点最短路径的叶子的权重。(其实也是它的编号)。如果存在多个解,则选择权重最小的那个。

解题思路: 1.需要解决一个问题:如何根据二叉树的中序遍历和后序遍历还原二叉树。 方法挺简单的,根据它们的各自定义可知,后序遍历中的最后一个数就是根节点值。然后在中序遍历中找到此值,它的左边为左子树,右边为右子树。然后递归求解。 同样的 如果知道二叉树的前序遍历和中序遍历又该如何还原二叉树呢?(中序遍历必须已知,否则二叉树不唯一。想想为什么?)。相仿,先序遍历中第一个值就是根节点。还原二叉树方法同上。

2. 如何求解权重和最小路径。这个只需要进行一次先序遍历,求出根节点到叶子节点所有的解。然后与最优解进行比较即可以得到。


ac代码如下:


#include <iostream>
#include <sstream>

using namespace std;

const int MAXN = 100000;
int in_order[MAXN], post_order[MAXN], lef[MAXN], righ[MAXN];

int NCNT =0; // 存放输入的数据的个数 

// 返回根节点 
int build(int l1, int r1, int l2, int r2) {
	if (l1> r1) 
		return 0;  
	int root = post_order[r2];
	int p = l1;
	while (in_order[p] != root)
		p++; 
	int rCnt = r1 - p;// 计算右子树的个数 
	int lCnt = p - l1; // 左子树个数
	lef[root] = build(l1, l1+lCnt-1, l2, l2+ lCnt-1);
	righ[root]  = build(p+1, r1, l2+lCnt, r2-1); // 要少去最后一个(根) 
	return root;
} 


bool read_list(int *pArr) {
	
	string line;
	if (!getline(cin, line))
		return false;
	stringstream ss(line);
	int x;NCNT = 0;
	while (ss>>x)
		pArr[NCNT++] = x;
	return NCNT>0;
}


// ans为最佳的节点的权重 ans_sum为最佳路径权重和 
int ans, ans_sum =100000;

// 采用先序遍历获取结果 
void dfs(int index, int sum) {
	sum += index;
	if (!lef[index] && !righ[index]) {
		// 此时为叶子节点
		if (sum < ans_sum || (sum == ans_sum && index < ans))  {
			ans = index;
			ans_sum = sum;
		}
	}
	if (lef[index])
		dfs(lef[index], sum);
	if (righ[index])
		dfs(righ[index], sum);
}

int main() {
	
	while (read_list(in_order)) {
		read_list(post_order);
		build(0, NCNT-1, 0, NCNT -1);
		ans_sum = 100000; // 假设为无穷大
		dfs(post_order[NCNT-1], 0); 
		cout<< ans<<endl;
	}
	
	return 0;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值