前言:
方法一(穷举法):
用二进制表示元素出现的位置,举例n=3;用三位二进制数来表示对应的子集,
二进制数上出现的1代表对应子集上出现的元素,
二进制数上出现的0代表对应子集上该元素没有出现。
n=3 子集元素---> | 123 | |
| 对应下列 | |
| 二进制数 | 对应子集 |
| 000 | { } |
| 100 | {1} |
| 010 | {2} |
| 110 | {12} |
| 001 | {3} |
| 101 | {13} |
| 011 | {23} |
| 111 | {123} |
算法描述:
n=3 brr[ ] 存放三位二进制数。三位二进制的种数一共有2^n种
所以要遍历2^n次二进制进位。
进位函数描述:
遇1化0,遇0进1,进位完成,退出。
主函数描述:
遍历所有二进制的种数,输出每一种二进制数对应的子集元素
代码展示:
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<vector>
using namespace std;
//采用二进制和数列的方法求解
void add(int b[], int n)//二进制进位
{
for (int i = 0; i < n; i++)//遍历数组
{
if (b[i]) //不是0就下一步变为0
{
b[i] = 0;
}
else
{
b[i] = 1;//碰到0就进位
break;//退出这次的进位
}
}
}
//求幂集
void pset01(int n)
{
//定义两个数组,b[]代表二进制数存储,a[]代表元素本身
int a[10], b[10];
//给元素本身赋值
for (int i = 0; i < 10; i++)
{
a[i] = i + 1;//数组代表的元素值从1开始
b[i] = 0;//二进制初始化为0
}
//求2^n的值,代表二进制的所有种数
int pw = (int)pow(2, n);
for (int i = 0; i < pw; i++)
{
cout << "{";
for(int j = 0; j < n;j++ )//将b[]的位置上的数全部输出
{
if (b[j])
{
cout << a[j];
}
}
cout << "} ";
add(b, n);
}
}
方法二(增量蛮力法):
第二种方法用到了vector容器,嵌套容器在大容器里面放小容器,然后往小容器里面塞元素,对于容器简单使用不了解的可以参考
算法描述:
在一个大的整型容器中放一个小的整型容器,起初这个子容器里是空的,代表这个容器是空集,然后把子容器复制出来,添加元素值进去组成新的子容器,再把子容器添加回大容器里,没有破坏原有的子容器,只是在原有的基础上增加了。
最后只要把幂集容器里的子容器读出来就可以了,每一个子容器代表一个子集。
代码展示:
void pset02(int n)
{
vector<vector<int>> ps1;//存放子幂集
vector<int> s; //空集
ps.push_back(s);//幂集中存放空集
for (int i = 1; i <=n; i++)
{
ps1 = ps;//之前得到的幂集作为子幂集
for (auto it = ps1.begin(); it != ps1.end(); it++)
{
(*it).push_back(i);//在子幂集的每一个集合中添加i
}
for (auto it = ps1.begin(); it != ps1.end(); it++)//将子幂集加到幂集中去组成新的幂集
{
ps.push_back(*it);
}
}
//输出幂集
for (auto it = ps.begin(); it != ps.end(); it++)//it读取幂集中的每个集合
{
cout << "{";
for (auto sit = (*it).begin(); sit != (*it).end(); sit++)//sit读取it集合中的每个元素
{
cout << (*sit);
}
cout << "}";
}
}
int main()
{
pset02(3);
return 0;
}