如何使用递归函数查找最大数目

时间:2019-02-04 06:57:02

标签: c recursion

我试图了解如何使用递归函数查找最大数量,但我并不真正了解如何。具有以下代码:

#include <stdio.h>
#include <stdlib.h>
int main()
{

    int ar[100],n,i;
    int *ptr;
    printf("Enter size of the list:");
    scanf("%d", &n);
    printf("Printing the list:\n");
    for (i = 0; i < n ; i++)
    {
        scanf("%d", &ar[i]);
    }
    ptr=&ar;
    int max=maximum(ptr,n);
    printf("ma %d",max);
    return 0;
}
int maximum(int ar[], int n)
{

    int max;
    if(n+1==1)
    {
        return ar[n];
    }
    max =maximum(ar,n-1);
    return ar[n]>max?ar[n]:max;
}

它实际上在做什么以及如何做? 使用指针指向整数数组是否正确? 希望您能帮助我理解它!

4 个答案:

答案 0 :(得分:1)

使用int ar[100]为100个整数数组预留内存,然后输入n,它是使用scanf("%d", &n)设置的。如果在此阶段输入的数字大于100,则程序将出现段错误,因为循环for (i = 0; i < n ; i++)将尝试访问ar[100],这是内存访问错误(可用的最高数组索引为{{1 }},请注意100-1 <100)。无论如何,您需要在循环中填充ar[100 - 1]的{​​{1}}个索引。 n只是将ar的起始地址分配给ptr = &ar。顺便说一下,ar也将起作用,ptr并不是必需的。现在您可以像使用ptr = ar一样使用&

了解递归的最简单方法是直接转到ptr的最后一个调用。但是首先,要了解您已将ar传递给了与传递maximum相同的函数(请记住,自ptr以来,它们在ar中是相同的。)。 / p>

因此,在对main的最后一次调用中,当ptr = ar(与maximum相同)时,它将返回n + 1 == 1,即n == 0,这是第一个您为ar[n]输入的数字(存储在ar[0]中)。

现在在倒数第二个对'Printing the list'的调用中,ar[0]是错误的,因为maximum,所以我们转到n + 1 == 1。这是我刚刚解释的对n = 1的最后一次调用的结果,因此max = maximum(ar, n - 1)的值为maximum。现在您有了max,它与ar[0]相同。与

相同
return ar[n] > max ? ar[n] : max

您会看到返回的是较大的return ar[1] > ar[0] ? ar[1] : ar[0]if (ar[1] > ar[0]) { return ar[1]; } else { return ar[0]; } 。现在,对于ar[0]的最后一次调用,ar[1]是对maximum的第二次调用的结果。您会看到模式出现。您将返回较大的值:maxmaximum用于对max的所有其余调用,并且当您到达对ar[n]的第一次调用时,将比较maximum中的所有值以找到最大值并将其返回。

此外,阿贾伊(Ajay)说的对,maximum正在访问一个您从未在循环中初始化的值。您应该在ar中写ar[n]来解决此问题。

答案 1 :(得分:1)

尾部递归的解决方案:

int maximum(int a[], int n)
{
    if (n == 1)
        return a[0];
    --n;
    return maximum(a + (a[0] < a[n]), n);
}

Demo on compiler explorer

答案 2 :(得分:0)

要了解maximum的工作原理,只需尝试在maximum函数中找到一些不变式

int maximum(int ar[], int n)
{
    int max;
    if(n==0)
    {
        return ar[n];
    }
    max =maximum(ar,n-1);
    /* at this point MAX keeps the maximum of the subarray [0..N-1] and using this 
       we try to get by induction the maximum of [1..N]. */
    return ar[n]>max?ar[n]:max;
}

答案 3 :(得分:0)

考虑该定义:

#include <stdio.h>
#include <stdlib.h>

void maximum(int nums[], int size, int index, int * max)
{
  if (index != size) {
    if (nums[index] > *max)
      *max = nums[index];
    maximum(nums, size, ++index, max);
  }
}

int main()
{
  int * nums;
  int size, i, max;

  fprintf(stderr, "Enter size of the list: "); /* stderr to flush without \n */
  if ((scanf("%d", &size) != 1) || (size <= 0)) {
    puts("wrong size");
    return 0;
  }

  if ((nums = malloc(size * sizeof(int))) == 0) {
    puts("cannot allocate nums");
    return 0;
  }

  for (i = 0; i != size; ++i) {
    if (scanf("%d", &nums[i]) != 1) {
      puts("invalid number");
      return 0;
    }
  }

  max = nums[0];
  maximum(nums, size, 1, &max);
  free(nums);
  printf("max = %d\n", max);

  return 0;
}

执行:

% gcc -O2 -pedantic -Wall m.c
% ./a.out
Enter size of the list: 3
3
1
2
max = 3

maximum 是递归的,但这是终端递归,因此编译器可以将其删除以生成循环。因此, maximum 似乎可以按照您的要求进行递归,但是即使数量很大,堆栈也不会爆炸:

% ( echo 100000000 ; yes 1 ) | ./a.out
Enter size of the list: max = 1

如果我删除选项-O2,则生成代码将使用递归,并且堆栈会爆炸:

% gcc -pedantic -Wall m.c
% ( echo 100000000 ; yes 1 ) | ./a.out
Enter size of the list: Segmentation fault