zoukankan      html  css  js  c++  java
  • uva 112 Tree Summing

    将原来的代码改了一个BUG即是存在负数后就AC了,但是时间不好,0.112

    实际上本题就是由扩展前序序列来建树,然后遍历,算路径的题目,考查了二叉树的基本知识,很好

     

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #define LEN sizeof(struct BTree)
    #define MAX 10010
    char num[MAX][20],stack[MAX];
    struct BTree
    {
        int data;
        struct BTree *lchild,*rchild;
    }*pre;
    int top,count,flag;
    
    void CUT()
    {
        int i=0,j=0;
        while( !(stack[i]>='0' && stack[i]<='9' || stack[i]=='-') ) i++;
        while(stack[i]>='0' && stack[i]<='9' || stack[i]=='-') { num[count][j++]=stack[i];  stack[i]='*'; i++; }
        num[count][j]='\0';  count++;
    }
    int move()
    {
        int i;
        for(i=top-1; i>=0; i--)  if(stack[i]=='(') break;
        return i-1;
    }
    void input()
    {
        char ch;
        while(1)
        {
            ch=getchar();
            if(ch==' ' || ch=='\n')  continue;
            else if(ch=='(')   
            {
                stack[++top]=ch;
                if(top>0 && ( stack[top-1]>='0' && stack[top-1]<='9' || stack[top-1]=='-'))
                    CUT();
            }
            else if(ch>='0' && ch<='9' || ch=='-')  stack[++top]=ch;
            else
            {
                stack[++top]=ch;
                if(stack[top-1]=='(')
                { num[count][0]='#'; num[count][1]='\0'; count++; top-=2;}
                else top=move();
            }
            if(top<0)  {ch=getchar();return;}
        }
    }
    void create_BTree(struct BTree* *T,int *i)
    {
        int a;
        (*i)++;
        if(num[*i][0]=='#')   (*T)=NULL;
        else
        {
            if(num[*i][0]!='-')
            sscanf(num[*i] , "%d" , &a);
            else
            { sscanf(num[*i]+1 , "%d" , &a); a=0-a; }
            (*T)=(struct BTree*)malloc(LEN);
            (*T)->data=a;
            create_BTree( &((*T)->lchild) , i);
            create_BTree( &((*T)->rchild) , i);
        }
    }
    void DFS_BTree(struct BTree *T)
    {
         if(!T)  return ;
         printf("%d ",T->data);
         DFS_BTree(T->lchild);
         DFS_BTree(T->rchild);
    }
    
    void search(struct BTree *T , int key , int sum)
    {
        if(flag)  return ;
        if(!T)
        {
            if(!pre->lchild  && !pre->rchild && sum==key)  flag=1;
            return ;
        }
        else
        {
            sum+=T->data;
            pre=T; search(T->lchild , key , sum);
            if(flag)  return ;
            pre=T; search(T->rchild , key , sum);
            if(flag)  return ;
        }
    }
    int main()
    {
        int i,key,sum;  struct BTree *T;
        while(scanf("%d",&key)!=EOF)
        {
            top=-1; count=0; 
            input();
    //        for(i=0; i<count; i++) printf("%s  ",num[i]);  printf("\n");
            i=-1; create_BTree(&T,&i);
    //         DFS_BTree(T);  printf("\n");
            if(!T)  {printf("no\n"); continue;}
            flag=sum=0; pre=T; search(T,key,sum);
            if(flag)  printf("yes\n");
            else      printf("no\n");
        }
        return 0;
    }

    仔细思考为什么建树的过程顺便计算结果就会WA,一定要把建树过程中同时遍历的程序写出来,因为这样时间将大大提高!

    一直WA的原因是,左右孩子指针可能是野指针

    经过总结和教训,指针在竞赛中是不适用的,所以尽量避免指针,即便是树这种数据结构也尽量用数组来实现

    //悲剧的是时间没有提高多少!!!

     

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #define LEN sizeof(struct BTree)
    #define MAX 100010
    #define INF 1948723892  //用INF表示#
    char num[MAX][20],stack[MAX];
    struct BTree
    {
        int data;
        struct BTree *lchild,*rchild;
    }*pre;   //建树时记录前驱结点
    int top,count,ok,len;
    int a[MAX];
    void CUT()
    {
        int i=0,j=0;
        while( !(stack[i]>='0' && stack[i]<='9' || stack[i]=='-') ) i++;
        while(stack[i]>='0' && stack[i]<='9' || stack[i]=='-') 
    { num[count][j++]=stack[i];  stack[i]='*'; i++; }
        num[count][j]='\0';
        if(num[count][0]!='-')  sscanf(num[count],"%d",&a[count]);
        else                 {sscanf(num[count]+1,"%d",&a[count]); a[count]=0-a[count];}
        count++;
    }
    int move()
    {
        int i;
        for(i=top-1; i>=0; i--)  if(stack[i]=='(') break;
        return i-1;
    }
    void input()
    {
        char ch;
        while(1)
        {
            ch=getchar();
            if(ch==' ' || ch=='\n')  continue;
            else if(ch=='(')   
            {
                stack[++top]=ch;
                if(top>0 && ( stack[top-1]>='0' && stack[top-1]<='9' || stack[top-1]=='-'))
                    CUT();
            }
            else if(ch>='0' && ch<='9' || ch=='-')  stack[++top]=ch;
            else
            {
                stack[++top]=ch;
                if(stack[top-1]=='(')
                { num[count][0]='#'; num[count][1]='\0'; a[count]=INF; count++; top-=2;}
                else top=move();
            }
            if(top<0)  {ch=getchar();return;}
        }
    }
    void create_BTree(struct BTree* *T,int sum,int key,int mark)
    {
        len++;
        if(a[len]==INF)   
        {
            (*T)=NULL;  //先赋空
            if(mark==2 && !(pre->lchild)  && sum==key) ok=1;
            return ;
    //这个判断就是造成不断WA的原因,我们的目的其实是判断这个结点是不是叶子,抑或还只是缺了其中一个孩子,只有是叶子才能//赋值,判断叶子不能直接的 !pre->lchild  && !pre->rchild  因为这两个可能是野指针!
    //试想一下扩展前序建树,其实和前序遍历的顺序是相同的,先是根结点,再左孩子,再右孩子,如果是叶子结点,那么左右孩子必//定为空,假设这个结点是左孩子,你能单纯地判断!pre->rchild吗?不能,因为这个时候的rchild是野指针,甚至都还没赋值,//你都不知道它还没有数据。有一个判断是一定准确的,那就是!如果这次的递归是用右边递归进来,而且是空结点,那么就只需要//判断前驱的左孩子是不是空,但问题是怎么知道这次的递归是用右边递归进来,那就是用mark来标记!
    //所以现在可以理解这个判断了吧 mark==2 && !(pre->lchild)  && sum==key 是从右边递归进来的,而前驱
    //的左孩子又是空,而sum又等于key,那就是这个结点了
    
        }
        else
        {
            pre=(*T)=(struct BTree*)malloc(LEN);
            (*T)->data=a[len];
            sum=sum+a[len]; 
            pre=(*T);  mark=1; create_BTree( &((*T)->lchild) , sum , key,mark); 
            if(ok)  return ;   //在每个递归函数的出口加一个判断条件,如果已经找到答案就直接返回
            pre=(*T);  mark=2; create_BTree( &((*T)->rchild) , sum , key,mark);  
            if(ok)  return ;   //在每个递归函数的出口加一个判断条件,如果已经找到答案就直接返回
        }
    }
    int main()
    {
        int i,key,sum,mark;  struct BTree *T;
        while(scanf("%d",&key)!=EOF)
        {
            top=-1; count=0; 
            input();
            len=-1; ok=sum=0; pre=NULL; mark=0; create_BTree(&T,sum,key,mark);
            if(ok==1)  printf("yes\n");
            else       printf("no\n");
        }
        return 0;
    }

     

     

  • 相关阅读:
    数据仓库010
    R语言- 实验报告
    数据仓库006
    数据仓库009
    多台Linux 7.x服务器具有相同的UUID网络链接参数,肿么办?
    数据仓库005
    数据仓库004
    我的编程竞赛生涯
    我的建模竞赛生涯
    再见了,亲爱的博客园
  • 原文地址:https://www.cnblogs.com/scau20110726/p/2712623.html
Copyright © 2011-2022 走看看