集合的全排列问题(递归实现)

设R={r1,r2,r3,.....rn}要进行全排列的n个元素,集合X中元素的全排列记为perm(X),则(ri)perm(X)表示在全排列perm(X)的每一个排列前加上前缀ri得到的排列。R的全排列定义可归纳定义如下:

当n=1时,perm(R) = (r),其中r为集合R中唯一元素

当n>1时,perm(R)由(r1)perm(R1)、(r2)perm(R2).........构成

因此可以设计全排列的递归算法;

//产生元素k—m的全排列,作为k-1个元素的后缀
void Perm(int list[], int k, int m){
    //构成一次全排列,输出结果
    if( k == m ){
        for( int i = 0; i < m; i++ )
            cout<<list[i]<<" ";
        cout<<endl; 
    }
    else{
        //在数组list中,产生元素k—m的全排列
        for( int j = k; j <= m; j++){
            swap(list[k],list[j]);
            Perm(list,k+1,m);
            swap(list[k],list[j]);
        } 
    } 
} 

递归实现对排列1,2,3,4进行全排列:

#include<iostream>
#include<algorithm> //sort(),swap()函数头文件 
using namespace std;
void Perm(int a[], int k, int m){
    if( k == m ){
        for(int i = 0; i <= m; i++)
            cout<<a[i]<<" ";
        cout<<endl;
    }
    else{
        for(int j = k; j <= m; j++){
            swap(a[k],a[j]);
            Perm(a,k+1,m);
            swap(a[k],a[j]);
        }
    }    
}
int main(){
    int a[4] = {1,2,3,4}; //对数组中的1,2,3,4进行全排列 
    Perm(a,0,3);
    return 0;
}

用C++STL库中的next_permutation(start,end),实现对集合的全排列。

next_permutation(start,end),和prev_permutation(start,end)。这两个函数作用是一样的,区别就在于前者求的是当前排列的下一个排列,后一个求的是当前排列的上一个排列。至于这里的“前一个”和“后一个”,我们可以把它理解为序列的字典序的前后,严格来讲,就是对于当前序列pn,他的下一个序列pn+1满足:不存在另外的序列pm,使pn<pm<pn+1.

对于next_permutation函数,其函数原型为:

     #include <algorithm>

     bool next_permutation(iterator start,iterator end)

当当前序列不存在下一个排列时,函数返回false,否则返回true

#include<iostream>
#include<algorithm>
using namespace std;
int main(){
    int a[4] = {1,2,3,4};
    do
    {
        cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<" "<<a[3]<<" "<<endl;
    }while(next_permutation(a,a+4));
    return 0;
}

另外,需要强调的是,next_permutation()在使用前需要对欲排列数组按升序排序。prev_permutation(start,end)在使用前需要对欲排列数组按降序排序

 

posted @ 2018-11-11 00:25  无心小男  阅读(2773)  评论(0编辑  收藏  举报