研究了递归生成n选m排列算法时,发现递归算法中有较多的重复计算。重复计算源自获取长排列时,对于每一个长排列的子集——短排列,都是重新计算得到的,没有对已经生成的短排列进行利用。通过研究格雷码生成算法(http://blog.csdn.net/aitazhixin/article/details/61915679),发现采用类似格雷码的插入算法,能避免这种重复获取短排列的问题。
插入算法的基本思想为:
1,首先生成单元素排列为:1;2;3;……;n;
2,在已生成的短排列上每个排列后面,插入1~n,对于短排列上已有的元素,则不重复插入;
运行效率比较:
插入算法的基本思想为:
1,首先生成单元素排列为:1;2;3;……;n;
2,在已生成的短排列上每个排列后面,插入1~n,对于短排列上已有的元素,则不重复插入;
3,重复步骤2将得到最终的m排列。
代码如下:
#include <iostream>
#include <vector>
#include <time.h>
using namespace std;
void FullPermutation(int m, int n);
int main()
{
int m, n;
cout << "Input number of count: ";
cin >> n;
cout << "Input permutation number: ";
cin >> m;
clock_t startTime = clock();
FullPermutation(m, n);
clock_t endTime = clock();
cout << "Processing Time: " << (endTime - startTime) << endl;
return 0;
}
void FullPermutation(int m, int n)
{
vector<vector<int>> vec;
if ((m < 1) && (n < 1))
return;
if (m > n)
{
FullPermutation(n, n);
return;
}
vec.resize(n);
for (int pIdx = 1; pIdx <= n; pIdx++)
{
vector<int> pvec;
pvec.push_back(pIdx);
vec[pIdx - 1].assign(pvec.begin(), pvec.end());
}
for (int pIdx = 2; pIdx <= m; pIdx++)
{
vector<vector<int>> tmpVec;
int vSize = vec.size();
int newVecIdx = 0;
tmpVec.assign(vec.begin(), vec.end());
vec.resize(vSize * (n - pIdx + 1));
for (int vIdx = 0; vIdx < vSize; vIdx++)
{
for (int tIdx = 1; tIdx <= n; tIdx++)
{
if (tmpVec[vIdx].end() == find(tmpVec[vIdx].begin(), tmpVec[vIdx].end(), tIdx))
{
vector<int> tVec;
vec[newVecIdx].assign(tmpVec[vIdx].begin(), tmpVec[vIdx].end());
vec[newVecIdx].push_back(tIdx);
newVecIdx++;
}
}
}
}
int aSize = vec.size();
//for (int aIdx = 0; aIdx < aSize; aIdx++)
//{
// vector<int>::iterator tmpIter = vec[aIdx].begin();
// for (; tmpIter != vec[aIdx].end(); tmpIter++)
// {
// cout << *tmpIter << "\t";
// }
// cout << endl;
//}
cout << "Number of Permutation: " << aSize << endl;
return;
}
运行效率比较:
本节算法
原算法(http://blog.csdn.net/aitazhixin/article/details/61414329)