n个元素的所有子集(递归+非递归 +不去重)
2016-06-12 17:29
288 查看
一、非递归方法
思路分析:n个元素的子集共有2^n个,其中包括空集。
(1)假设有3个元素{a, b, c},那么此时有 2^3 个子集,即8个子集。
(2)因为有8个子集,而且包括空集,注意7对应的二进制形式为111,并且二进制数刚好3位;所以(000 ~ 111)可分别对应一个子集,若该位为1,则表示该元素出现在子集中,若该位为0,则表示该元素不出现在子集中;
(3)注意:001中的1在低位,对应的是a,即数组中的首个元素。
(4)举例
111表示子集abc;
110表示子集bc;
101表示子集ac;
100表示子集c;
011表示子集ab
010表示子集b;
001表示子集a;
000则表示空集;
具体实现如下:
打印如下:
![](https://img-blog.csdn.net/20160612161234279)
二、递归方法
思路分析:同上
此处,我们添加一个标记数组tag,用于记录子集中对应的元素是否出现。每输出一个子集,结束当前步骤,并进入下一步,直至递归完毕。
具体实现如下:
输出如下:
![](https://img-blog.csdn.net/20160612173011074)
知识拓展:
(1)n个元素的所有子集(递归+非递归+去重)
(2)求元素数量为定值的所有子集;求元素和为定值的所有子集;
思路分析:n个元素的子集共有2^n个,其中包括空集。
(1)假设有3个元素{a, b, c},那么此时有 2^3 个子集,即8个子集。
(2)因为有8个子集,而且包括空集,注意7对应的二进制形式为111,并且二进制数刚好3位;所以(000 ~ 111)可分别对应一个子集,若该位为1,则表示该元素出现在子集中,若该位为0,则表示该元素不出现在子集中;
(3)注意:001中的1在低位,对应的是a,即数组中的首个元素。
(4)举例
111表示子集abc;
110表示子集bc;
101表示子集ac;
100表示子集c;
011表示子集ab
010表示子集b;
001表示子集a;
000则表示空集;
具体实现如下:
#include <iostream> using namespace std; typedef unsigned long DWORD; // DWORD 即double world,双字节。 // 求arr的子集,arr共有n个元素的所有子集,时间复杂度为2^n void print_allSubSet(int arr[],int n) { DWORD i,j,total,mask; if (n > 30) { printf("%d is too big\n",n); return ; } total= (1 << n); // 1 << n 即把1的二进制形式,左移n位;因为2^n不好表达,所以采用移位的方式;(n个元素共有2^n个子集,包括空集) for (j=0; j < total; j++) // 每循环一次选出一个子集 { printf("{ "); i = 0; // 每一次循环,i都重新置0;对应原数组中的第一个数字。 mask = j; // 序号j对应的是第(j+1)个子集。 while (mask > 0) // 通过移位的方式,直至mask的二进制形式中,所有位都为0。 { if (mask & 1) // 若mask的二进制形式的最后一位非0,输出该位对应的数字。 printf("%d ", arr[i]); mask >>= 1; // mask右移一位 i++; } printf("}\n"); } } int main(int argc, const char * argv[]) { int n=3; //求3个元素的所有子集。 int arr[32]; int i; for (i=0;i<n;i++) arr[i]=i+1; //arr表示一个集合,共有n个元素 print_allSubSet(arr, n); return 0; }
打印如下:
二、递归方法
思路分析:同上
此处,我们添加一个标记数组tag,用于记录子集中对应的元素是否出现。每输出一个子集,结束当前步骤,并进入下一步,直至递归完毕。
具体实现如下:
#include <iostream> using namespace std; // 递归 void allSubSet(int arr[], int tag[], int n) { if(n == 3) { cout<< "{ "; for(int i = 0; i < 3; i++) if(tag[i] == 1) cout << arr[i] << ' '; cout<< "}" << endl; return; } tag = 0; allSubSet(arr, tag, n+1); tag = 1; allSubSet(arr, tag, n+1); } int main(int argc, const char * argv[]) { int a[3]={1,2,3}; int tag[3]; allSubSet(a,tag,0); return 0; }
输出如下:
知识拓展:
(1)n个元素的所有子集(递归+非递归+去重)
(2)求元素数量为定值的所有子集;求元素和为定值的所有子集;
相关文章推荐
- 有关数据库SQL递归查询在不同数据库中的实现方法
- C#中的递归APS和CPS模式详解
- WinForm实现按名称递归查找控件的方法
- C#递归方法实现无限级分类显示效果实例
- 使用SqlServer CTE递归查询处理树、图和层次结构
- C#中的尾递归与Continuation详解
- C#递归实现显示文件夹及所有文件并计算其大小的方法
- php递归创建目录的方法
- PHP递归创建多级目录
- Javascript递归打印Document层次关系实例分析
- C++使用递归方法求n阶勒让德多项式完整实例
- oracle 使用递归的性能提示测试对比
- 使用curl递归下载软件脚本分享
- Perl脚本实现递归遍历目录下的文件
- JavaScript的递归之递归与循环示例介绍
- C# 递归查找树状目录实现方法
- 全排列算法的非递归实现与递归实现的方法(C++)
- php递归列出所有文件和目录的代码
- java递归菜单树转换成pojo对象
- 递归查找文件和递归删除文件