问题描述:
若有数字集合{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();
}
};
结果如图: