枚举子集的3种方式 -- C++描述
要求:
给定一个集合,枚举所有可能的子集。此处的集合是不包含重复元素的。
Method0: 增量构造法
思路:每次选取一个元素至集合中,为了避免枚举重复的集合,此处要采用定序技巧 -- 除了第一个元素,每次选取必须要比集合中的前一个元素要大!
// A 为原集合;
// B 为子集,每次调用函数即会打印一次
// cur 为子集元素个数
void print_subset0(int *A, int *B, int N, int cur) {
for(int i=0; i<cur; i++) {
printf("%5d", B[i]);
}
printf("\n");
if( cur < N ) {
for( int i=0; i<N; i++ ) {
if( !cur || A[i] > B[cur-1] ) {
B[cur] = A[i];
print_subset0(A, B, N, cur+1);
}
}
}
} int main() {
int Length = 3;
int A[Length] = {1, 3, 2};
printf("Method0:\n");
int B[Length] = {0};
print_subset0(A, B, Length, 0);
printf("\n");
return 0;
}
采用的是递归调用,但此处不需要return语句,因为当没有元素可用于枚举时,就不会调用函数,也就是不会继续递归。
此函数输出的子集中是包含空集的,如果不想用空集,则需判断 cur 是否为0,不为0才打印子集
测试样例的输出结果(包含空集):

Method1: 位向量法
思路:1个容量为N的集合,每个位置0~N-1,对于每个子集,要么被选中,要么没被选中。枚举每一个位置的状态,可得到各种子集。
// A 为原集合;
// A 为原集合
// used为当前A中每个位置的元素的状态(选中或未被选中)
// cur代表现在枚举A[cur]的状态
void print_subset1(int *A, int *used, int N, int cur) {
if( cur == N ) {
for(int i=0; i<N; i++) {
if( used[i] ) {
printf("%5d", A[i]);
}
}
printf("\n");
return ;
}
used[cur] = 0;
print_subset1(A, used, N, cur+1);
used[cur] = 1;
print_subset1(A, used, N, cur+1);
} int main() {
int Length = 3;
int A[Length] = {1, 3, 2}; printf("Method1:\n");
int B[Length] = {0};
print_subset1(A, B, Length, 0);
printf("\n"); return 0;
}
同样是递归枚举,这里需要用return终止递归,终止条件就是cur == N即枚举了一种子集,然后输出
此函数的输出是包含空集的,如果不想要空集,则需要判断used函数是否全为0,如果全为0,则不输出
样例输出(包含空集):

Method10: 二进制法
类似于位向量法,同样也是枚举各个位置的状态,但这次用二进制表示,二进制长度为N,与原集合大小相同。二进制的第 i 位代表原集合中的第 i 位是否被选中,枚举各种情况。集合大小为N,就是2的N次种方式。
void print_subset10(int *A, int N, int seq) {
for(int i=0; i<N; i++) {
if( seq & (1<<i) ) {
printf("%5d", A[i]);
}
}
printf("\n");
}
int main() {
int Length = 3;
int A[Length] = {1, 3, 2};
printf("Method10:\n");
for(int i=0; i<(1<<Length); i++) {
print_subset10(A, Length, i);
}
printf("\n");
return 0;
}
这种方式很好写,也很好记,但问题是,因为函数中的形参seq是int型的,所以N最大也就只能32,如果long long,那N也只能最大64,再超过64,就需要用大数或其它表示方式表示了。
如果不想要空集,可以将main函数中的 i 从1枚举起。
样例输出结果(包含空集):

