关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » 算法设计 »我是怎样击败Java自带排序算法的

    我是怎样击败Java自带排序算法的

    2015-09-05 00:00:00 出处:iheima
    分享

    微信扫一扫:分享

    Scan me!

    微信里点“发现”,扫一下

    二维码便可将本文分享至朋友圈。

    Java 8 对自带的排序算法进行了很好的优化。对于整形和其他的基本类型, Arrays.sort() 综合利用了双枢轴快速排序、归并排序和启发式插入排序。这个算法是很强大的,可以在很多情况下通用。针对大规模的数组还支持更多变种。我拿自己仓促写的排序算法跟Java自带的算法进行了对比,看看能不能一较高下。这些实验包含了对特殊情况的处理。

    首先,我编写了一个经典的快速排序算法。这个算法通过计算样本的平均值来估计整个数组的中心点,然后用作初始枢轴。

    我借鉴了一些Java的思路来适当改进我的快速排序,修改后的算法在对小数组进行排序的时候直接调用了插入排序。在这种情况下,我的排序算法和Java的排序算法可以达到相同的运行时间量级。Wild & al 指出,假如排序数组有很多的重复数据,标准的快速排序会比双枢轴的快速排序要快。我没有尝试任何字节或汇编级别的分析和优化。在大部分的问题中,我的版本的优化程序都远远不能跟Java系统程序相提并论。

    我一直都想测试脑海里的一个简单的排序算法,我称之为Bleedsort。这是一个分布式算法,它通过样本抽样方法对要排序的数组进行分布估计,根据估计结果把数据分配到相应的一个临时的数组里(如图 1 所示),并重写这个初始的数组。这是一个预处理过程,然后再应用其他的排序算法分别进行排序。在我的测试中,我使用了我编写的快速排序版本。假如使用合并排序应该会有更好的结果,因为合并排序被广泛应用在高度结构化的数组中。为了计算简单,我只测试了分布均匀的数据。

    Bleedsort在遇到相同的数据的时候都会放到右边,所以此算法在排序相对一致(译者注:会有很多重复数据)的数组的时候表现很差。所以我需要对排序的数组进行样本估计,当重复数很多的情况下应避免使用Bleedsort算法。

    我很清楚,Bleedsort算法在内存空间使用方面没办法跟归并排序(快速排序)相提并论,临时数组也比原来的数组要大四倍左右。同时其他的一些分布排序算法,比如Flashsort,在这方面也表现得要好很多。

    击败Java排序算法

    图1 Bleedsort举例说明

    我运用JMH来作为测试基准。为了简单起见,我就用整形数组进行测试。在1000.000 到10.000.0000 数量级的均匀分布的数组中,我的算法表现的最好。尽管我写的快速排序算法在一定程度上比不过Java自带的算法,但是我的预处理过程很好的弥补了这些不足(调用了我的快速排序的Bleedsort 87ms vs Java 自带算法105ms; 938ms vs 1.144s)

    Benchmark Mode Cnt Score Error Units Corrected
    
    MyBenchmark._1e6U sample 8512 0.024 ± 0.001 s/op
    
    MyBenchmark._1e7U sample 985 0.236 ± 0.001 s/op
    
    我生成了下面这些正确的基准数组
    
    MyBench.int1e6UQuickSort sample 1641 0.131 ± 0.001 s/op 0.107 ± 0.002
    
    MyBench.int1e6UBleedSort sample 2410 0.087 ± 0.001 s/op 0.063 ± 0.002
    
    MyBench.int1e6UJavaSort sample 1978 0.105 ± 0.001 s/op 0.081 ± 0.002
    
    MyBench.int1e7UQuickSort sample 200 1.483 ± 0.014 s/op 1.459 ± 0.015
    
    MyBench.int1e7UBleedSort sample 373 0.938 ± 0.009 s/op 0.914 ± 0.010
    
    MyBench.int1e7UJavaSort sample 200 1.144 ± 0.009 s/op 1.120 ± 0.010

    所以,我的这个没有特殊优化的算法程序在这些数据集上要比Java自带算法快大概 10-15% 。

    在1000.000数据级,包含 10% 或者 1% 的随机重复数据的均匀增加数据集上,我的算法表现的也不差。

    Benchmark Mode Cnt Score Error Units Corrected
    
    ._1e6Iwf010 sample 20705 9.701 ± 0.033 ms/op
    
    ._1e6Iwf001 sample 148693 1.344 ± 0.003 ms/op
    
    生成正确的基准数组
    
    .int1e6Iw010BleedSort sample 4159 49.377 ± 0.571 ms/op 39.68 ± 0.60
    
    .int1e6Iw010JavaSort sample 3937 52.139 ± 0.229 ms/op 42.44 ± 0.25
    
    .int1e6Iw010QuickSort sample 3899 52.457 ± 0.210 ms/op 42.76 ± 0.23
    
    10% 重复数据
    
    .int1e6Iw001BleedSort sample 6190 32.821 ± 0.219 ms/op 31.48 ± 0.22
    
    .int1e6Iw001JavaSort sample 8113 24.910 ± 0.079 ms/op 23.57 ± 0.08
    
    .int1e6Iw001QuickSort sample 8653 23.367 ± 0.056 ms/op 22.02 ± 0.06
    
    ^^ 1%

    但是,这个算法在只有10.000左右的小二项分布的数据集 (~bin(100,0.5))(译者加:考虑到括号里面是公式代码,并没有修改内部英文括号符号成中文符号)上表现的很差。 在这些数组中,平均下来,出现50这个数字的次数是795.5,而出现40组重复数组的次数是108.4。

    同时,在排序1000.0000量级的大数组的时候,这个算法要比 Arrays.sort() 慢两倍左右。这些数组都有很多的重复数据(比如有的大小为1e6的数组里只有450个不同的数值)。

    Benchmark Mode Cnt Score Error Units Corrected
    
    ._1e4bin100 sample 152004 1.316 ± 0.001 ms/op
    
    ^^ for correction
    
    .int1e4bin100BleedSort sample 148681 1.345 ± 0.001 ms/op 0.029 ± 0.002
    
    .int1e4bin100JavaSort sample 150864 1.326 ± 0.001 ms/op 0.010 ± 0.002
    
    .int1e4bin100QuickSort sample 146852 1.362 ± 0.001 ms/op 0.046 ± 0.002
    
    .int1e6bin1e4BleedSort sample 75344 2.654 ± 0.005 ms/op -
    
    .int1e6bin1e4JavaSort sample 146801 1.361 ± 0.002 ms/op -
    
    .int1e6bin1e4QuickSort sample 76467 2.615 ± 0.005 ms/op -

    在排序小型的(10.000, 100.000)均匀随机数组下,这个算法表现尚可,但是并不比系统算法更好。

    MyBench.int1e4UBleedSort sample 216492 0.924 ± 0.001 ms/op 0.683 ± 0.002
    
    MyBench.int1e4UJavaSort sample 253489 0.789 ± 0.001 ms/op 0.548 ± 0.002
    
    MyBench.int1e4UQuickSort sample 217394 0.920 ± 0.001 ms/op 0.679 ± 0.002
    
    MyBench.int1e5UBleedSort sample 18752 0.011 ± 0.001 s/op 0.009 ± 0.002
    
    MyBench.int1e5UJavaSort sample 22335 0.009 ± 0.001 s/op 0.007 ± 0.002
    
    MyBench.int1e5UQuickSort sample 18748 0.011 ± 0.001 s/op 0.009 ± 0.002

    总而言之,在内存不是很紧张的情况下,针对适当的大数据集,我会建议把分布搜索算法做为一个有效的补充选项。

    最后,让大家来认识一下二项分布的一些数据集 bin(100, 0.5) 和 bin(1000, 0.5),

    这里是两个随机抽样了100个数据的数据集(使用R语言生成)。

    > rbinom(100, 100, 0.5)
    
    [1] 43 49 51 47 49 59 40 46 46 51 50 49 49 45 50 51 50 49 53 52 45 53 48 56 45
    
    [26] 47 55 47 53 53 56 41 47 42 51 51 46 49 49 52 46 48 49 50 48 56 54 49 53 52
    
    [51] 54 48 45 45 50 48 54 49 52 50 48 48 49 45 54 54 50 41 53 45 51 48 53 52 52
    
    [76] 50 53 47 55 47 60 54 52 56 45 46 54 46 38 43 53 45 62 48 52 52 52 49 52 56
    
    > rbinom(100, 1000, 0.5)
    
    [1] 515 481 523 519 524 516 498 473 523 514 483 496 458 506 507 491 514 489
    
    [19] 475 489 485 507 486 523 521 492 502 500 503 501 504 482 518 506 498 525
    
    [37] 498 491 492 479 506 499 505 497 510 479 504 510 485 488 495 519 522 490
    
    [55] 517 511 511 488 519 508 475 521 505 493 480 498 490 492 492 476 490 506
    
    [73] 496 505 521 518 506 509 477 483 509 493 497 501 483 502 470 515 519 509
    
    [91] 510 496 477 508 506 481 490 511 498 476
    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    抖音安全与信任开放日:揭秘推荐算法,告别单一标签依赖

    ultraedit编辑器打开文件时,总是提示是否转换为DOS格式,如何关闭?

    Cornell大神Kleinberg的经典教材《算法设计》是最好入门的算法教材

    从 Microsoft 下载中心安装 Windows 7 SP1 和 Windows Server 2008 R2 SP1 之前要执行的步骤

    Llama 2基于UCloud UK8S的创新应用

    火山引擎DataTester:如何使用A/B测试优化全域营销效果

    腾讯云、移动云继阿里云降价后宣布大幅度降价

    字节跳动数据平台论文被ICDE2023国际顶会收录,将通过火山引擎开放相关成果

    这个话题被围观超10000次,火山引擎VeDI如此解答

    误删库怎么办?火山引擎DataLeap“3招”守护数据安全

    IT头条

    平替CUDA!摩尔线程发布MUSA 4性能分析工具

    00:43

    三起案件揭开侵犯个人信息犯罪的黑灰产业链

    13:59

    百度三年开放2.1万实习岗,全力培育AI领域未来领袖

    00:36

    工信部:一季度,电信业务总量同比增长7.7%,业务收入累计完成4469亿元

    23:42

    Gartner:2024年全球半导体营收6559亿美元,AI助力英伟达首登榜首

    18:04

    技术热点

    iOS 8 中如何集成 Touch ID 功能

    windows7系统中鼠标滑轮键(中键)的快捷应用

    MySQL数据库的23个特别注意的安全事项

    Kruskal 最小生成树算法

    Ubuntu 14.10上安装新的字体图文教程

    Ubuntu14更新后无法进入系统卡在光标界面解怎么办?

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。