子集生成

来源:互联网 发布:边境牧羊犬多聪明 知乎 编辑:程序博客网 时间:2024/06/06 02:15

生成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