咱們知道,java中泛型排序使用歸併排序或TimSort。歸併排序以O(NlogN)最壞時間運行,下面咱們分析歸併排序過程及分析證實時間複雜度;也會簡述爲何java選擇歸併排序做爲泛型的排序算法。java
假設輸入數組A[一、七、九、13],B[五、八、1五、17],算法過程以下。1與5比較,1存入數組C中;接下來7與5比較,5存入C中。算法
接着7與8比較,7存入C中;9與8比較,8存入C中。數組
接着這樣的過程進行比較,直到13與15比較,13存入C中。app
這時候A已經用完,將B中剩餘的元素所有拷貝到C中便可。spa
從圖中能夠看出,合併兩個排序表是線性的,最多進行N-1次比較(能夠改變輸入序列,使得每次只有一個數進入數組C,除了最後一次,最後一次至少有兩個元素進入C)。對於歸併排序,N=1的時候,排序結果是顯然的;不然,遞歸將前半部分與後半部分分別歸併排序。這是使用分治的思想。code
public class MergeSort {
public static void main(String[] args) {
Integer[] integers = {7, 1, 13, 9, 15, 5, 8,17};
System.out.println("原序列:" + Arrays.toString(integers));
mergeSort(integers);
System.out.println("排序後:" + Arrays.toString(integers));
}
public static <T extends Comparable<? super T>> void mergeSort(T[] a) {
//由於merge操做是最後一行,因此任什麼時候候只須要一個臨時數組
T[] tmpArray = (T[]) new Comparable[a.length];
mergeSort(a, tmpArray, 0, a.length - 1);
}
private static <T extends Comparable<? super T>> void mergeSort(T[] a, T[] tmpArray, int left, int right) {
if (left < right) {
int center = (left + right) / 2;
mergeSort(a, tmpArray, left, center);
mergeSort(a, tmpArray, center + 1, right);
merge(a, tmpArray, left, center + 1, right);
}
}
/**
* 合併左右數據方法
*
* @param a :原數組
* @param tmpArray : 臨時數組
* @param leftPos :左邊開始下標
* @param rightPos:右邊開始下標
* @param rightEnd:右邊結束下標
* @param <T>:元素泛型
*/
private static <T extends Comparable<? super T>> void merge(T[] a, T[] tmpArray, int leftPos, int rightPos, int rightEnd) {
int leftEnd = rightPos - 1;
int tmpPos = leftPos;
int numElements = rightEnd - leftPos + 1;
//合併操做
while (leftPos <= leftEnd && rightPos <= rightEnd) {
if (a[leftPos].compareTo(a[rightPos]) <= 0) {
tmpArray[tmpPos++] = a[leftPos++];
} else {
tmpArray[tmpPos++] = a[rightPos++];
}
}
// 複製前半部分
while (leftPos <= leftEnd) {
tmpArray[tmpPos++] = a[leftPos++];
}
//複製後半部分
while (rightPos <= rightEnd) {
tmpArray[tmpPos++] = a[rightPos++];
}
// 回寫原數組
for (int i = 0; i < numElements; i++, rightEnd--) {
a[rightEnd] = tmpArray[rightEnd];
}
}
}
咱們假設N是2的冪,咱們遞歸總能夠均分爲兩部分。對於N=1,歸併排序所用時間是常數,即O(1)。對於N個數歸併排序的用時等於兩部分時間之和再加上合併的時間。合併是線性的,由於最多使用N-1次比較。推導以下:orm
上面咱們假設了N=2k,對於N不是2的冪(一般都是這種狀況),其實,結果都是差很少的,也只是最多再多一次過程而已。對象
歸併排序與其餘O(NlogN)排序算法相比,時間很依賴比較算法與在數組中移動元素(包括臨時數組中)的相對開銷。這是與語言環境有關的。對於Java來講,進行比較可能比較耗時(使用Comparator);但移動元素屬於引用賦值,不是龐大對象的拷貝。歸併算法在全部流行的使用比較的算法中使用最少的比較次數。另外一個緣由是歸併排序是穩定的,這在某些特殊的場景特別重要。blog
本篇經過畫圖詳述了歸併排序的過程,還經過數學證實歸併排序時間複雜度穩定在O(NlogN);簡談了下java選擇歸併排序的緣由。java中對於基本類型的排序,使用的是快速排序。排序