遞迴、分治-排列問題
阿新 • • 發佈:2018-11-09
之前用暴力求解法求結果全排列,現在我們用分治的方法重新求解一遍。
輸入:陣列P大小n,陣列P中的各個元素。
輸出:陣列P的所有全排列。
執行結果:
設R = {r1,r2,..rn}是要進行排列的n個元素, Ri = R - {ri}.集合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),...,(rn)Perm(Rn)構成。
template <class Type> //模板函式 void Perm(Type list[], int k, int m) { //產生list[k, m]的所有排列 int i; if(k == m) { //只剩下一個元素 for(i = 0; i <= m; i++) cout << list[i] << " "; cout << endl; } else { //還有多個元素待排列,遞迴產生排列 for(i = k; i <= m; i++) { swap(list[k], list[i]); Perm(list, k+1, m); swap(list[k], list[i]); } } }
演算法Perm(list,k,m)遞迴地產生所有字首是list[0:k-1],且字尾是list[k,:m]的全排列的全排列的所有排列。函式呼叫Perm(list,0,n-1)則產生list[0,n-1]的全排列。
在一般情況下,k<m,演算法將list[k,m]中的每一個元素分別與list[k]中的元素交換。然後遞迴的計算list[k+1:m]的全排列,並將計算結果作為list[0:k]的字尾。演算法中Swap是用與交換兩個變數值的行內函數。