我同意其他人表示最好先開始製作循環版本更好的版本。改進名稱和將任務分解爲函數可以幫助您清楚地瞭解代碼。這是一個使用循環的版本。我試圖打破任務分成更小的功能可讀性幫助:
#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