递归查找列表中的最小偶数

时间:2020-07-14 15:12:33

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

我已经写了这个函数:

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。

4 个答案:

答案 0 :(得分:3)

因为如果列表在末尾位置包含奇数个整数,并且在任何地方至少包含个偶数整数,则该函数从递归返回后minimo_p可以为NULL。

>

此行是错误的:

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

您可以在此处添加空条件:

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

答案 1 :(得分:2)

您的算法是错误的,如果递归调用返回NULL,则可能会产生不确定的行为,因为将 minimo_p 设置为 NULL ,如果(top->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 $ 

答案 2 :(得分:1)

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

  • 如果当前列表仅包含一个元素
    • ->返回偶数,否则返回null
  • 如果列表包含更多元素
    • 获取最少的列表
    • 如果当前元素为奇数
      • 返回剩余最小值
    • 否则,如果rest为null
      • 返回此元素
    • 否则,如果rest不为null
      • 退回较小的

我不会对此抱以回避。如果列表很长,您将导致堆栈崩溃。

一个简单的循环会更简单,而且省去了很多弯弯的事情:

  • 将最小值初始化为NULL
  • 使用列表初始化迭代器
  • while迭代器!=空
    • 如果迭代器为偶数且最小值== Null
      • minimum =迭代器
    • 否则,偶数且迭代器<最小值
      • minimum =迭代器
    • 高级迭代器

答案 3 :(得分:0)

我的五分钱。我还包括了一个递归函数,该函数可找到具有最大偶数值的节点。

#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;
  }