递归之排列问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了递归之排列问题相关的知识,希望对你有一定的参考价值。

   设R={r1,r2,...,rn}是要进行排列的n个元素,Ri=R-{ri}.集合X中元素的全排列记为Perm(X)。

   (ri)Perm(X)表示在全排列Perm(X)的每一个排列前加前缀ri得到的排列。

R的全排列可以归纳定义如下:

   1. 当n=1时,Perm(R)=(r),其中r是集合R中唯一的元素;

   2. 当n>1时,Perm(R)由(ri)Perm(R1),(r2)Perm(R2),...,(rn)Perm(Rn)构成。

   由此递归定义,可设计产生Perm(R)的递归算法如下:(此处以int类型为例)

   void Perm(int list[],int k,int m)

   {//产生list[k;m]的所有排列

          if(k ==m){//要排列的只有一个元素

                           for(int i=0;i<=m;i++)  printf("%d",list[i]);

                           printf("\n");

          else{

                           for(int j=k;i<=m;j++){

                                                              Swap(list[j],list[k]);//每次交换第j和k个元素,这样每个元素都曾出现在最前面过,然后递归剩下的元素;

                                                              Perm(list,k+1,m);//进入递归;

                                                              Swap(list[k],list[i]);//恢复原本元素的次序;

                                                             }

  }

  inline void Swap(int *a,int *b)//交换函数的定义,此处用内联函数可以节省内存

  {

          int temp=*a;

          *a=*b;

          *b=temp;

  }

下面以{a,b,c}的全排列为例来说明这个算法:

{a,b,c}--->{a,b,c},第一次进入递归{a,(b,c)}--->{a,(b,c)},

第二次进入递归{a,b,(c)},此时k=m=2,输出"a,b,c",返回上一层的递归现场,恢复为{a,b,c}且j+1,

{a,b,c}--->{a,(c,b)},第三次进入递归{a,c,(b)},k=m=2,输出"a,c,b",返回上一层的递归现场,恢复为{a,b,c}且j+1,

{a,b,c}--->{b,a,c},第四次进入递归{b,(a,c)},

第五次进入递归{b,a,(c)},此时k=m,输出"b,a,c",返回上一层的递归现场,恢复为{b,(a,c)}且j+1,

{b,(a,c)}--->{b,(c,a)},第六次进入递归{b,c,(a)},k=m又输出"b,c,a",返回上一层的递归现场,恢复为{a,b,c}且j+1,

{a,b,c}--->{c,b,a},第七次进入递归(c,(b,a)),

第八次进入递归{c,b,(a)},此时k=m,输出"c,b,a",返回上一层的递归现场,恢复为{c,(b,a)}且j+1,

{c,(b,a)}--->{c,(a,b)},第九次进入递归{c,a,(b)},k=m又输出"c,a,b",返回上一层的递归现场,恢复为{a,b,c}且j+1,

执行到目前,j=4,for循环停止,算法结束.

 

以上是关于递归之排列问题的主要内容,如果未能解决你的问题,请参考以下文章

算法竞赛之递归——输出1-n的所有排列

字符串算法之 应用递归进行全排列

求全排列

全排列问题的递归算法(Perm)

递归解决全排列生成算法

回溯法之排列组合