POJ 1145 Tree Summing
| Time Limit: 1000MS | Memory Limit: 10000K | |
| Total Submissions: 7698 | Accepted: 1737 |
Description
This problem deals with determining whether binary trees represented as LISP S-expressions possess a certain property.
Given a binary tree of integers, you are to write a program that determines whether there exists a root-to-leaf path whose nodes sum to a specified integer. For example, in the tree shown below there are exactly four root-to-leaf paths. The sums of the paths are 27, 22, 26, and 18. 
Binary trees are represented in the input file as LISP S-expressions having the following form.
empty tree ::= () tree ::= empty tree (integer tree tree)
The tree diagrammed above is represented by the expression (5 (4 (11 (7 () ()) (2 () ()) ) ()) (8 (13 () ()) (4 () (1 () ()) ) ) )
Note that with this formulation all leaves of a tree are of the form (integer () () )
Since an empty tree has no root-to-leaf paths, any query as to whether a path exists whose sum is a specified integer in an empty tree must be answered negatively.
Input
Output
Sample Input
22 (5(4(11(7()())(2()()))()) (8(13()())(4()(1()()))))
20 (5(4(11(7()())(2()()))()) (8(13()())(4()(1()()))))
10 (3
(2 (4 () () )
(8 () () ) )
(1 (6 () () )
(4 () () ) ) )
5 ()
Sample Output
yes
no
yes
no
题目大意:输入一个整数sum,后面是一串字符,代表一颗二叉树,二叉树结点类型为(integer () () ),问是否存在一条从根节点到叶子节点的路径上数字之和为sum.
解题方法:先通过字符串构造一颗二叉树,然后通过二叉树的非递归后序遍历判断是否存在解,这道题费了我九牛二虎之力,终于AC了。
#include <stdio.h>
#include <iostream>
#include <string.h>
using namespace std; char str[]; typedef struct node
{
int data;
node *lchild;
node *rchild;
bool bleftvisted;//用于标记左孩子是否访问过
node()
{
lchild = rchild = NULL;
bleftvisted = false;
}
}TreeNode; //删除二叉树
void DeleteNode(TreeNode *pRoot)
{
if (pRoot != NULL)
{
DeleteNode(pRoot->lchild);
DeleteNode(pRoot->rchild);
}
delete pRoot;
} //创建一颗二叉树
void CreateTree(TreeNode *&pRoot)
{
TreeNode *StackNode[], *p;//StackNode为保存二叉树节点的栈
char StackCh[];//保存字符的栈
int topnode = -, topch = -, num, flag = , j = ;
bool isnum = false;
char ch;
num = ;
isnum = false ;
while(str[j] != '\0')
{
ch = str[j];
switch(ch)
{
case ')'://如果是右括号则把相应配对的左括号和他们之间的数字出栈
{
bool bflag = false;
while(StackCh[topch] != '(')
{
//如果遇见了数字,则必须让保存二叉树节点的栈退栈,
//表明该节点已经构造完了
if (isdigit(StackCh[topch]))
{
bflag = true;
}
--topch;
}
if (bflag)
{
--topnode;
}
j++;
--topch;
//如果某个节点的左孩子节点为空,则把左孩子访问标记为true
if (topnode >= )
{
StackNode[topnode]->bleftvisted = true;
}
break;
}
case '('://遇到左括号,直接入栈
StackCh[++topch] = ch;
j++;
break;
case '-':
flag = -;
j++;
break;
default://遇到数字,新建一个节点,然后插入到相应的位置
num = num * + (ch - '');
StackCh[++topch] = ch;
while(isdigit(ch = str[++j]))
{
num = num * + (ch - '');
StackCh[++topch] = ch;
}
p = new TreeNode;
p->data = num * flag;
flag = ;
num = ;
if (pRoot == NULL)//如果根节点为空,则把新节点赋给根节点
{
pRoot = p;
}
else
{
//如果左孩子节点未被访问,则先插入左孩子节点
if (StackNode[topnode]->bleftvisted == false)
{
StackNode[topnode]->lchild = p;
StackNode[topnode]->bleftvisted = true;
}
else//否则插入到右孩子节点
{
StackNode[topnode]->rchild = p;
}
}
StackNode[++topnode] = p;//新节点入栈
break;
}
}
} //二叉树的非递归后序遍历查找是否满足条件
bool Postorder(TreeNode *pRoot, int sum)
{
TreeNode *Stack[];
int top = -;
TreeNode *p = pRoot, *q;
if (pRoot != NULL)
{
do
{
while(p != NULL)
{
Stack[++top] = p;
p = p->lchild;
}
q = NULL;
while(top != -)
{
p = Stack[top];
//如果q == NULL则表示p的右孩子不存在,而左子树不存在或者已经访问,所以可以访问p节点,
//如果q != NULL则表示p的右子树已经被访问了,所以访问p节点
if (q == p->rchild)
{
if (p->lchild == NULL && p->rchild == NULL)
{
int temp = ;
//因为在后序遍历中,栈中保存的节点即为当前节点和它的所有父节点,
//所以便利一遍相加所得的和就是根节点到当前节点路径上所有节点之和
for (int i = ; i <= top; i++)
{
temp += Stack[i]->data;
}
if (temp == sum)
{
return true;
}
}
top--;
q = p;
}
else
{
p = p->rchild;
break;
}
}
} while (top != -);
}
return false;
} int main()
{
int sum;
while(scanf("%d", &sum) != EOF)
{
TreeNode *pRoot = NULL;
char ch;
int nCount = -;
while ((ch = getchar()) != '(');
str[++nCount] = ch;
int mark = ;
while(mark != )
{
ch = getchar();
switch(ch)
{
case ')':
mark--;
str[++nCount] = ch;
break;
case '(':
mark++;
str[++nCount] = ch;
break;
case '-':
str[++nCount] = ch;
break;
case ' ':
break;
case '\0':
break;
case '\n':
break;
default:
str[++nCount] = ch;
break;
}
}
str[nCount + ] = '\0';
CreateTree(pRoot);
if (pRoot == NULL)
{
printf("no\n");
continue;
}
if (Postorder(pRoot, sum))
{
printf("yes\n");
}
else
{
printf("no\n");
}
DeleteNode(pRoot);
}
return ;
}
POJ 1145 Tree Summing的更多相关文章
- POJ 题目1145/UVA题目112 Tree Summing(二叉树遍历)
Tree Summing Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 8132 Accepted: 1949 Desc ...
- UVa 112 - Tree Summing(树的各路径求和,递归)
题目来源:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=3&pa ...
- poj 3237 Tree [LCA] (树链剖分)
poj 3237 tree inline : 1. inline 定义的类的内联函数,函数的代码被放入符号表中,在使用时直接进行替换,(像宏一样展开),没有了调用的开销,效率也很高. 2. 很明显,类 ...
- poj 3237 Tree(树链拆分)
题目链接:poj 3237 Tree 题目大意:给定一棵树,三种操作: CHANGE i v:将i节点权值变为v NEGATE a b:将ab路径上全部节点的权值变为相反数 QUERY a b:查询a ...
- POJ 1741 Tree 求树上路径小于k的点对个数)
POJ 174 ...
- POJ 2378 Tree Cutting 3140 Contestants Division (简单树形dp)
POJ 2378 Tree Cutting:题意 求删除哪些单点后产生的森林中的每一棵树的大小都小于等于原树大小的一半 #include<cstdio> #include<cstri ...
- poj 1741 Tree(树的点分治)
poj 1741 Tree(树的点分治) 给出一个n个结点的树和一个整数k,问有多少个距离不超过k的点对. 首先对于一个树中的点对,要么经过根结点,要么不经过.所以我们可以把经过根节点的符合点对统计出 ...
- POJ 3723 Tree(树链剖分)
POJ 3237 Tree 题目链接 就多一个取负操作,所以线段树结点就把最大和最小值存下来,每次取负的时候,最大和最小值取负后.交换就可以 代码: #include <cstdio> # ...
- POJ 1741.Tree and 洛谷 P4178 Tree-树分治(点分治,容斥版) +二分 模板题-区间点对最短距离<=K的点对数量
POJ 1741. Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 34141 Accepted: 11420 ...
随机推荐
- HTML页面右键事件
<script type="text/javascript"> <!-- document.onmousedown = function (e) { var e ...
- SQL server的一个分割表值函数
CREATE FUNCTION [dbo].[Fn_Split] ( @SplitString text, -- 如果要传入NText类型,下面需要相应的修改,注释行为NText下同 ) = ','- ...
- wpf ListBox删除选择项(支持多项)
搞了个ListBox删除选择项,开始老是不能把选择项删除干净,剩下几个.后来调试一下原来是ListBox在删除一个选择项之后立即更新,选择项也有变化.结果我想了个这样的方法来删除呵呵. Departm ...
- 关于“为何Unicode中文字符占取2个字节,而 UTF-8却占3个字节”的网络解释修正
学到编码时,有个疑问——好好的占2字节的Unicode不用,却要用占3字节的UTF-8编码.发明 UTF-8的初衷不就是为了修正Unicode中任何字符至少占用2个字节的弊端吗? 虽然UTF-8英文字 ...
- noip模拟赛#14
#14: T1:f[x]=x-1(x&1)||x/2(x&1=0) 求[n,m]有多少个数可以通过变换得到k.(1e9). =>好像cf上看过类似的题,用二进制的方式来写.不过我 ...
- 2018.4.6 java交易记录系统
题目 ###1.交易明细文件内容如下例: 客户号 姓名 所述机构号 性别 帐号 发生时间 发生额 000001|刘德华|0000|1|4155990188888888|20060720200005|3 ...
- 简单的邮件发送mail.jar
public class MailSender { final static Logger logger = Logger.getLogger(MailSender.class); /** * 发送简 ...
- CodePlus #4 最短路
题目传送门 北极为什么会有企鹅啊,而且北纬91°在哪啊? 关键在建图 因为任意两个城市间都可以互相到达,再加上还有"快捷通道",光是建图就已经\(\rm{T}\)了-- 但这题给了 ...
- 【模板】树套树(线段树套Splay)
如题,这是一个模板... #include <algorithm> #include <iostream> #include <cstring> #include ...
- redis cluster 配置
#服务器192.168.56.111 192.168.56.112 192.168.56.113 计划1主2从 192.168.56.111 192.168.56.112 192.168.56.1 ...