产生所有排列---字典顺序-----2013年1月23日

简介:
   问题描述:以字典顺序产生所有排列。假定集合set是连续的并且按从小到大顺序排列好了的,并且有n个元素。
       思路:算法的思路分成两个部分:A是递归产生以某个数字开头的排列,B是调用A来依次生成  1为第一位的所有排列,2为第一位的所有排列,....n为第一位的所有排列。
       下面是A部分的详细思路:
        1.以1234为例子。从右到左来寻找< (j=i+1,i>0)。
        2.接着再从右到左查找第一个比大的元素,然后将二者交换位置,再将到集合末尾逆序。这样就找到了1234的按字典顺序的下一个元素。
        3.递归进行。要注意递归的一个关键就是递归的结束条件。这里,以1开头的排列的最后一个数是1432,也就是说最后一个元素到第2个元素(第一个元素为1,肯定不能动)都没有<,也就是说,第二位及以后的元素都按照逆序排列好了,也就是找到了最后一个元素。这就是递归结束的条件。
        A部分的代码如下:
 1 //find out all of the permutation in the set with first element 1 to n.
 2 void find_next()
 3 {
 4     set_print();
 5     int index_i,index_j,index_k;
 6     flag=0;
 7     for(index_i=n-2;index_i>0;index_i--)       
 8         if(set[index_i]<set[index_i+1])
 9         {
10             index_j=index_i+1;
11             flag=1;
12             break;
13         }
14     if(flag==0)
15         return ;
16     for(index_k=n-1;index_k>0;index_k--)
17         if(set[index_k]>set[index_i])
18             break;
19     swap(&set[index_i],&set[index_k]);
20     reverse(index_j,n-1);
21     
22     find_next();
23 }
 
        下面是B部分的详细思路:        
       1.B部分的算法主要负责执行A算法之后的增大首位的转折点,举个例子,就是1432的下一个元素是2134,从首位是1变到了首位是2。
       2.当A算法执行完后,元素是1432,这时,将第4位与第1位交换,就会得到2431,那么,很容易看出除了第一位之外其余都是按照逆序排列的,2431肯定不是1432的下一个数,2431与1432之间肯定还存在有符合条件的排列。于是,将除了第一位之外的元素逆序,就可达到目的,即2134。这才是1432的下一个元素。
       3.当到达2431后,即2开头的最后一个元素,又将第3位与第一位交换,再将首位之后的元素逆序,即可得到3开头的第一个数。
       4.那么,可以总结出,当首位为1时,就将最后一位与首位交换;当首位为2时,就将倒数第2位与首位交换;当首位为3时,就将倒数第3位与首位交换.....依次类推。这其中的道理很容易想明白。这样持续n次,所有结果就都得到了。
       B部分的代码如下:
 1  int count=1;
 2     int i=n-1;
 3     while(i>=0)
 4     {
 5         set[0]=count++;
 6         find_next(); 
 7         swap(&set[0],&set[i]);
 8         reverse(1,n-1);
 9         i--;
10     }
 
       完整的代码如下:
View Code
 1 #include <stdio.h>
 2 #define MAX 1000
 3 
 4 int n=4; 
 5 int set[MAX]={1,2,3,4};
 6 int flag=0;
 7 
 8 //swap a and b
 9 void swap(int *a,int *b)
10 {
11     int temp=*a;
12     *a=*b;
13     *b=temp;
14 }
15 
16 //reverse a range of a set
17 void reverse(int start,int end)
18 {
19     int index_r=0;
20     int new_end=end-start;
21     for(index_r=0;index_r<=new_end/2;index_r++)
22         swap(&set[index_r+start],&set[new_end-index_r+start]);
23 
24 }
25 
26 void set_print()
27 {
28     int index;
29     for(index=0;index<n;index++)
30         printf("%d ",set[index]);
31     printf("\n");
32 }
33 
34 //find out all of the permutation in the set with first element 1 to n.
35 void find_next()
36 {
37     set_print();
38     int index_i,index_j,index_k;
39     flag=0;
40     for(index_i=n-2;index_i>0;index_i--)       
41         if(set[index_i]<set[index_i+1])
42         {
43             index_j=index_i+1;
44             flag=1;
45             break;
46         }
47     if(flag==0)
48         return ;
49     for(index_k=n-1;index_k>0;index_k--)
50         if(set[index_k]>set[index_i])
51             break;
52     swap(&set[index_i],&set[index_k]);
53     reverse(index_j,n-1);
54     
55     find_next();
56 }
57 
58 int main()
59 {
60     int count=1;
61     int i=n-1;
62     while(i>=0)
63     {
64         set[0]=count++;
65         find_next(); 
66         swap(&set[0],&set[i]);
67         reverse(1,n-1);
68         i--;
69     }
70     return 0;
71 }
 本文转自NeilHappy 51CTO博客,原文链接:http://blog.51cto.com/neilhappy/1125052,如需转载请自行联系原作者
相关文章
|
4月前
|
NoSQL Java Redis
Redis09-----List类型,有序,元素可以重复,插入和删除快,查询速度一般,一般保存一些有顺序的数据,如朋友圈点赞列表,评论列表等,LPUSH user 1 2 3可以一个一个推
Redis09-----List类型,有序,元素可以重复,插入和删除快,查询速度一般,一般保存一些有顺序的数据,如朋友圈点赞列表,评论列表等,LPUSH user 1 2 3可以一个一个推
|
5月前
|
C语言
C语言----随机输入10个数,从小到大依次排列
C语言----随机输入10个数,从小到大依次排列
|
6月前
|
算法
题目----移除元素
题目----移除元素
32 0
|
6月前
题目----从小到大输出
题目----从小到大输出
30 0
|
12月前
数组篇----485
数组篇----485
|
JSON 数据格式 Python
一日一技:包含非hashable元素的列表如何去重并保持顺序?
一日一技:包含非hashable元素的列表如何去重并保持顺序?
108 0
|
算法 Python
一日一技:包含元组的列表,对第一个元素升序第二个元素降序
一日一技:包含元组的列表,对第一个元素升序第二个元素降序
99 0
|
Shell
List有序可重复,Set无序不重复!
List有序可重复,Set无序不重复,这里指的是添加数据的顺序。
176 0
List有序可重复,Set无序不重复!
sort() 函数按照字符串顺序对值进行排序。
sort() 函数按照字符串顺序对值进行排序。
193 0
|
机器学习/深度学习 人工智能
排序----4种排序
排序----4种排序
77 0