子集生成之增量构造法,位向量法,二进制法

 增量构造法

#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;
}

猜你喜欢

转载自blog.csdn.net/weixin_42373330/article/details/82469082
今日推荐