问题:按字典顺序输出1,2,。。。,n的所有排列。
例如:① n=1时,答案为 {1}。
② n=2时,答案为 {1,2},{2,1}。
③ n=3时,答案为 {1,2,3},{1,3,2},{2,1,3},{2,3,1},{3,1,2},{3,2,1}。
④ n=4时,。。。。。。
n个元素的一个排列就是一个序偶(A1,A2,。。。,An),其中 Ai ∈[1,n],且 Ai≠Aj,当 i ≠ j 时。首先,我们解决如何输出所有的排列,而暂时不考虑是否符合字典顺序。
第一步能够做什么?在没有思路的时候,我们可以先尝试枚举或者搜索的思路。
第一步,列举所有A1可能的值。当我们将某一个元素放在A1的位置上后,问题就转换为构造剩下的n-1的元素的排列。因此,问题的规模减小。然后,列举所有A2可能的值。。。最后列举An的所有可能的值。
1 #include<stdio.h>
2 #define maxn 9
3 int array[maxn+1];
4 int visit[maxn+1];
5
6 void print()
7 {
8 int i;
9 for(i=1;i<=maxn;i++) printf("%d",array[i]);
10 printf("/n");
11 }
12
13 void DFS(int k)
14 {
15 int i;
16 for(i=1;i<=maxn;i++)
17 {
18 if(visit[i]==0)
19 {
20 array[k]=i;
21 visit[i]=1;
22
23 if(k==maxn) print();
24 else DFS(k+1);
25
26 visit[i]=0;
27 array[k]=0;
28 }
29 }
30 }
31
32 int main()
33 {
34 DFS(1);
35
36 return 0;
37 }
38
上面的这种方法叫做深度优先搜索(Depth-First-Search),使用了递归。下面是不用递归的写法:
1 #include<stdio.h>
2 #define maxn 9
3 int array[maxn+1];
4 int visit[maxn+1];
5
6 void print()
7 {
8 int i;
9
10 for(i=1;i<=maxn;i++)
11 printf("%d",array[i]);
12 printf("/n");
13 }
14
15 int main()
16 {
17 int i;
18
19 i=1;array[i]=0;
20 while(i>0)
21 {
22 visit[array[i]]=0; /* 退栈 */
23 array[i]=array[i]+1;
24 while(array[i]<=maxn&&visit[array[i]]) array[i]++;
25
26 if(array[i]>maxn)
27 i--; /* 回溯 */
28 else
29 {
30 visit[array[i]]=1; /* 进栈 */
31
32 if(i==maxn) print();
33 else { i++,array[i]=0; }
34 }
35 }
36
37 return 0;
38 }
39
第二种写法有的书上称为回溯,但是我还是没有体会到回溯和深度优先搜索有什么区别。