【问题标题】:recursive find number in between in C在C中递归查找数字
【发布时间】:2018-08-15 15:01:24
【问题描述】:

我想在数组的某个范围内查找数字,并且必须采用递归方式。无法修改函数变量。

假设在 2 和 3 的范围内

输入是:int a[] = {4, 1, 3, 1, 3, 2};

输出将是 = {3,3,2} ,找到 3 个

不确定在这种情况下如何编写递归函数。下面的我试过不工作。

int within(int a[], int N, int lower, int upper, int result[])
{
 if(N == 1 && N <= upper && N>= lower) 
    return a[0];

 return within(&a[1], N-1, lower, upper, result);
}

int main()
{
    int a[] = {4, 1, 3, 1, 3, 2};
    int result[6] = {0};
    int i, nResult;

    nResult = within(a, 6, 2, 3, result);

    printf("%d data passed the bounds\n", nResult);
    for (i = 0; i < nResult; i++){
        printf("%d ", result[i]);
    }
    printf("\n");

    return 0;
}

【问题讨论】:

  • 为什么要递归函数?
  • 你能定义N - 它是a 的元素数量吗 - 你为什么要检查N 的值 - 看起来你应该查询a[i] 的值
  • 你永远不会给结果数组赋值;在每个递归调用中发送相同的数组元素; N 似乎根本不相关。你可能想回到这本书。
  • 只需使用循环。更快、更安全、更易读、更少的堆栈使用,在所有可能的方面都更好。
  • 听起来像是家庭作业。

标签: c algorithm function recursion range


【解决方案1】:

我想在数组的某个范围内查找数字

假设在 2 和 3 的范围内

通常for 循环或类似的循环在这里会容易得多

如果它必须是递归的......

// need to have another number - r - number in range
//  r starts at zero
// 
// normally lower case for variable and capitals for things you #define
// N starts at the number of elements of a less one 
//
int within(int a[], int N, int lower, int upper, int r, int result[])
{
  if(a[0] <= upper && a[0]>= lower) {
     result[r]= a[0];
     r++;
  }
  if(N==0) {
     return r;
  } else { 
     r = within(&a[1], N-1, lower, upper, r, result);
    return r;
  }
}

该函数将给出在该范围内找到的值的数量的返回值。

上面的代码是递归的,但是比一个简单的循环要复杂和脆弱得多……比如下面的片段

  for (i=0;i<N;i++) {
    if(a[i] <= upper && a[i]>= lower) {
     result[r]= a[i];
     r++;
    }
  }

如果它必须是没有 r 的递归...

// need to have another number - result[0] - number in range
//  result[0] starts at zero
// 
// normally lower case for variable and capitals for things you #define
// N starts at the number of elements of a less one 
//
int within(int a[], int N, int lower, int upper, int result[])
{
  if(a[0] <= upper && a[0]>= lower) {
     result[0]++;
     result[result[0]]= a[0];
  }
  if(N==0) {
     return result[0];
  } else { 
     result[0] = within(&a[1], N-1, lower, upper, result);
    return result[0];
  }
}

现在结果包含

{范围内的数字,范围内的第一个数字,范围内的第二个数字......}

【讨论】:

  • 函数使用了冗余参数r。
  • @VladfromMoscow r 不是多余的——它会跟踪介于上下限之间的值的数量——如果我们将值放入result[],我们需要知道有多少值已添加到 result
  • @VladfromMoscow,但我在我的简单循环中发现了一个错误 - 查看您的代码可能不需要 r - 但我不确定您的代码或我的代码是否更“可读”
  • @如果你不确定那你的qi\ualification不够高。就是这样。:)
  • @VladfromMoscow 好的-所以我没有仔细查看您的代码细节。现在我更仔细地查看它,它看起来好像您有参数m,它与我的参数r 完成相同的工作,尽管我更喜欢称它们为变量。就像我的例程返回 r 的值一样,你返回 m 的值。 -- 但是你的代码的优点是你为结果分配了足够的内存......:-)
【解决方案2】:

以下代码将以递归方式为您工作。如果您不想打印数字,只需注释掉函数printfRange 内的printf 语句即可。希望你能理解其中的逻辑:-

