题目描述:给出一个n个元素的集合,要求打印出所有的子集;
思路分析:n个元素的子集共有2^n个,其中包括空集。
(1)假设有3个元素{a, b, c},那么此时有 2^3 个子集,即8个子集。
(2)因为有8个子集,而且包括空集,注意7对应的二进制形式为111,并且二进制数刚好3位;所以(000 ~ 111)可分别对应一个子集,若该位为1,则表示该元素出现在子集中,若该位为0,则表示该元素不出现在子集中;
举例:
111表示子集abc;
110表示子集bc;
101表示子集ac;
100表示子集c;
011表示子集ab
010表示子集b;
001表示子集a;
000则表示空集;
那么问题就变得简单了,程序的思路就变为:
求出子集的个数n---->从0开始到n循环传入一个数---->根据这个数的各个位是否为1来选择是否打印该位元素
程序的核心就变为判断这个数的各个位是否位1,利用位运算很简单就可以实现;
例如: 当传入的数为5时:对应二进制为 101
用5%2可以得到二进制的最后一位是1,然后将5右移一位(5>>1)得到的是010;循环这个过程就可以判断每一位是否为1;
代码:
void print(int arr[],int length,int n)
{
for (int i = 0; i < length; i++) //从0到length循环代表这个集合一共有length个元素,需要依次判断是否需要打印
{
if (n % 2) //判断n对应的二进制最后一位是否为1
{
cout << arr[i]<<' ';
}
n = n >> 1; //将n右移一位继续循环这个过程,直到所有的元素都判断结束则退出循环
}
cout << endl;
}
void subset(int arr[], int length)
{
int num = pow(2, length); //计算子集的个数
for (int i = 0; i < num; i++)
{
print(arr, length,i); //打印函数,每个i值对应的二进制都代表了一个子集
}
}
int main()
{
int ar[] = {1, 2,3,4,5};
int n = sizeof(ar)/sizeof(ar[0]);
subset(ar,n);
}