1. 程式人生 > >遞迴、分治-排列問題

遞迴、分治-排列問題

之前用暴力求解法求結果全排列,現在我們用分治的方法重新求解一遍。

輸入:陣列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是用與交換兩個變數值的行內函數。