本文最后更新于:2020年6月29日 晚上

问题描述:

若有数字集合{1,2,3},则其子集为NULL、{1}、{2}、{3}、{1,2}、{1,3}、{2,3}、{1,2,3}。现给定数组,求其的全部子集。

实现如下:

//非递归
//{1,2,3}
// 0  0  0
// 0  0  1
// 0  1  0
// 0  1  1
// 1  0  0
// 1  0  1
// 1  1  0
// 1  1  1
//计算子集的个数,即2的元素个数次方
//一次规律
//空集需要特殊输出
class Solution
{
public:
	void subset(int *value, int size)
	{
		if (value == NULL || size < 1) return;//防御性动作

		int *tmp = (int *)malloc(size * sizeof(int));//开辟空间存放输出标志
		assert(tmp != NULL);
		memset(tmp, 0, size*sizeof(int));

		int num = (int)pow((double)2, (double)size);//计算子集个数
		cout << "NULL" << endl;
		for (int i = 1; i < num; ++i)
		{
			for (int j = 0; j < size; ++j)//给输出标志赋值,二进制计算
			{
				if (tmp[j] == 1) tmp[j] = 0;//逢二进一
				else if (tmp[j] == 0)
				{
					tmp[j] = 1;
					break;
				}
			}
			for (int j = 0; j < size; ++j)//比较输出标志,得出子集所包含元素
			{
				if (tmp[j] == 1) cout << value[j] << " ";
			}
			cout << endl;
		}
		delete tmp;//释放内存空间
	}
};

//递归
class Solution
{
public:
	int *tmp;//指向动态数组的指针
	void createArray(int size)//创建动态数组
	{
		tmp = (int *)malloc(size * sizeof(int));
		assert(tmp != NULL);
		memset(tmp, 0, size * sizeof(int));
	}
	void deleteArray()//释放内存空间
	{
		free(tmp);
	}
	void subsetRecursive(int *value, int m, int size)
	{
		if (m == -1)//此时标志位都已赋值,进行统计输出
		{
			for (int i = size - 1; i >= 0; --i)
			{
				if (tmp[i] == 1) cout << value[i] << " ";//为1输出
			}
			cout << endl;
		}
		else
		{
			tmp[m] = 0;//先将此标志位赋值为0,即不输出
			subsetRecursive(value, m - 1, size);//递归到下一位
			tmp[m] = 1;//再将此标志位赋值为1,即输出
			subsetRecursive(value, m - 1, size);//递归到下一位
		}
	}
	void subset(int *value, int size)
	{
		if (value == NULL || size < 1) return;//防御性动作
		createArray(size);
		subsetRecursive(value, size - 1, size);//从最高位开始
		deleteArray();
	}
};

结果如图:

求子集算法结果