求集合幂集的几种方法

方法1:位运算

原理:
幂集即原集合所有子集组成的元素;对原集合中的每个元素取或不取,构成的所有情况,即与原集合所有子集一一对应;对取或不取用二进制1或0表示,即可用2原集合元素个数个数字来表示原集合的所有子集。


c++代码实现:

#include 
#include //有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头文件。这种写法即能见名知意,又能保证移植时,不会因为类型的范围出错。)

c代码实现:

#include 
#include //有uint64_t类型的定义
void funPowerSet(int * b, int iSetLen) //集合中元素大于64时此方法失效
{
	for (uint64_t i = 0; i < (1<<iSetLen); i++)
	{
		printf("{");
		for (uint64_t j = 0; j < iSetLen; j++)
		{
			if (i&(1<<j))
				printf("%d,", b[j]);
		}
		printf("}\n");
	}
}

方法2:递归


思路:
所谓幂集,就是元素的所有子集。
递归边界条件:整个序列只有一个元素时,它的所有子集就是取这个元素和不取这个元素。
递归部分:序列元素数大于1时, 取第一个元素与其余元素的所有子集的组成的集合,并上不取这个元素与其他元素所有子集的组成的集合。既是整个序列的所有子集。
每次递归调用,序列元素都会减1,所以一定能达到递归边界条件。
实现:

#include 
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);
}


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

你可能感兴趣的:(求集合幂集的几种方法)