求子集的三种方式的总结

求自己总共有三种方式:

增量构造

位向量

二进制

首先假设集合A中有n个元素,而且是非重集,一个下标唯一对应一个元素,那么求A的子集就变成了求0~n-1的子集。这个思想对于所有的三种方式都是通用的。

第一种增量构造法的思想是,每一次都从0~n-1中挑出一个元素来,每挑一次,就是一个集合。然后再挑元素进入这个集合,但是这次挑选元素的时候,必须比之前的那个元素大。

下面是代码实现:

//假设后一个非可重集合P,里面的元素各不相同,现在要从中挑选出它的所有子集来
//这个问题可以转换成挑选出P数组的下标的所有子集。即若P中有n个元素,那么就挑选出0~n-1之间的所有子集来
//以上的分析适合于所有的子集生成算法
//增量构造法的本质是这样的,每次从0~n-1 中挑选出一个元素来,每挑选一次,就是一个子集。然后再给这个已经挑选出来的子集中挑选元素,这次挑选出来的元素
//必须比之前的元素要大
#include<cstdio>
using namespace std;

const int maxn = 100 + 10;
int ans[maxn];
int n;

void print_sub_set(int cur)
{
    for(int i = 0; i < cur; i++)
    {
        printf("%d ",ans[i]);
    }
    printf("\n");
    int s = cur ? ans[cur - 1] + 1 : 0;
    for(int i = s;i < n; i++)
    {
        ans[cur] = i;
        print_sub_set(cur +1);
    }
}

int main()
{
    n = 3;
    print_sub_set(0);
    return 0;
}

第二种方式是位向量法,如上一种方式所述,问题已经被转换成求0~n-1的子集,这时再转换一次,转换为求一个长度位n位的向量B[i],当b[i]为1时,代表i在这个集合中。在实现的时候,采用了递归的思想,每次都决定每一位的归属。

下面是代码实现:

//在上一篇说过,问题转换成了枚举0~n-1之间的所有的子集
//在位向量法中,还需要再次去转换,即将问题转换为构造一个有n位的向量,当b[i]为1的时候,表示i-1在此集合中,即元素A[i - 1]在集合中
#include<cstdio>
using namespace std;
const int maxn = 100 + 10;
int B[maxn];
int n;

void print_subset(int cur)
{
    if(cur == n)
    {
        for(int i = 0;i < n;i++)
        {
            if(B[i])
                printf("%d ",i);
        }
        printf("\n");
    }
    else
        for(int i = 0; i <= 1; i++)
    {
        B[cur] = i;
        print_subset(cur + 1);
    }

}

int main()
{
    n = 3;
    print_subset(0);
    return 0;
}

最后是二进制法,二进制法的本质和位向量法是一致的,只不过位向量法中的向量B[],变成了一个整数转换为二进制时有n位的整数,这样就可以从0枚举到1<<n - 1,然后再去依次判断各个位的情况

下面附上代码:需要注意的一点就是如何判断各位的情况,就是x&1<<i

//二进制法的本质和位向量法是一致的,都是构造一组向量
//但是二进制法使用的是位运算的方式
#include<cstdio>
using namespace std;

int n;
//const int ALL_BITS = 1<<n - 1;

void print_subset(int x)
{
    for(int i = 0; i < n;i++)
    {
        if(x & (1 << i))
        {
            printf("%d ",i);
        }
    }
    printf("\n");
}

int main()
{
    n = 3;
    for(int i = 0;i < 1<<n;i++)
    {
        print_subset(i);
    }
    return 0;

}

经过比较这三种方式的效率,增量构造的效率最高,二进制次之,位向量最慢

当输入达到26的时候,增量构造法11s,二进制15s,位向量20s

但是编程的复杂度而言二进制最简单,增量构造和位向量一致

&符号代表所有的位一起与。

原文地址:https://www.cnblogs.com/TorettoRui/p/10466839.html

时间: 2024-11-04 12:51:27

求子集的三种方式的总结的相关文章

使用DataSet Datatable 更新数据库的三种方式

1:自动生成命令的条件 CommandBuilder 方法a)动态指定 SelectCommand 属性b)利用 CommandBuilder 对象自动生成 DataAdapter 的 DeleteCommand.InsertCommand 和 UpdateCommand.c)为了返回构造 INSERT.UPDATE 和 DELETE .SQL CommandBuilder 必须执行 SelectCommand.即:必须额外经历一次到数据源的行程,这可能会降低性能.这也是自动生成命令的缺点.d)

