我写这个代码,使用递归函数找到数组中的最小数字

时间:2017-01-22 09:03:01

标签: c

int smallest(int arr[],int i,int small,int n)
{
   if(i==n)
       return small;

    else  if(small>=arr[i])
   {
      smallest(arr,i+1,arr[i],n);
   }
}

所以编译器说控件到达非void函数的结尾。有什么建议吗?

2 个答案:

答案 0 :(得分:1)

重写它,这样你就不会在没有返回任何东西的情况下掉出函数的末尾; e.g。

int smallest(int arr[],int i,int small,int n)
  {
  if (i == n)
    return small;
  else if(small >= arr[i])
    return smallest(arr, i+1, arr[i], n);
  else
    return smallest(arr, i+1, small, n);
  }

您也可能希望提供一个替代且更简单的调用,以便调用用户代码进行所需的初始化,在这种情况下,您可能希望将上述内容重命名为basic_smallest,然后创建一个新函数< / p>

#include <limits.h>

int smallest(int arr[], int i)
  {
  return basic_smallest(arr, i, INT_MAX, 0);
  }

另外,请记住,像这样的递归实现会让您面临为大型阵列炸毁堆栈的风险。非递归实现可能更安全:

int smallest(int arr[], int i)
  {
  int n;
  int small;

  for(n = 0 ; n < i ; ++n)
    small = (small >= arr[n] ? arr[n] : small);

  return small;
  }

答案 1 :(得分:1)

您在逻辑流程中错过了两个返回案例,并且您正在努力使其变得比它无论如何更难。

关于两个缺失的退货声明,请注明以下内容:

int smallest(int arr[],int i,int small,int n)
{
    if(i==n)
        return small;

    else  if(small>=arr[i])
    {
        smallest(arr,i+1,arr[i],n); // here
    }

    // and here
}

当您删除无用的else用法时,这两个都变得更加明显。它不是必需的。如果先前的if为真,则该函数已退出。

int smallest(int arr[],int i,int small,int n)
{
    if(i==n)
        return small;

    if(small>=arr[i])
        smallest(arr,i+1,arr[i],n); // here

    // and here
}

同样的问题,但现在它应该在视觉上更明显,实际返回任何内容的唯一地方是i == n。在下面两种情况下(当small >= arr[i]为真或假时)都是提供的任何返回值。

然后,如果保留现有接口,则解决方案是添加返回AND最终大小写,从而覆盖所有逻辑路径以使其可达return

int smallest(int arr[],int i,int small,int n)
{
    if(i==n)
        return small;

    if(small>=arr[i])
        return smallest(arr,i+1,arr[i],n);

    return smallest(arr,i+1,small,n); // note small. it's important
}

不同的方法

递归smallest()只能使用序列地址和长度。您不需要标记small值,也不需要围绕该索引进行标记。相反,您可以简单地使用指针算法来移动基本序列地址,直到耗尽给定元素,同时调整最终告诉我们需要停止递归的剩余序列长度。所有相关数据都已在递归堆栈中保留给您;你只需要知道如何使用它:

int smallest(const int arr[], size_t len)
{
    if (len < 2) // 1
        return *arr;

    int small = smallest(arr+1, len-1); // 2
    return (*arr < small ? *arr : small); // 3
}

以下注意点的说明

  1. 基地救助案。如果len < 2为真,则只返回序列开头的任何内容。我遗漏了一个缺乏迂腐的步骤。可以想象有人可以传递一系列长度,如果是这种情况,则应将其视为运行时错误。如果这是除了练习之外的任何事情(它看起来像是),请记住这一点。
  2. 使用递归获取*arr的基本元素后面的元素的最小值。请注意,arr+1是第一个参数。这意味着递归调用将引用序列中的 next 元素作为 base 元素(*arr)。另请注意len-1,注意现在序列中剩余的元素少了一个。一旦序列耗尽,我们依赖于从上面的(1)触发基本情况,我们需要停止递归。
  3. 基本上表示的三元表达式,&#34;如果基本元素小于所有后面元素中的最小元素,则返回基本元素,否则返回后面的最小元素。&#34;
  4. 示例运行如下所示:

    #include <iostream>
    #include <random>
    #include <utility>
    
    #include <stdio.h>
    
    int smallest(const int arr[], size_t len)
    {
        if (len < 2)
            return *arr;
    
        int small = smallest(arr+1, len-1);
        return (*arr < small ? *arr : small);
    }
    
    int main()
    {
        int arr[] = { 7,3,5,1,9,2,4,6,8 };
        printf("Smallest : %d\n", smallest(arr, sizeof arr / sizeof *arr));
    }
    

    <强>输出

    Smallest : 1