声明:
本篇文章用到的算法代码均是本人复习完对应的算法后,用自己的思维亲手编写的,由于时间问题,没有能够参考权威、标准的 api 源码,因此本文中的所有排序算法大概率还有优化的可能,执行效率大概率还可以更快,更稳,更省空间;希望大神发现以后可以在评论区广泛讨论,毕竟社区的力量是伟大的,开源的力量是无穷的!!!
废话不说,先看 PK 结果
从图片可以看出,如果数据量非常小,堆排序、归并排序、快速排序、桶排序、timeSort排序、计数排序的表现都是非常优异的;那么数据量非常小的情况下,我们应该选择哪种排序算法进行排序呢?笔者推荐堆排序或归并排序或快速排序或timesort排序,以下是参考条件
- 冒泡排序属于暴力排序,对cpu的运算负载非常大,直接忽略
- 插入排序,希尔排序,选择排序属于低阶排序算法,在本轮测试中表现不是非常好,而且其一般用于其他排序算法的辅助性工具,所以忽略
- 堆排序没有用到辅助性的数组,所以它占用的空间可以忽略为待排序数组的大小,测试中耗时最短,对栈的依赖适中,可以接受
- 归并排序用到了辅助性数组,所以它占用的空间可以忽略为两倍的待排序数组的大小,测试中耗时最短,对栈的依赖适中,比堆排序稍差
- 快速排序没有用到辅助性的数组,所以它占用的空间可以忽略为待排序数组的大小,测试中耗时偏短,但对栈的依赖最高,所以递归深度最深,比堆排序稍差
- 桶排序严格意义上说是一种策略,一种思想,且桶排序的执行效率与编码人员的综合素质息息相关,是一种下限极低,上限极高的极度自由的排序算法,用到小数据量的排序有点大材小用
- timeSort是 jdk 官方默认排序算法,能被官方作为默认的排序算法,必然非常优秀;且它结合了归并排序和插入排序的优点
- 基数排序用到了辅助性数组,所以它占用的空间可以忽略为两倍的待排序数组的大小,测试中耗时偏高,但空间复杂度极低,也比较优秀
- 计数排序用到了模板性的辅助数组,所以它占用的空间可以很小,也可以很大,取决于待排序数组的分布情况,但时间复杂度极低,也比较优秀,如果待排序数组的最大最小值较小,可以考虑
从图片可以看出,如果 timeSort排序,堆排序,归并排序,快速排序,基数排序均可作为选择,计数排序需要开发人员判断待排序序列的取值范围再做打算
从图片可以看出,如果数据量稍微大的情况下,因此数据量稍微大的情况下 timeSort排序,堆排序,归并排序,快速排序均可作为选择;至于 冒泡排序,插入排序,希尔排序,选择排序,在 十万级别数据量及以上 的情况下可以彻底放弃了,性能差距非常大;对其余排序算法做简单分析
- 可以明显看出,基数排序算法从此刻开始,已经有点力不从心了,所以如果数据量以万为单位的话,可以基数排序算法了
- 计数排序算法的变现也比较优秀,但是它还是老问题,需要开发人员判断待排序序列的取值范围再做打算,否则可能会太过耗费内存空间
- 快速排序在到达 100000 这个级别(甚至更多)的时候,会明显的暴露出一个问题——对栈(递归)的依赖太高了,如果不修改参数,大概率会出现爆栈的情况,运行时,需要配置以下参数给 jvm 虚拟机
从图片可以看出,如果数据量偏大的情况下,timeSort 排序算法的表现依旧非常卓越,必然为首选;因此数据量偏大的情况下 timeSort排序,归并排序,堆排序,快速排序,桶排序均可作为选择,对其余排序算法做简单分析
- 堆排序、归并排序在百万级数据量下的表现差距还不是很明显,且实际表现都比较优秀,可以作为选择
- 快速排序需要注意的是,从 100000 这个级别开始就会出现明显的爆栈问题,但是其综合变现还是非常优秀的,如果要使用,注意配置 jvm 参数
- 可以明显看出,在数据量达到 百万级别甚至更多 的情况下,桶排序开始发力了,且不鸣则已,一鸣惊人
- 计数排序算法的变现尤其优秀,但是它还是老问题,需要开发人员判断待排序序列的取值范围再做打算,否则可能会太过耗费内存空间
从图片可以看出,如果数据量较大的情况下,桶排序 算法强悍的统治力已经显现;除此之外数据量较大的情况下 timeSort排序,归并排序,快速排序,桶排序均可作为选择,对其余排序算法做简单分析
- 可以明显看出,堆排序算法从此刻开始,已经有点力不从心了,有点跟不上老对手归并排序的步伐了,所以如果数据量以 千万为单位甚至更多的话,可以忽略堆排序算法了
- 计数排序的表现虽然十分亮眼,但是根据其特性,笔者建议,在数据量达到千万级别甚至更多的情况下,不要考虑计数排序了,否则参考模板给内存空间的压力是在太大了
从图片可以看出,如果数据量较大的情况下,桶排序 算法已经可以做到一枝独秀了;除此之外数据量较大的情况下 timeSort排序,归并排序,快速排序,桶排序均可作为选择,对其余排序算法做简单分析
- 可以明显看出,堆排序算法在此刻已经被彻底淘汰
- 根据实战,可以得出一个结论,如果数据量以亿为单位,首选 桶排序,可以这么说,桶排序就是为大数据量排序量身定制的,在足够大的数据量下,无论是作为武林盟主(IT界被人人奉为经典的排序王者)的快速排序还是身居兵马大元帅(被 Java 和 Python 钦点为官方默认排序算法)的 TimeSort ,都在绝对实力的面前显得黯然失色!!!
从始至终,你可以看到有两种排序算法一直处于巅峰状态,它们就是——归并排序、快速排序、TimeSort排序。因此,无论在何种情况下,你都可以毫不犹豫的选择归并排序或快速排序或TimeSort排序进行对任意目标数据的排序操作,它们绝对不会让你失望;那么他们三者,谁最强?下面进行分析
- 归并排序不仅快,而且稳,无论数据是全部有序,还是部分有序甚至完全倒序的情况下,他都可以做到一如既往的快,这就是王者的实力!可以说是宗师般的存在,这也是 TimeSort 将归并作为主要底层排序算法的底气所在,因此说归并排序是曾经的王者,教科书般的典范自然毫不夸张
- 快速排序在绝大多数情况下,的确要比归并排序更快,但是它有两个缺点——其一是不稳定,如果数据在大致有序甚至完全有序的情况下,快排的效率会大打折扣,可谓是一步一坑!要比归并慢很多;其二是快排对栈内存的依赖太高了,在一般的情况下,数据量达到 10万 级别,就会出现爆栈的情况,需要修改 jvm 运行参数,否则会直接奔溃
- TimeSort 排序算法是一种混合型的排序算法,和归并,快排并不是完全一样的类型;但是从它一出生那一刻起,便注定了荣华富贵,师承天下第一的归并排序,还又使用插入排序将存在的逆序序列矫正,最后将多个有序的序列利用归并排序合并,无论在那种情况,TimeSort 都比归并排序有过之而无不及,可谓是青出于蓝而胜于蓝。因此 TimeSort 是当之无愧的天下第一
综上所述,如果说归并排序是张三丰,那么 TimeSort 就是张无忌,从对武学的修养,领悟,造诣方面讲,张无忌自然不是张三丰的对手,甚至不在一个级别,但是若真起来,张三丰也不一定能打赢张无忌,毕竟九阳神功提供强大的源源不断的内力,乾坤大挪移更是开挂般的存在,可以瞬间恢复伤势;那么 快速排序是谁?自然是 常胜宝树王,论综合实力,不敌张三丰与张无忌,但是若配合圣火令中的武功,有时候张无忌也不敌
是个人就有优缺点,同样排序算法也一样;归并排序没有缺点吗?有!归并排序需要用到额外的数组,内存空间更大,而冒泡排序不需要用到额外的内存空间;TimeSort没有缺点吗?有,数据量极大的情况下,没有桶的思想,属实更不上时代的步伐;快速排序缺点不止一个,就更不用说了。所以要想在每种情况下都想得到最快的排序结果,单独使用一种排序算法肯定做不到,得分情况而论;以下情况不一定就是最优解,需要配合各自机器的配置特点进一步分析
Ⅰ10000 及以下数据量排序算法的选择
在数据完全有序或完全倒序的情况下,TimeSort排序 的表现最为优秀
在数据部分有序的情况下,堆排序、归并排序、快速排序、计数排序、TimeSort排序 会轮流登上王者,可随意选择,但注意计数排序的特性
Ⅱ 100000 左右数据量排序算法的选择
在数据完全有序或完全倒序的情况下,TimeSort 的表现最为优秀
在数据部分有序的情况下,如果取值范围不是很大,计数排序的表现最为优秀
在数据部分有序,且确定不适合使用计数排序的情况下,堆排序、归并排序、快速排序、TimeSort排序 会轮流登上王者,可随意选择
Ⅲ 100000 左右数据量排序算法的选择
经核实,在数据完全有序或完全倒序的情况下,TimeSort 的表现最为优秀
在数据部分有序的情况下,如果取值范围不是很大,计数排序的表现最为优秀
在数据部分有序,且确定不适合使用计数排序的情况下堆排序、归并排序、快速排序、TimeSort排序 会轮流登上王者,可随意选择
Ⅳ 1000000 左右数据量排序算法的选择
在数据完全有序或完全倒序的情况下,TimeSort 的表现最为优秀
在数据部分有序的情况下,如果取值范围不是很大,计数排序的表现最为优秀
在数据部分有序,且确定不适合使用计数排序的情况下,桶排序、堆排序、归并排序、快速排序、TimeSort排序 会轮流登上王者,可随意选择
Ⅴ 10000000 及以上左右数据量排序算法的选择
在数据完全有序或完全倒序的情况下,TimeSort 的表现最为优秀
在数据部分有序情况下,桶排序一直处于巅峰,第一梯队首选桶排序,第二梯队为 TimeSort排序,第三梯队为快速排序,第四梯队为归并排序
(已设置终生免费下载,可放心下载)
时间工具类
排序工具类
排序算法公用抽象类
冒泡排序
插入排序
希尔排序
选择排序
堆排序
归并排序
快速排序
桶排序
基数排序
计数排序
TimeSort 排序(JDK默认排序算法)
各种算法的 PK 结果与代码质量、数据分布、参数配置、机器配置、机器实时可用资源等息息相关,本文仅代表当时的情境下,笔者代码质量的前提下执行的情况,不代表标准算法的科学研究与对比