Arrays.sort()详解

参考:https://www.cnblogs.com/gw811/archive/2012/10/04/2711746.html
查看Arrays.sort()的源码可以看到
Java Arrays中提供了对所有类型的排序。其中主要分为针对基本类型(除了boolean)和Object两大类。
1.基本类型数组的排序
其中针对于基本数据类型调用的是DualPivotQuicksort类的sort()方法
对于基本数据类型的数组,假设数组长度为length:
如果length<47,那么采用插入排序算法。
如果47<=length<286,或者286<=length,但数组不具备特定结构,那么使用快速排序的一种优化形式:双轴快排算法。
如果286<=length,并且数组具备特定结构,那么使用归并排序算法。
在这里插入图片描述

1.1数组是否具备特定结构
在判断是否使用归并排序前,要先判断数组是否具备特定结构,这是一个什么意思呢?

// Check if the array is nearly sorted
    for (int k = left; k < right; run[count] = k) {        
        if (a[k] < a[k + 1]) { // ascending
            while (++k <= right && a[k - 1] <= a[k]);
        } else if (a[k] > a[k + 1]) { // descending
            while (++k <= right && a[k - 1] >= a[k]);            
            for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {                int t = a[lo]; a[lo] = a[hi]; a[hi] = t;
            }
        } else { // equal
            for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {
                            if (--m == 0) {
                                sort(a, left, right, true);
                                                    return;
                }
            }
        }        /*
         * The array is not highly structured,
         * use Quicksort instead of merge sort.
         */
        if (++count == MAX_RUN_COUNT) {
            sort(a, left, right, true);
             return;
        }
    }

这里主要作用是看他数组具不具备结构:实际逻辑是分组排序,每个降序序列为一个组,像1,9,8,7,6,8。9到6是降序,为一个组,然后把降序的一组排成升序:1,6,7,8,9,8。然后再从最后的8开始继续往后面找。
每遇到这样一个降序组,++count,当count大于MAX_RUN_COUNT(67),被判断为这个数组不具备结构,也就是说这数据时而升时而降,波峰波谷太多,排列太过陡峭,说明不适合采用归并排序,还是使用快速排序为宜。
如果count少于MAX_RUN_COUNT(67)的,说明这个数组还有点结构,就继续往下走下面的归并排序。
2. 对象类型数组的排序
对于对象类型的数组,假设数组长度为length:
如果length<32,那么采用不包含合并操作的mini-TimSort算法。
如果32<=length,那么采用完整TimSort排序算法(一种结合了归并排序和插入排序的算法)。
3. 为什么要采用不同的算法?
对于长度较小的数组使用插入排序这很好理解,虽然插入排序的时间复杂度为O(n^2),但在n较小的情况下,插入排序性能要高于快速排序。
其次我们要知道,在n的数量较大时,归并排序和快速排序,都是性能最优的排序算法,他们的时间复杂度平均都在O(nlogn)左右,只不过区别在于归并排序是稳定的,快速排序是不稳定的。
稳定是指相等的数据在排序之后仍然按照排序之前的前后顺序排列。
对于基本数据类型,稳定性没有意义,所以它可以使用不稳定的快排(当然它也使用了归并排序)
而对于对象类型,稳定性是比较重要的,因为对象相等的判断比较复杂,我们无法寄希望于每个程序员都会重写准确的equal方法,故而稳妥起见,最好相等对象尽量保持排序前的顺序,故而我们使用都是稳定算法的归并排序和插入排序结合而成的TimSort算法。
另外一个原因是归并排序的比较次数比快排少,移动(对象引用的移动)次数比快排多,而对于对象来说,比较是相对耗时的操作,所以它不适合使用快排。
而对于基本数据类型来说,比较和移动都不怎么耗时,所以它用归并或者快排都可以
4.总结
基本数据类型数组使用快排+归并是因为:
基本数据类型无所谓稳定性,可以采用非稳定的快排。
对于基本数据类型来说,比较和移动都不怎么耗时,所以它用归并或者快排都可以。
对象数据类型数组使用TimSort排序是因为(或者换句话说,对象数据类型不使用快排是因为):
对象数据类型要求稳定性,需要采用稳定的归并+插入。
对于对象来说,比较操作相对耗时,所以用比较操作较少的归并排序可以扬长避短。

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值