Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C递归程序从数组中求最大元素_C_Recursion - Fatal编程技术网

C递归程序从数组中求最大元素

C递归程序从数组中求最大元素,c,recursion,C,Recursion,因此,我在培训中有一项任务,听起来是这样的: 编写一个子程序,递归地从数组中查找最大元素,并编写主函数来调用它。 我没有完全理解什么是递归。我想问你们我的代码是不是递归的。如果不是,我应该做什么更改/递归的真正含义是什么 #include <stdio.h> int find_maximum(int[], int); int main() { int c, array[100], size, location, maximum; printf("Input numbe

因此,我在培训中有一项任务,听起来是这样的: 编写一个子程序,递归地从数组中查找最大元素,并编写主函数来调用它。 我没有完全理解什么是递归。我想问你们我的代码是不是递归的。如果不是,我应该做什么更改/递归的真正含义是什么

#include <stdio.h>

int find_maximum(int[], int); 

int main() {
  int c, array[100], size, location, maximum;

  printf("Input number of elements in array\n");
  scanf("%d", &size);

  printf("Enter %d integers\n", size);

  for (c = 0; c < size; c++)
    scanf("%d", &array[c]);

  location = find_maximum(array, size);
  maximum  = array[location];

  printf("Maximum element location = %d and value = %d.\n", location + 1, maximum);
  return 0;
}

int find_maximum(int a[], int n) {
  int c, max, index;

  max = a[0];
  index = 0;

  for (c = 1; c < n; c++) {
    if (a[c] > max) {
       index = c;
       max = a[c];
    }
  }

  return index;
}

谢谢大家抽出时间

不,它不是递归函数

要了解递归,此链接非常有用

要创建递归函数来解决您的问题,请尝试以下操作

您可以尝试使用此伪代码来声明数组全局和max=0全局以及size全局

int find_maximum(int i)
{
if (i == size )
    return max;
else if ( max < array[i])
    max =array [i];
return find_maximum(i+1);
}

其中i是数组索引

不,您的程序肯定不是递归的。作为定义,递归函数必须使用终止条件调用自身

请阅读关于C语言的教程要点

更新@JonathanLeffler的评论:
请注意,引用中的输出将溢出。

否,您的代码不使用递归。递归是指一个函数调用自身,或者调用另一个函数,从而导致再次调用自身

您可以这样更改代码,使其具有一个递归的无状态函数,该函数可以确定数组的最大值

int find_maximum(int a[], int n) {
   return find_maximum_r(a, 0, n);
} 

int find_maximum_r(int a[], int index, int n) {
  if (index + 1 == n) {
    return a[index];
  }

  int maxRight = find_maximum_r(a, index + 1, n);
  return a[index] > maxRight ? a[index] : maxRight;
}
#include <stdio.h>

// function to find the max of 2 numbers
int max(int x, int y)
{
    return (x > y) ? x : y;
}

// the recursive function
int find_max(int *p, int n)
{
    if (n == 1) return *p;

    return max(*p, find_max(p + 1, n - 1));
}

int main(void)
{
    int arr[] = {23, 3, 11, -98, 99, 45};
    printf("max: %d\n", find_max(arr, sizeof arr / sizeof arr[0]));
}

考虑将数组中的最大数计算为数组中第一个元素的最大数和剩余元素的最大数。类似于:maxfirst\u elem,MaxLeving\u elem

实际函数:find_max非常简单,如果数组中只有一个元素,则返回该元素。否则,我们将得到数组的第一个元素和其余元素的最大值

int find_maximum(int a[], int n) {
   return find_maximum_r(a, 0, n);
} 

int find_maximum_r(int a[], int index, int n) {
  if (index + 1 == n) {
    return a[index];
  }

  int maxRight = find_maximum_r(a, index + 1, n);
  return a[index] > maxRight ? a[index] : maxRight;
}
#include <stdio.h>

// function to find the max of 2 numbers
int max(int x, int y)
{
    return (x > y) ? x : y;
}

// the recursive function
int find_max(int *p, int n)
{
    if (n == 1) return *p;

    return max(*p, find_max(p + 1, n - 1));
}

int main(void)
{
    int arr[] = {23, 3, 11, -98, 99, 45};
    printf("max: %d\n", find_max(arr, sizeof arr / sizeof arr[0]));
}

非常适合递归的问题可以分解为更小、更简单的子问题。这是赋予递归强大功能的因素之一。当尝试使用递归来解决问题时,通常最好尝试将问题分解为更简单的子问题来找到解决方案

您可能会注意到,在查找存储在数组中的最大值时,它要么是第一个元素的值,要么是其余元素的最大值。这将问题分为两部分:如果第一个元素比任何剩余元素都大,那么就完成了;否则,必须继续并查看下一个图元是否大于其余图元。在代码中,这可能看起来像:

