已知一个集合,其子集包括空集和本身。怎样将所有的子集打印出来?最简单的O(N^3)算法不难想到,但是太过于朴素,应该还有更巧的方法。
我们已知,一个元素个数为n的集合,其子集个数为2^n个。比如set { 1, 2 },含有两个元素,一共有四个子集,分别为{ },{ 1 },{ 2 },{ 1,2 }。 我们取一个只有两位的bitset,显然这个两位的bitset只有四种组合,00、01、10、11。 假设我们让bitset的每一位对应上面集合中的一个元素,那么集合的每个子集就可以用bitset的一个组合来表示:
{ } 对应 00
{ 1 } 对应 01
{ 2 } 对应 10
{ 1,2 } 对应 11
在这个对应关系中,bitset的某一位为1,则代表其对应的集合中的元素选入这个子集,为0则代表不选入。
扩展开,一个具有n个元素的集合,可以用n位的bitset来表示, 将n位的bitset转换为十进制,其范围刚好就是【0,2^n)。上面的特例,bitset转换为十进制后,分别为0、1、2、3。那么,打印一个集合的子集,我们只需要遍历从0到2^n-1的数字,将每个数字看作bitset,只要某位为1则输出该位对应元素。
根据这个思想,形成代码:
-
#include <iostream>
-
#include <math.h>
-
using
namespace
std;
-
-
void Print(int set[], int n, int k)
-
{
-
if (k==
0)
-
{
-
cout <<
"空集";
-
return;
-
}
-
-
int mask =
1;
-
int index =
0;
-
-
while (index < n)
-
{
-
if (k&mask)
-
{
-
cout <<
set[index] <<
" ";
-
}
-
mask <<=
1;
-
index++;
-
}
-
}
-
-
void PrintSubSet(int set[], int n)
-
{
-
int i;
-
-
for (i=
0; i<
pow(
2,n); i++)
-
{
-
Print(
set, n, i);
-
cout <<
endl;
-
}
-
}
-
-
void main()
-
{
-
int
set[
4] = {
1,
2,
3,
4};
-
PrintSubSet(
set,
4);
-
}
输出结果: