設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)在使用前需要對欲排列數組按降序排序