/*
组合的生成
*/
#include<stdio.h>
#include<stdlib.h>
void generate_i(int *c,int n,int r,int *i)
{
int j;
for(j=r;j>=1;j--){
if(c[j]<(n-r+j)){
break;
}
}
*i=j;
}
void set_cj(int *c,int r,int i)
{
int j;
for(j=i+1;j<=r;j++){
c[j]=c[j-1]+1;
}
}
void print(int *c,int r)
{
int x;
printf("c ");
for(x=1;x<=r;x++){
printf("%d ",c[x]);
}
printf("\n\n");
}
void main()
{
int n,r,N,*c,x,i;
printf("请输入n:");
scanf("%d",&n);
printf("请输入r:");
scanf("%d",&r);
c=(int*)malloc((r+1)*sizeof(int));
//初始化c
for(x=0;x<=r;x++){
c[x]=x;
}
print(c,r);
//求出c(n,r)
for(x=n,N=1;x>(n-r);x--){
N*=x;
}
for(x=r;x>1;x--){
N/=x;
}
//循环N-1次求出每次的组合
for(x=0;x<N-1;x++){
generate_i(c,n,r,&i);
c[i]=c[i]+1;
set_cj(c,r,i);
print(c,r);
}
scanf("%d",&x);
}
有时候我们需要组合作为一个程序模块——以C的角度来说,我们需要组合的生成作为一个.h文件和一个.c文件,需要的时候包含该.h文件就行。
所以我把上面的程序改写成如下形式:
首先是.h文件:
#ifndef COMBINATION_H
#define COMBINATION_H
typedef enum
{
FIRST_TIME,
NOT_FIRST_TIME
}WHICH_TIME;
int get_combination(WHICH_TIME which_time,int n,int r,int * res);
#endif
下面是.c文件:
#include "combination.h"
void get_i(int *c,int n,int r,int *i)
{
int j;
for(j=r;j>=1;j--){
if(c[j]<(n-r+j)){
break;
}
}
*i=j;
}
void set_cj(int *c,int r,int i)
{
int j;
for(j=i+1;j<=r;j++){
c[j]=c[j-1]+1;
}
}
int get_combination(WHICH_TIME which_time,int n,int r,int * res)
{
static int mn;
static int mr;
static int N;
static int count=1;
int i;
if(r>n||n<0||r<0)
{
return 0;
}
if(which_time==FIRST_TIME)
{
mn=n;
mr=r;
for(i=1;i<=mr;i++)
{
res[i]=i;
}
for(i=n,N=1;i>(mn-mr);i--)
{
N*=i;
}
for(i=r;i>1;i--)
{
N/=i;
}
return 1;
}
count++;
if(count>N)
{
return 0;
}
get_i(res,mn,mr,&i);
res[i]=res[i]+1;
set_cj(res,mr,i);
return 1;
}
下面是使用这个模块的示例:
#include<stdio.h>
#include<stdlib.h>
#include"combination.h"
int main(void)
{
int i;
int n,r,*list;
scanf("%d",&n);
scanf("%d",&r);
list=(int *)malloc(sizeof(int)*(r+1));
if(get_combination(FIRST_TIME,n,r,list))
{
do
{
for(i=1;i<=r;i++)
{
printf("%d ",list[i]);
}
printf("\n");
}while(get_combination(NOT_FIRST_TIME,n,r,list));
}
scanf("%d",&i);
return 1;
}
如果你要使用这个模块,有几点需要注意:
1.你需要开辟一个(r+1)的Int数组空间用来接收结果,并且在你获得的结果里不要管第一项,也就是下标为0的那一项。
2.你需要指定是第一次调用还是之后的调用,即FIRST_TIME和NOT_FIRST_TIME
3.欢迎改写