(一)遞迴的全排列演算法
(A、B、C、D)的全排列為
1、A後面跟(B、C、D)的全排列
2、B後面跟(A、C、D)的全排列
3、C後面跟(A、B、D)的全排列
4、D後面跟(A、B、C)的全排列
而對1中的(B、C、D)照樣可以按照上面的形式進行分解。
/********************************************************************** * Compiler: GCC * Last Update: Mon 07 May 2012 07:08:58 PM CST * File Name: 1.cpp * Description: 利用stl中的next_permutation進行全排列 ************************************************************************/#include <iostream>using namespace std;template<typename T>void permutation(T array[], int begin, int end){ int i; if(begin == end){ for(i = 0; i <= end; ++i){ cout<<array[i]<<" "; } cout<<endl; return; } else { //for迴圈遍曆該排列中第一個位置的所有可能情況 for(i = begin; i <= end; ++i) { swap(array[i], array[begin]); permutation(array, begin + 1, end); swap(array[i], array[begin]); } }}int main(int argc, char **argv){ int a[4] = {1, 2, 3, 4}; permutation(a, 0, sizeof(a) / sizeof(int) - 1); return 0;}
(二)非遞迴全排列演算法,即按字典序排列演算法。
基本思想是:
1.對初始隊列進行排序,找到所有排列中最小的一個排列Pmin。
2.找到剛剛好比Pmin大比其它都小的排列P(min+1)。
3.迴圈執行第二步,直到找到一個最大的排列,演算法結束。
如排列ABCDE,這是所有排列中最小的一個排列,剛好比ABCDE大的排列是:ABCED。
演算法如下:
給定已知序列P = A1A2A3.....An
對P按字典排序,得到P的一個最小排列Pmin = A1A2A3....An ,滿足Ai > A(i-1) (1 < i <= n)
從Pmin開始,找到剛好比Pmin大的一個排列P(min+1),再找到剛好比P(min+1)大的一個排列,如此重複。
1.從後向前(即從An->A1),找到第一對為升序的相鄰元素,即Ai < A(i+1)。
若找不到這樣的Ai,說明已經找到最後一個全排列,可以返回了。
2.從後向前,找到第一個比Ai大的數Aj,交換Ai和Aj。
3.將排列中A(i+1)A(i+2)....An這個序列的數逆序倒置,即An.....A(i+2)A(i+1)。因為由前面第1、2可以得知,A(i+1)>=A(i+2)>=.....>=An,這為一個升序序列,應將該序列逆序倒置,所得到的新排列才剛剛好比上個排列大。
4.重複步驟1-3,直到返回。
這個演算法是C++ STL演算法next_permutation的思想。
/********************************************************************** * Compiler: GCC * Last Update: Mon 07 May 2012 07:08:58 PM CST * File Name: 1.cpp * Description: ************************************************************************/#include <iostream>#include <cstring>using namespace std;//交換數組a中下標為i和j的兩個元素的值void swap(int *a,int i,int j){ a[i]^=a[j]; a[j]^=a[i]; a[i]^=a[j];}//將數組a中的下標i到下標j之間的所有元素逆序倒置void reverse(int a[],int i,int j){ for(; i<j; ++i,--j) { swap(a,i,j); }}void print(int a[],int length){ for(int i=0; i<length; ++i) cout<<a[i]<<" "; cout<<endl;}//求取全排列,列印結果void combination(int a[],int length){ if(length<2) return; bool end=false; while(true) { print(a,length); int i,j; //找到不符合趨勢的元素的下標i for(i=length-2; i>=0; --i) { if(a[i]<a[i+1]) break; else if(i==0) return; } for(j=length-1; j>i; --j) { if(a[j]>a[i]) break; } swap(a,i,j); reverse(a,i+1,length-1); }}int main(int argc, char **argv){ int a[4] = {1, 2, 3, 4}; combination(a, sizeof(a) / sizeof(int)); return 0;}
用STL實現:
STL有一個函數next_permutation(),它的作用是如果對於一個序列,存在按照字典排序後這個排列的下一個排列,那麼就返回true且產生這個排列,否則返回false。
/********************************************************************** * Compiler: GCC * Last Update: Mon 07 May 2012 07:08:58 PM CST * File Name: 1.cpp * Description: 利用stl中的next_permutation進行全排列 ************************************************************************/#include <iostream>#include <algorithm>using namespace std;template <typename BidirectionalIterator>void permutation(BidirectionalIterator array, int len){ sort(array, array + len); do{ for(int i = 0; i < len; ++i){ cout<<array[i]<<" "; } cout<<endl; }while(next_permutation(array, array + len));}int main(int argc, char **argv){ int a[4] = {1, 2, 3, 4}; permutation(a, sizeof(a) / sizeof(int)); return 0;}
@@@@@@@@
來源:http://blog.csdn.net/hackbuteer1/article/details/6657435
http://plutoblog.iteye.com/blog/976216
http://blog.csdn.net/aipb2008/article/details/2227490