Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.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,我想把我的函数变成一个递归函数,因为我认为它会有一个更清晰的外观,但我不知道如何去做 void perm_rec_1(int N, int nr_vals){ int arr[N]; int i=0; while(i < N) { arr[i] = 0; i++; } int k=0; do { int z=0; while(z < N) { printf("%d ",arr[z]); z++;

我想把我的函数变成一个递归函数,因为我认为它会有一个更清晰的外观,但我不知道如何去做

void perm_rec_1(int N, int nr_vals){
  int arr[N];
  int i=0;
  while(i <  N)
  {
    arr[i] = 0;
    i++;
  }
  int k=0;
  do {
    int z=0;
    while(z < N) {
      printf("%d ",arr[z]);
      z++;
    }
    printf("\n");
    k = N - 1;
    while (k >= 0) {
      arr[k]++;
      if (arr[k] < nr_vals) {
        break;
      }
      arr[k] = 0;
      k--;
    }
  } while (k >= 0);
}
void perm_rec_1(整数N,整数N){
int-arr[N];
int i=0;
而(i=0){
arr[k]++;
如果(arr[k]=0);
}

首先,如果您想要的只是更干净的外观,您可能需要执行以下操作:

/*
 * prints all numbers in base base
 * will a number of digits up to num_digits
 */
void perm_rec_1(int num_digits, int base) {

  // create an array of size num_digits, initialize to 0
  int arr[num_digits];
  int i=0;
  while(i <  num_digits) {
    arr[i] = 0;
    i++;
  }

  int current_digit=0;
  do {

    // print everything in arr on one line
    int i=0;
    while(i < num_digits) {
      printf("%d ", arr[i]);
      i++;
    }
    printf("\n");

    // reset the current digit to the rightmost digit
    current_digit = num_digits - 1;
    while (current_digit >= 0) {

      // increment the current digit
      arr[current_digit]++;

      // if the current digit is less than the base
      // go to the top of the loop (print the line)
      if (arr[current_digit] < base) {
        break;
      }

      // else reset the digit and shift it over one
      arr[current_digit] = 0;
      current_digit--;

    } // end while
  } while (current_digit >= 0); // end 'do'
}
/*
*以基数打印所有数字
*将一个数字的数目增加到num_个数字
*/
void perm_rec_1(整数位数,整数基数){
//创建一个大小为num_的数字数组,初始化为0
int arr[数字];
int i=0;
while(i=0){
//增加当前数字
arr[当前_位]+;
//如果当前数字小于基数
//转到循环的顶部(打印行)
if(arr[当前数字]<基数){
打破
}
//否则,重置数字并将其移到一位上
arr[当前数字]=0;
当前_位--;
}//结束时
}while(当前_位>=0);//结束'do'
}
与其完全重写它,不如考虑一些更有用的变量名。回答这个问题最费时的部分之一就是弄清楚它想做什么。如果可以避免,请不要使用单字符变量名。想一想实际反映变量用途的东西。注释也很好,但是好的变量名更好


现在,来回答你的问题。以下是同一程序的递归版本:

void print_arr(int len, int* arr) {
  int i;
  for (i = 0; i < len; i++) {
    printf("%d ", arr[i]);
  }
  printf("\n");
}


void perm_rec_1_helper(int num_digits, int base, int curr_digit, int* arr) {

  if (num_digits == curr_digit) {
    print_arr(num_digits, arr);
    return;
  }

  int i;
  for (i = 0; i < base; i++) {
    arr[curr_digit] = i;
    perm_rec_1_helper(num_digits, base, curr_digit+1, arr);
  }

}


void perm_rec_1(int num_digits, int base) {
  int arr[num_digits];
  perm_rec_1_helper(num_digits, base, 0, arr);
}
void print\u arr(int len,int*arr){
int i;
对于(i=0;i

看看你是否能通过代码来理解它。如果你不能,我会对我的答案做一些解释。

我同意其他人的看法,他们表示最好先改进循环版本。改进名称并将任务分解为函数可以大大提高代码的清晰度。这是一个使用循环的版本。我尝试将任务分解为更小的函数,以帮助提高可读性:

#include <stdio.h>
#include <stdbool.h>

void show_perms(size_t arr_sz, size_t nr_vals);
void print_perm(size_t arr_sz, int arr[arr_sz]);
bool next_array(size_t arr_sz, int arr[arr_sz], size_t nr_vals);

int main(void)
{
    size_t nr_vals;
    size_t arr_sz;

    printf("Enter number of values: ");
    scanf("%zu", &nr_vals);
    printf("Enter size of array: ");
    scanf("%zu", &arr_sz);

    show_perms(arr_sz, nr_vals);

    return 0;
}

void show_perms(size_t arr_sz, size_t nr_vals)
{
    int arr[arr_sz];

    for (int i = 0; i < arr_sz; i++)
        arr[i] = 0;

    do{
        print_perm(arr_sz, arr);
    } while (next_array(arr_sz, arr, nr_vals));
}

void print_perm(size_t arr_sz, int arr[arr_sz])
{
    for (int i = 0; i < arr_sz; i++)
        printf("%d ", arr[i]);
    putchar('\n');
}

bool next_array(size_t arr_sz, int arr[arr_sz], size_t nr_vals)
{
    int i;

    for (i = (arr_sz - 1); i >= 0; i--) {
        arr[i] = (arr[i] + 1) % nr_vals;
        if (arr[i] != 0)
            break;
    }

    if (i < 0)
        return false;
    else
        return true;
}
以下是示例运行的输出:

Enter number of values: 2
Enter size of array: 3
0 0 0 
0 0 1 
0 1 0 
0 1 1 
1 0 0 
1 0 1 
1 1 0 
1 1 1 

如果你的动机是一种“干净”的外观,你应该在考虑递归之前做几件事。首先,使用有意义的变量名,而不是一个字母的。其次,将其拆分为具有有意义名称的不同函数。第三,使用适当的格式/缩进。最后,添加注释和签名文档。当你完成所有这些的时候,你会更容易找到如何将它转换为递归。另外一个注意事项是,如果你不知道如何使它递归,那么几乎没有证据表明它实际上会改进任何东西。我仍然会看看我能为你做些什么。这是我的问题,我不擅长做递归函数,我会很感激@jcolemangI通常更喜欢循环而不是递归。我的大脑承受着与计算机一样的递归负担:必须记住整个堆栈。我记得我唯一使用递归的时候是在一棵树上行走:在每一片叶子上,迭代所有的叶子并递归到它们上。我也喜欢这样,但是老师们通常强调递归的主题,所以我认为一旦我们离开学校并开始为公司工作,它将是我们真正需要的东西。我尝试将我所做的每一个程序都进行递归转换,即使我不必这样做,这样我就能做得更好,因为我知道这是我的弱点。对
print\u all\u digits\u helper()
的函数调用应该重命名为
perm\u rec\u 1\u helper()
,反之亦然。@DavidBowling哇,忘了重命名它们了。感谢感谢在阅读了你的代码之后,我对我需要做的事情越来越清楚了
Enter number of values: 2
Enter size of array: 3
0 0 0 
0 0 1 
0 1 0 
0 1 1 
1 0 0 
1 0 1 
1 1 0 
1 1 1