首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用二进制计数来计数数组的所有子集

使用二进制计数来计数数组的所有子集
EN

Stack Overflow用户
提问于 2014-08-26 08:15:17
回答 3查看 2.4K关注 0票数 0

因此,如果给我一个数组,如

代码语言:javascript
复制
a = {1, 2, 3} 

我们知道,给定的子数组(包括非连续子数组)是(这表示功率集)。

代码语言:javascript
复制
{1} {2} {3} {1,2,3} {1,2} {1,3} {2,3}

我也知道这些子集可以用二进制数来表示

代码语言:javascript
复制
000 -> 111 (0 to 7), where each 1 bit means we 'use' this value from the array
e.g. 001 corresponds to the subset {3}

我知道这种方法可以用来生成所有子集,但我不太确定如何在c++中实现这一点。

基本上,我要问的是,如何(如果可以)使用二进制计数来生成功率集?

任何其他的方法,以产生一个功率集也是非常感谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-08-26 08:21:44

对于具有3个set元素的示例,只需执行以下操作:

代码语言:javascript
复制
for (s = 1; s <= 7; ++s)
{
     // ...
}

下面是一个演示程序:

代码语言:javascript
复制
#include <iostream>

int main()
{
    const int num_elems = 3;                      // number of set elements
    const int elems[num_elems] = { 1, 2, 3 };     // mapping of set element positions to values

    for (int s = 1; s < (1 << num_elems); ++s)    // iterate through all non-null sets
    {
        // print the set
        std::cout << "{";
        for (int e = 0; e < num_elems; ++e)       // for each set element
        {
            if (s & (1 << e))                     // test for membership of set
            {
                std::cout << " " << elems[e];
            }
        }
        std::cout << " }" << std::endl;
    }
    return 0;
}

编译和测试:

代码语言:javascript
复制
$ g++ -Wall sets.cpp && ./a.out

{ 1 }
{ 2 }
{ 1 2 }
{ 3 }
{ 1 3 }
{ 2 3 }
{ 1 2 3 }

请注意,使最小有效位对应于第一个set元素是一种常见的约定。

还请注意,我们省略了空集s= 0,因为您似乎不想包括这个。

如果您需要使用大于64个元素的集合(即uint64_t),则需要更好的方法--您可以将上述方法扩展为使用多个整数元素,或者使用std::bitsetstd::vector<bool>,或者使用类似@Yochai的答案(使用std::next_permutation)。

票数 5
EN

Stack Overflow用户

发布于 2014-08-26 08:55:42

实际上,创建集合非常容易--只需使用按位操作>>=&一次测试一点点。假设输入向量/数组a[]已知有3个元素,因此产生7个向量输出:

代码语言:javascript
复制
std::vector<std::vector<T>> v(7);
for (int n = 1; n <= 7; ++n)   // each output set...
    for (int i = 0, j = n; j; j >>= 1, ++i)  // i moves through a[i],
                                             // j helps extract bits in n 
        if (j & 1)
             v[n-1].push_back(a[i]);
票数 0
EN

Stack Overflow用户

发布于 2014-08-26 09:27:09

对于编译时大小,可以使用bitset,如下所示:

代码语言:javascript
复制
template <std::size_t N>
bool increase(std::bitset<N>& bs)
{
    for (std::size_t i = 0; i != bs.size(); ++i) {
        if (bs.flip(i).test(i) == true) {
            return true;
        }
    }
    return false; // overflow
}

template <typename T, std::size_t N>
void display(const std::array<T, N>& a, const std::bitset<N>& bs)
{
    std::cout << '{';
    const char* sep = "";

    for (std::size_t i = 0; i != bs.size(); ++i) {
        if (bs.test(i)) {
            std::cout << sep << a[i];
            sep = ", ";
        }
    }
    std::cout << '}' << std::endl;
}

template <typename T, std::size_t N>
void display_all_subsets(const std::array<T, N>& a)
{
    std::bitset<N> bs;

    do {
        display(a, bs);
    } while (increase(bs));
}

实例化

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25501051

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档