zoukankan      html  css  js  c++  java
  • 产生所有排列字典顺序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 }

     参考资料:《C语言名题精选百则技巧篇》

    如果你觉得我的文章对你有帮助,请推荐一下,非常感谢!

  • 相关阅读:
    Security headers quick reference Learn more about headers that can keep your site safe and quickly look up the most important details.
    Missing dollar riddle
    Where Did the Other Dollar Go, Jeff?
    proteus 与 keil 联调
    cisco router nat
    router dhcp and dns listen
    配置802.1x在交换机的端口验证设置
    ASAv931安装&初始化及ASDM管理
    S5700与Cisco ACS做802.1x认证
    playwright
  • 原文地址:https://www.cnblogs.com/NeilHappy/p/2873737.html
Copyright © 2011-2022 走看看