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 ...
随机推荐
- selenium-Python之上传文件
对于web 页面的上传功能实现一般有一下两种方式 普通上传:普通的附件上传是将本地文件的路径作为一个值放在input标签中,通过form表单将这个值提交给服务器 插件上传:一般是指基于flash.ja ...
- Git随笔:尝试将本地工程上传至Github上的repository仓库,构建远端与本地协同的Git环境
上传工程至自己的Github公开库,步骤如下: 第1步:建立本地 git 仓库,cd 到你的本地项目根目录下,执行 git init 命令: 第2步:将本地项目工作区的所有文件添加到暂存区.小数点 & ...
- SAP公有云和私有云解决方案概述
SAP公有云解决方案见下图最右侧,比较著名的有SAP SuccessFactors和SAP Cloud for Customer(C4C)等,作为SAP软件即服务(SaaS)的解决方案. 而最左侧的S ...
- Object Modeling
https://developer.apple.com/library/content/documentation/General/Conceptual/CocoaEncyclopedia/Objec ...
- 【转】 iOS学习之NSBundle介绍和使用
bundle是一个目录,其中包含了程序会使用到的资源.这些资源包含了如图像,声音,编译好的代码,nib文件(用户也会把bundle称为plug-in).对应bundle, cocoa提供了类NSBun ...
- BOM属性对象方法
本文原链接:https://cloud.tencent.com/developer/article/1018747 BOM 1.window对象 2.location对象 3.history对象 BO ...
- c++ 定义一个结构体student,输入多个student的信息并以三种方式显示
#include <iostream> #include <string> using namespace std; const int slen = 30; struct s ...
- vc文件操作汇总—支持wince
一.判断文件及文件夹是否存在 // 判断文件是否存在 BOOL IsFileExist(const CString& csFile) { DWORD dwAttrib = GetFileAtt ...
- Voyager下的Dashboard Widgets
widgets设置,voyager.php下找到'widgets': 'widgets' => [ 'TCG\\Voyager\\Widgets\\UserDimmer', 'TCG\\Voya ...
- Linux菜鸟起飞之路【七】文件合并、归档和压缩
一.文件合并操作 1.覆盖符号与追加符号 a)“>”代表将左边文件的内容覆盖右边文件的内容,如果右边文件不存在则创建这个文件 b)“>>”代表将左边文件的内容追加到右边文件中,如果右 ...