如何在k组中生成n个元素的所有组合? 例如,从[aaa]到[ddd]的3个组中的takig“abcd”?
编辑:到目前为止我“完成了什么”:
int main (int argc, char * argvc[]) {
int tComb = 0, array[7] = { 48 , 48 , 48 , 48 , 48 , 48 , 48 };
while ( tComb < atoi(argvc[1]) ) {
for (int i = 6 ; i>0 ; i--) {
if (array[i] == 58)
array[i] = 65;
if (array[i] == 91)
array[i] = 97;
if (array[i] == 123){
array[i] = 48;
array[i-1]++;
}
}
std::cout << "Current Combination: ";
std::cout << array;
std::cout << "\n";
tComb++;
array[6]++;
}
}
它会尝试向后生成最新的字母数字字符组合,但它是硬编码的,不会很好用。
答案 0 :(得分:2)
我不确定,但我认为这是你问题的答案。如果你想要三个组,你应该有3个不同的循环。当你看到这个程序的输出时,它非常简单。 你只需要在可能的组合中增加你想要生成的值。
以下代码将生成&#34; abcd&#34;的所有可能组合。分为3组,从[aaa]到[ddd]。
int main()
{
char ch1;
char ch2;
char ch3;
for(ch1='a';ch1<='d';ch1++)
{
for(ch2='a';ch2<='d';ch2++)
{
for(ch3='a';ch3<='d';ch3++)
{
printf("%c %c %c\n",ch1,ch2,ch3);
}
printf("\n"); //just to have clean and understandable output
}
printf("\n\n\n"); //just to have clean and understandable output
}
return 0;
}
答案 1 :(得分:2)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
unsigned powu(unsigned base, unsigned exp){
unsigned result = 1;
while(exp > 0){
if(exp & 1)
result *= base;
base = base * base;
exp >>=1;
}
return result;
}
int main(int argc, char *argv[]){
if(argc != 3){
fprintf(stderr, "Usage : RepeatedPermutation abcd 3\n");
return -1;
}
char *list = argv[1];
unsigned gp_len = atoi(argv[2]);
unsigned list_len = strlen(list);
char *gp = calloc(gp_len+1, sizeof(char));
int total_n = powu(list_len, gp_len);
int i, j;
for(i=0;i<total_n;++i){
int n = i;
for(j=0;j<gp_len;++j){
gp[gp_len -j -1] = list[n % list_len];
n /= list_len;
}
printf("[%s]\n", gp);
}
free(gp);
return 0;
}
答案 2 :(得分:1)
生成所有组合的一种方法是将其视为数字计数程序。
计数算法
我们以“数字”为例:a,b,c和d。
第一个号码是:aaaa
。与十进制非常相似: 0000
第二个号是:aaab
。十进制: 0001 。
第三个数字是:aaac
,十进制: 0002
第四个数字是:aaad
,十进制: 0003 。
此过程称为递增,例如每次添加一个常量值。
现在是棘手的部分,增加最后一位数。根据数字计数规则,当到达最后一位时,最后一位被第一位替换, next 列中的位被替换。这相当于从09到10递增的十进制数。
因此,在上面的示例中,序列中的下一个数字是:aaba
。
这被称为 carry ,因为您将溢出传送到下一个数字。
将算法转换为代码
看起来有一个从第一个数字到最后一个数字的循环:
#define MAXIMUM_DIGIT_POSITIONS 4
const char FIRST_CHAR = 'a';
const char LAST_CHAR = 'd';
std::vector<char> number(MAXIMUM_DIGIT_POSITIONS); // Reserve some slots.
void Print_Number(const std::vector<char>& number);
int main(void)
{
// Initialize the number
int position = 0;
for (position = 0; position < MAXIMUM_DIGIT_POSITIONS; ++position)
{
number.push_back(FIRST_CHAR);
}
Print_Number(number);
// Loop: incrementing
position = MAXIMUM_DIGIT_POSITIONS - 1; // Because arrays are zero based indexing
while (number[position] < LAST_CHAR)
{
number[position] = number[position] + 1; // Increment to next digit, same position.
Print_Number(number);
}
// Pause before closing
std::cout << "Paused. Press ENTER to close.\n";
std::cin.ignore(100000, '\n');
return EXIT_SUCCESS;
}
void Print_Number(const std::vector<char>& number)
{
for (std::vector<char>::const_iter iter = number.begin();
iter != number.end();
++iter)
{
std::cout << *iter;
}
cout << "\n";
}
处理携带
上述程序演示了单列计数。但是如何处理最后一位数的递增?
看起来我们需要递增 之前位置的数字。
展望未来,前一列中的值将递增,直到它也需要递增。因此,进位将传播到前一列。看起来像另一个循环:
// Loop: number of positions
int propagation_position = position - 1;
while (propagation_position >= 0)
{
while (number[position] < LAST_CHAR)
{
number[position] = number[position] + 1; // Increment to next digit, same position.
Print_Number(number);
}
// Propagate the carry.
while (propagation_position >= 0)
{
if (number[propagation_position] != LAST_CHAR)
{
++number[propagation_position];
number[propagation_position + 1] = FIRST_CHAR;
break;
}
--propagation_position;
}
position = 0;
}
上面的新片段有一个外部while循环和一个第二个内部while循环。外部while循环控制数字位置。第二个内部while循环处理进位。
整个程序的设计使您可以调整数字位置的数量和序列中的位数。
<强>摘要强>
用于打印所有组合的强力方法类似于计数。同样的原则适用:当最后一个数字递增时,它被第一个数字替换,下一个数字的数字递增。重复这一过程直到所有位置都被计算在内。
使用调试器或笔和纸遍历上述代码,找出任何缺陷并理解算法。
了解算法后,搜索您最喜欢的C ++参考“c ++组合排列算法”。