方法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);
}
以上為個人理解,可能有偏頗疏漏,歡迎交流指正。