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

时间:2017-07-09 09:40:51

标签: c recursion

所以我的训练任务听起来像这样: 编写一个子程序,它将递归地从数组中找到最大元素,并编写main函数来调用它。 我没有完全理解的是递归是什么。我想问你们,我的代码是否是递归的。如果没有,我应该做什么改变/递归真正意味着什么?

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

谢谢大家的时间!

7 个答案:

答案 0 :(得分:1)

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

您可以像这样更改代码,以获得可以确定数组最大值的递归无状态函数。

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

答案 1 :(得分:1)

将数组中的最大数量计算为第一个元素的最大值和数组中其余元素的最大值。类似于:max(first_elem,max(remaining_elems))。

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

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

答案 2 :(得分:1)

非常适合递归的问题可以分解为更小,更简单的子问题。这是赋予递归权力的东西之一。当尝试使用递归来解决问题时,通常最好尝试将问题分解为更简单的子问题,以找到解决问题的方法。

您可能会注意到,在查找存储在数组中的最大时,它可以是第一个元素的值,也可以是其余元素的最大值。这将问题分为两部分:如果第一个元素大于任何剩余元素,则完成;否则,您必须继续查看下一个元素是否大于其余元素。在代码中,这可能如下所示:

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

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

使用铅笔和纸来绘制每个函数调用的图表,其变量的值以及返回的内容将有助于准确理解此递归的工作原理。

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

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_ndx可以访问原始数组中的值。

同样,当到达基本情况时,数组中的当前位置将是数组的结尾,因此在return语句中要比较的第一个元素将朝向数组的末尾,向前移动数组。请注意,此处使用的是>=,而不是>,因此会返回第一个最大值的索引;如果您想要 last 最大值的索引,只需将其更改为>

这是一个完整的程序。请注意使用辅助函数find_max()来调用递归函数find_max_r(),它允许调用者使用与发布的代码使用的签名相同的函数(使用{{1}除外) } types,这是数组索引的正确类型):

size_t

节目输出:

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

答案 3 :(得分:0)

不,只有当你直接或间接地调用函数find_maximum时,你的代码才是递归的。

由于你的函数不仅试图获得最大值,而且还试图得到数组中的位置,我稍微修改了接口以返回引用(即指向值的指针),因此我们可以推断出位置数组元素的直接来自元素指针的减法。这样,我可以直接向数组指针传递函数和数组大小,然后将数组分成两半,并将相同的函数应用于两半(可以证明,如果某个元素的最大值是数组,它必须大于或等于每一半的最大值。出于同样的原因,我修改了main()函数中定义的一些变量,以允许使用引用:

max.c

#include <stdio.h>
#include <assert.h>

int *find_maximum(int a[], int n); /* return a reference pointer to the maximum value */

int main() {
  int c, array[100], size, *location, /* location must be a pointer */
  maximum;

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

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

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

  location = find_maximum(array, size);
  maximum  = *location; /* access to the value is granted by pointer dereference */
  printf("Maximum element location = %td and value = %d.\n", 
         location - array, /* pointer difference gives the array position */ 
         maximum);
  return 0;
} /* main */

/* somewhat efficient recursive way of a divide and conquer method 
 * to get the maximum element reference. */
int *find_maximum(int a[], int n)
{
    if (n == 1) return a; /* array of 1 element */
    int *left  = find_maximum(a,       n/2), /* left half begins at a
                                              * and has n/2 elements */
        *right = find_maximum(a + n/2, (n+1)/2); /* right half begins 
                                                  * at a + n/2, and
                                                  * has (n+1)/2 
                                                  * elements */
    return *left > *right 
           ? left 
           : right;
} /* find_maximum */

如你所见,我必须除以2,但由于我有任何长度的数组,我必须小心不要在下一步中遗漏任何元素。这是在函数的递归调用的右半部分中使用(n+1)/2元素数组的原因。我在前半部分包含n/2元素(向下舍入),我必须在右半部分包含(n+1)/2元素(向上舍入),以确保我将所有数组元素包含在两半中

答案 4 :(得分:0)

首先,递归意味着-函数调用自身。

enter image description here

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

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

enter image description here

来源:C Program To Find Biggest Element of An Array using Recursion

答案 5 :(得分:-1)

不,它不是递归函数

了解递归此链接非常有用https://www.khanacademy.org/computing/computer-science/algorithms/recursive-algorithms/a/recursion/

制作一个递归函数来解决你的问题试试这个

你可以尝试这个伪代码声明你的数组全局和max = 0全局和大小全局

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

其中i是数组索引

答案 6 :(得分:-1)

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

请阅读关于C中的recursion的TutorialsPoint。

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

相关问题