枚举所有子集的三种算法详解-《算法入门经典》

方法一:增量构造法

  理解递归必须得理解函数到底是做什么的。

#include<cstdio>

void print_subset(int n,int *a,int cur)  //print_subset的功能是打印集合{0,1,...,n-1}的cur个元素的子集,并且目前a数组中已经存储了要打印的集合
{
    printf("{ ");
    for (int i=0;i<cur;i++) printf("%d ",a[i]);
    printf("}\n");
    int mi=cur?a[cur-1]+1:0;  //利用字典序避免重复打印
    for (int i=mi;i<n;i++)  //枚举下一位可以添加什么元素
    {
        a[cur]=i;
        print_subset(n,a,cur+1);  //递归打印cur+1个元素的子集
    }
}

int main()
{
    int n;
    int a[10]={};
    scanf("%d",&n);
    print_subset(n,a,0); //初始时a中存储了0个元素的子集,开始递归打印
    return 0;
}

方法二:位向量法

  枚举每一位选或者不选,复杂度比方法一略高但更好理解,因为与输出全排列思路差不多,满n位就输出。

#include<cstdio>

int a[10];

void print_subset(int n,int *b,int cur)  //确定第cur位选或者不选
{
    if (cur==n)  //如果确定好了n位,打印结果
    {
        printf("{ ");
        for (int i=0;i<n;i++)
            if (b[i]) printf("%d ",a[i]);
        printf("}\n");
    }
    else
    {
        b[cur]=1;  //这一位选
        print_subset(n,b,cur+1);  //递归下一位
        b[cur]=0;  //这一位不选
        print_subset(n,b,cur+1);  //递归下一位
    }
}

int main()
{
    int n;
    int b[10]={};
    scanf("%d",&n);
    for (int i=0;i<n;i++) a[i]=i;
    print_subset(n,b,0);
    return 0;
}

  缺点是输出不是按照字典序。

方法三:二进制法

  稍加思考就会发现,方法二其实与二进制是对应的。

#include<cstdio>

int a[10];

void print_subset(int n,int b)  //n位的集合,b状态打印
{
    printf("{ ");
    for (int i=0;i<n;i++)
        if (b&(1<<i)) printf("%d ",a[i]);
    printf("}\n");
}

void p_s(int n)
{
    for (int i=0;i<(1<<n);i++) print_subset(n,i);  //枚举所有状态
}

int main()
{
    int n;
    scanf("%d",&n);
    for (int i=0;i<n;i++) a[i]=i;
    p_s(n);
    return 0;
}

  这个方法优点就是代码简单。

注意:以上三种方法输出顺序不同。

时间: 2024-10-09 01:34:23

枚举所有子集的三种算法详解-《算法入门经典》的相关文章

查看登陆系统用户的信息的三种方法详解

查看登陆系统用户的信息的三种方法详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.who这个命令显示可以谁在登陆,但是这个有很多的花式玩法,这个命令超简单 语法:who [OPTION]... [ FILE | ARG1 ARG2 ] 1.参数:-u,显示闲置时间,若该用户在前一分钟之内有进行任何动作,将标示成"."号,如果该用户已超过24小时没有任何动作,则标示出"old"字符串. 例如: 2.参数:-m,此参数的效果和指定"a

多表连接的三种方式详解 HASH JOIN MERGE JOIN NESTED LOOP

在多表联合查询的时候,如果我们查看它的执行计划,就会发现里面有多表之间的连接方式. 之前打算在sqlplus中用执行计划的,但是格式看起来有点乱,就用Toad 做了3个截图. 从3张图里我们看到了几点信息: 1.       CBO 使用的ALL_ROWS模式 Oracle Optimizer CBO RBO http://blog.csdn.NET/tianlesoftware/archive/2010/08/19/5824886.aspx 2.       表之间的连接用了hash Join

用例图中三种关系详解(转)

