方法1:位运算
幂集即原集合所有子集组成的元素;对原集合中的每个元素取或不取,构成的所有情况,即与原集合所有子集一一对应;对取或不取用二进制1或0表示,即可用2原集合元素个数个数字来表示原集合的所有子集。代码实现如下:
#include <iostream>
#include <cstdint>//有uint64_t类型的定义
using namespace std;
void funPowerSet(int * b, int iSetLen)//此方法只适用于集合元素小于等于64
{
for (uint64_t i = 0; i <(1 << iSetLen); i++)
{
cout << "{";
for (uint64_t j = 0; j < iSetLen; j++)
{
if (i&(1 << j))
cout << b[j] << ", ";
}
cout << "}\n";
}
}
(ps: uint64_t,代表64位无符号整数类型。这样写需要包含 stdint.h头文件。这种写法即能见名知意,又能保证移植时,不会因为类型的范围出错。)
以上实现方法的问题是待求集合的元素个数不能超过63,因为c++目前只支持64位整数。
解决办法是用bitset,不过bitset没有自增运算,需要自己再给bitset写个自增函数,整体代码如下:
#include <iostream>
#include <cstdint>//有uint64_t类型的定义
#include <bitset>
using namespace std;
//不考虑溢出 相当于 ++bs
//如果溢出,bs不改变
template<size_t _Nb>
bitset<_Nb> & add1(bitset<_Nb> &bs){
int i=0, n=bs.size();
for(; i<n; i++){
if(bs[i]==0){
bs[i]=1;
break;
}
else if(bs[i]==1){
bs[i]=0;
}
}
return bs;
}
#define MAX_NUM_OF_ELEM 100
//此处宏定义代表集合最大元素数,因为bitset的模板参数只能使用常量,所以此处用宏定义
void funPowerSet(int * b, int iSetLen)
{
bitset<MAX_NUM_OF_ELEM+1> it;
bitset<MAX_NUM_OF_ELEM+1> itEnd;
itEnd[iSetLen]=1;
for ( ; it!=itEnd; add1(it) )
{
cout << "{";
for (uint64_t j = 0; j < iSetLen; j++)
{
if (it[j])
cout << b[j] << ", ";
}
cout << "}\n";
}
}
用递归实现位运算思路,也没有元素数量限制。实现代码如下:
#include <iostream>
using namespace std;
template<class T>
void powerSet(T list[], int k, int len)
{
static bool * isNo = new bool[len];
if (k == len - 1)
{
for (int i = 1; i >= 0; i--)
{
isNo[k] = !i;
cout << "{";
for (int i = 0; i < len; i++)
if (isNo[i])
cout << list[i] << ",";
cout << "}\n";
}
return;
}
isNo[k] = 0; powerSet(list, k + 1, len);
isNo[k] = 1; powerSet(list, k + 1, len);
}
int main()
{
powerSet("abc", 0, 3);
}
以上为个人理解,可能有偏颇疏漏,欢迎交流指正。