歸併排序是採用分治策略,將問題分成一些小的問題然後遞歸求解,讓後將得到的結果合併到一起。
歸併排序:
時間複雜度是O(nlogn)
最好情況O(nlogn)
最壞情況O(nlogn)
空間複雜度 O(n)
歸併排序是佔用額外內存的,是穩定的。
圖解
合併的具體實現,我們需要藉助一個臨時數組排序,排好序後將臨時數組中的元素複製到原先數組中即可。
/**
* 分 + 合方法
* @param arr
* @param left
* @param right
* @param temp
*/
public static void mergeSort(int[] arr,int left,int right,int[] temp){
if (left < right){
//中間索引
int mid = (left + right) /2;
//向左遞歸分解
mergeSort(arr,left,mid,temp);
//向右遞歸分解
mergeSort(arr,mid + 1,right,temp);
//合併
merge(arr,left,mid,right,temp);
}
}
/**
* 合併的方法
* @param arr 排序的原始數組
* @param left 左邊有序序列的初始索引
* @param mid 中間索引
* @param right 右邊索引
* @param temp 做中轉的數組
*/
public static void merge(int[] arr,int left,int mid,int right,int[] temp){
//初始化i,左邊有序序列的初始索引
int i = left;
//初始化j,右邊有序序列的初始索引
int j = mid +1;
//指向temp數組的當前索引
int t = 0;
//(一)先把左右兩邊(有序)的數據按照規則填充到temp數組
//直到左右兩邊有序序列,有一邊處理完畢爲止
while (i <= mid && j <= right){
//如果左邊的有序序列的當前元素,小於等於右邊有序序列的當前元素
//即將左邊的當前元素,填充到temp數組
if (arr[i] <= arr[j]){
temp[t] = arr[i];
t += 1;
i += 1;
}else {
//反之,將右邊有序序列的當前元素,填充到temp數組
temp[t] = arr[j];
t += 1;
j += 1;
}
}
//(二)把剩餘數據的一邊的數據依次全部填充到temp
while (i <= mid){
//左邊的有序序列還有剩餘元素,就全部填充到temp
temp[t] = arr[i];
t += 1;
i += 1;
}
while (j <= right){
temp[t] = arr[j];
t += 1;
j += 1;
}
//(三)將temp數組的元素拷貝到arr
t = 0;
int tempLeft = left;
while (tempLeft <= right){
arr[tempLeft] = temp[t];
t += 1;
tempLeft += 1;
}
}