您的位置:首页 > 其它

[UVA548]Tree[根据中序后序构建树][UVA536]Tree Recovery[根据前序中序构建树]

2015-07-24 19:18 393 查看
题目链接:[UVA548]Tree[根据中序后序构建树]

题意分析:给出树的中序后序,节点编号等于节点的权值,问:那个叶子到根节点的权值和最小,输出号码最小的那个叶子

解题思路:把树建立起来,然后从根节点开始向下进行求和操作,每个节点的权值和等于当前权值加上父节点权值和。

个人感受:人生第一道建树题TAT参考了别人的代码,算是略理解了。感觉树是个神奇的东西。

然后是这道题:[UVA536]Tree Recovery[根据前序中序构建树] 。两道题真是让我醉了。两者构建树还是有点点区别的,害我自己电脑上debug了很久。这道题还涉及到一个后序遍历的问题,看看码就能了解了。

具体代码如下:

[UVA548]Tree[根据中序后序构建树]

#include<iostream>
#include<cstdio>
#include<cstring>
#include<sstream>
#include<string>
#include<cmath>
#include<algorithm>
#include<map>
#include<set>
#include<stack>
#include<queue>
#include<bitset>
using namespace std;
typedef vector<int> V;
const int MAXN = 1e4 + 111;
int va[MAXN], lch[MAXN], rch[MAXN]; //lch、rch分别为i点的左右节点坐标 
V in, pos; //中序,后序 
string s;
int root;

void init() //初始化 
{
	int a;
	memset(lch, 0, sizeof lch);
	memset(rch, 0, sizeof rch);
	memset(va, 0, sizeof va);
	stringstream ss(s);
	in.clear(), pos.clear();
	while (ss >> a) in.push_back(a);
	getline(cin, s);
	stringstream ss2(s);
	while (ss2 >> a) pos.push_back(a);
}

void build(V& a, V& b)
{
	if (a.size() <= 1 || b.size() <= 1) return;
	int rt = b.back();
	V::iterator it = find(a.begin(), a.end(), rt); //在中序中找到根节点 
	V la(a.begin(), it); //左子树的中序 
	V ra(it + 1, a.end());   //右子树的中序 
	int l = la.size(), r = ra.size();
	V lb(b.begin(), b.begin() + l ); //左子树的后序 
	V rb(b.begin() + l, b.begin() + l + r); //右子树的后序 
	if (!lb.empty()) lch[rt] = lb.back(); //标记左右节点 
	if (!rb.empty()) rch[rt] = rb.back();
	build(la, lb); build(ra, rb); //递归建树 
}

int main()
{
#ifdef LOCAL
	freopen("C:\\Users\\apple\\Desktop\\in.txt", "r", stdin);
#endif
	while (getline(cin, s))
	{
		init();
		build(in, pos);
		root = pos.back();
		queue<int> q; q.push(root);
		va[root] = root;
		int mi = 0x3f3f3f3f, ans = 0x3f3f3f3f;  //mi:最小下标 ,ans:最小权值和 
		while (!q.empty())  //当前节点的权值等于当前节点本身值加上父节点权值 
		{
			int cur = q.front(); q.pop();
			int l = lch[cur], r = rch[cur];
			if (l)
			{
				va[l] = l + va[cur];
				q.push(l);
			}
			if (r)
			{
				va[r] = r + va[cur];
				q.push(r);
			}
			if (!l && !r)
			{
				if (ans > va[cur])
				{
					ans = va[cur];	
					mi = cur;
				}
				if (ans == va[cur] && mi > cur) 
					mi = cur;
			}
		}
		cout << mi << '\n';
	}
	return 0;
}


[UVA536]Tree Recovery[根据前序中序构建树]

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<sstream>
#include<cmath>
#include<algorithm>
#include<map>
#include<set>
#include<stack>
#include<queue>
#include<bitset>
using namespace std;
typedef vector<int> V;
const int MAXN = 40;
int lch[MAXN], rch[MAXN];
string sa, sb;
V pre, in;

void init()
{
	pre.clear(), in.clear();
	memset(lch, 0, sizeof lch);
	memset(rch, 0, sizeof rch);
	for (int i = 0; sa[i]; ++i) pre.push_back(sa[i] - 'A' + 1);//下标从1开始
	for (int i = 0; sb[i]; ++i) in.push_back(sb[i] - 'A' + 1); 
}

void build(V& a, V& b)
{
	if (a.size() <= 1 || b.size() <= 1) return;
	int rt = a.front();
	V::iterator it = find(b.begin(), b.end(), rt);
	V lb(b.begin(), it);
	V rb(it + 1, b.end()); //中序左右子树 
	int l = lb.size(), r = rb.size();
	//cout << l << ' ' << r << endl;
	V la(a.begin() + 1, a.begin() + l + 1); // <-就是这里。如果不加一下个根节点还是最底层的那个根节点 
	V ra(a.begin() + l + 1, a.begin() + l + r + 1);
	if (!la.empty()) lch[rt] = la.front();
	if (!ra.empty()) rch[rt] = ra.front();
	build(la, lb); build(ra, rb);
}

void pos(int rt)
{
	if (rt != 0)
	{
		pos(lch[rt]);
		pos(rch[rt]);
		printf("%c", rt - 1 + 'A');
	}
}

int main()
{
#ifdef LOCAL
	freopen("C:\\Users\\apple\\Desktop\\in.txt", "r", stdin);
#endif
	while (cin >> sa >> sb)
	{
		//cout << sa << ',' << sb << '\n';
		init();
		//cout << "inital ok" << endl;
		build(pre, in);
		//cout << "build ok" << endl;
		int root = pre.front();
		pos(root);
		cout << '\n';
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: