1.起因
提起排序算法,大家都能随意讲出一大堆,比如冒泡,Shell,插入,快排等...然而有没有想过自己实现一个排序算法。我曾经在前年的时候实现了一个本应该由GPU来执行的移位排序算法,可惜没有搞到硬件和软件,那篇文章是:(http://blog.csdn.net/dog250/article/details/5303538)《移位排序算法--从赛跑想到的》,该文用递推的方式实现了移位排序,代码冗长,很不清晰,如今我自己都懒得剖析了。同样基于赛跑的思想,本文实现了一个超级简洁的移位排序算法,效率嘛,快得出奇,又慢得可以!
2.思想
大家都知道赛跑,在跑道上每人一道,看谁先跑到终点谁就是冠军,然后看剩下的人中谁先跑到终点,此为亚军,然后季军,...一直到倒数第一。
实际上,计算机实现的排序非常符合这个思想,以往的传统算法为了排序,难免要在待排序数中做两两比较,何不用一个外部基准,一起上呢?这一点我觉得赛跑规则的发明真是一项创举,否则就需要比赛者两两比赛了,不把人累死才怪!相比之下诸如摔跤,相扑,拳击以及乒乓球等项目却都是两两比较的项目,然而两两比较也是讲策略的,比如分组赛,淘汰赛等,实际上传统的排序算法都是基于两两比较的算法,就是因为比赛策略不同,才出现不同的大O。
本文实现的排序算法不需要两两比较,完全基于外部的基准来进行,特别容易利用硬件特性来并行实现。那么外部基准是什么呢?我想起刘翔的110米栏,每撞栏一次就会减速一次,结果撞栏最少的获胜的可能性最大(当然还有别的因素,状态,实力,运气...),所有待排序的数字都是同一类型,同一类型数据拥有同一宽度,比如32系统int型就是32位,char型一般8位,把数据的宽度作为栏杆,那么对于int类型,所有的待排序数据就都要跨过32个栏杆了,如果某个栏杆处某个数据对应的位是1,那么就表示跨过了该栏杆,若是0,则表示撞到了该栏杆,需要减速,本质上,算法逻辑需要判别一个指标,那就是“谁跑得远”而不是谁先到终点,第4节会说明为何这么做。
3.代码与效率
3.1.版本一:使用Integer
该版本使用Integer是因为在Eclipse中可以自动补全方法,写起来比较方便。用这种方法快速完成一个能跑的程序
用同样的方法写出冒泡,插入,快排等算法,在Linux下用time命令测试,比特排序算法在大量数据情况下效率明显高很多,有时虽然略逊快排一筹,然则直追之,不幸的是,使用了递归,又大量使用对象,空间复杂度极高。
3.2.版本二:使用int数组
使用数组是最直接的,因为版本一并不能证明比特移位排序是最快的,原因是我们不知道ArrayList的add以及set方法内部做了什么,有可能set方法是瓶颈呢...因此版本二不使用对象,而是直接使用int数组来完成排序:
用这个版本测试下来,发现该算法总是比不过快排,因此着手优化之,本来脑子里面的算法很完美,结果写出来还是很丑陋,这是仓促的结果,因此必须有版本三
3.3.优化版本二
该版本讲逻辑判断优化掉,理由很简单,因为判断涉及到跳转,进而涉及分支预测,而分支预测一旦失败的代价极高!
测试下来发现,BitSort无疑是最快的。
空间换时间,在内存不值钱的今天这无疑是一剂猛药,然而算法开发的成本也极高,一个月一个程序员少说也有4位数,这一个个一组组的4位大洋数交给一个没有任何立杆见影产出的所谓算法,在国内实属玩物丧志...
4.实质
为何不测谁先到终点呢?因为基于时间的测试在计算机的同一个程序中很难进行,因为冯诺依曼机器就是在时间轴上顺序执行的。那么就要采用一个变通的测试。先到终点的肯定在某一个时刻跑得最远。在这个算法执行的比赛中,是不能存在超越的。如果为待比较元素都维护一个计数器来表示“谁跑的远”这项测试指标的话,最终我们还需要来比较这些计数器的大小,这又回到了最终的问题,那就是排序!好在我们可以充分使用计算机的知识,在这个例子里,递归调用恰好为我们完成“看谁跑的远”这个测试,最终这项指标就落实在了看谁的递归调用深度最深这个指标。
我们完全信任递归,实质上,递归是一个“按照一定的顺序来执行自身”的算法,这个“一定的顺序”就是我们需要实现的逻辑,也就是程序的逻辑!大多数情况下,我们只关心递归的调用逻辑,殊不知递归其本身也可以被利用,这就是本例排序算法的本质!
5.感言
这个程序有很多缺点,但是其最大的优点我觉得是它非常简单,仅仅几行就能搞定完全的排序操作。在效率上,由于消除了两两比较和交换操作,更有效的利用了局部性原理,提高了cache的利用率,这也许为它能胜出绝大多数竞赛加了分。消除交换是很有意义的,因为消除了频繁交换,也就消除大量的cache失效,因此会些许提升些效率。
分享到:
相关推荐
最快的排序算法 C语言最简单的排序算法冒泡排序并返回排序前索引序号,排序算法数据结构
排序算法包 各种排序算法 java源 堆排序,快排等各种排序算法
最快的排序算法 最快的内部排序法—桶排序法,排序算法数据结构
最快的排序算法 计算机最快的算法-史上14个最快速算法:孩子的计算能力爆表!大脑堪比计算机!...,排序算法数据结构
5.3.2一种更快的作业排序算法,排序算法数据结构.doc
快速排序法(quick sort)是目前所公认最快的排序方法之一(视解题的对象而定),虽然快速排序法在最差状况下可以达O(n2),但是在多数的情况下,快速排序法的效率表现是相当不错的。 快速排序法的基本精神是在数列中...
最快的排序算法 最快的内部排序法—桶排序法 (1),排序算法数据结构
最快的排序算法 把Excel里的一列数字按照奇偶数的形式排序出来怎样做才是最好最快的方法,排序算法数据结构
排序算法是一种基本并且常用的算法。由于实际工作中处理的数量巨大,所以排序算法 对算法本身的速度要求很高。 而一般我们所谓的算法的性能主要是指算法的复杂度,一般用O方法来表示。在后面我将 给出详细的说明...
C++实现希尔、快速、堆排序、归并排序算法,一些中文注释可能成乱码了,但是不影响代码执行。
一个比快速算法更快的算法,排序算法数据结构.pdf
试通过随机数据比较快速排序、起泡排序各算法的关键字比较次数和关键字移动次数。 (1)待排序表的表长不小于100;其中的数据要用伪随机数产生程序产生;至少要用5组不同的输入数据作比较;比较的指标为有关键字...
合并排序算法和快速排序算法采用了采用分治法、递归的方法,将时间复杂度降为O(nlogn)。在本次实验中将数据量提到5万的时候,该类算法运行时间仍在几毫秒左右,而上面的3种算法运行时间已经到达十几秒左右,效率...
一个堆排序算法 c++写的 逻辑相同 可自行 改为java 写一个堆排序算法 c++ 写一个堆排序算法 c++ 写一个堆排序算法 c++ 写一个堆排序算法 c++ 写一个堆排序算法 c++ 写一个堆排序算法 c++ 写一个堆排序算法 c++ 写一...
支持任意类型数据的排序,采用5中排序算法冒泡排序,选择,插入,快速,堆排序。
桶式排序法桶式排序法桶式排序法桶式排序法
最快的排序算法 谁才是最强的排序算法:快速排序-归并排序-堆排序,排序算法数据结构
一个更快的带有期限的作业排序问题,排序算法数据结构 最快的排序算法
3.1实验目的与要求 1、熟悉快速排序的串行算法 2、熟悉快速排序的并行算法 ...6、在最优的情况下并行算法形成一个高度为logn的排序树 7、完成快速排序的并行实现的流程图 8、完成快速排序的并行算法的实现
该程序包含7大排序算法: # sort.bubbleSort() #冒泡排序 # sort.shellSort() #希尔排序 # sort.insertionSort() #插入排序 # sort.Selectionsort1() #选择排序 # sort.heapSort() #堆排序 # sort.countSort() ...