C或C++-与重复的组合
C or C++ - Combination with repetition
如何生成k组中n个元素的所有组合?例如,将"abcd"分成3组,从[aaa]到[ddd]?
编辑:到目前为止我所"完成的":
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]++;
}
}
它将尝试向后生成最新的字母数字字符组合,但它是硬编码的,不能很好地工作。
#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 3n");
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;
}
我不确定,但我认为这就是你问题的答案。如果你想要三组,那么你应该有三个不同的循环当你看到这个程序的输出时,它非常简单。你只需要增加你想要生成的可能组合的值。
以下代码将生成"abcd"的所有可能组合,每组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 %cn",ch1,ch2,ch3);
}
printf("n"); //just to have clean and understandable output
}
printf("nnn"); //just to have clean and understandable output
}
return 0;
}
生成所有组合的一种方法是将其视为一个数字计数程序。
计数算法
让我们以"数字"为例:a、b、c和d。
第一个数字是:aaaa
。很像十进制:0000
第二个数是:aaab
。小数:0001
第三个数字是:aaac
,十进制:0002
第四个数字是:aaad
,小数:0003。
这个过程被称为递增,例如每次添加一个常数值。
现在是棘手的部分,增加最后一个数字。根据计数规则,当到达最后一位时,最后一位将被第一位替换,下一个列中的数字将被替换。这相当于一个十进制数从09增加到10。
所以在上面的例子中,序列中的下一个数字是:aaba
。
这被称为进位,因为您正在将溢出进位到下一位。
将算法转换为代码
看起来有一个从第一位到最后一位的循环计数:
#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++组合置换算法"。
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 可组合的lambda/std::函数与std::可选
- 如何将两个不同矢量的同一位置的两个元素组合在一起
- 混合组合和继承的C++问题
- 我需要将多个函数组合为一个函数
- 构建可组合有向图(扫描仪生成器的汤普森构造算法)
- 通过组合不同的类型来创建唯一的id
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 模板元编程:如何将参数包组合成新的参数包
- 检查向量是否具有所有可能的字符组合
- 如何在加密++中将两个源组合成新的源
- 根中的组合
- 更改 C++ 中的组合分类变量
- 错误:(-210:不支持的格式或格式组合)功能'create'中的硬件视频解码器不支持视频源
- 组合字符串不适用于 libCurl,C++
- 测试两个类型列表中的所有组合
- 将多个 for 循环组合成单个迭代器
- 如何从组合指数中找到仓位
- 防止组合框被关闭
- 如何解决可能的唯一组合问题