集合的所有子集

方法一:

对于任意一个元素,都可以使用一个bit位表示该元素的存在与否,例如:
集合{a, b, c},可以使用{1, 1, 1}表示{a, b, c},{1, 0 , 1}表示{a,c}。

故可以使用一个整型变量来映射整个集合,从000…000 ~ 111…111,分别表示不同的情况,一共有 2 N 种情况。我们只需要从000…000开始,每次加1,就可以获得相应的子集,打印即可。

需要注意的是,由于该方法使用整型变量来映射集合,所以该方法仅局限于集合个数小于整型数位数(一般为32)的情况。

void print_subset_1(vector<int> arr,int mark)
{
    if(mark == 0)
        cout << "空集";
    for(int i=0;i<arr.size();i++)
    {
        if(((1 << i) & mark) != 0)
        {
            cout << arr[i] << ends;
        }
    }
    cout << endl;
}

void subset_1(vector<int> arr)
{
    if(arr.size() == 0 || arr.size() > 31)
        return;
    int end = (1 << arr.size()) - 1;    
    for(int i=0; i<=end; i++)   //000...000~111...111
    {
        print_subset_1(arr,i);
    }
}

方法二:

也是使用0和1来标记一个元素是否存在。但这次是用一个布尔型的数组来映射集合而不是一个整型变量,这样对集合的个数就没有限制了。通过递归将所有的子集打印出来即可。

void print_subset_2(vector<int> arr,bool *mark)
{
    bool allZero = true;
    for(int i=0;i<arr.size();i++)
    {
        if(mark[i] == 1)
        {
            allZero = false;
            cout << arr[i] << ends;
        }
    }
    if(allZero)
        cout << "空集";
    cout << endl;
}

void subset_2_1(vector<int> arr,bool **mark,int index)
{
    if(index > arr.size()-1)
        print_subset_2(arr,*mark);
    else
    {
        (*mark)[index] = 1;
        subset_2_1(arr,mark,index+1);
        (*mark)[index] = 0;
        subset_2_1(arr,mark,index+1);
    }
}

void subset_2(vector<int> arr)
{
    if(arr.size() == 0)
        return;
    bool *mark = new bool[arr.size()];
    memset(mark,0,arr.size());
    subset_2_1(arr,&mark,0);
}

猜你喜欢

转载自blog.csdn.net/qq_34342154/article/details/79508996