组合算法:开一个数组,其下标表示1到m个数,数组元素的值为1表示其下标代表的数被选中,为0则没有选中。
首先初始化,将数组前n个元素置1,表示第一个组合为前n个数;然后从左到右扫描数组元素值的“10”组合,找到第一个“10”组合后将其变为“01”组合,同时将其左边的所有“1”全部移动到数组的最左端;当第一个“1”移动到数组的m-n位置,即n个“1”全部移动到最右端时,就得到了最后一个组合。
例如求5中选3的组合:
1 1 1 0 0 //1, 2, 3
1 1 0 1 0 //1, 2, 4
1 0 1 1 0 //1, 3, 4
0 1 1 1 0 //2, 3, 4
1 1 0 0 1 //1, 2, 5
1 0 1 0 1 //1, 3, 5
0 1 1 0 1 //2, 3, 5
1 0 0 1 1 //1, 4, 5
0 1 0 1 1 //2, 4, 5
0 0 1 1 1 //3, 4, 5
void output1(int value[], char* middle, int length)
{
for(int i=0; i<length; i++)
{
if(middle[i] == '1')
{
printf("%d ", value[i]);
}
}
printf("\n");
}
bool find10(char* middle, int M, int* index)
{
bool find = false;
for(int i=0; i<M; i++)
{
if (middle[i] == '1' && middle[i + 1] == '0')
{
*index = i;
find = true;
break;
}
}
return find;
}
void move1(char* middle, int index)
{
int count = 0;
for(int i=0; i<index; i++)
{
if (middle[i] == '1')
{
swap(middle[count++], middle[i]);
}
}
}
//从M 个数中取 N 个数的组合
void enumkind(int value[], int M, int N)
{
char *middle = new char[M + 1];
middle[M] = '\0';
memset(middle, '1', N);
memset(middle + N, '0', M - N);
printf("%s: ", middle);
output1(value, middle, M);
int index = 0;
while(find10(middle, M, &index))
{
swap(middle[index], middle[index+1]);
move1(middle, index);
printf("%s: ", middle);
output1(value, middle, M);
}
delete middle;
}
int _tmain(int argc, _TCHAR* argv[])
{
int value[5] = {1,2,3,4,5};
enumkind(value, sizeof(value)/sizeof(int), 4);
getchar();
return 0;
}