UVa 548 树

题意:给出中序和后序序列,求从根到叶子结点这样路径和值最小的叶子结点。如果和值相等,则选择叶子结点值较小的那个。

思路:由中序和后序序列递归地构造二叉树。顺序存储显然不行,使用链式存储。由于每个结点输入的是数字而不是字母,这里采用整型数组来存的,而不再是字符串,可能更方便些。build(n,a1,a2)函数是利用中序序列a1和后序序列a2构造有n个结点的二叉树,返回根结点指针。递归构造出二叉树后,再进行深度优先搜索即可,这里实现的是非递归形式,使用栈。

注意:多条路径具有最小和值时,选择叶子结点最小的那个输出。

有多处小错误,最后调通了竟然发现输入环节还有错,如果把while中等价改为cnt1++就会出现错误,不能相应的把判断break的条件改为==1,因为只有一个结点时也是为1。

另外,如果程序卡在等待输入时,会RE错误。即如果把main里的跳出while(1)的条件if(cnt1==0)注释掉,则RE错误。

另外测试了下,读到文件尾时,还可以再继续读,仍然返回EOF。即把if(cnt1==0)注释掉,换成if(!cnt1&&!cnt2)依旧AC,第一个while循环读到EOF时,第二个while循环还读是没问题的,不过仍是EOF。(这个完全是开始RE但还没找出错误时,想了很多~~)这个好像是因为EOF并不是真正存在的字符,而是一个标记位。

另外,初始的最小值leastv要设置足够大,开始设成了MAXN,就WA了~~亲测。。。

刚开始RE的时候发现没有remove_tree,以为是内存泄露导致。刚又亲测了一下,把remove_tree注释掉可过,这题竟然没有。。

Code:

#include<stdio.h>
#include<stdlib.h>
#define MAXN 10010

typedef struct node
{
 int data;
 bool lvisit;
 bool rvisit;
 struct node *left,*right;
}Node;

int dfs(Node *u);
Node* build(int n,int *a1, int *a2);
int find(int t,int *a,int len);
Node* newNode();
void remove_tree(Node *u);

int main()
{
 int a1[MAXN],a2[MAXN];
 while(1)
 {
  int cnt1=0,cnt2=0;
  while((scanf("%d",&a1[cnt1]))==1)
  {
   cnt1++;
   char c=getchar();
   if(c=='\n') break;
  }
  //if(cnt1==0) break;
  while((scanf("%d",&a2[cnt2]))==1)
  {
   cnt2++;
   char c=getchar();
   if(c=='\n'||c==EOF) break;
  }
  if(!cnt1&&!cnt2) break;
  Node *root=build(cnt1,a1,a2);
  printf("%d\n",dfs(root));
  remove_tree(root);
 }//while
 return 0;
}

int dfs(Node *u)
{
 Node *stack[MAXN]; int top=0;
 stack[++top]=u;
 int count=u->data; int leaf=0; int leastv=1000000000;
 while(top)
 {
  Node *t=stack[top];
  if(t->left==NULL && t->right==NULL)
  {//叶子节点,出栈
   if(count<leastv) {leastv=count; leaf=t->data;}
   else if(count==leastv && t->data<leaf) leaf=t->data;
   count=count-t->data;
   top--;
  }
  else if(!t->lvisit && t->left!=NULL)
  {//非叶节点,左孩子入栈
   stack[++top]=t->left;
   t->lvisit=1;
   count=count+stack[top]->data;
  }
  else if(!t->rvisit && t->right!=NULL)
  {//非叶节点,右孩子入栈
   stack[++top]=t->right;
   t->rvisit=1;
   count=count+stack[top]->data;
  }
  else
  {//非叶节点出栈
   count=count-stack[top]->data;
   top--;
  }
 }//while
 return leaf;
}

Node* build(int n,int *a1, int *a2)
{
 if(n<=0) return NULL;
 Node *root=newNode();
 root->data=a2[n-1];//最后一个元素是n-1位
 int p=find(a2[n-1],a1,n);
 root->left=build(p,a1,a2);
 root->right=build(n-p-1,a1+p+1,a2+p);
 return root;
}

int find(int t,int *a,int len)
{
 int i=0;
 while(i<len)
 {
  if(a[i]==t) break;
  i++;
 }
 return i;
}

Node* newNode()
{
 Node *u=(Node*)malloc(sizeof(Node));
 if(u!=NULL)
 {
  u->data=0;
  u->lvisit=0;
  u->rvisit=0;
  u->left=u->right=NULL;
 }
 return u;
}

