求子集PHP,求子集的三种方式的总结

本文探讨了求非重集子集的三种高效算法:增量构造法通过逐个增加元素形成子集,位向量法通过构造n位向量表示元素归属,而二进制法则将问题转化为整数的二进制表示。增量构造法效率最高,位向量法次之,二进制法虽简单但速度较慢。
摘要由CSDN通过智能技术生成

求自己总共有三种方式:

增量构造

位向量

二进制

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

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

下面是代码实现:

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

#include

using namespacestd;const int maxn = 100 + 10;intans[maxn];intn;void print_sub_set(intcur)

{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);

}

}intmain()

{

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

using namespacestd;const int maxn = 100 + 10;intB[maxn];intn;void print_subset(intcur)

{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);

}

}intmain()

{

n= 3;

print_subset(0);return 0;

}

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

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

//二进制法的本质和位向量法是一致的,都是构造一组向量//但是二进制法使用的是位运算的方式

#include

using namespacestd;intn;//const int ALL_BITS = 1<

void print_subset(intx)

{for(int i = 0; i < n;i++)

{if(x & (1 <

{

printf("%d",i);

}

}

printf("\n");

}intmain()

{

n= 3;for(int i = 0;i < 1<

{

print_subset(i);

}return 0;

}

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

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值