基于格雷码生成算法的n选m排列算法

研究了递归生成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)




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值