【问题标题】:Find the minimum even number in a list recursively递归查找列表中的最小偶数
【发布时间】:2020-11-03 23:22:43
【问题描述】:

我写了这个函数:

struct nodo * MinimoPariListaRic(struct nodo * top) {
  struct nodo * minimo_p = NULL; //this should be the minimum even number

  //list have one or no one element
  if(top) {
    if(!top->next) 
        if(top->valore % 2 == 0) return top; // valore(italian) = value
        else return NULL;
  }
  else return NULL;


  if(top->next)
    minimo_p = MinimoPariListaRic(top->next);

  if (top->valore % 2 == 0)
  {
     if(minimo_p->valore < top->valore) return minimo_p;
     else return top;
  }
  else return minimo_p;
}

如果列表的元素都是偶数,函数会返回最小值,没关系。 但如果出现奇数,则该功能无法正常工作。 如果所有数字都是奇数,函数应该返回 NULL。

【问题讨论】:

    标签: c recursion linked-list singly-linked-list function-definition


    【解决方案1】:

    因为如果列表包含最后一个位置的奇数任何位置至少一个偶数,则函数从递归返回后 minimo_p 可以为 NULL。

    这行是错误的:

    if(minimo_p->valore < top->valore) return minimo_p;
    

    你可以在这里添加空条件:

    if(minimo_p && minimo_p->valore < top->valore) return minimo_p;
    

    【讨论】:

      【解决方案2】:

      你的算法是错误的,如果递归调用返回 NULL,你可能会有一个未定义的行为,因为将 minimo_p 设置为 NULL,如果 (top-&gt;valore % 2 == 0),你将取消引用它,并且它太复杂了,您不需要递归调用,只需抛出列表即可,例如:

      struct nodo * MinimoPariListaRic(struct nodo * l) {
        struct nodo * minimo_p = NULL; //this should be the minium even number
      
        while (l != NULL) {
          if (l->valore % 2 == 0) {
            if ((minimo_p == NULL) || (l->valore < minimo_p->valore))
              minimo_p = l;
          }
          l = l->next;
        }
      
        return minimo_p;
      }
      

      因为您编辑的主题需要递归调用,例如:

      struct nodo * MinimoPariListaRic(struct nodo * l) {
        if (l == NULL)
          return NULL;
        else {
          struct nodo * minimo_p = MinimoPariListaRic(l->next);
      
          return ((l->valore % 2 == 0) &&
                  ((minimo_p == NULL) || (l->valore < minimo_p->valore)))
             ? l :  minimo_p;
        }
      }
      

      如您所见,这很简单,如果 valore 是否为奇数等,我只在程序中检查一次


      使用完整的程序检查:

      #include <stdio.h>
      #include <stdlib.h>
      
      struct nodo {
        struct nodo * next;
        int valore;
      };
      
      struct nodo * MinimoPariListaRic(struct nodo * l) {
        if (l == NULL)
          return NULL;
        else {
          struct nodo * minimo_p = MinimoPariListaRic(l->next);
      
          return ((l->valore % 2 == 0) &&
                  ((minimo_p == NULL) || (l->valore < minimo_p->valore)))
             ? l :  minimo_p;
        }
      }
      
      int main(int argc, char ** argv)
      {
        /* make a list from the args */
        struct nodo * l = NULL;
        
        while (argc > 1) {
          struct nodo * r = malloc(sizeof(*r));
          
          r->next = l;
          if (sscanf(argv[--argc], "%d", &r->valore) != 1) {
            puts("invalid number");
            return 0;
          }
          l = r;
        }
        
        /* show list well made */
      
        struct nodo * ll;
        
        for (ll = l; ll != NULL; ll = ll->next)
          printf("%d ", ll->valore);
        putchar('\n');
        
        /* */
        
        ll = MinimoPariListaRic(l);
        
        if (ll == NULL)
          puts("no even value");
        else
          printf("min even value is %d\n", ll->valore);
        
        /* free resources */
      
        while (l) {
          ll = l->next;
          free(l);
          l = ll;
        }
        
        return 0;
      }
      

      编译和执行:

      pi@raspberrypi:/tmp $ gcc -Wall l.c
      pi@raspberrypi:/tmp $ ./a.out 1 4 2 7 8
      1 4 2 7 8 
      min even value is 2
      pi@raspberrypi:/tmp $ ./a.out
      
      no even value
      pi@raspberrypi:/tmp $ ./a.out 3
      3 
      no even value
      pi@raspberrypi:/tmp $ ./a.out 3 3 1 5
      3 3 1 5 
      no even value
      pi@raspberrypi:/tmp $ valgrind ./a.out 3 4 5 2 0
      ==16881== Memcheck, a memory error detector
      ==16881== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
      ==16881== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
      ==16881== Command: ./a.out 3 4 5 2 0
      ==16881== 
      3 4 5 2 0 
      min even value is 0
      ==16881== 
      ==16881== HEAP SUMMARY:
      ==16881==     in use at exit: 0 bytes in 0 blocks
      ==16881==   total heap usage: 6 allocs, 6 frees, 1,064 bytes allocated
      ==16881== 
      ==16881== All heap blocks were freed -- no leaks are possible
      ==16881== 
      ==16881== For lists of detected and suppressed errors, rerun with: -s
      ==16881== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
      pi@raspberrypi:/tmp $ 
      

      【讨论】:

      • 我已经做了迭代版本,是的,非常非常简单,我知道。 “挑战”是把它变成一个递归函数。
      • @LuigiV。为什么你没有在你的问题中说它必须是递归的?
      • @LuigiV。我编辑了我的答案以使用递归添加另一个提议
      • @LuigiV。我在前面的评论中犯了两次相同的错字,我想说:如果 test 为真,则(test) ? st1 : st2 的表单值 st1 的值,否则 st2 ,所以return (test) ? st1 : st2;type r; if (test) r = st1; else r = st2; return r; 相同,但第一种形式更简洁易读
      • 非常感谢这个例子,它帮助了我,现在我理解了(test) ? st1 : st2 的形式。但是,我立即尝试并在我的程序中实现了您的功能!
      【解决方案3】:

      如果你必须使用递归,你应该先尝试用伪语言写下来:

      • 如果当前列表只有一个元素
        • ->如果是偶则返回,否则返回null
      • 如果列表有更多元素
        • 获取列表其余部分的最小值
        • 如果当前元素是奇数
          • 返回剩余最小值
        • 如果 rest 为空,则为 else
          • 返回此元素
        • 如果 rest 不为空,则为 else
          • 返回较小的那个

      我不会对此进行回避。如果列表很长,您的堆栈会崩溃。

      一个简单的循环会更简单,更少费神:

      • 初始化最小值为 NULL
      • 使用列表初始化迭代器
      • 而迭代器!= Null
        • 如果迭代器偶数和最小值 == Null
          • 最小值 = 迭代器
        • else if even and iterator
        • 最小值 = 迭代器
      • 高级迭代器

      【讨论】:

        【解决方案4】:

        我的五美分。我还包含了一个递归函数,它可以找到具有最大偶数值的节点。

        #include <stdio.h>
        #include <stdlib.h>
        #include <time.h>
        
        struct nodo
        {
            int valore;
            struct nodo *next;
        };
        
        int push_front( struct nodo **top, int valore )
        {
            struct nodo *nodo_nuovo  = malloc( sizeof( struct nodo ) );
            int success = nodo_nuovo != NULL;
            
            if ( success )
            {
                nodo_nuovo->valore = valore;
                nodo_nuovo->next = *top;
                *top = nodo_nuovo;
            }
            
            return success;
        }
        
        FILE * display( struct nodo *top, FILE *fp )
        {
            for ( ; top != NULL; top = top->next )
            {
                fprintf( fp, "%d -> ", top->valore );
            }
            
            fputs( "null", fp );
            
            return fp;
        }
        
        struct nodo * MinimoPariListaRic( struct nodo * top )
        {
            if ( !top )
            {
                return top;
            }
            else
            {
                struct nodo *minimo = MinimoPariListaRic( top->next );
                
                
                if ( minimo == NULL )
                {
                    minimo = top->valore % 2 == 0 ? top : minimo;
                }
                else if ( top->valore % 2 == 0 )
                {
                    minimo = minimo->valore < top->valore ? minimo : top;
                }
        
                return minimo;
            }
        }
        
        struct nodo * MassimoPariListaRic( struct nodo * top )
        {
            if ( !top )
            {
                return top;
            }
            else
            {
                struct nodo *massimo = MassimoPariListaRic( top->next );
                
                
                if ( massimo == NULL )
                {
                    massimo = top->valore % 2 == 0 ? top : massimo;
                }
                else if ( top->valore % 2 == 0 )
                {
                    massimo = top->valore < massimo->valore ? massimo : top;
                }
        
                return massimo;
            }
        }
        
        int main(void) 
        {
            struct nodo *top = NULL;
            enum { N = 10 };
            
            srand( ( unsigned int )time( NULL ) );
            
            for ( int i = 0; i < N; i++ )
            {
                push_front( &top, rand() % N );     
            }
        
            fputc( '\n', display( top, stdout ) );
            
            struct nodo *minimo = MinimoPariListaRic( top );
            
            if ( minimo != NULL )
            {
                printf( "Minimo pari valore is %d\n", minimo->valore );
            }
            else
            {
                puts( "there is no minimo pari valore" );
            }
            
            struct nodo *massimo = MassimoPariListaRic( top );
            
            if ( massimo != NULL )
            {
                printf( "Massimo pari valore is %d\n", massimo->valore );
            }
            else
            {
                puts( "there is no massimo pari valore" );
            }
        
            return 0;
        }
        

        程序输出可能看起来像

        8 -> 9 -> 9 -> 9 -> 7 -> 9 -> 7 -> 3 -> 1 -> 2 -> null
        Minimo pari valore is 2
        Massimo pari valore is 8
        

        至于你的函数定义那么你需要检查指针是否 调用返回的minimo_p

          if(top->next)
            minimo_p = MinimoPariListaRic(top->next);
        

        在下一个 if 语句中等于 NULL

          if (top->valore % 2 == 0)
          {
             if(minimo_p->valore < top->valore) return minimo_p;
             else return top;
          } 
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-11-28
          • 2018-06-13
          • 2013-03-17
          • 1970-01-01
          • 2017-03-25
          • 1970-01-01
          • 2020-05-13
          • 2019-12-18
          相关资源
          最近更新 更多