JDK1.8中的數組排序


Array.sort()

核心思路

根據不同的情況,選擇不同的排序算法。

1、當需要排列的元素較少的時候,采用普通的插入排序

當被排序的數組長度小於47但排序不是從數組起始位置開始的時候,那么就會選擇哨兵插入排序的方式進行排序。
這種情況主要是當sort被雙基准快排遞歸調用的時候才會使用

2、如果元素較多,大於插入排序的閾值,但是小於歸並排序的閾值,這時采用快速排序
在進行快排之前,首先會將這個不長不斷的數組按照1/7的長度划分,最后划分后的結果為:

        // Inexpensive approximation of length / 7
        int seventh = (length >> 3) + (length >> 6) + 1;

        /*
         * Sort five evenly spaced elements around (and including) the
         * center element in the range. These elements will be used for
         * pivot selection as described below. The choice for spacing
         * these elements was empirically determined to work well on
         * a wide variety of inputs.
         */
        int e3 = (left + right) >>> 1; // The midpoint
        int e2 = e3 - seventh;
        int e1 = e2 - seventh;
        int e4 = e3 + seventh;
        int e5 = e4 + seventh;

然后對這5個划分點進行排序:
2.1 如果這五個划分點的數據倆倆各不相同,則以第一個划分點和最后一個划分點作為基准點,采用雙基准快排
采用雙基准快排也有優化的地方,如果中間的元素過多(超過整個排序部分的七分之四),將會針對這一區間內的重復鍵進行優化。
與基准1和基准2 相同的鍵將會被分到前后兩個分區,並會被從接下來要繼續遞歸排序的中間分區中剔除,盡可能減少了中間分區的大小。

                for (int k = less - 1; ++k <= great; ) {
                    int ak = a[k];
                    if (ak == pivot1) { // Move a[k] to left part
                        a[k] = a[less];
                        a[less] = ak;
                        ++less;
                    } else if (ak == pivot2) { // Move a[k] to right part
                        while (a[great] == pivot2) {
                            if (great-- == k) {
                                break outer;
                            }
                        }
                        if (a[great] == pivot1) { // a[great] < pivot2
                            a[k] = a[less];
                            /*
                             * Even though a[great] equals to pivot1, the
                             * assignment a[less] = pivot1 may be incorrect,
                             * if a[great] and pivot1 are floating-point zeros
                             * of different signs. Therefore in float and
                             * double sorting methods we have to use more
                             * accurate assignment a[less] = a[great].
                             */
                            a[less] = pivot1;
                            ++less;
                        } else { // pivot1 < a[great] < pivot2
                            a[k] = a[great];
                        }
                        a[great] = ak;
                        --great;
                    }
                }

2.2 如果這五個划分點有相同的情況,則采用三路快排。
3、如果數組的長度超過了快排的閾值
首先進行有序性的判斷,判斷這個數組是否是基本有序
將有序部分中斷處的位置記錄下來,如果中斷個數大於某個閾值則判斷為無序,反之有序。
3.1 如果是基本有序,則采用歸並方式排序,這里會按照剛才記錄的有序部分的中斷點作為歸並點。
3.2 如果判定為無序,則依然采用快排。

Collections.sort()

TimSort

Arrays.parallelSort()


免責聲明!

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



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