n個數的排列

 

1求n個數的排列遞歸算法不重複。

Code:
  1. /*     
  2. 可以使用遞迴將問題切割為較小的單元進行排列組合,     
  3. 例如1 2 3 4的排列可以分為1 [2 3 4]、2 [1 3 4]、     
  4. 3 [1 2 4]、4 [1 2 3]進行排列,     
  5. 這邊利用旋轉法,先將旋轉間隔設為0,     
  6. 將最右邊的數字旋轉至最左邊,並逐步增加旋轉的間     
  7. 隔,     
  8. 例如:      
  9. 1 2 3 4 -> 旋轉1 -> 繼續將右邊2 3 4進行遞迴處理      
  10. 2 1 3 4 -> 旋轉1 2 變為 2 1-> 繼續將右邊1 3 4進行遞迴處理      
  11. 3 1 2 4 -> 旋轉1 2 3變為 3 1 2 -> 繼續將右邊1 2 4進行遞迴處理      
  12. 4 1 2 3 -> 旋轉1 2 3 4變為4 1 2 3 -> 繼續將右邊1 2 3進行遞迴處理      
  13. */      
  14.       
  15. #include <stdio.h>         
  16. #include <stdlib.h>         
  17. #define N 8          
  18. void perm(int*, int);           
  19. int main(void)        
  20. {         
  21.     int num[N+1], i;           
  22.     for(i = 1; i <= N; i++)         
  23.         num[i] = i;           
  24.     perm(num, 1);           
  25.     return 0;         
  26. }           
  27.       
  28. void perm(int* num, int i)        
  29. {         
  30.     int j, k, tmp;          
  31.         
  32.     if(i < N)        
  33.     {         
  34.         for(j = i; j <= N; j++)       
  35.         {         
  36.             tmp = num[j];         
  37.             // 旋轉該區段最右邊數字至最左邊         
  38.             for(k = j; k > i; k--)       
  39.                 num[k] = num[k-1];         
  40.             num[i] = tmp;           
  41.             perm(num, i+1);        
  42.                       
  43.             // 還原         
  44.             for(k = i; k < j; k++)         
  45.                 num[k] = num[k+1];         
  46.             num[j] = tmp;         
  47.         }         
  48.     }       
  49.              
  50.     else        
  51.     {  // 顯示此次排列         
  52.         for(j = 1; j <= N; j++)         
  53.             printf("%d ", num[j]);         
  54.         printf("/n");         
  55.     }         
  56. }       

 2、有重複數字遞歸算法

Code:
  1.   
  2. #define N 20   
  3. // 下標爲N的data的個數   
  4. int ndata[N]={0};   
  5. // 總的個數   
  6. int n;   
  7. // 互不相同的數的個數   
  8. int m;   
  9. // 放數的位置   
  10. int place[N];   
  11. // 數   
  12. int data[N];   
  13. void printdata(int p)   
  14. {   
  15.     int i=0;   
  16.     if (p==n)   
  17.     {   
  18.         //所有的位置已經填滿了輸出   
  19.         for(i=0;i<n;i++)   
  20.             printf("%d", place[i]);   
  21.         printf("/n");   
  22.         return ;   
  23.     }   
  24.   
  25.    for (i=0; i<m; i++)   
  26.    {   
  27.        // 判斷m個不同的數是否用完了   
  28.      if (ndata[i]>0)   
  29.      {   
  30.          // 把數填到p位置   
  31.         place[p] = data[i];   
  32.         ndata[i]--;   
  33.         // 繼續填下一個位置   
  34.         printdata(p+1);   
  35.         ndata[i]++;   
  36.      }   
  37.    }   
  38. }   
  39. int main(int argc, char* argv[])   
  40. {   
  41.   
  42.     int i;   
  43.     int j;   
  44.     int temp;   
  45.     m = 0;   
  46.     while(scanf("%d", &n))   
  47.     {   
  48.         for (i=0; i<n;i++)   
  49.         {   
  50.             scanf("%d", &temp);   
  51.             // 找到就加1   
  52.             for (j=0; j<m; j++)   
  53.             {   
  54.                 if (data[j] == temp)   
  55.                 {   
  56.                 ndata[j]++;   
  57.                 break;   
  58.                 }   
  59.             }   
  60.   
  61.             // 找不到是新的數就m加1   
  62.             if (j==m)   
  63.             {   
  64.                 data[m]=temp;   
  65.                 ndata[j]++;   
  66.                 m++;   
  67.             }   
  68.         }   
  69.   
  70.         printdata(0);   
  71.     }   
  72.     return 0;   
  73. }  

 

 3求n個數的排列非遞歸算法。

Code:
  1. // Function:求n個數的排列非遞歸算法。   
  2. // Data:2011/4/10   
  3. /*  
  4. 觀察n=3的數排列:  
  5. A:1 2 3  
  6. B:1 3 2  
  7. C:2 1 3  
  8. D:2 3 1  
  9. E:3 1 2  
  10. F:3 2 1  
  11. 1、從右往左查找一個比右邊數小的位置。對A爲2的位置p1。  
  12. 2、從右往左找一個比p1位置數大的第一個數的位置p2.A爲3的位置  
  13. 3、把p1與p3調換位置。  
  14. 4、把位置p1以後右邊的數逆轉。  
  15. 對於從B到C。p1的位置爲1(1<3),p2位置爲2(2>1)。1和2交換。得到231  
  16. 對p1以後的數逆轉。p1後面的數爲31逆轉爲13.所以有C:213  
  17. */  
  18. #include <stdio.h>   
  19. #include <stdlib.h>   
  20. #include <malloc.h>   
  21.   
  22. // 交換兩個數   
  23. void swap(int *a, int *b)   
  24. {   
  25.     int temp;   
  26.     temp = *a;   
  27.     *a = *b;   
  28.     *b = temp;   
  29. }   
  30. int main(void)   
  31. {   
  32.     int N;   
  33.     int i;   
  34.     int j;   
  35.     int k;   
  36.     // 輸入   
  37.     scanf("%d", &N);   
  38.   
  39.     // 分配內存   
  40.     int *Num = (int *)malloc(sizeof(int)*N);   
  41.   
  42.     // 初始化   
  43.     for (i=0; i<N; i++)   
  44.         Num[i] = i+1;   
  45.   
  46.     do  
  47.     {   
  48.         for (i=0; i<N; i++)   
  49.             printf("%2d", Num[i]);   
  50.         printf("/n");   
  51.         // 從右往左找到一個比右邊的數小的數作爲位置:1   
  52.         for(i=N-1; i>0; i--)   
  53.             if (Num[i]>Num[i-1])   
  54.                 break;   
  55.             // 當Num[1] < Num[0]時i==0結速for循環   
  56.             // 找不到位置:1   
  57.             // 跳出do循環   
  58.             if (0 ==  i)   
  59.                 break;   
  60.   
  61.             // 從右往左找,直到找到第一個數比位置1上的數大   
  62.             for (j=N-1; j>i-1; j--)   
  63.                 if (Num[j]>Num[i-1])   
  64.                     break;   
  65.   
  66.                 // 交換兩個數的位置   
  67.                 swap(&Num[j], &Num[i-1]);   
  68.   
  69.                 // 把1位置後面的數逆轉   
  70.                 for (j=i, k=N-1; j<k; j++, k--)   
  71.                     swap(&Num[j], &Num[k]);   
  72.   
  73.     }while(1);   
  74.   
  75.     // 釋放內存   
  76.     free(Num);   
  77.     return 0;   
  78. }  

 

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