歸併排序
歸併排序用到了分治法的思想。用代碼實現時,按從小到大排序爲例,主要的思路分爲分解和合並兩大步驟:
分解:
- 第一次分解時,根據數組的頭尾下標,得出分界線的位置,即:mid=(left+right)/2;
- 向左遞歸分解:就是將數組的頭下標和分界線的下標當做新序列的頭尾下標再次分解;
- 向右遞歸分解:就是將分界線的下標後一位(mid+1)和數組的尾下標當做新序列的頭尾下標再次分解;
- 分解結束後(即頭尾相等時)開始合併操作。
合併:
- 初始化左邊序列的開始下標:i=left;右邊序列的開始下標:j=mid+1;
- 左右下標對應的當前值依次比較,將較小的值放入臨時數組中,然後每次從較小值的那邊開始繼續移動下標;
- 第2步操作結束後會出現三種情況:1)左右序列的數據全部放入臨時數組中了;2)左邊序列還剩數據沒有放入臨時數組中;3)右邊序列還剩數據沒有放入臨時數組中。考慮後兩種情況,將剩下的數據複製到臨時數組中;
- 將臨時數組複製到原始數組。
上述如有錯誤之處,還望指出,我會及時改正。其代碼如下:
package com.sort.mergetSort;
import java.util.Arrays;
public class MergeSortDemo2 {
public static void main(String[] args) {
int array[] = { 8, 4, 5, 7, 1, 3, 6, 2 };
int temp[] = new int[array.length];// 歸併排序需要一個額外空間
System.out.println("排序前:" + Arrays.toString(array));
mergeSort(array, 0, array.length - 1, temp);
System.out.println("排序後:" + Arrays.toString(array));
}
/**
* 歸併排序
*
* @param array
* @param left
* @param right
* @param temp
*/
public static void mergeSort(int[] array, int left, int right, int[] temp) {
if (left >= right) {
return;
}
int mid = (left + right) / 2;
// 向左遞歸分解
mergeSort(array, left, mid, temp);
// 向右遞歸分解
mergeSort(array, mid + 1, right, temp);
// 合併
merge(array, left, mid, right, temp);
}
/**
* 合併操作
*
* @param array 原始數組
* @param left 左邊有序序列的初始下標
* @param mid 中間值的下標 ,分界線
* @param right 最右邊下標
* @param temp 臨時數組
*/
public static void merge(int[] array, int left, int mid, int right, int[] temp) {
// 1.定義左邊序列和右邊序列開始下標
int i = left;
int j = mid + 1;
int t = 0;// 記錄臨時數組的下標
// 2.比較左右兩個序列中的值
while (i <= mid && j <= right) {
// 2.1如果左邊序列的當前值小於等於右邊序列的當前值,就將左邊序列當前值暫存在臨時數組
if (array[i] <= array[j]) {
temp[t] = array[i];
t++;
i++;
} else {// 2.2反之,如果右邊序列的當前值大於左邊序列的當前值,就將右邊序列的當前值暫存在臨時數組
temp[t] = array[j];
t++;
j++;
}
}
// 3.上面循環結束時,可能會出現兩種情況
// 3.1右邊序列遍歷完了,但是左邊序列還剩數據
while (i <= mid) {
temp[t] = array[i];
t++;
i++;
}
// 3.2左邊序列遍歷完了,右邊序列還剩數據
while (j <= right) {
temp[t] = array[j];
t++;
j++;
}
// 4.數據全部放到臨時數組後,開始將temp複製給array
// 4.1.下標位置重新置爲0
t = 0;
// 4.2.定義array數組的下標,每次從left開始放
int tempLeft = left;
// 4.3.開始複製數組
while (tempLeft <= right) {
array[tempLeft] = temp[t];
tempLeft++;
t++;
}
}
}