求解n个元素{r1,r2,…,rn}的全排列。
n个元素的全排列有n!种可能。解题基本方法:
(1)固定位置放元素
(2)固定元素找位置
1.固定位置放元素
假设R={r1,r2,…,rn}是待排列的n个元素,Ri=R-{ri}。假设集合Ri中元素的全排列记为perm(Ri)。
(ri)perm(Ri)表示在全排列perm(Ri)的每一个排列的第一个位置加前缀ri得到的排列。
#include <stdio.h>
int swap(int *a,int *b)
{
int temp;
temp=*a;
*a=*b;
*b=temp;
return 0;
}
void perm(int r[], int i, int n) {
if ( i == n ) { // 只有一个数值
for (int j = 0; j <= n; j++) { // 输出结果
printf("%d",r[j]);
}
printf("\n");
}
else {
for (int j = i; j <= n; j++) {
int *a = &r[i];
int *b = &r[j];
swap(a,b); // 交换r[i]与r[j]
perm(r, i + 1, n); //计算i+1~ n 全排列
swap(a,b);
}
}
}
int main (void){
int arr[] = {1,2,3};
perm(arr,0,2);
}
2.固定元素找位置
在 n-1 个元素的全排列基础上,将某个元素插入到每个位置上,进而得出 n 个元素的全排列。基本过程:
将n放在p[1]位置上,并求得剩余N-1个元素在p[2]~p[n]的全排列,这就是一个子问题了;
将n放在p[2]位置上,并用p[1]和p[3]~p[n]产生n-1个元素的全排列;
将n放在p[3]位置上,并用p[1]、p[2]和p[4]~p[n]产生n-1个元素的全排列;
...........
直到将n放在p[n]位置上,并用p[1..n-1]产生n-1个元素的全排列。
#include <stdio.h>
void perm2(int p[], int n) {
int NUM = n-1;//这里是计算数组最大的下标
int i,j;
if (n == 0) { // 元素集合为空
for (i = 0; i <= NUM ; i++) { // 输出结果
printf("%d",p[i]);
}
printf("\n");
}
else {
for (j = 0; j <= NUM; j++) {
if (p[j] == 0) {
p[j] = n;
perm2(p, n-1);
p[j] = 0;
}
}
}
}
void main(void)
{
int arr[] = {0,0,0};
perm2(arr,3);
}