Arrays.sort(Object[] arr)排序源碼分析

簡介:
    在1.8以前的版本中對此方法進行了重寫,若是還須要使用以前的排序算法,須要加上系統屬性java.util.Arrays.useLegacyMergeSort=true,以前的排序使用優化後的歸併排序,在1.8中使用TimSort算法來進行排序,TimSort算法是由Tim Peters在2002提出並首先實如今了phtyon中,是結合了合併排序(merge sort)和插入排序(insertion sort)的一種高效穩定的算法。算法原理看這裏 https://blog.csdn.net/yangzhongblog/article/details/8184707java

Arrays.sort(Object[] a)分析
一、 方法聲明算法

/**
 * 根據Comparable的天然排序將給定數組升序排序。全部元素必須實現Comparable 接口
 * 並且,全部元素能相互比較,否則可能會拋出ClassCastException異常
 *
 * 此排序確保是穩定的,若是兩個元素e1.equals(e2),那麼他們不會被再次排序
 *
 * 該實現是一個穩定、自適應、重複的歸併排序,當給定數組是局部排序的數組時它的時間複雜度比 nlogn更小,
 * 然而當給定數組是隨機排序,它與傳統的歸併排序性能相同。若是給定數組大致有序,該算法只須要大概n次比較便可完成排序。
 *
 * 該算法在輸入數組爲升序或降序時都能發揮優點,而且在該數組部分有序的狀況下也能發揮其優點,
 * 它能經過簡單鏈接便可很好的完成將多個數組進行合併
 */
public static void sort(Object[] a) {
//若是要兼容1.8以前的排序程序,在系統屬性中須要添加屬性,如:java -jar -Djava.Arrays.uselegacyMergeSort=true xx.jar
    if (LegacyMergeSort.userRequested)
        legacyMergeSort(a);
    else
		//真正的TimSort算法實如今ComparableTimSort中
        ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
	}

二、 ComparableTimSort.sort(Object[] a, int lo, int hi, Object[] work, int workBase, int workLen)分析數組

/**
 * 將數組指定範圍內的元素排序
 *
 * [@param](https://my.oschina.net/u/2303379) a 被排序數組
 * [@param](https://my.oschina.net/u/2303379) lo 排序開始元素index
 * [@param](https://my.oschina.net/u/2303379) hi 排序結束元素index,不包含此index
 * [@param](https://my.oschina.net/u/2303379) work a workspace array (slice)
 * [@param](https://my.oschina.net/u/2303379) workBase origin of usable space in work array
 * @param workLen usable size of work array
 * @since 1.8
 */
static void sort(Object[] a, int lo, int hi, Object[] work, int workBase, int workLen) {
	
	//保證數組的合法性
    assert a != null && lo >= 0 && lo <= hi && hi <= a.length;
	
    int nRemaining  = hi - lo;
	//對於只有0|1個元素的數組,不須要進行排序
    if (nRemaining < 2)
        return;  // Arrays of size 0 and 1 are always sorted

    // If array is small, do a "mini-TimSort" with no merges
	//若是數組比較小,直接使用二叉插入排序進行排序
    if (nRemaining < MIN_MERGE) {
		//計算數組頭部遞增或遞減的的序列長度,若是是遞減,則翻轉,保持升序
        int initRunLen = countRunAndMakeAscending(a, lo, hi);
		//使用二叉插入排序對在initRunLen後的元素進行排序
        binarySort(a, lo, hi, lo + initRunLen);
        return;
    }

    /**
     * March over the array once, left to right, finding natural runs,
     * extending short natural runs to minRun elements, and merging runs
     * to maintain stack invariant.
     */
	 //構造ComparableTimSort對象
    ComparableTimSort ts = new ComparableTimSort(a, work, workBase, workLen);
	//計算最小run的長度
    int minRun = minRunLength(nRemaining);
    do {
        // Identify next run
		//計算當前排序的run的長度,若是爲遞減數組則翻轉
        int runLen = countRunAndMakeAscending(a, lo, hi);

        // If run is short, extend to min(minRun, nRemaining)
		//若是當前run的長度小於minRun,則進行擴展,在擴展過程當中使用二叉排序來排序擴展的的元素
        if (runLen < minRun) {
            int force = nRemaining <= minRun ? nRemaining : minRun;
            binarySort(a, lo, lo + force, lo + runLen);
            runLen = force;
        }

        // Push run onto pending-run stack, and maybe merge
		//將此run放入棧中
        ts.pushRun(lo, runLen);
		//執行合併邏輯,合併的時候也作了一些優化
        ts.mergeCollapse();

        // Advance to find next run
        lo += runLen;
        nRemaining -= runLen;
    } while (nRemaining != 0);

    // Merge all remaining runs to complete sort
    assert lo == hi;
	//保證最後的run都被合併
    ts.mergeForceCollapse();
    assert ts.stackSize == 1;
}
相關文章
相關標籤/搜索