基于格雷码生成算法的n选m排列算法
2017-03-13 16:15
190 查看
研究了递归生成n选m排列算法时,发现递归算法中有较多的重复计算。重复计算源自获取长排列时,对于每一个长排列的子集——短排列,都是重新计算得到的,没有对已经生成的短排列进行利用。通过研究格雷码生成算法(http://blog.csdn.net/aitazhixin/article/details/61915679),发现采用类似格雷码的插入算法,能避免这种重复获取短排列的问题。
插入算法的基本思想为:
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)
插入算法的基本思想为:
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)
相关文章推荐
- 基于字典序的组合生成算法
- 基于Excel的QR二维码生成工具——原理及算法详解(之七)
- 基于OpenGL的三种直线生成算法
- 格雷码生成算法详解(c语言)
- 基于L0范数平滑的图像漫画特效生成算法
- 也谈自动生成格雷码算法
- 基于最小生成树的实时立体匹配算法简介
- [代码]基于RNN的文本生成算法
- 基于邻接矩阵存储的图的最小生成树的Prime算法
- 基于多线程的随机数生成算法
- 基于OpenGL的三种直线生成算法
- 基于最小生成树的实时立体匹配算法简介
- 基于递归分割的迷宫生成算法与自动寻路
- 基于RNN的文本生成算法的代码运转
- 基于矩阵实现的最小生成树算法
- Gray码的生成算法(直接由二进制数转格雷码)
- 基于Excel的QR二维码生成工具——原理及算法详解(之四)
- 基于高度图的三维地形生成算法入门篇 —— 均匀网格地形生成算法
- 第2章 基于划分-测试的实值检测器生成算法 (2.1-2.3)
- 基于递归分割的迷宫生成算法与自动寻路