UVa 112 - Tree Summing解题报告

题意:

题目要求很简单,意思是要构造一颗二叉树,然后求出所有根结点到叶结点的路径上的数字之和,如果有一个是和题目所给的一样,那么输出yes,否则no

左括号‘(' 表示新建一个子结点, 优先建立左儿子,如果左儿子建立过了,则建立右儿子。 右括号表示退回父结点。如果一对括号内是空的,表示这个结点

也是空的。


思路:

输入比较复杂, 有括号,有数字,又有空格,于是用getchar()一个一个读, 过滤掉空格,保存到一个数组里。然后再处理。  然后利用栈建二叉树, 进行深搜,得到路径和。

另一个思路比较简单,题目给出的数据本身具备前序遍历的顺序,可以直接算路径和。但是我想熟悉一下建二叉树和深度搜索,所以用的是建树深搜的思路。

PS:下面代码有个小bug,如果只有一个叶子节点的情况下,建的二叉树都会把叶子作为左叶子。但是不影响结果。

//112 - Tree Summing
#include <iostream>
#include <cstring>
#include <stack>
using namespace std;

struct Nobe
{
	int value;
	Nobe *left = NULL, *right = NULL;
	bool haveleft = false;//判断是否已有右节点
};
char str[5200];
void DFS(Nobe *, int, int);
bool found;
int main()
{
	freopen("data.txt", "r", stdin);
	int sum;
	while (scanf("%d", &sum) != EOF)
	{
		int bracket = 0, len = 0;
		char c;
		while ((c = getchar()) != '(');//跳过前面的空格
		str[len++] = c;//
		bracket++;

		while (bracket)//括号匹配就退出
		{
			while((c = getchar()) == ' ' || c == '\n');//跳过中间的空格和换行符
			if(c == '(')//
				bracket++;
			if(c == ')')
				bracket--;
			str[len++] = c;
		}

		if(str[0] == '(' && str[1] == ')')//如果是空树
		{
			printf("no\n");
			continue;
		}

		stack<Nobe*> st;

		int x;
		sscanf(&str[1], "%d", &x);//取出字符串中的数字
		Nobe *s = new Nobe;
		s->value = x;
		Nobe *root = s;//初始化根
		st.push(s);
		int i = 1;

		while (!st.empty())
		{
			while(str[i] != '(' && str[i] != ')')//跳过数字占用的字符
				i++;
			if(str[i] == '(' && str[i + 1] != ')')//排除"()"的情况
			{
				sscanf(&str[++i], "%d", &x);
				Nobe *s = new Nobe;
				s->value = x;
				st.push(s);
			}
			else if(str[i] == ')' && str[i - 1] != '(')//排除"()"的情况,出栈建树
			{
				Nobe *p;
				p = st.top();
				st.pop();
				if(!st.empty())
					if(!st.top()->haveleft)//
					{
						st.top()->left = p;
						st.top()->haveleft = true;
					}
					else
						st.top()->right = p;
			}
			i++;
		}

		found = false;
		DFS(root, sum, 0);
		if(found)
			printf("yes\n");
		else
			printf("no\n");
		memset(str, 0, sizeof(str));
	}
	return 0;
}

void DFS(Nobe *s, int sum, int n)
{
	if(found)
		return;
	n += s->value;
	if(s->left == NULL && s->right == NULL)
	{
		if(n == sum)
			found = true;
		return;
	}
	if(s->left)
		DFS(s->left, sum, n);
	if(s->right)
		DFS(s->right, sum, n);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值