请高手分析一下此递归程序的算法思想!

2024-11-25 20:43:47
推荐回答(1个)
回答1:

/* 重命名注释版 */
#include
#include

enum Bool { False, True };

int cnt; /* 排列计数 */
int *perm; /* 当前试验的排列 */
enum Bool *valid; /* 标记某个数字是否用过 */

/* 其实就是穷举n^n种有重复数字的排列,从中挑出无重复数字的排列,算法效率不高。
* 调用try1(n, digit)表示接着当前的排列,先试填数字digit。注意同一数先填后填会造成不同的排列。
* 当valid数组全部为True,即各位都没有填数字的时候,就是从某个数开始填。
* 当找到一个无重复的数输出后,由于多层递归逐层返回,恰好也把所有的位都置回可填。
*/
void try1(int n, int digit) /* digit是试验要填入的数字 */
{
int cur; /* 当前试验的数位 */
for (cur = 0; cur < n; ++cur) /* 逐位试填 */
{
if (valid[cur] == True) { /* current位未填 */
perm[cur] = digit; /* 填数 */
valid[cur] = False; /* current位已填,在下面的递归中不能再填 */
if (digit == n) { /* 试出一个无重复的数字 */
int k;
cnt++; /* 计数 */
for(k = 0; k < n; ++k) /* 输出 */
printf("%d", perm[k]);
putchar('\n');
}
else
try1(n, digit + 1); /* 递归试验下一个数字 */
valid[cur] = True; /* 当前位试填完,取出,可在下一轮填。注意是在递归返回后执行 */
}
}
}

int main()
{
int n, i;

printf("input n = "); /* n是位数 */
scanf("%d", &n);

/* 开两个动态数组 */
perm = (int*) malloc(n * sizeof(int));
valid = (Bool*) malloc(n * sizeof(enum Bool));
if (perm == NULL || valid == NULL) exit(1);

for (i = 0; i < n; ++i) /* 初始化为全部数位可用 */
valid[i] = True;

try1(n, 1); /* 一开始试填1 */

printf("cnt = %d\n", cnt);

return 0;
}