集合的所有子集


方法一:

對於任意一個元素,都可以使用一個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);
}

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com