上一章的算法笔记,并不算一个算法系列的一个合适的开始。而本章将会介绍一种产生随机全排列的方法,下一章开始,就正式开始我们的排序算法了。
在我们的排序算法演示器中,我们需要一组随机的数据来作为排序的开始,而本章,就会产生这么一组随机数据。
(一)实现分析
我们需要一组随机的数据,而且似乎产生的方法不会太难。我们只需要通过rand()函数获得一个随机数,让其对count(排序的规模)取模,结果作为数组的索引,其值是当前已产生的随机数的个数,如果已经存在了,继续查找,直到产生随机数的个数与总数相同。
这种方法的最大问题在于,我们需要产生的是一组全排列,当排序的规模较大时,最后几个数字的命中率低的可怕,这种方法只能被抛弃。
说到全排列,似乎还有一种方法,我们可以通过标准库中的一个算法,next_permutation(),依次得到全排列,那么我们可以先有序排列,然后获得n次下一个全排列,n为一个随机数,它从0到全排列的种类。问题又来了,全排列种类怎么算的?阶乘,太可怕了,这个种类的总数在达到一定规模的时候,不见得会比上面一种方法快。这种方法也被pass。
然后就是我们今天要使用的方法了,抽牌法。首先声明哈,这种方法,是我从某杂志上看来的,并非完全原创。
我们可以想想生活中发牌的实例,我们经过一轮洗牌发牌之后,似乎只需要一遍就能够搞定了,而且根本不可能存在未命中的情况。它是怎么实现的呢?首先随机抽出一张牌,将其从牌堆中取出,再从剩下的牌堆中,再随机抽出一张....以此类推。
(二)构建模型
其实从上面的说法,模型已经很明显了。我们需要一个牌盒来放还剩下的牌,需要另一个牌盒,来放入取出的牌。依次从剩下的牌中随机抽出一张牌,直到最后没有剩下牌为止。
1. 创建两个数组,我们可以使用vector,也可以通过动态分配,给int型指针分配count个整数。
2. 然后利用rand()函数,从中抽出一个数来,将其存入另一个数组中。
3. 剩余牌盒中将被抽到的这个数字和剩余牌盒中最后一个数字交换,下次只从前count-1个数中抽取,下一次重复2中的操作,直到剩余数组中个数为0。
4. 如果使用了指针,做些清理工作。
(三)代码实现
这段代码,暂时就不写了,相信熟练掌握任何一种语言的程序员都能够按照上述方法以o(n)的效率产生全排列随机数了吧。
好了,从下篇博客中,我们就要开始排序啦,各种各样排序算法,将会通过我们的演示程序一一展示出来,想起来又略有点小兴奋。
算法笔记(二)抽牌法产生随机全排列,布布扣,bubuko.com
原文地址:http://blog.csdn.net/fukainankai/article/details/33747495