当前位置: 首页 > 科技观察

我是如何战胜Java内置排序算法的

时间:2023-03-17 11:22:39 科技观察

Java8对内置排序算法进行了很好的优化。对于整数和其他基本类型,Arrays.sort()使用双轴快速排序、合并排序和启发式插入排序的组合。这个算法非常强大,可以在很多情况下使用。大型阵列支持更多变体。我把自己草草写的排序算法和Java自带的算法进行了比较,看能不能比较。这些实验包括特殊情况的处理。首先,我写了一个经典的快速排序算法。该算法通过计算样本的均值来估计整个阵列的中心点,然后将其用作初始枢轴。我借用了一些Java思想来适当改进我的快速排序。修改后的算法在对小数组进行排序时直接调用插入排序。这样的话,我的排序算法和Java的排序算法可以达到相同数量级的运行时间。Wild&al指出,如果排序的数组有很多重复项,标准快速排序可以比双轴快速排序更快。我没有尝试任何字节或汇编级别的分析和优化。在大多数问题中,我的优化器版本远不及Java系统程序。我一直想在脑海中测试一个简单的排序算法,我称之为Bleedsort。这是一种分布式算法,通过样本抽样的方式估计待排序数组的分布,根据估计的结果将数据赋值给一个对应的临时数组(如图1所示),并改写初始数组。这是在应用其他排序算法单独排序之前的一个预处理过程。在我的测试中,我使用了我编写的一个快速排序版本。如果您使用归并排序,您应该会得到更好的结果,因为归并排序广泛用于高度结构化的数组。为了计算简单,我只测试了均匀分布的数据。Bleedsort遇到相同的数据就把相同的数据放在右边,所以这个算法在排序比较一致的数组时表现很差。所以需要对排序后的数组做样本估计,重复次数多的时候要避免Bleedsort算法。我很清楚,Bleedsort算法在内存空间占用方面无法与归并排序(快速排序)相提并论,临时数组大约是原始数组的四倍。同时,其他一些分布式排序算法,如Flashsort,在这方面也表现得更好。图1Bleedsort举例说明了我使用JMH作为基准。为简单起见,我正在使用整数数组进行测试。我的算法在1000.000到10.000.0000数量级的均匀分布数组上效果最好。虽然我写的快速排序算法在一定程度上不如Java自带的算法,但是我的预处理过程弥补了这些不足(调用我的快速排序Bleedsort87msvsJava自带算法105ms;938msvs1.144s)BenchmarkModeCntScore错误单位校正myBenchmark._1E6U样本85120.024±0.001s/opmybenchmark._1E7U样本9850.236±0.001s/opopop我我生成生成了生成了了了下面下面下面下面下面这些这些这些的这些组数数数数数数24100.087±0.001s/op0.063±0.002myBench.int1e6ujavasort样本19780.105±0.001s/op0.081±0.002myBench.int1e7uquicksort2001.483±0.014s/op1.459±0.0.099±0.011±0.097±0.097±0.0977.±0.010MyBench.int1e7UJavaSortsample2001.144±0.009s/op1.120±0.010因此,我的没有特别优化的算法程序大约是10-15%。在具有1000.000数据级别的均匀增强数据集上,包含10%或1%的随机重复,我的A算法表现不差。基准模式CNT分数错误单位校正。±0.229ms/op42.44±0.25.int1e6iw010quicksort样品389952.457±0.210ms/op42.76±0.2310%±0.2310%重复.int1e6iw001BledsbledsbledSortSampe619032.821±0.219MS/OP32.821MS/OP31.219MS/OP31.48±0.2.2.2.2.2.2.2.2.2.2.2.2e.2.19.2.2.219.2.219.2.2rimelavy3.2.2.2.2.19.48±;.int1e6Iw001QuickSortsample865323.367±0.056ms/op22.02±0.06^^1%但是,该算法仅适用于具有大约10.000(~bin(100,0.5))的小二项分布的数据集(译者加:考虑括号里面是公式代码,内部英文括号符号没有修改成中文符号),性能很差。在这些数组中,平均而言,数字50出现的次数为795.5,而40的数组重复次数为108.4。同时,在对1000.0000量级的大数组进行排序时,该算法比Arrays.sort()慢两倍左右。这些数组有很多重复的数据(例如,一些大小为1e6的数组只有450个不同的值)。基准模式CNT分数错误单元已纠正。1468521.362±0.001ms/op0.046±0.002.int1e6bin1e4BleedSortsample753442.654±0.005ms/op-.int1e6bin1e4JavaSortsample1468011.361±0.002ms/op-.int1e6bin1e4QuickSortsample764672.615±0.005ms/op-在排序小型的(10.000,100.000)uniformrandomarray,这个算法的性能尚可,但并不比系统算法好。MyBench.int1e4UBleedSortsample2164920.924±0.001ms/op0.683±0.002MyBench.int1e4UJavaSortsample2534890.789±0.001ms/op0.548±0.002MyBench.int1e4UQuickSortsample2173940.920±0.001ms/op0.679±0.002MyBench.int1e5UBleedSortsample187520.011±0.001s/op0.009±0.002MyBench.int1e5UJavaSortsample223350.009±0.001s/op0.007±0.002MyBench.int1e5UQuickSortsample187480.011±0.001s/op0.009±0.00不适用于非常大的内存集,in2,我建议将分布式搜索算法作为一种有效的补充选项。最后让大家认识一下二项分布的一些数据集bin(100,0.5)和bin(1000,0.5)。这里有两个随机抽取100个数据的数据集(使用R语言生成)。>rbinom(100,100,0.5)[1]43495147495940464651504949455051504953524553485645[26]475547535356414547514649495246484950485654495352[51]544845455048544952504848494554545041534551485352575675554525645454654463843434562485252525252525256>Rbinom(100,1000,0.5)[1]515481523524519516498473523514483483483458506506506506506506506506506506506506506506506506506506506506506506506506506506506506491514489[19]475489489485507486523523523521492521492521492502502502502501501501501501501501504482518518518492492525[37]37]479506506506506497497497510479521505493480498498492492492476490506[73]496505521521518506509483509483501497501483502470515905195