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 ...
随机推荐
- vue分环境打包配置不同命令
1.安装cross-env (cross-env能跨平台地设置及使用环境变量)cnpm/npm i cross-env -D 2.新建模板 红色的为相关文件 3.配置各个文件 (1)config下 ...
- POJ 2923 Relocation(01背包+状态压缩)
题意:有人要搬家,有两辆车可以运送,有若干家具,车有容量限制,而家具也有体积,那么如何运送会使得运送车次最少?规定两车必须一起走,两车一次来回只算1躺. 思路:家具怎么挑的问题,每趟车有两种可能:1带 ...
- windows server 2008 r2 启用 Windows Defender
单击“开始”,指向“管理工具”,然后单击“服务器管理器”. 在“服务器管理器”中,单击“功能”,然后在“服务器管理器”细节窗格中的“功能摘要”下,单击“添加功能”. 此时会启动“添加功能向导”. 在“ ...
- 卓越管理的实践技巧(3)推动团队管理的要点 Facilitation Essentials for Managers
Facilitation Essentials for Managers 前文卓越管理的秘密(Behind Closed Doors)最后一部分提到了总结的13条卓越管理的实践技巧并列出了所有实践技巧 ...
- Processing分形之一——Wallpaper
之前用C语言实现过一些分形,但是代码比较复杂.而对于天生对绘图友好的Processing,及其方便. 在大自然中分形普遍存在,我们用图形模拟,主要是找到一个贴近的函数. 代码 /** * Wallpa ...
- python3从尾到头打印链表
题目描述 输入一个链表,按链表值从尾到头的顺序返回一个ArrayList. 方法一:通过栈实现 # -*- coding:utf-8 -*- # class ListNode: # def __ini ...
- appium---命令行启动appium
在客户端的appium长时间运行的时候,出产生一些数据.日志有可能会对appium的内存有所增长,严重的会使appium产生崩溃,这个时候就推荐使用通过cmd进行运行appium, 安装前提需要安装N ...
- SC || 那些CheckStyle中的错误们
lab5里给了我们一个checkstyle查代码风格的方法.. 然后 lab4代码 copy一份! 添加checkstyle! 项目 右键 checkstyle!(自信脸) 3s后——7256 war ...
- 直接用bcdedit创建bootmgr数据库和修复启动菜单
直接用bcdedit创建bootmgr数据库和修复启动菜单 使用下面方法之前需要bcdedit和bootsect两条命令,这两条命令可以到vista或者windows 7安装光盘上获得.bootsec ...
- 2018 noip 提高组初赛参考答案
这里有pdf文件:戳这儿