全排列

數字的全排列常見的是遞歸的方法。

  1. #include "stdafx.h"  
  2. #include <iostream>  
  3. using namespace std;  
  4.  
  5.  
  6.  
  7. int n = 0;    
  8. void output(int str[], int begin,int N)    
  9. {    
  10.     if (begin == N - 1)    
  11.     {    
  12.         for (int i = 0; i < N; i++)    
  13.         {    
  14.             cout<<str[i]<<"\t";    
  15.         }    
  16.         cout<<endl;    
  17.         n++;    
  18.         return;    
  19.     }    
  20.     for (int p = begin; p < N; p++)    
  21.     {    
  22.         int t = str[p];    
  23.         str[p] = str[begin];    
  24.         str[begin] = t;    
  25.         output(str, begin+1,N);    
  26.         t = str[p];    
  27.         str[p] = str[begin];    
  28.         str[begin] = t;    
  29.     }    
  30. }    
  31.  
  32. int _tmain(int argc, _TCHAR* argv[])    
  33. {    
  34.     int a[5],i;    
  35.     for (i = 0; i < 5; i++)    
  36.     {    
  37.         a[i] = i+1;    
  38.     }    
  39.     cout<<"所有的排序:"<<endl;    
  40.     output(a, 0,5);    
  41.     cout<<endl<<"共有 "<<n<<"種"<<endl;    
  42.     system("pause");    
  43.     return 0;    
  44. }  

如果不用遞歸,可以有以下方法:

非遞歸全排列算法的基本思想是:
    1.找到所有排列中最小的一個排列P.
    2.找到剛剛好比P大比其它都小的排列Q,
    3.循環執行第二步,直到找到一個最大的排列,算法結束.
下面用數學的方法描述:
給定已知序列 P =  A1A2A3An ( Ai!=Aj , (1<=i<=n  , 1<=j<=n, i != j  ) )
找到P的一個最小排列Pmin = P1P2P3Pn  有  Pi > P(i-1) (1 < i <= n)
從Pmin開始,總是目前得到的最大的排列爲輸入,得到下一個排列.
方法爲:
1.從低位到高位(從後向前),找出“不符合趨勢”的數字。即找到一個Pi,使Pi < P(i+1)。
  若找不到這樣的pi,說明我們已經找到最後一個全排列,可以返回了。
2.在 P(i+1)P(i+2)Pn 中,找到一個Pj,便得 Pj"剛剛好大於"Pi. 
  ("剛剛好大於"的意思是:在 P(i+1)P(i+2)Pn 中所有大於Pi的元素構成的集合中最小的元素.)其實從後向前找,第一個大於Pi的即是
3.交換 Pi , Pj 的位置.注意:此處不改變i和j的值,改變的是Pi和Pj.
4.交換後, P1P2P3Pn  並不是準確的後一個排列。因爲根據第1步的查找,我們有P(i+1) > P(i+2) > . > Pn
  即使進行了Pi和Pj的交換,這仍然是這一部分最大的一個排列。將此排列逆序倒置(變成最小的排列)即爲所求的下一個排列.
5.重複步驟1-4,直到步驟1中找不到“不符合趨勢”的數字.

 這個所謂的大小可以這麼理解:

1,2,3,4         3,2,1             ((3 * (3) + 2) * (2) + 1) * (1) = 23
1,2,4,3         3,2,0             ((3 * (3) + 2) * (2) + 0) * (1) = 22
1,3,2,4         3,1,1             ((3 * (3) + 1) * (2) + 1) * (1) = 21
1,3,4,2         3,1,0             ((3 * (3) + 1) * (2) + 0) * (1) = 20
1,4,3,2         3,0,1             ((3 * (3) + 0) * (2) + 1) * (1) = 19
.上面的中間轉換指的是:每一個數字後面比當前位數字大的數字的個數。                   .                      .

  1. #include "stdafx.h"    
  2. #include <stdio.h>    
  3. #include <stdlib.h>    
  4. #include <string.h>    
  5. #include <iostream>    
  6. using namespace std;    
  7. //交換數組a中下標爲i和j的兩個元素的值    
  8. void swap(int* a,int i,int j)    
  9. {    
  10.     a[i]^=a[j];    
  11.     a[j]^=a[i];    
  12.     a[i]^=a[j];    
  13. }    
  14. //將數組a中的下標i到下標j之間的所有元素逆序倒置    
  15.  
  16. void reverse(int a[],int i,int j)    
  17. {    
  18.     while (i < j)    
  19.         swap(a,i++,j--);    
  20. }    
  21. void print(int a[],int length)    
  22. {    
  23.     for(int i=0;i<length;++i)    
  24.         cout<<a[i]<<" ";    
  25.     cout<<endl;    
  26. }    
  27. //求取全排列,打印結果    
  28. void combination(int a[],int length)    
  29. {    
  30.     if(length<2) return;    
  31.     while(true)    
  32.     {    
  33.         print(a,length);    
  34.         int i,j;     
  35.         for(i=length-2;i>=0;--i) //找升序的相鄰2數,前一個數即替換數     
  36.         {    
  37.             if(a[i]<a[i+1]) break;    
  38.             else if(i==0) return;    
  39.         }    
  40.         for(j=length-1;j>i;--j) //從後往前找到替換點後第一個比替換數大的數    
  41.             if(a[j]>a[i]) break;    
  42.         swap(a,i,j);     
  43.         reverse(a,i+1,length-1); //將替換點以後的序列反轉    
  44.     }    
  45. }    
  46. int QsortCmp(const void *pa, const void *pb)      
  47. {      
  48.     return *(char*)pa - *(char*)pb;      
  49. }    
  50. int main()    
  51. {    
  52.     int arr[5] = {1,2,3,4,5};    
  53.     qsort(arr, 5, sizeof(arr[0]), QsortCmp); //排序之前先將數組遞增排序    
  54.     combination(arr, 5);    
  55. }   

另外更簡單的方法是可以用next_permutation函數,要包含頭文件algorithm,但要求數組是排好序的

  1. #include "stdafx.h"    
  2. #include <stdio.h>    
  3. #include <stdlib.h>    
  4. #include <string.h>    
  5. #include <iostream>    
  6. #include <algorithm>  
  7. using namespace std;    
  8.    
  9. int main()    
  10. {    
  11.     int a[] = {1,2,3};  
  12.     do{  
  13.         cout << a[0] << " " << a[1] << " " << a[2] << endl;  
  14.     }  
  15.     while (next_permutation(a,a+3));  
  16.     return 0;  
  17. }   

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章