C语言排列组合问题
最近在学习《Linux C编程一站式学习》,其中,第8.3 数组应用实例:直方图的习题2中提到全排列问题。
定义一个数组,编程打印它的全排列。比如定义:
#define N 3 int a[N] = { 1, 2, 3 };
要求:
程序要具有通用性,如果改变了N和数组a的定义(比如改成4个数的数组),其它代码不需要修改就可以做4个数的全排列(共24种排列)
思路:
- 把第1个数换到最前面来(本来就在最前面),准备打印1xx,再对后两个数2和3做全排列。
- 把第2个数换到最前面来,准备打印2xx,再对后两个数1和3做全排列。
- 把第3个数换到最前面来,准备打印3xx,再对后两个数1和2做全排列。
这是一个递归的过程,把对整个序列做全排列的问题归结为对它的子序列做全排列的问题
折腾了两天,昨晚跑步的时候终于理解了思路,今天中午解决了恢复原状的bug,调试成功。代码:
#include <stdio.h>
#define N 4
#define M 2
int a[] = {1, 2, 3, 4};
int count = 0;
void print_a()
{
int i;
for(i = 0; i < N; i++)
printf("%d ", a[i]);
printf("\n");
}
void swap(int i, int j)
{
int t;
t = a[i];
a[i] = a[j];
a[j] = t;
}
void param(int i)
{
if(i == M)
{
print_a();
count++;
}
else
{
int j;
for(j = i; j < N; j++)
{
swap(i, j);
param(i+1);
swap(i, j); //恢复原状,以便交换a[i]和a[i+2]
}
}
}
int main(void)
{
param(0);
printf("%d\n", count);
return 0;
}
还有两个引申的问题,这个程序同样适用于第二个问题.
第三个问题暂时没想好,搞定再记录。
第二个问题:如果再定义一个常量M表示从N个数中取几个数做排列(N == M时表示全排列),原来的程序应该怎么改?
第三个问题:如果要求从N个数中取M个数做组合而不是做排列,就不能用原来的递归过程了,组合的递归过程应该怎么描述,程序如何改?