对一组数字输出其全排列
设R= {r1,r2,...,rn}是要进行排列的n个元素, Ri = R - {ri}。集合X中元素的全排列记为perm(X )。 (ri)perm(X)表示在全排列perm(X)的每一个排列前加上前缀ri得到的排列。R的全排列可归纳定义如下:
当 n = 1 时, perm(R) = (r),其中r是集合R中唯一的元素。
当 n > 1 时, perm(R)由(r1)perm(R1),(r2)perm(R2),...,(r3)perm(R3)构成。
比如:把1,2,3三个数进行全排列,程序的主要思路是:
把第1个数换到最前面来(本来就在最前面),准备打印1xx,再对后两个数2和3做全排列。
把第2个数换到最前面来,准备打印2xx,再对后两个数1和3做全排列。
把第3个数换到最前面来,准备打印3xx,再对后两个数1和2做全排列。
可见这是一个递归的过程,把对整个序列做全排列的问题归结为对它的子序列做全排列的问题。
解题过程:
(1) 当 N = 1的时候,则直接打印数列即可。
(2) 当 N = 2的时候,设数组为 [a, b]
打印a[0], a[1] (即a,b)
交换a[0],a[1]里面的内容
打印a[0],a[1] (此时已变成了 [b, a] )
(3) 当 N = 3的时候,数组为 [a, b, c]
把a放在 a[0] 的位置(原本也是如此,a[0] = a[0]),打印b,c的全排列(即a[1], a[2]的全排列)
a b c
a c b
把b放在a[0]的位置(这时候需要交换原数组的a[0]和a[1]),然后打印a, c的全排列
b a c
b c a
打印完后再换回原来的位置,即a还是恢复到a[0],b还恢复到a[1]的位置
把c放在a[0]的位置(这时候需要交换的是原数组的a[0]和a[2]),然后打印a, b的全排列
c b a
c a b
打印完后再换回原来的位置,即a还是恢复到a[0],b还恢复到a[1]的位置,至此,全排列完成
当 N = 4,5,6,……的时候,以此类推。
C语言程序:
1 #include<stdio.h> 2 //全排列问题 3 void perm(int *a, int k, int m) 4 { 5 int i; 6 int temp; 7 8 if(k == m) 9 { 10 for(i = 0; i <= m; ++i) 11 printf("%d", a[i]); 12 printf(" "); 13 } 14 else 15 { 16 for(i = k; i <= m; ++i) 17 { 18 temp = a[i]; //依次将第k个元素与剩余元素交换 19 a[i] = a[k]; 20 a[k] = temp; 21 perm(a, k + 1, m); //对数组a进行除第k个元素外的所有元素全排列 22 temp = a[i]; //排列完成后换回原来的位置 23 a[i] = a[k]; 24 a[k] = temp; 25 } 26 } 27 } 28 29 int main(void) 30 { 31 int b[4] = {1,2,3,4}; 32 perm(b, 0, 3); 33 34 return 0; 35 }
不过这样存在一点小小的缺陷:两个相同的数也进行了交换
代码改进
去掉重复符号的全排列:在交换之前可以先判断两个符号是否相同,不相同才交换,这个时候需要一个判断符号是否相同的函数。
1 #include<stdio.h> 2 //全排列问题 3 int isSwap(int *a, int nBegin, int nEnd) //判断是否相等,如果相等则不交换 4 { 5 int i; 6 7 for(i = nBegin; i < nEnd; i++) 8 if (a[i] == a[nEnd]) 9 return 0; 10 return 1; 11 } 12 13 void perm(int *a, int k, int m) 14 { 15 int i; 16 int temp; 17 18 if(k == m) 19 { 20 for(i = 0; i <= m; ++i) 21 printf("%d", a[i]); 22 printf(" "); 23 } 24 else 25 { 26 for(i = k; i <= m; ++i) 27 { 28 if(isSwap(a, k, i) ) 29 { 30 temp = a[i]; //依次将第k个元素与剩余元素交换 31 a[i] = a[k]; 32 a[k] = temp; 33 perm(a, k + 1, m); //对数组a进行除第k个元素外的所有元素全排列 34 temp = a[i]; //排列完成后换回原来的位置 35 a[i] = a[k]; 36 a[k] = temp; 37 } 38 } 39 } 40 } 41 42 int main(void) 43 { 44 int b[4] = {1,2,3,4}; 45 int c[4] = {2,2,3,4}; 46 perm(b, 0, 3); 47 printf(" "); 48 perm(c, 0, 3); 49 50 return 0; 51 }