int max_in(size_t rest_sz, int *rest)
{
    int curr_val = rest[0];
    if (rest_sz == 1) {
        return curr_val;
    }

    int max_in_rest = max_in(rest_sz-1, rest+1);

    return curr_val > max_in_rest ? curr_val : max_in_rest;
}
size_t find_max_r(int arr[], int *rest, size_t rest_sz, size_t curr_ndx)
{
    if (rest_sz == 1) {
        return curr_ndx;
    }

    int curr_val = arr[curr_ndx];
    size_t max_in_rest_ndx = find_max_r(arr, rest+1, rest_sz-1, curr_ndx+1);
    int max_in_rest = arr[max_in_rest_ndx];

    return curr_val >= max_in_rest ? curr_ndx : max_in_rest_ndx;
}
这里有一个基本情况:如果rest_sz为1,则无需进一步研究;第一个元素curr_val=rest[0]的值是最大值,返回该值。如果不满足基本情况,则继续执行该函数。max_in_rest是递归函数调用max_inrest_sz-1,rest+1的结果。这里rest_sz-1表示由rest+1表示的数组部分中剩余的元素数。在新的函数调用中,再次满足基本情况,最终这种情况将为真,因为rest_sz随着每次递归调用而递减。发生这种情况时,将返回当前堆栈帧中的curr_val值;请注意,此值是数组中最后一个元素的值。然后,当函数返回到其调用者时,该帧中的max_in_rest将获得返回值,然后curr_val或max_in_rest中的较大值将返回到前一个调用者,依此类推,直到最后控制返回到main

使用铅笔和纸绘制每个函数调用的图表、变量的值以及返回的内容将有助于准确理解这种递归是如何工作的

您可以应用相同的方法来解决查找数组最大值的索引的问题。在这种情况下,如果第一个元素的值大于任何剩余元素的值,则最大元素的索引是第一个元素的索引;否则,最大元素的索引就是剩余元素的最大值的索引。在代码中,这可能看起来像:

int max_in(size_t rest_sz, int *rest)
{
    int curr_val = rest[0];
    if (rest_sz == 1) {
        return curr_val;
    }

    int max_in_rest = max_in(rest_sz-1, rest+1);

    return curr_val > max_in_rest ? curr_val : max_in_rest;
}
size_t find_max_r(int arr[], int *rest, size_t rest_sz, size_t curr_ndx)
{
    if (rest_sz == 1) {
        return curr_ndx;
    }

    int curr_val = arr[curr_ndx];
    size_t max_in_rest_ndx = find_max_r(arr, rest+1, rest_sz-1, curr_ndx+1);
    int max_in_rest = arr[max_in_rest_ndx];

    return curr_val >= max_in_rest ? curr_ndx : max_in_rest_ndx;
}
还有更多的信息要记录。这里,如果基本情况得到满足,并且rest_sz为1,则没有理由进一步查看,当前索引curr_ndx是最大值的索引。否则,将递归调用find_max_r,rest递增以指向数组的其余元素,rest_sz适当递减。这一次,curr_ndx跟踪当前索引与原始数组的关系,并将该值传递到每个函数调用中;此外,指向原始数组的第一个元素arr的指针被传递到每个函数调用中,以便索引值curr\u ndx可以访问原始数组中的值

同样,当到达基本大小写时,数组中的当前位置将是数组的结尾,因此在return语句中要比较的第一个元素将接近数组的结尾,移动到 在阵列的前面。注意这里使用>=而不是>以便返回第一个最大值的索引;如果您想要最后一个最大值的索引,只需将其更改为>

这是一个完整的程序。请注意,使用助手函数find_max调用递归函数find_max_r,该函数允许调用者使用与发布代码使用的签名相同的函数,但大小类型除外,大小类型实际上是数组索引的正确类型:

#include <stdio.h>

int max_in(size_t sz, int *rest);
size_t find_max(size_t sz, int arr[]);
size_t find_max_r(int arr[], int *rest, size_t rest_sz, size_t curr_ndx);

int main(void)
{
    int array[] = { 2, 7, 1, 8, 2, 5, 1, 8 };
    size_t array_sz = sizeof array / sizeof array[0];

    int max_val = max_in(array_sz, array);
    printf("Maximum value is: %d\n", max_val);

    size_t max_ndx = find_max(array_sz, array);
    printf("Maximum value index: %zu\n", max_ndx);

    return 0;
}

int max_in(size_t rest_sz, int *rest)
{
    int curr_val = rest[0];
    if (rest_sz == 1) {
        return curr_val;
    }

    int max_in_rest = max_in(rest_sz-1, rest+1);

    return curr_val > max_in_rest ? curr_val : max_in_rest;
}

size_t find_max(size_t sz, int arr[])
{
    int *rest = arr;
    return find_max_r(arr, rest, sz, 0);
}

size_t find_max_r(int arr[], int *rest, size_t rest_sz, size_t curr_ndx)
{
    if (rest_sz == 1) {
        return curr_ndx;
    }

    int curr_val = arr[curr_ndx];
    size_t max_in_rest_ndx = find_max_r(arr, rest+1, rest_sz-1, curr_ndx+1);
    int max_in_rest = arr[max_in_rest_ndx];

    return curr_val >= max_in_rest ? curr_ndx : max_in_rest_ndx;
}

不,只有直接或间接调用函数find_max时,代码才是递归的

