如何将迭代函数转换为递归函数?

时间:2016-10-22 20:55:29

标签: 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++;
    }
    printf("\n");
    k = N - 1;
    while (k >= 0) {
      arr[k]++;
      if (arr[k] < nr_vals) {
        break;
      }
      arr[k] = 0;
      k--;
    }
  } while (k >= 0);
}

2 个答案:

答案 0 :(得分:2)

首先,如果你想要的只是一个更清洁的外观,你可能想要做这样的事情:

/*
 * 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'
}

不要完全重写它,而是想一些更有用的变量名。回答这个问题最耗时的部分之一就是弄清楚我们要做什么。如果可以避免,请不要使用单个字符变量名。想一想实际反映变量用途的东西。评论也很好,但好的变量名称更好。

现在,要真正回答你的问题。这是同一程序的递归版本:

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

看看你是否可以通过代码来理解它。如果你不能,我会在答案中加上一些解释。

答案 1 :(得分:-1)

我同意那些表示最好先制作带循环版本的人。改进名称和将任务分解为函数可以帮助您清楚地了解代码。这是一个使用循环的版本。我试图将任务分解成更小的函数以帮助提高可读性:

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

我首先编写了上述版本,并将其用作构建此递归解决方案的指南。起初我有一个布尔函数finished()检查当前排列是否是最后一个,但后来我意识到将index变量从size_t更改为int允许index在找到最终排列后保持值-1。这简化了递归代码,并让我再次查看循环解决方案,它还有一个名为is_another()的测试函数。我删除了此功能并更改了next_array()函数,如果有更多排列,则返回true,如果没有,则更改false(当i为负时)。

递归解决方案使用两个相互递归的函数来构建和打印排列。函数print_permutations()通过声明一个数组并将其归零来启动。然后调用print_perm()函数,首先打印第一个排列(全零),然后调用next_perm()函数。此函数递归调用自身直到找到下一个排列,此时再次调用print_perm(),一切都重新开始。这一直持续到index的值达到-1,此时对next_perm()的最后一次调用返回。

#include <stdio.h>

void print_permutations(size_t arr_sz, size_t nr_vals);
void print_perm(size_t arr_sz, int arr[arr_sz], size_t nr_vals);
void next_perm(size_t arr_sz, int arr[arr_sz], size_t nr_vals, int index);

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

    print_permutations(arr_sz, nr_vals);

    return 0;
}

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

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

    print_perm(arr_sz, arr, nr_vals);
}

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

    next_perm(arr_sz, arr, nr_vals, (arr_sz - 1));
}

void next_perm(size_t arr_sz, int arr[arr_sz], size_t nr_vals, int index)
{
    if (index < 0)
        return ;

    arr[index] = (arr[index] + 1) % nr_vals;
    if (arr[index] != 0)
        print_perm(arr_sz, arr, nr_vals);
    else
        next_perm(arr_sz, arr, nr_vals, (index - 1));
}

以下是样本运行的输出:

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