求集合幂集的几种方法


方法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);
}


以上为个人理解,可能有偏颇疏漏,欢迎交流指正。


免责声明!

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



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM