子集生成

生成n个元素的子集,我认为可以这样理解:有n个不同的桶,编号1~n,每个桶最多放置一个球。遍历一遍桶,可以将球放入也可以不放入,这样,

在遍历结束后,收集放置元素的桶,打印其编号,即得到一个子集。

而放与不放有2种选择,所以共有2^n个子集,这样,可以采用二进制的形式。

示例:3个元素

000  3个桶都不放球,空集

001  第一个放球,{1}

010  第二个放球,{2}

011 第一、二放球,{1,2}

…… 依次类推

思路:从右至左,找到第一个0,记位置为pos,将pos置1,且将pos后(不含pos)元素全部置0,得到一个集合。

代码:

[cpp]  view plain  copy
 print ?
  1. void printSeq(int *arr, int *tool, int len)  
  2. {  
  3.     cout << "{ ";  
  4.     for(int i = 0; i < len; i++)  
  5.     {  
  6.         if(tool[i] == 1)  
  7.             cout << arr[i] << " ";  
  8.     }  
  9.     cout << "}";  
  10.     cout << endl;  
  11. }  
  12.   
  13.   
  14. void generate(int *arr, int len)  
  15. {  
  16.     int *tool = new int[len];  
  17.     for(int i = 0; i < len; i++)  
  18.         tool[i] = 0;  
  19.   
  20.     int pos = -1;  
  21.     while(true)  
  22.     {  
  23.         //找0  
  24.         for(int i = len-1; i>=0; i--)  
  25.         {  
  26.             if(tool[i] == 0)  
  27.             {  
  28.                 pos = i;  
  29.                 break;  
  30.             }  
  31.         }  
  32.         //打印集合  
  33.         printSeq(arr, tool, len);  
  34.   
  35.         //没有找到0,出现全1情况,即全集  
  36.         if(pos == -1)  
  37.             break;  
  38.   
  39.         //置1  
  40.         tool[pos] = 1;  
  41.         //pos后元素全部置0  
  42.         for(int i = pos+1; i < len; i++)  
  43.             tool[i] = 0;  
  44.   
  45.         pos = -1;  
  46.     }  
  47.   
  48.     delete [] tool;  
  49. }  
  50.   
  51.   
  52.   
  53. int _tmain(int argc, _TCHAR* argv[])  
  54. {  
  55.     int coll[] = {1,2,3};  
  56.     int len    = sizeof(coll) / sizeof(int);  
  57.   
  58.     generate(coll, len);  
  59.   
  60.     system("pause");  
  61.   
  62.     return 0;  
  63. }  


结果:




输入n

输出1到n这个集合中包含的所有子集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/*
//方法一:
//思路:构造一个位向量visit,而不是直接构造子集A本身
#include<iostream>
using namespace std;
 
void fun(int *visit, int cur, int n)
{
     if(cur == n+1)
     {
         for(int i = 1;i <= n;++ i)
             if(visit[i])
                 cout << i << ' ';
         cout<<endl;
         return;
     }
     visit[cur] = true;
     fun(visit,cur+1,n);
     visit[cur] = false;
     fun(visit,cur+1,n);
}
int main()
{
     int n;
     cout<<"输入n,产生集合1到n中所有的子集。"<<endl;
     while(cin >> n)
     {
         bool *visit=new bool[n + 1];
         for(int i = 1;i <= n;++ i)
             visit[i] = false;
         fun(a,1,n);
     }
     return 0;
}
*/
//方法二:
//思路:一次选出一个元素放到集合中
#include<iostream>
using  namespace  std;
 
void  print_subset( int  *A, int  n, int  cur)
{
     for ( int  i = 0;i < cur;++ i)   //打印当前集合
         cout << A[i] <<  ' ' ;
     cout << endl;
     int  s = cur ? A[cur - 1] + 1 : 0;
     for ( int  i = s;i < n; ++ i)
     {
         A[cur] = i;
         print_subset(A,n,cur + 1);
     }
}
 
int  main()
{
     int  n;
     cout<< "输入n,产生集合1到n中所有的子集。" <<endl;
     while (cin >> n)
     {
         int  *A= new  int [n + 1];
         for ( int  i = 1;i <= n;++ i)
             A[i] = i;
         print_subset(A,n,1);
     }
     return  0;
}

  



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值