共性:都是从现有的用例中抽取出公共的那部分信息,作为一个单独的用例,然后通后过不同的方法来重用这个公共的用例,以减少模型维护的工作量. 1.包含(include) 包含关系:使用包含(Inclusion)用例来封装一组跨越多个用例的相似动作(行为片断),以便多个基(Base)用例复用.基用例控制与包含用例的 关系,以及被包含用例的事件流是否会插入到基用例的事件流中.基用例可以依赖包含用例执行的结果,但是双方都不能访问对方的属性.包含关系对典型的应用就是复用,也就是定义中说的情景.但是有时当某用例

虚拟机中的三种网络详解

一.三种网络区别 1. vmnet0        vmnet0实际上就是一个虚拟的网桥,这个网桥有很若干个端口,一个端口用于连接你的Host,一个端口用于连接你的虚拟机,他们的位置是对等的,谁也不是谁的网关.所以在Bridged模式下,你可以让虚拟机成为一台和你的Host相同地位的机器. 2. vmnet1 vmnet1这是一个Host-Only网络模式,这是用于建立一个与世隔绝的网络环境所用到的,其中vmnet1也是一个虚拟的交换机,交换机的一个端口连接到你的Host上,另外一个端口连接到虚

Hibernate 的三种状态详解

hibernate的对象有3种状态,分别为:瞬时态(Transient).持久态(Persistent).脱管态(Detached). 处于持久态的对象也称为PO(Persistence Object),瞬时对象和脱管对象也称为VO(Value Object). 瞬时态 由new命令开辟内存空间的java对象, eg. Person person = new Person("xxx", "xx"); 如果没有变量对该对象进行引用,它将被java虚拟机回收. 瞬时对象

ZigBee、Z-Wave与AllSeen 智能家居三种技术标准详解

随着物联网时代的到来,智能家居是物联网最贴近我们生活最先落地的物联网产业.智能家居若要发挥最大功能就要通过技术手段实现系统内的互联互通,这里所说的技术手段就是智能家居通信技术标准.抛开有线技术不提,目前较流行的无线通信标准就有ZigBee.Z-Wave.WiFi等几种,下面我们就来看看三种技术标准的具体内容. 智能家居技术标准 Zwave技术具备稳定性,室内有效覆盖面积为30米,适用于窄宽带应用场合.其安全性高于WiFi但远不如Zigbee.此外,Zwave采用树状组网结构,一旦树枝上端断掉,下

PHP实现链式操作的三种方法详解

这篇文章主要介绍了PHP实现链式操作的三种方法,结合实例形式分析了php链式操作的相关实现技巧与使用注意事项,需要的朋友可以参考下 本文实例讲述了PHP实现链式操作的三种方法.分享给大家供大家参考,具体如下: 在php中有很多字符串函数,例如要先过滤字符串收尾的空格,再求出其长度,一般的写法是: strlen(trim($str)) 如果要实现类似js中的链式操作,比如像下面这样应该怎么写? $str->trim()->strlen() 下面分别用三种方式来实现: 方法一.使用魔法函数__ca

【REACT NATIVE 系列教程之四】刷新组件RENDER(重新渲染)的三种方式详解

本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/react-native/2242.html 开发过游戏的都应该很清楚,"刷屏"是多么的重要.其实开发应用也如此,当组件的数据被修改后,如何及时更新组件呈现出最新的数据与效果一样至关重要. 那么这里Himi大概讲三种常用的方式: this.setState()  [最为常用] 这是在事件处理函数中和请求回调函数中触发 UI 更新的主要

基于JavaScript 声明全局变量的三种方式详解

JS中声明全局变量主要分为显式声明或者隐式声明下面分别介绍. 声明方式一: 使用var(关键字)+变量名(标识符)的方式在function外部声明,即为全局变量,否则在function声明的是局部变量.该方式即为显式声明详细如下: var test = 5; //全局变量 function a() { var cc=3; //局部变量 alert(test); } function b(){alert(test);} 声明方式二: 没有使用var,直接给标识符test赋值,这样会隐式的声明了全局