方法一:
对于任意一个元素,都可以使用一个bit位表示该元素的存在与否,例如:
集合{a, b, c},可以使用{1, 1, 1}表示{a, b, c},{1, 0 , 1}表示{a,c}。
故可以使用一个整型变量来映射整个集合,从000…000 ~ 111…111,分别表示不同的情况,一共有 种情况。我们只需要从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);
}