int within(int *a, int rngH, int rngL, int length)
{
  int len = length;
  static int i = 0;
  static int found = 0;
  if(len <=0 )
  {
   return i;
  }
  if (*a == rngH)
  {
   printf("%d,",*a);
   i++;
   found = 1;
   within(++a,rngH, rngL,--len);
  }
  else if(*a == rngL && found > 0)
  {
   printf("%d,",*a);
   i++;
   within(++a,rngH, rngL,--len);
  }
  else
  {
    within(++a,rngH, rngL,--len);
  }
   return i;
}

int main() {
int a[] = {4, 1, 3, 1, 3, 2};

int total = within(a,3,2,6);
printf("\n");
printf("Total :%d\n",total);
return 0;
}

【讨论】:

  • 该函数应该返回一个目标元素数组。它不应该输出任何东西。
【解决方案3】:

类似的东西。如果要实现递归函数,请尝试以递归调用在最后发生的方式进行。

#include <stdio.h>

int find_in_range(int* out, int const *in, int length, int from, int to)
{
    if (length == 0)
    {
        return 0;
    }

    int addon;

    if (*in >= from && *in <= to)
    {
        *out = *in;
        ++out;
        addon = 1;
    }
    else
    {
        addon = 0;
    }

    return find_in_range(out, in + 1, length - 1, from, to) + addon;
}

#define N 6

int main()
{
    int in[N] = {4, 1, 3, 1, 3, 2};
    int out[N] = {0};

    int num_found = find_in_range(out, in, N, 2, 3);

    for (int i = 0; i < num_found; ++i)
    {
        printf("%d ", out[i]);
    }

    printf("\n");

    return 0;
}

【讨论】:

    【解决方案4】:

    您可以根据需要修改以下代码。这只是概念验证代码:

    #include <stdio.h>
    #include <stdlib.h>
    
    static int result[4];
    static int ctr1 = 0;
    static int ctr2 = 0;
    void recFind(int* arr, int* key){
    
        if(ctr2 == 8)
            return;
        if(*arr >= key[0] && *arr <= key[1])
            result[ctr1++] = *arr;
    
            arr++;
            ctr2++;
            recFind(arr, key);
    }
    int main(){
    
        int arr[] = {1,3,3,6,4,6,7,8};
        int key[] = {1,4};
    
        recFind(arr, key);
        printf(" { ");
        for(int i = 0; i < 4; i++){
            printf("%d ", result[i]);
        }
        printf("}\n");
    }
    

    【讨论】:

    • 这是一个糟糕的代码。它使用全局变量和幻数。
    • @VladfromMoscow 这只是一个概念证明,我在上面已经提到过。它确实使用全局变量和固定大小的数组,但这就是重点。它不应该被插入,因为它在任何有生产力的地方,而是提问者必须自己理解和实施它。我刚刚提供了如何做到这一点的指导方针。
    • 这只是概念的一个糟糕的证明。
    【解决方案5】:

    从赋值的描述中可以看出,函数应该提供两个值:满足条件的元素数量和包含元素本身的数组。

    很明显,数组应该是动态分配的。当函数本身返回元素个数而指向生成数组的指针作为参数通过引用传递时,这在逻辑上是一致的。

    递归函数可以这样看

    #include <stdio.h>
    #include <stdlib.h>
    
    size_t get_range( const int a[], size_t n, int lower, int upper, int **out )
    {
        size_t m;
    
        if ( n )
        {
            m = get_range( a, n - 1, lower, upper, out );
    
            if ( lower <= a[n-1] && a[n-1] <= upper )
            {
                int *tmp = realloc( *out, ( m + 1 ) * sizeof( int ) );
    
                if ( tmp )
                {
                    tmp[m] = a[n-1];
                    *out = tmp;
                    ++m;
                }               
            }
        }
        else
        {
            *out = NULL;
            m = 0;
        }
    
        return m;
    }
    
    int main(void) 
    {
    
        int a[] = { 1, 2, 3, 4, 5, 4, 3, 2, 1 };
        const size_t N = sizeof( a ) / sizeof( *a );
    
        int lower = 2, high = 3;
        int *out;
    
        size_t n = get_range( a, N, lower, high, &out );
    
        for ( size_t i = 0; i < n; i++ )
        {
            printf( "%d ", out[i] );
        }
    
        putchar( '\n' );
    
        free( out );
    
        return 0;
    }
    

    程序输出为

    2 3 3 2 
    

    【讨论】:

      猜你喜欢
      • 2022-06-23
      • 2015-05-13
      • 2017-09-25
      • 2013-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-02
      相关资源
      最近更新 更多