我试图了解如何使用递归函数查找最大数量,但我并不真正了解如何。具有以下代码:
#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;
}
它实际上在做什么以及如何做? 使用指针指向整数数组是否正确? 希望您能帮助我理解它!
答案 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
的第二次调用的结果。您会看到模式出现。您将返回较大的值:max
或maximum
用于对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);
}
答案 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