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;
- }