c语言输出数组的全排列组合,定义一个数组,编程打印它的全排列

定义一个数组,编程打印它的全排列。比如定义:

#define N 3

int a[N] = { 1, 2, 3 };

则运行结果是:

$ ./a.out

1 2 3

1 3 2

2 1 3

2 3 1

3 2 1

3 1 2

1 2 3

程序的主要思路是:

把第1个数换到最前面来(本来就在最前面),准备打印1xx,再对后两个数2和3做全排列。

把第2个数换到最前面来,准备打印2xx,再对后两个数1和3做全排列。

把第3个数换到最前面来,准备打印3xx,再对后两个数1和2做全排列。

可见这是一个递归的过程,把对整个序列做全排列的问题归结为对它的子序列做全排列的问题

解题过程:

(1) 当 N = 1的时候,则直接打印数列即可。

(2) 当 N = 2的时候,设数组为 [1, 2]

打印a[0], a[1] (即1,2)

交换a[0],a[1]里面的内容

打印a[0],a[1]   (此时已变成了 [2, 1] )

(3) 当 N = 3的时候,数组为 [1, 2, 3]

a.把1放在 a[0] 的位置(原本也是如此,a[0] = a[0]),打印2,3的全排列(即a[1], a[2]的全排列)

1  2  3

1  3  2b.  把2放在a[0]的位置(这时候需要交换原数组的a[0]和a[1]),然后打印1, 3的全排列

2   1  3

2   3  1

打印完后再换回原来的位置,即1还是恢复到a[0],2还恢复到a[1]的位置

c.把3放在a[0]的位置 (这时候需要交换的是原数组的a[0]和a[2]),然后打印1, 2的全排列

3   2  1

3   1  2

打印完后再换回原来的位置,即1还是恢复到a[0],3还恢复到a[2]的位置,

至此全排列完成

(4)N = 4, 5, 6....的思路与此相同

点击(此处)折叠或打开

#include

#define N 3

int a[N];

void perm(int); /*求数组的全排列 */

void print();

void swap(int, int);//交换前缀

int main(){

int i;

for(i = 0; i

a[i] = i + 1;

}

perm(0);

}

void perm(int offset){

int i, temp;

if(offset == N-1){

print();

return;

}else{

for(i = offset;i < N; i++){

swap(i, offset);//交换前缀

perm(offset + 1);//递归

swap(i, offset);//将前缀换回来,继续做前一次排列

}

}

}

void print(){

int i;

for(i = 0; i < N; i++)

printf(" %d ",a[i]);

printf("/n");

}

void swap(int i, int offset){

int temp;

temp = a[offset];

a[offset] = a[i];

a[i] = temp;

}

完成了上述要求之后再考虑第二个问题:如果再定义一个常量M表示从N个数中取几个数做排列(N == M时表示全排列),原来的程序照如下方式修改:

点击(此处)折叠或打开

#include

#include

#define N 4

#define M 3

int a[N]; /* N个数 */

int temp[M]; /* 从N个数中选出的M个数 */

void perm(int, int); /* 排列 */

void swap(int, int); /* 交换两个数 */

void print(); /* 打印 */

int main(){

int i;

int start = 0;//起始位置

int count = M;//排列到个数

for(i = 0; i < N; i++){

a[i] = i + 1;

}

perm(start, count);

}

void perm(int offset, int count){

int i;

if( count == 0 ){

print();

return;

}else{

for(i = offset; i < N; i++){

temp[offset] = a[i];

swap(offset, i);

perm(offset+1, count-1);

swap(offset, i);

}

}

}

void swap (int offset, int i){

int another;

another = a[offset];

a[offset] = a[i];

a[i] = another;

}

void print(){

int i;

for(i = 0; i < M; i++)

printf(" %d ",temp[i]);

printf("/n");

}

最后再考虑第三个问题:从N个数中取M个数做组合,

先看一个例子:

C(5,3) = 10

1 2 3

1 2 4

1 2 5

1 3 4

1 3 5

1 4 5

2 3 4

2 3 5

2 4 5

3 4 5

分析

1 | 2 3

1 | 2 4

1 | 2 5

1 | 3 4

1 | 3 5

1 | 4 5

------ C(4, 2)∵可以在{2, 3, 4, 5}中挑2个出来。

2 | 3 4

2 | 3 5

2 | 4 5

------ C(3, 2)∵可以在{3, 4, 5}中挑2个出来。

3 | 4 5

------ C(2, 2)∵只能在{4, 5}中挑2个出来。

这样就很容易写出递归算法来:

点击(此处)折叠或打开

Algorithm combination(n, k, A[l..n+l-1])

if k = 0

print ary[1..k]

else

for i←1 to n-k+1

ary[index++] = A[l+i-1]

combination(n-i, k-1, A[l+i..n+l-1])

--index

endfor

源代码如下:

点击(此处)折叠或打开

#include

#include

#define N 4

#define M 3

int a[N]; /* N个数 */

int temp[M]; /* 从N个数中选出的M个数 */

int top;

void comb(int, int); /* 组合 */

void swap(int, int); /* 交换两个数 */

void print(); /* 打印 */

int main(){

int i;

int start = 0;//起始位置

int count = M;//排列到个数

for(i = 0; i < N; i++){

a[i] = i + 1;

}

comb(start, count);

}

void comb(int offset, int count){

int i;

if( count == 0 ){

print();

return;

}else{

for(i = offset; i < N - count + 1; i++){

temp[top++] = a[i];

comb(i+1, count-1);

--top;

}

}

}

void print(){

int i;

for(i = 0; i < M; i++)

printf(" %d ",temp[i]);

printf("/n");

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值