使用向量迭代地创建集合的子集

时间:2015-02-17 01:57:34

标签: c++

所以我想创建一个子集,通过代码运行该子集,然后创建一个新的子集。我正在为集合和子集使用向量。到目前为止,我有3个嵌套for循环,但我无法找出我需要的变量。

这就是我想要做的。 set = {0,1,2,3,4,5}该值与索引匹配只是为了简化此示例。我现在想要subset = {} - > {0} - > {1} - > ... - > {0,1} - > {0,2} - > ... - > {0,5} - > {0,1,2} - > ... - > {0,4,5}。我在用变量表示条件方面遇到了麻烦。

基本上我希望第一个for循环增加子集大小。从0到set.size()(这很容易)。在该循环中,我希望有一个迭代器对应于子集元素中的索引。我将此迭代器初始化为subset.size(),以便我们首先使用最后一个元素,然后以我们的方式处理子集中的第一个元素。然后是第3个for循环,我想在集合中的可能值之间进行迭代。假设我们当前的子集= {0,1,2}我如何让我的程序知道将值'2'放在子集的最后一个元素中,然后是1然后是0?

我认为它会涉及从set.size() - 1和subset.size() - 1中获取差异的东西吗?但我不太清楚如何。所以我想迭代直到{0,1,5}然后{0,4,5},但我又不知道如何告诉程序停在4,而不是5.再次我认为这是不同的东西,但我无法弄明白。

回顾:

for loop to iterate through subset size
    for loop to iterate through subset "working" element, starting from back
        for loop to iterate through that index of subset,
        starting from the correct corresponding set value to ending
        at the correct corresponding set value

这样子集来自{} - > {0} - > {1} - > ...-> {0,1} - > {4,5} - > {1,2,3} - > ... - > {1,4,5}而我实际上并不需要subset = {1,2,3,4,5},但如果我不能在此之前停止,它不会伤害我的代码。我想再次将起点和终点表示为变量以使内循环工作,但我无法弄明白。非常感谢能帮助我的人。

2 个答案:

答案 0 :(得分:0)

这大约是我如何去做的。

//handle null subset
for ( int size = 1; size < n; i++ ) {
    int indices[size];
    for ( int i = 0; i < size; i++ ) indices[i] = i;

    while ( indices[0] <= n - size ) {
        int i;
        for ( i = 1; indices[size - i] == n - i; i-- );
        indices[i]++;
        for ( i = i + 1; i < size; i++ ) indices[i] = indices[i-1] + 1;
        //print out elems using the indices in `indices`
    }
    //done with all subsets of size `size`
}

外循环应该是非常自我解释的。包括0似乎会让一些内部逻辑变得烦人,所以我从大小为1的子集开始。

indices包含应包含在当前子集中的元素的索引。它以索引0 - size-1开始。

while的条件并不明显。这个生成的最后一个有效子集包含最后size个元素,因此如果第一个索引超过n - size,我们就会走得太远。

while循环的内部只是递增子集。它查找可以递增的最后一个元素,并仍然给出一个有效的子集,递增它,然后将所有后续元素重置为尽可能小。然后你以某种方式打印出来。

这应该接近能够做你想做的事情。如果需要澄清或更正,请告诉我。

答案 1 :(得分:0)

枚举所有子集的技巧是置换“选择标志”数组,其中每个元素都指示是否选择了原始数组中的对应元素。

以下是示例代码:

void foo(const vector<int>& a)
{
    size_t size = a.size();

    // selection flag array
    // '1' indicates selected, '0' indicates unselected
    vector<int> f(size, 0);

    for (size_t i = 1; i <= size; i++)
    {
        // increase the count of selected elements
        f[i - 1] = 1;

        do
        {
            for (size_t i = 0; i < size; i++)
            {
                if (f[i])
                {
                    printf("%d\t", a[i]);
                }
            }
            printf("\n");

        } while (next_permutation(f.begin(), f.end(), [](int a, int b){ return a > b; }));
        // next_permutation tries to permutate the array
        // i.e. '1 1 0 0' -> '1 0 1 0' -> '0 1 1 0' -> ... -> '0 0 1 1'(end)
    }
}