参考资料: 《算法竞赛入门经典(第2版)》
枚举子集的3种方式 -- C++描述的更多相关文章
- Java Enum枚举 遍历判断 四种方式(包括 Lambda 表达式过滤)
示例代码如下: package com.miracle.luna.lambda; import java.util.Arrays; /** * @Author Miracle Luna * @Date ...
- iOS中枚举定义的三种方式
最简单的方式 typedef enum{ num1 = 0, num2 = 1, num3 = 2 }num; 同时我们还可以使用NS_ENUM的方式定义枚举 typedef NS_ENUM (NSI ...
- Java Array数组 遍历 四种方式(包含 Lambda 表达式遍历)
示例代码如下: package com.miracle.luna.lambda; import java.util.Arrays; /** * @Author Miracle Luna * @Date ...
- Java List集合 遍历 四种方式(包含 Lambda 表达式遍历)
示例代码如下: package com.miracle.luna.lambda; import java.util.ArrayList; import java.util.List; /** * @A ...
- Java Map集合 遍历 五种方式(包含 Lambda 表达式遍历)
示例代码如下: package com.miracle.luna.lambda; import java.util.HashMap; import java.util.Iterator; import ...
- ASP.NET Core 四种方式绑定枚举值
前言 本节我们来讲讲在ASP.NET Core MVC又为我们提供了哪些方便,之前我们探讨过在ASP.NET MVC中下拉框绑定方式,这节我们来再来重点看看枚举绑定的方式,充分实现你所能想到的场景,满 ...
- verilog描述表决器的两种方式简易分析
命题:设计一个三变量表决器.真值表如下: 可以写出并简化得出公式:F=AB+BC+AC. 以下是两种算法: 第一种:仅从算法方面描述为:A.B.C的和大于1则输出结果为1,否则为0:源码如下: mod ...
- 《JS高程》创建对象的7种方式(完整版)
一.理解对象 ECMA-262定义对象:无序属性的集合,其属性可以包含基本值.对象或者属性. 我们可以把 ECMAScript 的对象想象成 散列表:无非就是一组 名值对,其中值可以是数据或函数. 创 ...
- uva1354 天平难题 【位枚举子集】||【huffman树】
题目链接:https://vjudge.net/contest/210334#problem/G 转载于:https://blog.csdn.net/todobe/article/details/54 ...
随机推荐
- frame.origin.x 的意思和作用?
frame.origin.x 的意思和作用? scrollView.frame 一个view的frame 包含它的矩形形状(size)的长和宽. 和它在父视图中的坐标原点(origin)x和y坐标 f ...
- 不直接用NSLog
公司中不直接使用NSLog,而是利用宏定义自己的打印函数,将该打印函数写在项目的.pch文件中.调试的时候往往用到好多打印,但发布的时候确不需要.(一下是在公司中的一些处理) 自定义NSLog 一,固 ...
- 空类的默认函数—— SAP电面(2)/FEI
定义一个空类 class Empty { }; 默认会生成以下几个函数 2. 拷贝构造函数 Empty(const Empty& copy) { } 3. 赋值运算符 Empty& o ...
- Structs
1.服务端的运行程序 2.Servlet的三个方法 init service:抽象方法 destroy 3.步骤 (1).在web.xml中 <servlet> <servlet-n ...
- mybatis日记配置Log4j
拷贝log4j-1.2.16.jar到项目lib下 方式一是在src下新建一个log4j.xml文件,其具体内容如下 <?xml version="1.0" encoding ...
- Oracle SQL篇(二)oracle自连接操作
oracle 的自连接(self join)操作 对于oracle数据库来说,目前支持两套语法,一套是oracle自己的sql语法,一套是通行标准的SQL99语法,那么对于oracle的连接操 ...
- 超强1000 JQuery插件
转载:超强1000个jquery插件! http://www.cnblogs.com/chu888chu888/archive/2011/12/18/2292014.html
- Nginx 的 Echo 模块 —— echo-nginx-module(转)
Nginx 有个 echo 模块可以用来输出一些简单的信息,例如: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 2 ...
- JAVA GUI学习 - 总结
一:项目 二:重要组件补充 三:组件高级操作
- C标准函数库中获取时间与日期、对时间与日期数据操作及格式化
表示时间的三种数据类型[编辑] 日历时间(calendar time),是从一个标准时间点(epoch)到现在的时间经过的秒数,不包括插入闰秒对时间的调整.开始计时的标准时间点,各种编译器一般使用19 ...