由于您的函数不仅要获取最大值,还要获取数组中的位置,因此我稍微修改了接口以返回引用,即指向该值的指针,这样我们就可以直接从元素指针的减法中推断数组元素的位置。通过这种方式,我可以直接将数组指针和数组大小传递给函数,然后将数组分成两半,并将相同的函数应用于两半,可以证明,如果某个元素是数组的最大值,出于同样的原因,它必须大于或等于每一半的最大值,我修改了主函数中定义的一些变量,以允许使用引用:

最高温度
正如您所看到的,我必须除以2,但是由于我有任意长度的数组,所以我必须小心不要在下一步中遗漏任何元素。这就是在函数递归调用的右半部分使用n+1/2元素数组的原因。我在前半部分包含n/2个元素,在右半部分包含n+1/2个元素,以确保在两半部分包含所有数组元素。

首先,递归意味着函数调用本身

你们写的不是递归函数。我将发布使用递归查找数组中最大或最大元素的最简单方法

#include<stdio.h>  
  
#define N 5  
  
int biggest(int num[], int n, int big)  
{  
    if(n < 0)  
        return big;  
    else  
    {  
        if(big < num[n])  
            big = num[n];  
  
        return biggest(num, --n, big);  
    }  
}  
  
int main()  
{  
    int a[N], i;  
  
    printf("Enter %d integer number\n", N);  
    for(i = 0; i < N; i++)  
        scanf("%d", &a[i]);  
  
    printf("Biggest Element in the array: %d\n", biggest(a, N - 1, a[0]));  
  
    return 0;  
} 

来源:

谢谢@idmean。但是在主功能中,一切都正常,对吗?一切看起来都正常。请注意,我的示例函数返回的是最大值,而不是最大值的索引。递归函数肯定不必有终止条件。@idmean:它是否会落入无限递归中,从而导致运行时堆栈溢出?我肯定提到过这种情况-通常称为,尽管如此。请注意,为讨论而链接到的TutorialPoint网站包括“阶乘”的示例和“阶乘15是2004310016”的声明。正确答案是1307674368000,它太大,无法放入32位整数。1307674368000模2^31==2004310016。该示例遇到整数溢出。这对那些试图从网站上学习的人来说不是个好兆头。请找一个更好的参考网站并更新你的答案。问题是,一旦一个网站发布了一个非常错误的答案并且没有注意到溢出,那么该网站所说的一切都会变得可疑。您的替代方案生成有效的输出,但不能防止溢出。事情变得一团糟。我的自动选择可能是维基百科,但每个都有自己的。检查你的参考资料是个好主意,以合理地确定它是正确的。也许你对TutorialsPoint的体验比我更积极。当你在谷歌上搜索递归的定义时,最直接的三个结果是什么?你对作业的描述模棱两可。你必须找到最大值,但不关心位置,还是必须找到保持最大值的位置。两者都是有效的需求,但它们是不同的。显示的代码找到了位置。使用全局变量将数据传递给这样的函数是个坏主意。给定数组int数组[]={-4,-7,-19,-24,-3,-9};,您的代码将错误地返回0作为最大值。我也不相信you give-matryoshka玩偶很有趣,但很难清楚地解释递归。请注意,这段代码找到了最大值,但没有记录找到最大值的位置。问题中的代码是迭代的,但找到了保持最大值的位置。在引用C代码时,请谨慎使用“reference”一词。有些人对术语的使用相当狂热,因为它在C++中有单独的含义,人们常常不清楚人们是否认识到了差异。您还可以使用n-n/2来获取数组上半部分的元素数,而不是n+1/2。没有实际的区别-计算成本是相同的一个加法或减法;一个师,你好,我知道。作为C/C++的一个很好的参考,我完全理解您的意图,但是引用在本文中使用,因为它准确地表示了函数被假定为retu的内容
注册护士。在C++中,返回类型应该是int和事实,并且许多避免用于引用引用的星号都应该避免…但是我们在谈论C++,而不是C++。我在遵循这种方式之前采取了双重检查问题标签的预防措施。无论如何谢谢你!谢谢你的编辑,因为我不是天生的英国作家either@JonathanLeffler,关于n-n/2方法,我同意你的观点,它确实是一样的,而且更清晰。我写的时候根本就没有想到这个,所以我觉得它有点模糊,这就是在注释中解释它的原因。请注意,location-array的类型为ptrdiff_t,因此应该使用%td转换说明符而不是%d来打印这个值,同时避免使用UB。此外,我不认为这里使用的分而治之的方法比我的方法更有效;在一个包含6个元素的输入数组上,您的版本需要11个递归调用,而我的版本需要6个递归调用。@DavidBowling,好吧,这不是一个竞争对手,所以如果我的方法没有比您的方法更有效,就不会受到惩罚。但我还是说过这样的话。无论如何,关于格式字符串的断言是正确的,但我接受过古代K&R的培训,没有时间研究它们。如果您愿意,请随意编辑答案以更正它。效率的提高来自于这样一个事实,即这是一种除以二的方法,因此,它需要logn堆栈资源,而不是像head/tail方法那样的线性方法。在大型阵列上,这会更好,至少在堆栈消耗方面是这样。