我想将我的函数转换为递归函数,因为我认为它会更清晰,但我不知道如何去做。
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);
}
答案 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