//全排列演算法:<br />//<br />// 思路很簡單很經典,目的是由小到大依次輸出結果;非遞迴方法<br />// 不知道該怎樣描述,所以給個例子:<br />//例子:<br />// 假如當前排列dbeca,求其下個排列(經過人工排列,結果顯然是dcabe)。<br />// 1)從右向左尋找第一個由小到大的(長度為2的)字串,這裡是be<br />// 2)那麼b後面是字串eca,其中比b大的最小字元是c<br />// 3)將b和c交換,則現在的排列是dceba<br />// 4)將c後面的字串eba由小到大排序,則現在的排列是dcabe(這就是結果)<br />// 5)重複第1步<br />//使用語言:c++<br />//經測試:10個字元全排列需要8分鐘左右,主要費時在列印結果在螢幕;如果不列印,<br />// 僅需10秒左右;cpu是AMD 3500+<br />//如有錯誤,請指正! </p><p>#include "stdafx.h"<br />#include <iostream><br />#include <vector><br />#include <cassert><br />#include <algorithm> </p><p>typedef char Kind;//定義比較資料的種類,這裡是char。只是為了修改方便 </p><p>bool Compare(const std::vector<Kind>& Array, int nIndex1, int nIndex2)<br />{<br />//比較Array[nIndex1]和Array[nIndex2]的大小;如果大於,則返回true;否則返回false;<br />//[IN]Array: 一個排列<br />//[IN]nIndex1, nIndex2: Array的下標<br />//附:定義這個函數只是為了增強易修改行;如果Kind是其他類型,比如是string類型,<br />// 只修改這函數的比較規則就行了<br />//注意:顯然忽略了相等的情況,假設了各個元素不相等 </p><p> assert(Array[nIndex1] != Array[nIndex2]); </p><p> return ( Array[nIndex1] > Array[nIndex2] );<br />} </p><p>int FirstSmallToBig(const std::vector<Kind>& Array)<br />{<br />//在Array中,從右向左尋找第一個由小到大的(長度為2的)字串,並返回此字串在<br />// Array中的位置<br />//[IN]Array: 一個排列<br />//傳回值:尋找到的字串在Arrray中的位置;如果傳回值為-1表示沒有找到 </p><p> int nPos = -1;//傳回值 </p><p> for(int i=Array.size()-1; i>=1; --i)<br /> {<br /> if( Compare(Array, i, i-1) )<br /> {<br /> nPos = i-1;<br /> break;<br /> }<br /> } </p><p> return nPos;<br />} </p><p>int MinBigThan(const std::vector<Kind>& Array, int nIndex)<br />{<br />//獲得Array[nIndex+1]到Array末尾中,比Array[nIndex]大的最小元素在Array中的位置<br />//[IN]Array: 一個排列<br />//[IN]nIndex: Array的下標<br />//傳回值:Array[nIndex+1]到Array末尾中,比Array[nIndex]大的最小元素在Array中的<br />// 位置(即下標) </p><p> int nPos = -1;//傳回值<br /> std::vector<Kind> v;//用於儲存(Array[nIndex+1]到Array末尾中)比Array[nIndex]大的最小元素<br /> v.push_back( Array[nIndex] );<br /> std::vector<Kind>::iterator it = v.begin(); </p><p> //尋找第一個比Array[nIndex]大的元素<br /> for(int i=nIndex+1; i<Array.size(); ++i)<br /> {<br /> if( Compare(Array, i, nIndex) )<br /> {<br /> v[0] = Array[i];<br /> nPos = i;<br /> break;<br /> }<br /> }<br /> ++i;<br /> if( i == Array.size() )<br /> {<br /> assert(nPos != -1);<br /> return nPos;<br /> } </p><p> assert(v[0] != Array[nIndex]); </p><p> //獲得Array[nIndex+1]到Array末尾中,比Array[nIndex]大的最小元素在Array中的位置<br /> for(; i<=Array.size(); ++i)<br /> {<br /> if( Compare(Array, i, nIndex) && Array[i]<v[0])<br /> {<br /> v[0] = Array[i];<br /> nPos = i;<br /> }<br /> } </p><p> assert(nPos != -1);<br /> return nPos;<br />} </p><p>void Swap(std::vector<Kind>& Array, int nIndex1, int nIndex2)<br />{<br />//Array[nIndex1]和Array[nIndex2]交換元素 </p><p> assert( nIndex1>=0 && nIndex1<Array.size() );<br /> assert( nIndex2>=0 && nIndex2<Array.size() ); </p><p> std::vector<Kind> temp;<br /> temp.push_back(Array[nIndex1]);<br /> Array[nIndex1] = Array[nIndex2];<br /> Array[nIndex2] = temp[0]; </p><p>} </p><p>void Print(const std::vector<Kind>& Array)<br />{<br />//列印結果 </p><p> using std::cout;<br /> using std::endl; </p><p> for(int i=0; i<Array.size(); ++i)<br /> cout<<Array[i];<br /> cout<<endl; </p><p>}<br />void Permutation(std::vector<Kind>& Array)<br />{<br />//求全排列<br />//[IN]Array: 全排列的數組;要求升序排列 </p><p> int nIndex1,nIndex2; </p><p> int nNum=0;//用於統計結果的個數 </p><p> Print(Array);//列印一個結果<br /> nNum++;<br /> while(1)<br /> {<br /> nIndex1 = FirstSmallToBig( Array );//從右向左尋找第一個由小到大的(長度為2的)字串<br /> if(nIndex1 == -1) break;//如果找不到,表示已經是降序排列,程式結束。<br /> nIndex2 = MinBigThan( Array, nIndex1 );//獲得Array[nIndex+1]到Array末尾中,比Array[nIndex]大的最小元素在Array中的位置<br /> Swap( Array, nIndex1, nIndex2 );//Array[nIndex1]和Array[nIndex2]交換元素<br /> std::sort( Array.begin()+nIndex1+1 , Array.end() );//對Array[nIndex+1]到Array末尾的元素排序 </p><p> Print(Array);//列印一個結果<br /> nNum++;<br /> } </p><p> std::cout<<"結果的個數:"<<nNum<<std::endl; </p><p>} </p><p>const int nsize =10;//元素的個數<br />int main(int argc, char* argv[])<br />{<br /> Kind a[20] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n'};<br /> std::vector<Kind> Array(a,a+nsize); </p><p> Permutation(Array); </p><p> return 0;<br />}