求集合的子集

最近看算法和数据结构书,从网上摘取了两种不同的方法:

一。不用递归

http://blog.chinaunix.net/u/15929/showart_156126.html

思路:   
      如何求出一个集合的所有子集呢?方法很简单。我们知道一个集合的子集是这个集合元素的2的幂,那么就可以用一个n位的二进制来模拟它。比如说有这么一个集合{1,2,3,4,5,6},那么再构造出这样的一个数组a[6]={0,0,0,0,0,0}.其中a[6] = {0,0,0,0,0,0}对应空集,a[6] = {1,0,0,0,0,0}对应集合{1},以此类推直到a[6] = {1,1,1,1,1,1};
 
代码实现:
#include<iostream>
#include<math.h>
using namespace std;
 
void change(bool*ptr, int len);
 
int main()
{
 char aa[]={'1','2','3','4','5','6'};
 int n=sizeof(aa)/sizeof(aa[0]); 
 bool bo[]={0,0,0,0,0,0};
 
 int pw=pow(2,n);
 for(int i = 0; i < pw; i++)
 {
  cout<<'{';
  for(int k = 0; k < n; k++)
  {
   if(bo[k])
   {
    cout<<aa[k]<<' ';
   }
  }
  cout<<'}'<<endl;
  change(bo,n);
 }
 return 0;
}

void change(bool*ptr, int len)
{
 for(int i = 0; i < len; i++)
 {
  if(*ptr)
  {
   *ptr = 0;
  }
  else
  {
   *ptr = 1;
   break;
  }
  ptr++;
 }
}

 

http://hi.baidu.com/walkpigs/blog/item/3f3ad345c997613e8794733e.html

    一般来说,求集合自己的一个很实用的方法是用1代表该位置的元素存在于子集中,利用0表示不存在于子集中。按照这个思路只要定义一个变量,让它从0递增到2^n-1即可,每次递增把它除以2求余数,并且将余数存储在一个大小为n的bool型数组中,在逐次检验就可以了。一下是用另一种方法实现的:

/*编写递归函数,求n个元素集合的所有子集。
不妨令集合元素为小写字母,原集合为{'a', 'b', …, 'a' + n - 1}。
输入:input.txt,仅包含整数n(1-26)。
输出:若输入合法,输出集合的所有子集;否则输出"WRONG"。
子集输出格式为每行一个子集,空集用空行表示,非空集合每个元素间用一个空格间隔,
最后一个元素之后不能有空格。例如,对n=3,可能的输出为:
―――――――――――

a
a b
a b c
a c
b
b c
c

――――――――――――-*/
#include<iostream.h>

void move(char a[], int m, int n)
{
     char tmp=a[m];
     for(int i=m;i<n-1;i++)
         a[i]=a[i+1];
     a[n-1]=tmp;
}

void faction(char a[],int k,int m)
{
     if(k==m)
         for(int j=0;j<2; j++,k--)
   {
    for(int i=0; i<k; i++)
     cout<<a[i];
    cout<<endl;
         }
     else
         for(int i=0; i<m-k; i++)
   {
    faction(a,k+1,m-i);
             move(a,k,m);
         }
}

void main()
{
int m,k=0;                      //m为输入的整数,即集合个数
char char_a='a',a[26];       
cout<<"请输入一个(1—26)的整数:";
cin>>m;
for(int i=0;i<m;i++,char_a++)
   a[i]=char_a;
cout<<"----------------------------"<<endl;
if(m<1)
   cout<<"WRONG!!!"<<endl;
else
{
   if(m>26)
    cout<<"WRONG!!!"<<endl;
   else
    faction(a,k,m);
}
cout<<"-----------------------------"<<endl;
}

 

二。递归算法
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值