Java集合-Arrays.sort中采用的排序算法

1、概要

写到集合的末尾,就来介绍下Arrays工具类中的sort方法吧。因为Collections.sort的方法也最终调用的是Arrays.sort方法的。

Java6中sort方法默认采用的是传统快速排序,从Java7开始则使用改进版的双轴快速排序。

Java8中Arrays的排序方法只提供了两种算法的实现:

1、sort方法:双轴快速排序算法实现。
2、parallelSort方法:并行归并排序算法实现。

让我们一起来研究分析sort方法的排序吧。

2、传统快速排序算法

先来看下快速排序算法的特征吧:

1、是一种交换排序算法,即通过交换两个元素的大小来保证有序。
2、相对于其他的排序算法(冒泡排序、插入排序、希尔排序、选择排序等),平均速度最快。
3、是一个不稳定的排序算法。

快速排序基本思想

选择一个基准元素(也称为轴元素),通常选择第一个元素或者最后一个元素,通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素,此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分。

实例

在排序过程中,会首先选择第一个元素作为基准元素,并用最后一个元素作为比对的起始元素,然后利用交换及变换待比对的元素,变换规则为向基准元素的方向靠拢缩小,达到一趟扫描后确定基准元素最终位置的目的。再用递归的方式对基准元素左边和右边的子集合进行排序。

Java集合-Arrays.sort中采用的排序算法_第1张图片
快速排序图

实现

public class QuickSort {

    int a[] = { 49, 38, 65, 97, 76, 13, 27, 49, 78, 
            34, 12, 64, 5, 4, 62, 99, 98, 54, 56, 
            17, 18, 23, 34, 15, 35, 25, 53, 51 };

    public QuickSort() {
        quick(a);
        for (int i = 0; i < a.length; i++) {
            System.out.print(a[i] + ",");
        }
    }

    private int getMiddle(int[] list, int low, int high) {
        int tmp = list[low]; // 数组的第一个作为中轴
        while (low < high) {
            while (low < high && list[high] >= tmp) {
                high--;
            }

            list[low] = list[high]; // 比中轴小的记录移到低端
            while (low < high && list[low] <= tmp) {
                low++;
            }

            list[high] = list[low]; // 比中轴大的记录移到高端
        }
        list[low] = tmp; // 中轴记录到尾
        return low; // 返回中轴的位置
    }

    private void _quickSort(int[] list, int low, int high) {
        if (low < high) {
            int middle = getMiddle(list, low, high); // 将list数组进行一分为二
            _quickSort(list, low, middle - 1); // 对低字表进行递归排序
            _quickSort(list, middle + 1, high); // 对高字表进行递归排序
        }
    }

    public void quick(int[] a2) {
        if (a2.length > 0) { // 查看数组是否为空
            _quickSort(a2, 0, a2.length - 1);
        }
    }
}

3、双轴快速排序

关于双轴快速排序的介绍,推荐两篇文章:
1、快速排序算法原理及实现(单轴快速排序、三向切分快速排序、双轴快速排序)
2、DualPivotQuickSort 双轴快速排序 源码 笔记

讲的比较清楚,也介绍了Java8中源码的实现,笔者里就不做介绍了。

主要说明两点:

1、在双轴快速排序算法中,如果数组的长度小于47,采用插入排序或成对插入排序算法实现。
2、数组长度小于286,会直接使用双轴快排。
3、如果数组中局部有序的片段比较多,则采用TimSort排序算法(一种改进的归并排序算法)。

总结

Arrays.sort主要采用双轴快速排序实现,但并非单纯的采用一种算法就解决所有的排序问题。而是根据具体的数组情况采用合适的算法来实现,例如,插入排序,TimSort排序。所以Java8中排序算法实现的复杂度,总能给我们一些启发,那就是解决一个问题不要局限于单一的方案,可以多设计出几种方案,发扬每个方案的优点,弱化各自的缺点,结合起来就是一个更好的方案。事实上,很多算法、硬件软件的设计等的演进过程就是如此。

Java集合-Arrays.sort中采用的排序算法_第2张图片

你可能感兴趣的:(Java集合-Arrays.sort中采用的排序算法)