子集生成
一:增量构造法
思路是一次选出一个元素放入集合中
#include<stdio.h>
void print_subset(int n,int a[],int cur)
{
for (int i = 0; i < cur; i++)
printf("%d ", a[i]);
printf("\n");
int s = cur? a[cur - 1] + 1 : 0;//cur为0则s为0,否则s=a[cur-1]+1,s为当前元素中最小值
for (int i = s; i < n; i++)//a中本身已经定序,所以不会重复输出
{
a[cur] = i;
print_subset(n, a, cur + 1);//递归构造子集
}
}
int main()
{
int a[50];
print_subset(5, a, 0);
return 0;
}
二:位向量法
思路是构造一个位向量b[i],用0和1标示元素,从而控制输出,通过递归达到输出所有结果的目的
#include<stdio.h>
void print_subset(int n,int b[],int cur)
{
if (cur == n)
{
for (int i = 0; i < n; i++)
if (b[i])
printf("%d ", i);
printf("\n");
return;
}
b[cur] = 1; //选第cur个元素
print_subset(n, b, cur + 1);
b[cur] = 0; //不选第cur个元素
print_subset(n, b, cur + 1);
}
int main()
{
int a[50];
print_subset(5, a, 0);
return 0;
}
三:二进制法
用二进制表示子集s,s从n个0到n个1,第i个位置位置为1表面包含i
#include<stdio.h>
void print_subset(int n)
{
for (int s = 0; s < (1 << n); s++)//s范围为[0,2^n-1],写成二进制就是n位,从n个0到n个1
{
for (int i = 0; i < n; i++)
if (s&(1 << i)) //这里就是s中第i位为1的意思,也就是子集中包含i
printf("%d ", i);
printf("\n");
}
}
int main()
{
print_subset(5);
return 0;
}