估计高斯混合模型参数的三种方式

对于如下的两类别的高斯混合模型 \[ \pi\cdot N(\mu_1,\sigma_1^2)+(1-\pi)\cdot N(\mu_2,\sigma_2^2) \] 参数为\(\theta = (\pi, \mu_1,\mu_2,\sigma_1,\sigma_2)\).至今,我了解到有三种方式来估计这五个参数.这三种方式分别为梯度下降法.EM算法和Gibbs采样,而且这三种算法并非毫不相关.EM算法其实是简化梯度下降法中对于对数似然的计算,而Gibbs采样跟EM算法区别在于前者采样后者求最大

AngularJs学习——实现数据绑定的三种方式

三种方式: 方式一:<h5>{{msg}}</h5>  此方式在页面刷新的时候会闪现{{}} 方式二:<h5 ng-bind="msg"></h5> 方式三:<h5 ng-clock class="ng-clock">{{msg}}</h5> 示例代码: <!DOCTYPE html> <html lang="en" ng-app="myapp&q

小蚂蚁学习页面静态化(2)——更新生成纯静态化页面的三种方式

更新生成纯静态化页面的三种方式:1.按照时间间隔更新.2.手动更新.3.定时更新(需要系统配合). 1. 按照时间间隔更新. 当用户第一次访问这个页面的时候,程序自动判断,该静态文件是否存在,并且该文件是否还在有效时间内,如果该文件未超出了有效时间,用户访问的是已经生成的静态文件.如果超出了有效时间,用户得到的是动态输出的内容,同时重新生成静态文件.稍微修改一下昨天的代码为例: <?php //首先判断是否有静态文件,并且文件的最新修改时间到现在是否大于20秒 if(is_file('./tex

Linux中设置服务自启动的三种方式

有时候我们需要Linux系统在开机的时候自动加载某些脚本或系统服务 主要用三种方式进行这一操作: ln -s                       在/etc/rc.d/rc*.d目录中建立/etc/init.d/服务的软链接(*代表0-6七个运行级别之一) chkonfig                命令行运行级别设置 ntsysv                   伪图形运行级别设置 注意:1.这三种方式主要用于以redhat为基础的发行版 2.如果还不知道运行级别是什么,那么最

Linux识别ntfs及挂载的三种方式

NTFS-3G是一个开源软件,支持在Linux操作系统下读写NTFS格式的分区.它能快速且安全的操作Windows XP,Windows Server 2003, Windows 2000 以及WindowsVista文件系统. 1 .环境准备 安装该软件需要依赖于fuse, Centos6.*中应该默认安装过fuse: [[email protected] yum.repos.d]# rpm -q fuse fuse-2.8.3-4.el6.i686 已经安装 如果没有安装可以yum安装或者编

Tomcat热部署的三种方式

热部署是指在你修改项目BUG的时候对JSP或JAVA类进行了修改在不重启WEB服务器前提下能让修改生效.但是对配置文件的修改除外! 1.直接把项目web文件夹放在webapps里. 2.在tomcat\conf\server.xml中的<host></host>内部添加<context/>标签: <Context debug="0" docBase="D:\demo1\web" path="/demo1"

【Struts2】Struts2获取session的三种方式

1.Map<String,Object> map =  ActionContext.getContext().getSession(); 2.HttpSession session = ServletActionContext.getRequest().getSession(); 3.让Action实现SessionAware接口,并实现public void setSession(Map<String, Object> session) {} 方法,Struts2会在实例化Act

虚拟机NetworkAdapter三种方式的区别

虚拟机在安装时默认的有三块网卡,VMnet1和VMnet8,另外还有VMnet0 Vmware 还提供了三种网络连接模式: 分别为: A 桥接bridge  B NAT 网络地址转换 C  主机模式 下面来简单说一下 三种方式的区别  : 1) bridge : 默认使用VMnet0,不提供DHCP服务 在桥接模式下,虚拟机和宿主计算机处于同等地位,虚拟机就像是一台真实主机一样存在于局域网中.因此在桥接模式下,我们就要像对待其他真实计算机一样为其配置IP.网关.子网掩码等等.当我们可以自由分配局