基本思想
歸併排序(MERGE-SORT)是利用歸併的思想實現的排序方法,該算法採用經典的分治(divide-and-conquer)策略(分治法將問題分(divide)成一些小的問題然後遞歸求解,而治(conquer)的階段則將分的階段得到的各答案"修補"在一起,即分而治之)。
分而治之
可以看到這種結構很像一棵完全二叉樹,本文的歸併排序我們採用遞歸去實現(也可採用迭代的方式去實現)。分階段可以理解爲就是遞歸拆分子序列的過程,遞歸深度爲log2n。
合併相鄰有序子序列
再來看看治階段,我們需要將兩個已經有序的子序列合併成一個有序序列,比如上圖中的最後一次合併,要將[4,5,7,8]和[1,2,3,6]兩個已經有序的子序列,合併爲最終序列[1,2,3,4,5,6,7,8],來看下實現步驟。
代碼實現
public class MergeSort {
public static void main(String[] args) {
int[] arr = { 8, 4, 5, 7, 1, 3, 6, 2 };
int[] temp = new int[arr.length];
mergeSort(arr,0,arr.length - 1,temp);
System.out.println(Arrays.toString(arr));
}
//先分解後合併
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){
int i = left;//初始化i 左邊有序序列的初始指針
int j = mid + 1;//初始化j 右邊有序序列的初始指針
int t = 0;//指向temp當前指針
/**
* 第一步:先把左右兩邊(有序)的數據按照規則填充到temp數組,
* 直到左右兩邊序列,有一邊處理完畢爲止
*/
while (i <= mid && j <= right){
/**
* 如果左邊的有序序列當前元素,小於等於右邊有序當前元素
* 即將左邊的數拷貝到temp數組中,左邊序列指針向前移動一下,
* temp指針向前移動一下
*/
if(arr[i] <= arr[j]){
temp[t] = arr[i];
t++;
i++;
}else{//反之
temp[t] = arr[j];
t++;
j++;
}
}
/**
* 第二步:如果能走到這一步,說明上一個while循環條件中必定有一個條件爲false,
* 條件爲false,說明左右序列中有一個序列已經執行完畢,
* 所以把有剩餘數據的一邊的數據依次填充到temp中
*/
while(i <= mid){//左邊序列有剩餘數據
temp[t] = arr[i];
t++;
i++;
}
while(j <= right){//右邊序列有剩餘數據
temp[t] = arr[j];
t++;
j++;
}
/**
* 第三步:將temp數組中的元素拷貝到arr數組中
*/
t = 0;
int tempLeft = left;
while(tempLeft <= right){
arr[tempLeft] = temp[t];
t++;
tempLeft++;
}
}
}
運行結果