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

全排列遞迴實現

#include <iostream>
using namespace std;
void swap(int &a,int &b){
    int temp=a;
    a=b;
    b=temp;
}
void perm(int list[],int low,int high){
    if(low==high){   //當low==high時,此時list就是其中一個排列,輸出list
        for(int i=0;i<=low;i++)
            cout<<list[i];
        cout<<endl;
    }else{
        for(int i=low;i<=high;i++){//每個元素與第一個元素交換
            swap(list[i],list[low]); 
            perm(list,low+1,high); //交換後,得到子序列,用函式perm得到子序列的全排列
            swap(list[i],list[low]);//最後,將元素交換回來,復原,然後交換另一個元素
        }
    }
}
int main()
{

int list[]={1,2,3};
perm(list,0,2);
return 0;
}



我們把上面全排列的方法歸納一下,基本上就是:任意選一個數(一般從小到大或者從左到右)打頭,對後面的n-1個數進行全排列。聰明的讀者應該已經發現,這是一個遞迴的方法,因為要得到n-1個數的全排列,我們又要先去得到n-2個數的全排列,而出口是隻有1個數的全排列,因為它只有1種,為它的本身。寫成比較規範的流程:


1.開始for迴圈。


2.改變第一個元素為原始陣列的第一個元素(什麼都沒做)。


3.求第2個元素到第n個元素的全排列。


4.要求第2個元素到第n個元素的全排列,要遞迴的求第3個元素到第n個元素的全排列。......


5.直到遞迴到第n個元素到第n元素的全排列,遞迴出口。


6.將改變的陣列變回。


7.改變第一個元素為原始陣列的第二個元素。




(注:理論上來說第二次排列時才改變了第一個元素,即第6步應該此時才開始執行,但由於多執行一次無義的交換影響不大,而這樣使得演算法沒有特殊情況,更容易讀懂,如果一定要省時間可以把這步寫在此處,這種演算法我在下文中便不給出了,讀者可以自己寫。)5.求第2個元素到第n個元素的全排列。


6.要求第2個元素到第n個元素的全排列,要遞迴的求第3個元素到第n個元素的全排列。......
5.直到遞迴到第n個元素到第n元素的全排列,遞迴出口。6.將改變的陣列變回。......
8.不斷地改變第一個元素,直至n次使for迴圈中止。