1. 程式人生 > >遞迴實現全排列問題

遞迴實現全排列問題

問題:

有一組數R,需要輸出它的全排列。R的遞迴可定義如下: 當個數n為1時,Perm(R) = (r),其中r是集合R中唯一的元素 當個數n大於1時,Perm(R)由(r1)Perm(R1),(r2)Perm(R2),(r3)Perm(R3),…,(rn)Perm(Rn)構成 其中Ri = R - {ri} 即該集合中減去對應元素

思路:

遞迴地把這組數規模一個一個地縮小,如1,2,3,4. 先把1固定,遞迴地求2,3,4的全排列,又把2固定,遞迴地求3,4的全排列……直到只剩一個數,輸出這個排列。當獲取遞迴陣列時,從該組數的第一個,依次和每一位交換(包括本身),得以產生一個新遞迴陣列(如1,2,3,4,先是1和1交換,產生新的2,3,4),當1和1交換產生的所有遞迴完成之後,實際上已經完成了1234,1243,1324,1342,1432,1423的輸出,因為1和自己交換之後,產生了2,3,4。在這個過程中,當1,2,3固定時,只有4剩餘,所以輸出1,2,3,4.然後固定1,2,交換3,4的位置。輸出1,2,4,3.此時1,2固定的已經全部輸出,於是返回到只有1固定,那麼此時2需要與3交換位置,再進行1,3固定的遞迴。如下圖所示:

核心程式碼:

void Perm(Type list[],  int k, int m )
{ //產生[list[k:m]的所有排列
    if(k==m)
     {  //只剩下一個元素
         for (int i=0;i<=m;i++) 
     cout<<list[i];
         cout<<endl;
    }
    else  //還有多個元素待排列,遞迴產生排列
       for (int i=k; i<=m; i++)
        {
           swap(list[k],list[i]);
           Perm(list,k+1,m);   
           swap(list[k],list[i]);         
         }
}

完整程式碼:

#include <iostream>
#include <algorithm>

using namespace std;

void Perm(Type list[],  int k, int m )
{ //產生[list[k:m]的所有排列
    if(k==m)
     {  //只剩下一個元素
         for (int i=0;i<=m;i++) 
     cout<<list[i];
         cout<<endl;
    }
    else  //還有多個元素待排列,遞迴產生排列
       for (int i=k; i<=m; i++)
        {
           swap(list[k],list[i]);
           Perm(list,k+1,m);   
           swap(list[k],list[i]);         
         }
}

int main() {
    
    char s[]="abc";
    Perm(s,0,2);

    return 0;
}