我同意其他人表示最好先开始制作循环版本更好的版本。改进名称和将任务分解为函数可以帮助您清楚地了解代码。这是一个使用循环的版本。我试图打破任务分成更小的功能可读性帮助:
#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
如果你的动机是一个“干净”的样子,你应该考虑你之前的递归做几件事情。首先,使用有意义的变量名称,而不是单字母变量名称。其次,用有意义的名字将它分成不同的功能。第三,使用适当的格式/缩进。最后,添加评论和签名文档。当你完成所有这些工作时,试图弄清楚如何将其转换为递归将会容易得多。 – Jameson
另外需要注意的是,如果你不知道如何去做递归,那么几乎没有证据表明它会改善任何事情。我仍然会看到我可以为你做什么 – jcolemang
是啊,这是我的问题,我不善于做递归函数,我将不胜感激@jcolemang – TheOne817