遞迴實現全排列問題
阿新 • • 發佈:2018-12-11
問題:
有一組數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; }