void remove_tree(Node *u)
{
 if(u!=NULL)
 {
  remove_tree(u->left);
  remove_tree(u->right);
  free(u);
 }
}
时间: 2024-10-13 03:06:09

UVa 548 树的相关文章

UVa 548 树(已知其中两种遍历, 还原树)

题意: 给出后序遍历和先序遍历, 还原一棵树, 然后求出从根节点到叶子的最小路劲和. 分析: 已知后序遍历, 那么后序的最后一个节点就是根节点, 然后在中序中找到这个节点, 它的左边就是左子树, 它的右边就是右子树, 然后递归下去. 技巧是不断的变动[r1,l1] [r2,l2] r1 l1是中序的区间 r2 l2是后序的区间 #include <bits/stdc++.h> using namespace std; const int maxn = 10000 + 10; int In_or

UVA 548.Tree-fgets()函数读入字符串+二叉树(中序+后序遍历还原二叉树)+DFS or BFS(二叉树路径最小值并且相同路径值叶子节点权值最小)

Tree UVA - 548 题意就是多次读入两个序列,第一个是中序遍历的,第二个是后序遍历的.还原二叉树,然后从根节点走到叶子节点,找路径权值和最小的,如果有相同权值的就找叶子节点权值最小的. 最后输出来叶子节点. 一开始写的时候是用gets读入的,报CE, 要用fgets写,关于fgets(),传送门: fgets函数及其用法,C语言fgets函数详解 一开始用bfs过的,后来发现,好多人都是dfs过的,又写了一下dfs... 代码: 1 //二叉树的中序和后序遍历还原树并输出最短路径的叶子

[2016-02-08][UVA][548][Tree]

UVA - 548 Tree Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description You are to determine the value of the leaf node in a given binary tree that is the terminal node of a path of least value from the root

UVA 548(二叉树重建与遍历)

J - Tree Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Appoint description:  System Crawler  (2014-05-16) Description  Tree  You are to determine the value of the leaf node in a given binary tree that is the ter

Tree UVA - 548 已知中序遍历和后序遍历,求这颗二叉树。

You are to determine the value of the leaf node in a given binary tree that is the terminal node of a path of least value from the root of the binary tree to any leaf. The value of a path is the sum of values of nodes along that path. Input The input

UVa 112 树求和

题意:给定一个数字,以及一个描述树的字符序列,问存不存在一条从根到某叶子结点的路径使得其和等于那个数.难点在于如何处理字符序列,因为字符间可能有空格.换行等. 思路:本来想着用scanf的(后发现scanf貌似不能做),感觉太麻烦,想看网上有没有处理比较好的,一搜全是用C++的cin流的~  还是自己用C写了一下.用的getchar().getchar()主要就是比较繁琐,需要一个一个字符比较,记得刚开始做字符串题目时比较喜欢用getchar(),有的用scanf就行的自己也喜欢用getchar

UVa 548 Tree(建树,递归遍历)

题意  给你一个树的中序遍历和后序遍历  某个节点的权值为从根节点到该节点所经过节点的和  求权值最小的叶节点的值  如果存在多个  输出值最小的那个 把树建好就好说了  递归递归dfs msun保存最小叶节点权值  ans保存答案 #include<cstdio> #include<cctype> #include<cstring> using namespace std; const int maxn = 10005, INF = 0x3f3f3f3f; int i

Tree UVA 548

说说: 做了这么久,终于做到树了.先说下题意,题目给出了两组数,分别是对一棵树的中序遍历和后序遍历.然后要求的是到达根节点的路径和最短的叶子的值.所谓的路径和就是从叶子到根的路径上所有节点的值的和.这无非就是个树的遍历的问题啦.后序序列的最后一个值为子树根,然后再中序序列中找到该节点,然后树就被分成两棵子树了.然后再递归操作就可以了.这里有一点提醒一下,虽然在开始的时候,对于同一棵树,中序序列和后序序列的起始点都是相同的.但随着不断递归深入,同一棵子树的中序序列和后序序列的各自的起始位置是不同的

Uva 122 树的层次遍历 Trees on the level lrj白书 p149

是否可以把树上结点的编号,然后把二叉树存储在数组中呢?很遗憾如果结点在一条链上,那将是2^256个结点 所以需要采用动态结构 首先要读取结点,建立二叉树addnode()+read_input()承担这样的工作 然后遍历二叉树,读取结点编号输出bfs() 这道题有内存池应用的背景 附链接  http://blog.csdn.net/shawngucas/article/details/6574863 #include <cstdio> #include <cstring> #inc