元素子集

#include <iostream>
#include <math.h>
#include <assert.h>
using namespace std;

template<class T> class CElementSubset  
{  
private :
 CElementSubset(){} // 必须定义, 且为private.  
 CElementSubset(const CElementSubset&);            // 不实现. 
 CElementSubset& operator=(const CElementSubset&); // 不实现.  
 ~CElementSubset(){} // 可声明为public, 但这里声明为private没有错, 可被调用.

public :
 static CElementSubset& GetInstance()
 {
  static CElementSubset theSingleton;
  return theSingleton;
 }

public :
 //非递归求元素子集可以考虑使用二进制方法求解,但是当长度超出32比特位时,处理起来就有问题了
 void ES_Unrecursion(T data[], int n);

 //另一种非递归方法可以借助非递归组合方法进行求解,这种不受32比特位长度的限制
 void ES_Unrecursion1(T data[], int n);

 //求元素子集最直接的办法就是依次找1~N元素的子集即可
 void ES_Recursion(T data[], int n);

 //mask是标示位数组,c代表从第c个元素开 始寻找子集里面的元素
 void ES_Recursion1(T data[],  bool mask[], int n,  int c);

 void ES_Recursion2(T data[],int n,int nLow,int nHigh);

private :
 //1. 首先从n个数中选取编号最大的数,然后在剩下的n-1个数里面选取m-1个数,直到从n-(m-1)个数中选取1个数为止。
 //2. 从n个数中选取编号次小的一个数,继续执行1步,直到当前可选编号最大的数为m。

 // 求从数组a[1..n]中任选m个元素的所有组合。
 // a[1..n]表示候选集,n为候选集大小,n>=m>0。
 // b[1..M]用来存储当前组合中的元素(这里存储的是元素下标),
 // 常量M表示满足条件的一个组合中元素的个数,M=m,这两个参数仅用来输出结果。
 void Comb_Recursion( T a[], int n, int m, T b[], const int M );

 // 求从数组a[1..n]中任选m个元素的所有组合。
 // a[1..n]表示候选集,m表示一个组合的元素个数。
 // 返回所有排列的总数。
 void Comb_Unrecursion(T data[],int n,int m);

};


template<class T> void CElementSubset<T>::ES_Unrecursion(T data[], int n)
{
 assert(data!=NULL,"In ES_Unrecursion ,data is NULL/n");
 assert(n>0,"In ES_Unrecursion ,len is <=0/n");

 if (n <= 0 || data == NULL)
 {
  return;
 }
 int value = (int)pow((double)2,(double)n) - 1;

 int curpos=0;
 int curvalue = 0;
 do
 {  
  curpos=0;
  curvalue = value;

  while(curvalue>0)
  {
   if (curvalue % 2 != 0)
   {
    cout<<data[curpos]<< " ";
   }
   curvalue = curvalue/2;
   curpos++;
  }
  cout<<endl;
 } while (--value > 0);
}

template<class T> void CElementSubset<T>::ES_Unrecursion1(T data[], int n)
{
 assert(data!=NULL,"In ES_Unrecursion1 ,data is NULL/n");
 assert(n>0,"In ES_Unrecursion1 ,len is <=0/n");

 for (int k=1;k<=n;k++)
 {
  T* data1 = new T[k];
  memset(data1,0,sizeof(T)*k);
  Comb_Unrecursion(data, n, k);
  delete[] data1;
 }
}

template<class T> void CElementSubset<T>::ES_Recursion(T data[], int n)
{
 assert(data!=NULL,"In ES_Recursion ,data is NULL/n");
 assert(n>0,"In ES_Recursion ,len is <=0/n");

 for (int k=1;k<=n;k++)
 {
  T* data1 = new T[k];
  memset(data1,0,sizeof(T)*k);
  Comb_Recursion (data, n,k,data1,k);
  delete[] data1;
 }
}

template<class T> void CElementSubset<T>::ES_Recursion1(T data[],  bool mask[], int n,  int c)
{
 assert(data!=NULL,"In ES_Recursion1 ,data is NULL/n");
 assert(mask!=NULL,"In ES_Recursion1 ,mask is NULL/n");
 assert(n>0,"In ES_Recursion1 ,len is <=0/n");

 if  (c == n)
 {
  //如果是从最后一个元素开始寻找自己里面的元素,那就直接将mask为1的元素加到自己里面来。这个是递归结束条件
  for  (int  i  =  0;  i  <  n;  i++)
   if  (mask[i])
    cout<<data[i]<<" ";
  cout<<endl;
 }
 else
 {
  //子集分割为求含有第C个元素的子集和没有含第C个元素的子集, 这样反复递归

  //将第c个元素的标示位置为1,即第c个元素是子集里面的一个元素(1)
  mask[c] = true;
  //从第c+1个元素开始寻找子集中的元素
  ES_Recursion1 (data,  mask,  n,  c + 1);

  //将第c个元素的标示位置为0,即第c个元素不是子集里面的一个元素(2)
  mask[c] = false;
  //从第c+1个元素开始寻找子集中的元素
  ES_Recursion1 (data,  mask,  n,  c + 1);
 }                                            
}


template<class T> void CElementSubset<T>::ES_Recursion2(T data[],int n,int nLow,int nHigh)
{
 assert(data!=NULL,"In ES_Recursion2 ,data is NULL/n");
 assert(n>0,"In ES_Recursion2 ,len is <=0/n");

 if(nLow < nHigh && nHigh <= n)
 {
  for(int i = nLow;i < nHigh;i++)
  {
   cout <<data[i]<<" ";
  }
  cout <<endl;
 }
 if(nHigh == n)
 {
  ES_Recursion2(data,n,nLow+1,nLow+2);
 }
 else if(nHigh <= n)
 {
  ES_Recursion2(data,n,nLow,nHigh+1);
 }
}

template<class T> void CElementSubset<T>::Comb_Recursion( T a[], int n, int m, T b[], const int M )
{
 assert(a!=NULL,"In Comb_Recursion ,a is NULL/n");
 assert(b!=NULL,"In Comb_Recursion ,b is NULL/n");

 for(int i=n; i>=m; i--)
 {
  b[m-1] = i - 1;
  if (m > 1)
  {
   Comb_Recursion(a,i-1,m-1,b,M);
  }
  else
  {
   for(int j=M-1; j>=0; j--)
    cout << a[b[j]] << " ";
   cout << endl;
  }
 }
}

template<class T> void CElementSubset<T>::Comb_Unrecursion(T data[],int n,int m)
{
 assert(data!=NULL,"In Comb_Recursion ,data is NULL/n");
 assert(n>0,"In ES_Recursion2 ,len is <=0/n");
 assert(m>0,"In ES_Recursion2 ,m is <=0/n");

 int index,i;
 int* tmpdata = new int[m];
 if(tmpdata==NULL)
  return ;
 memset(tmpdata,0,sizeof(int)*m);

 index=0;  
 tmpdata[index]=0;
 while(true)
 {
  if(tmpdata[index]>=n)
  {
   //以index-1前面个数组成的组合已经全部走完,需要回退一步,
   if(index==0)
   {
    //各种情况取完了,不能再回退了  
    break;
   }  
   index--;//回退一步
   tmpdata[index]++;//替换元素
  }
  else if(index==m-1)
  {
   //找到一个组合了
   for (int i=0;i<m;i++)
   {
    cout<<data[tmpdata[i]]<<" ";
   }
   cout<<endl;
   tmpdata[index]++; //替换元素
  }
  else
  {
   //加入一个元素
   index++;
   tmpdata[index]=tmpdata[index-1]+1;
  }
 }  
 delete[] tmpdata;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值