组合算法的实现
今天同学笔试,碰到了一个问题:从100个数中选出任意10个数,打印出所有可能。
这是排列,组合的问题,上网查了一下,挺多这方面的资料的,这是介绍一个组合算法:
假设从0-----5中选出3个数,那么可定义一个数组,数组下标为数据值,数组存储0,1,1表示选中,0表示未选中:
1 1 1 0 0
1 1 0 1 0
1 0 1 1 0
0 1 1 1 0
1 1 0 0 1
1 0 1 0 1
0 1 1 0 1
1 0 0 1 1
0 1 0 1 1
0 0 1 1 1
根据这个算法,自己写了一个程序(但是不知道到底为什么这样,如果有谁知道,请指教):
#include <stdio.h>
#include <stdlib.h>
int * NUM; //指向实际的数值
char * NUMFLAG; //指向标志位
static int number; //存储总个数
int sum=0; //记录有多少次
#define MAXNUM 5
#define NUM(i) (*(NUM+(i))) //第i个所存储的值
#define NUMFLAG(i) (*(NUMFLAG+(i))) //表示第i个是否被选中,保存的为0,1
#define swap(x,y) do {(x)=(x)^(y);(y)=(x)^(y);(x)=(x)^(y);}while(0);
void set(int num,int Allnum) //设置小于num的为1,大于的为0
{
int i;
for(i=0;i<Allnum;i++)
{
if(i<num)
NUMFLAG(i)='1';
else
NUMFLAG(i)='0';
}
}
int init()
{
int i;
printf("there are %d number,please input the number you want to take out:\n",MAXNUM);
scanf("%d",&number);
if(number>MAXNUM)
{
printf("sorry,the number is too big!\n");
return 1;
}
NUM=(int *)(malloc(sizeof(int)*MAXNUM));
NUMFLAG=(char *)(malloc(sizeof(char)*MAXNUM));
set(number,MAXNUM);
for(i=0;i<MAXNUM;i++)
{
NUM(i)=i;
}
return 0;
}
void print()
{
int i=0;
sum++;
while(i<MAXNUM)
{
if(NUMFLAG(i)=='1')
printf("%d ",NUM(i));
i++;
}
printf("\n");
}
void assemble()
{
int j=0,k=0,number_0=0,number_1=0;
print();
do{
if(NUMFLAG(k)=='1'&&NUMFLAG(k+1)=='0')
{
swap(NUMFLAG(k),NUMFLAG(k+1)); //交换1,0
set(number_1,k); //将所有1移到最左
print();
number_1=0;
number_0=0;
k=0;
}else{ //并不是连续的1,0
if(NUMFLAG(k)=='1')
number_1++; //记录之前1的个数
else number_0++; //记录0的个数
k++;
}
}while((k+1)<MAXNUM);
}
int main()
{
init();
assemble();
printf("there are %d\n",sum);
}
#include <stdlib.h>
int * NUM; //指向实际的数值
char * NUMFLAG; //指向标志位
static int number; //存储总个数
int sum=0; //记录有多少次
#define MAXNUM 5
#define NUM(i) (*(NUM+(i))) //第i个所存储的值
#define NUMFLAG(i) (*(NUMFLAG+(i))) //表示第i个是否被选中,保存的为0,1
#define swap(x,y) do {(x)=(x)^(y);(y)=(x)^(y);(x)=(x)^(y);}while(0);
void set(int num,int Allnum) //设置小于num的为1,大于的为0
{
int i;
for(i=0;i<Allnum;i++)
{
if(i<num)
NUMFLAG(i)='1';
else
NUMFLAG(i)='0';
}
}
int init()
{
int i;
printf("there are %d number,please input the number you want to take out:\n",MAXNUM);
scanf("%d",&number);
if(number>MAXNUM)
{
printf("sorry,the number is too big!\n");
return 1;
}
NUM=(int *)(malloc(sizeof(int)*MAXNUM));
NUMFLAG=(char *)(malloc(sizeof(char)*MAXNUM));
set(number,MAXNUM);
for(i=0;i<MAXNUM;i++)
{
NUM(i)=i;
}
return 0;
}
void print()
{
int i=0;
sum++;
while(i<MAXNUM)
{
if(NUMFLAG(i)=='1')
printf("%d ",NUM(i));
i++;
}
printf("\n");
}
void assemble()
{
int j=0,k=0,number_0=0,number_1=0;
print();
do{
if(NUMFLAG(k)=='1'&&NUMFLAG(k+1)=='0')
{
swap(NUMFLAG(k),NUMFLAG(k+1)); //交换1,0
set(number_1,k); //将所有1移到最左
print();
number_1=0;
number_0=0;
k=0;
}else{ //并不是连续的1,0
if(NUMFLAG(k)=='1')
number_1++; //记录之前1的个数
else number_0++; //记录0的个数
k++;
}
}while((k+1)<MAXNUM);
}
int main()
{
init();
assemble();
printf("there are %d\n",sum);
}