1求n個數的排列遞歸算法不重複。
- /*
- 可以使用遞迴將問題切割為較小的單元進行排列組合,
- 例如1 2 3 4的排列可以分為1 [2 3 4]、2 [1 3 4]、
- 3 [1 2 4]、4 [1 2 3]進行排列,
- 這邊利用旋轉法,先將旋轉間隔設為0,
- 將最右邊的數字旋轉至最左邊,並逐步增加旋轉的間
- 隔,
- 例如:
- 1 2 3 4 -> 旋轉1 -> 繼續將右邊2 3 4進行遞迴處理
- 2 1 3 4 -> 旋轉1 2 變為 2 1-> 繼續將右邊1 3 4進行遞迴處理
- 3 1 2 4 -> 旋轉1 2 3變為 3 1 2 -> 繼續將右邊1 2 4進行遞迴處理
- 4 1 2 3 -> 旋轉1 2 3 4變為4 1 2 3 -> 繼續將右邊1 2 3進行遞迴處理
- */
- #include <stdio.h>
- #include <stdlib.h>
- #define N 8
- void perm(int*, int);
- int main(void)
- {
- int num[N+1], i;
- for(i = 1; i <= N; i++)
- num[i] = i;
- perm(num, 1);
- return 0;
- }
- void perm(int* num, int i)
- {
- int j, k, tmp;
- if(i < N)
- {
- for(j = i; j <= N; j++)
- {
- tmp = num[j];
- // 旋轉該區段最右邊數字至最左邊
- for(k = j; k > i; k--)
- num[k] = num[k-1];
- num[i] = tmp;
- perm(num, i+1);
- // 還原
- for(k = i; k < j; k++)
- num[k] = num[k+1];
- num[j] = tmp;
- }
- }
- else
- { // 顯示此次排列
- for(j = 1; j <= N; j++)
- printf("%d ", num[j]);
- printf("/n");
- }
- }
2、有重複數字遞歸算法
- #define N 20
- // 下標爲N的data的個數
- int ndata[N]={0};
- // 總的個數
- int n;
- // 互不相同的數的個數
- int m;
- // 放數的位置
- int place[N];
- // 數
- int data[N];
- void printdata(int p)
- {
- int i=0;
- if (p==n)
- {
- //所有的位置已經填滿了輸出
- for(i=0;i<n;i++)
- printf("%d", place[i]);
- printf("/n");
- return ;
- }
- for (i=0; i<m; i++)
- {
- // 判斷m個不同的數是否用完了
- if (ndata[i]>0)
- {
- // 把數填到p位置
- place[p] = data[i];
- ndata[i]--;
- // 繼續填下一個位置
- printdata(p+1);
- ndata[i]++;
- }
- }
- }
- int main(int argc, char* argv[])
- {
- int i;
- int j;
- int temp;
- m = 0;
- while(scanf("%d", &n))
- {
- for (i=0; i<n;i++)
- {
- scanf("%d", &temp);
- // 找到就加1
- for (j=0; j<m; j++)
- {
- if (data[j] == temp)
- {
- ndata[j]++;
- break;
- }
- }
- // 找不到是新的數就m加1
- if (j==m)
- {
- data[m]=temp;
- ndata[j]++;
- m++;
- }
- }
- printdata(0);
- }
- return 0;
- }
3求n個數的排列非遞歸算法。
- // Function:求n個數的排列非遞歸算法。
- // Data:2011/4/10
- /*
- 觀察n=3的數排列:
- A:1 2 3
- B:1 3 2
- C:2 1 3
- D:2 3 1
- E:3 1 2
- F:3 2 1
- 1、從右往左查找一個比右邊數小的位置。對A爲2的位置p1。
- 2、從右往左找一個比p1位置數大的第一個數的位置p2.A爲3的位置
- 3、把p1與p3調換位置。
- 4、把位置p1以後右邊的數逆轉。
- 對於從B到C。p1的位置爲1(1<3),p2位置爲2(2>1)。1和2交換。得到231
- 對p1以後的數逆轉。p1後面的數爲31逆轉爲13.所以有C:213
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <malloc.h>
- // 交換兩個數
- void swap(int *a, int *b)
- {
- int temp;
- temp = *a;
- *a = *b;
- *b = temp;
- }
- int main(void)
- {
- int N;
- int i;
- int j;
- int k;
- // 輸入
- scanf("%d", &N);
- // 分配內存
- int *Num = (int *)malloc(sizeof(int)*N);
- // 初始化
- for (i=0; i<N; i++)
- Num[i] = i+1;
- do
- {
- for (i=0; i<N; i++)
- printf("%2d", Num[i]);
- printf("/n");
- // 從右往左找到一個比右邊的數小的數作爲位置:1
- for(i=N-1; i>0; i--)
- if (Num[i]>Num[i-1])
- break;
- // 當Num[1] < Num[0]時i==0結速for循環
- // 找不到位置:1
- // 跳出do循環
- if (0 == i)
- break;
- // 從右往左找,直到找到第一個數比位置1上的數大
- for (j=N-1; j>i-1; j--)
- if (Num[j]>Num[i-1])
- break;
- // 交換兩個數的位置
- swap(&Num[j], &Num[i-1]);
- // 把1位置後面的數逆轉
- for (j=i, k=N-1; j<k; j++, k--)
- swap(&Num[j], &Num[k]);
- }while(1);
- // 釋放內存
- free(Num);
- return 0;
- }