JDK提供的排序方法Arrays.sort()

87 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第15天,点击查看活动详情

指定数组升序排序

Arrays.java类
public static void sort(int[] a) {
    DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
}

如果元素小于286,使用快速排序

但对于该方法中还进行有单独判断用来区分相应排序规则(插入排序或者快速排序)

DualPivotQuicksort.sort(int[] a, int left, int right,
                     int[] work, int workBase, int workLen){
    // 小型数组上使用快速排序---QUICKSORT_THRESHOLD=286为阀值
    if (right - left < QUICKSORT_THRESHOLD) {
        //<286的数组集合单独区分排序
        sort(a, left, right, true);
        return;
    }
    ... ...
}

如果元素小于47的时候使用插入排序

sort(int[] a, int left, int right, boolean leftmost) {
        int length = right - left + 1;

        // 在小型数组上使用插入排序---INSERTION_SORT_THRESHOLD=47为阀值
        if (length < INSERTION_SORT_THRESHOLD) {
            ... ...
        }
}

如果元素大于47的使用快速排序

  • 从数列中挑出5个元素作为基准
  • 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作
  • 递归(recursive)地把小于基准值元素的子数列和大于基准值元素的子数列排序

如果元素大于286,使用归并排序

  • 排序前会判断排序的数据是否具备结构,不具备高度结构化的使用快速排序
// 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;
    }
}

总的排序流程

包含有插入排序,快速排序,归并排序三种排序的组合

  • 0~47:插入排序
  • 47~286:快速排序
  • 大于286:
    • 具备高度结构化数据:归并排序
    • 不具备:>47:快速排序