白书练习之子集生成

一.子集生成

下面介绍三种方法进行子集的生成

二.方法一:构造增量法

首先观察子集生成的解答树,我们可以发现有很明显得层次特征,第一层的每个子集都只有一个元素,第二层有两个元素,以此类推,那么我们就可以根据模拟解答树的方法每次加入一个元素到集合里面,然后输出就可以了,既然有了解答树,那我们当然可以用遍历树得方法去遍历生成解答树,所以这种方法本质上就是dfs。

三.方法二:位向量法

该方法就是遍历每个元素,
每个元素都有两个状态,即是在子集中或者不在子集中,只要遍历这个状态即可,仔细分析这种方法发现其解答树其实是一个二叉树,所以我们还是可以用dfs的思想来实现它。

四.方法三:二进制法

和位向量法一样,二进制法也是希望通过遍历每个元素的两个状态来进行子集的生成,发现每个元素的状态可以通过二进制的0和1来模拟,可以知道我们的全集就是2^n-1即(1<<n)-1,所以我们只要遍历0到(1<<n)-1的所有数字即可遍历所有状态,给出这个方法的代码实现

#include <iostream>
#include <cstring>
using namespace std;
void print_subset(int n,int t,int *s)
{
	for(int i=0;i<n;i++)
	{
		if(t&(1<<i)) cout<<s[i];
	}
	cout<<endl;
}
int main()
{
	int n;
	int s[]={2,5,6,9,7};
	n=5;
	for(int i=0;i<(1<<n);i++)
	{
		print_subset(n,i,s);
	}
	return 0;	
} 

t&(1<<i)段代码很有意思,为了判断第t的二进制形式中第i位是否是1,就可以构造1<<i来(10000(只有第i位是1))和t来按位取交集,这样如果第i位在t中是1结果就是是非零的,否则结果就是零。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值