八大排序(二):歸併排序
阿新 • • 發佈:2019-02-11
歸併排序(MERGE-SORT)是建立在歸併操作上的一種有效的排序演算法,該演算法是採用分治法(Divide and Conquer)的一個非常典型的應用。分治法即將問題分(divide)成一些小的問題然後遞迴求解,而治(conquer)的階段則將分的階段得到的各答案”修補”在一起,歸併排序的速度僅次於快速排序,比較次數小於快速排序的比較次數,而移動次數一般多於快速排序的移動次數。
歸併排序的過程可以結合下圖來理解:
其中,“治”階段的過程如下圖:
一般歸併排序的程式碼把“分”和“治”的操作分開了,以下的的程式碼把劃分和合併合在一起,用空格隔開了。歸併排序和之前劍指offer-題36:陣列中的逆序對
在最後一層遞迴呼叫後,tempArray會是排序完成的結果,而array是排序之前的結果。此時把結果返回給倒數第二層,注意,此時倒數第二層array對應最後一層的tempArray,而tempArray對應array,也就是說倒數第二層的array是上一層最新的排序好的結果,而tempArray是次新的結果。在倒數第二層經過後半段的排序後,此時的tempArray會成為最新排序好的結果返回倒數第三層的array,而array會作為次新的結果返回給倒數第三層的tempArray(可能把你繞暈了,可以畫一個圖方便理解)。根據這個規律,執行到遞迴最開始的那一層時,array是最新排序好的,在程式的後半段,再根據array的順序進行最後一次歸併,tempArray會成為最終排序的結果,因此最後返回的結果是tempArray。具體程式碼如下
歸併排序:
public float[] mergeSort(float[] array) {
float[] tempArray = new float[array.length];
System.arraycopy(array, 0, tempArray , 0, array.length);
mergeSortCore(array, tempArray, 0, array.length - 1);
return tempArray;
}
// 歸併排序
public void mergeSortCore(float [] array, float[] tempArray, int start, int end) {
if (start == end) {
tempArray[start] = array[start];
return;
} else if (start < end) {
int middle = (start + end) >> 1;
mergeSortCore(tempArray, array, start, middle);
mergeSortCore(tempArray, array, middle + 1, end);
int i = start;
int j = middle + 1;
int k = start;
while (i <= middle && j <= end) {
if (array[i] <= array[j]) {
tempArray[k++] = array[i++];
} else {
tempArray[k++] = array[j++];
}
}
while (i <= middle) {
tempArray[k++] = array[i++];
}
while (j <= end) {
tempArray[k++] = array[j++];
}
}
}