yhyan

问题:按字典顺序输出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  

  

  第二种写法有的书上称为回溯,但是我还是没有体会到回溯和深度优先搜索有什么区别。

分类:

技术点:

相关文章: