演算法4 七大排序之:歸併排序
上一篇總結了直接插入排序和希爾排序,這一篇要總結的是歸併排序,這也是七大排序的最後一種排序演算法。
首先來看一下歸併排序(Merge Sort) 的基本原理。它的原理是假設初始序列有n個元素,則可以看成是n個有序的子序列,每個子序列的長度為1,然後兩兩歸併,得到n/2個長度為2或1的有序子序列;再兩兩歸併,…… ,如此重複,直至得到一個長度為n的有序序列為止,這種排序方法就稱為歸併排序。
1、歸併排序的
下面用來說明歸併排序的過程:
圖一:
圖二:
2、歸併排序的代碼
MergeSort.java
public class MergeSort { public static void main(String[] args) { int[] list = {50, 10, 90, 30, 70}; System.out.println("************歸併排序************"); System.out.println("排序前:"); display(list); System.out.println(""); System.out.println("排序後:"); mergeSort(list, new int[list.length], 0, list.length - 1); display(list); } /** * 歸併排序演算法 * * @param list 待排序的列表 * @param tempList 臨時列表 * @param head 列表開始位置 * @param rear 列表結束位置 */ public static void mergeSort(int[] list, int[] tempList, int head, int rear) { if (head < rear) { // 取分割位置 int middle = (head + rear) / 2; // 遞迴劃分列表的左序列 mergeSort(list, tempList, head, middle); // 遞迴劃分列表的右序列 mergeSort(list, tempList, middle + 1, rear); // 列表的合併作業 merge(list, tempList, head, middle + 1, rear); } } /** * 合併作業(列表的兩兩合并) * * @param list * @param tempList * @param head * @param middle * @param rear */ public static void merge(int[] list, int[] tempList, int head, int middle, int rear) { // 左指標尾 int headEnd = middle - 1; // 右指標頭 int rearStart = middle; // 臨時列表的下標 int tempIndex = head; // 列表合并後的長度 int tempLength = rear - head + 1; // 先迴圈兩個區間段都沒有結束的情況 while ((headEnd >= head) && (rearStart <= rear)) { // 如果發現右序列大,則將此數放入臨時列表 if (list[head] < list[rearStart]) { tempList[tempIndex++] = list[head++]; } else { tempList[tempIndex++] = list[rearStart++]; } } // 判斷左序列是否結束 while (head <= headEnd) { tempList[tempIndex++] = list[head++]; } // 判斷右序列是否結束 while (rearStart <= rear) { tempList[tempIndex++] = list[rearStart++]; } // 交換資料 for (int i = 0; i < tempLength; i++) { list[rear] = tempList[rear]; rear--; } } /** * 遍曆列印 */ public static void display(int[] list) { System.out.println("********展示開始********"); if (list != null && list.length > 0) { for (int num : list) { System.out.print(num + " "); } System.out.println(""); } System.out.println("********展示結束********"); }}
運行結果: