增量构造法
#include<stdio.h>
int num[10],n;
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;//确定当前元素的最小可能值
for(int i = s; i < n; i ++)
{
A[cur] = i;
print_subset(n,A,cur+1);//递归构造子集
}
return;
}
int main()
{
n = 4;
print_subset(n,num,0);
return 0;
}
位向量法
void print_subset(int n,int *B,int cur)
{
if(cur==n)
{
for(int i=0;i<cur;i++)
if(B[i]) printf("%d ",i);//打印当前集合,B[i]为1时表示i在该集合中
printf("\n");
return ;
}
B[cur]=1; //选第cur 个元素
print_subset(n,B,cur+1);
B[cur]=0; //不选第cur 个元素
print_subset(n,B,cur+1);
}
B[cur]=1与B[cur]=0类似于有一排扑克牌,每张牌有翻和盖两种选择,n张牌就有2^n种结果,每种结果以翻着的牌构成一个子集
二进制法
二进制是由0与1构成,在这里,1与0表示对应的数的有无;下面以1010(二进制表示)(表格第二行红色表示有,否则表示无)为例,代表的就是{0,1,2,3}的一个子集{1,3}
1 | 0 | 1 | 0 |
3 | 2 | 1 | 0 |
#include<stdio.h>
void print_subset(int n,int s)//打印{0,1,2,···,n-1}的子集s
{
for(int i=0;i<n;i++)
if(s&(1<<i)) printf("%d ",i); //这里利用了C语言“非零值都为真”的规定
printf("\n");
}
//而枚举子集和枚举整数一样简单
/*
for(int i=0;i<(1<<n);i++)
print_subset(n,i);
*/
int main()
{
int n=2;
//枚举各子集所对应的编码0,1,2···,2^n -1
//由于每个i都不同,那么每个i代表的每个子集就不同,
//以n=2为例,i取值有0,1,2,3 二进制表示00,01, 10, 11
// 分别代表的子集是:{},{0},{1},{0,1}
for(int i=0;i<(1<<n);i++)
print_subset(n,i);
printf("-----\n");
n=4;
for(int i=0;i<(1<<n);i++)
print_subset(n,i);
return 0;
}