[整理] JDK8中Arrays.sort的排序算法


點進sort方法:

1 // Use Quicksort on small arrays
2 if (right - left < QUICKSORT_THRESHOLD) {//QUICKSORT_THRESHOLD = 286
3   sort(a, left, right, true);
4   return;
5 }

點進去sort(a, left, right, true);方法:

1 // Use insertion sort on tiny arrays
2     if (length < INSERTION_SORT_THRESHOLD) { //INSERTION_SORT_THRESHOLD(47)
3         if (leftmost) {
4         ......

 如果元素少於47這個閥值,就用插入排序

            /*
             * Traditional (without sentinel) insertion sort,
             * optimized for server VM, is used in case of
             * the leftmost part.
             */
            for (int i = left, j = i; i < right; j = ++i) {
                int ai = a[i + 1];
                while (ai < a[j]) {
                    a[j + 1] = a[j];
                    if (j-- == left) {
                        break;
                    }
                }
                a[j + 1] = ai;

 插入排序

 

大過INSERTION_SORT_THRESHOLD(47)的,用一種快速排序的方法:
1.從數列中挑出五個元素,稱為 “基准”(pivot);
2.重新排序數列,所有元素比基准值小的擺放在基准前面,所有元素比基准值大的擺在基准的后面(相同的數可以到任一邊)。在這個分區退出之后,該基准就處於數列的中間位置。這個稱為分區(partition)操作;
3.遞歸地(recursive)把小於基准值元素的子數列和大於基准值元素的子數列排序。
快速排序(Quick Sort)
 
至於大於286的,它會進入歸並排序(Merge Sort),但在此之前,它有個小動作:
    // 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),被判斷為這個數組不具備結構(也就是這數據時而升時而降),然后送給之前的sort(里面的快速排序)的方法(The array is not highly structured,use Quicksort instead of merge sort.)。

如果count少於MAX_RUN_COUNT(67)的,說明這個數組還有點結構,就繼續往下走下面的歸並排序:

   // Determine alternation base for merge
    byte odd = 0;
    for (int n = 1; (n <<= 1) < count; odd ^= 1);

從這里開始,正式進入歸並排序(Merge Sort)!

    // Merging
    for (int last; count > 1; count = last) {
        for (int k = (last = 0) + 2; k <= count; k += 2) {
            int hi = run[k], mi = run[k - 1];
            for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
                if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
                    b[i + bo] = a[p++ + ao];
                } else {
                    b[i + bo] = a[q++ + ao];
                }
            }
            run[++last] = hi;
        }
        if ((count & 1) != 0) {
            for (int i = right, lo = run[count - 1]; --i >= lo;
                b[i + bo] = a[i + ao]
            );
            run[++last] = right;
        }
        int[] t = a; a = b; b = t;
        int o = ao; ao = bo; bo = o;
    }

總結:
從上面分析,Arrays.sort並不是單一的排序,而是插入排序,快速排序,歸並排序三種排序的組合,流程圖如下:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM