排列组合
来源:互联网 发布:怎么激活电脑windows 编辑:程序博客网 时间:2024/04/30 14:28
#include <iostream>
#include <assert.h>
using namespace std;
template<class T> class CPermComb
{
private :
CPermComb(){} // 必须定义, 且为private.
CPermComb(const CPermComb&); // 不实现.
CPermComb& operator=(const CPermComb&); // 不实现.
~CPermComb(){} // 可声明为public, 但这里声明为private没有错, 可被调用.
public :
static CPermComb& GetInstance()
{
static CPermComb theSingleton;
return theSingleton;
}
public :
//(1)把数组设初值为递增序列,即:1,2,3,4,5,6…
//(2)设置第一个数为最左端,最后一个数为最右端
//(3)如果最左端与最右端相同,则输出之,并返回。
//(4)如果最左端与最右端不同,从左端到右端,逐个遍历
//(5)在遍历时,遍历到的数与其最左端的数交换
//(6)把最左端加一作为新的最左端,最右端不变,递归调用自身(2)-(8)。
//(7)递归调用返回后(即:递归调用的子函数执行(3)后),递归调用前(即:(6)前)的遍历到的数再次与其最左端的数交换,以恢复到递归调用数据交换前的状态。
//(8)本函数执行完成,返回。
void Perm_Recursion(T data[], int mid, int max);
//(1)把数组设初值为递增序列,即:1,2,3,4,5,6…
//(2)输出数组
//(3)从后向前查找,看有没有后面的数大于前面的数的情况,若有则停在后一个数的位置i。
//(4)若没有后面的数大于前面的数的情况,说明已经到了最后一个排列,返回
//(5)从后查到i,查找大于p[i - 1]的最小的数,记入j
//(6)反序排列
//(7)重复(2)-(6)
//1. 从当前序列最尾端开始往前寻找两个相邻元素,令前面一个元素为*i,后一个元素为*ii,且满足*i<*ii;
//2. 再次从当前序列末端开始向前扫描,找出第一个大于*i的元素,令为*j(j可能等于ii),将i,j元素对调;
//3. 将ii之后(含ii)的所有元素颠倒次序,这样所得的排列即为当前序列的下一个排列。
void Perm_Unrecursion(T data[], int max);
//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 CPermComb<T>::Perm_Recursion(T data[], int mid, int max)
{
assert(data!=NULL,"In Comb_Recursion ,data is NULL/n");
int curmax;
if (mid == max)
{
//找到一个组合项
for (curmax = 0; curmax <= max; curmax++)
cout<<data[curmax] << " ";
cout<<endl;
}
else
{
for (curmax=mid; curmax <= max; curmax++)
{
swap (data[mid], data[curmax]);
Perm_Recursion (data, mid+1, max);
swap (data[mid], data[curmax]);
}
}
}
template<class T> void CPermComb<T>::Perm_Unrecursion(T data[], int max)
{
assert(data!=NULL,"In Comb_Recursion ,data is NULL/n");
assert(max>0,"In Sort_Counting ,max is <=0/n");
int i,j;
int *tmpdata = new int[max];
if(tmpdata==NULL)
{
return ;
}
memset(tmpdata,0,sizeof(int)*max);
for(i=0;i<max;i++)
{
tmpdata[i]=i;
}
while(true)
{
for(i=0;i<max;i++)
{
cout<<data[tmpdata[i]]<<" ";
}
cout<<endl;
//从后向前查找,看有没有后面的数大于前面的数的情况,若有则停在后一个数的位置i
for(i=max-1;i>0 && tmpdata[i]<tmpdata[i-1];i--);
//若没有后面的数大于前面的数的情况,说明已经到了最后一个排列,返回
if(i==0)
break;
//从后查到i,查找大于p[i - 1]的最小的数,记入j
for(j=max-1;j>i && tmpdata[j]<tmpdata[i-1];j--);
//交换p[i-1]和p[j]
swap(tmpdata[i-1], tmpdata[j]);
////倒置p[i]到p[n-1]
for(i=i,j=max-1;i<j;i++,j--)
{
swap(tmpdata[i], tmpdata[j]);
}
}
delete[] tmpdata;
}
template<class T> void CPermComb<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 CPermComb<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;
}
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 排列组合
- 堆操作
- 几个API
- 矩阵操作
- 以后
- 《Linux那些事儿之我是USB》我是U盘(6)未曾开始却似结束
- 排列组合
- Unsupported major.minor version 49.0的错误(JDK 编译与运行 版本不匹配)
- 密码学常用网址
- 查找
- C 指针变量 也是 传值 调用
- Android 建立Menu选单&&onOptionsItemSelected
- 常见网站漏洞及解决办法
- 关于《现代密码学》教材与教学改革的几点思考
- QTP中发送邮件