歸併排序(Mergesort)之Java實現
阿新 • • 發佈:2018-12-23
歸併排序演算法介紹
歸併排序是一個分治演算法(Divide and Conquer)的一個典型例項,把一個數組分為兩個大小相近(最多差一個)的子陣列,分別把子陣列都排好序之後通過歸併(Merge)手法合成一個大的排好序的陣列,歸併的過程依然用撲克來解釋,想象一下桌子上有兩堆排好序(從小到大)的牌,每一次從兩堆裡面各抽取一張,比較一下兩張的大小,如果兩張一樣大,都取出放到目標陣列,否則取出較小的放到目標陣列,另外一個放回原堆裡面。歸併排序需要額外的空間來儲存臨時資料,不過它的最壞執行時間都是O(nlogn)。
歸併排序演算法Java實現
如《插入排序(Insertsort)之Java實現》一樣,先實現一個數組工具類。程式碼如下:
public class ArrayUtils { public static void printArray(int[] array) { System.out.print("{"); for (int i = 0; i < array.length; i++) { System.out.print(array[i]); if (i < array.length - 1) { System.out.print(", "); } } System.out.println("}"); } }
歸併排序為分治法,分體現在把一個數組分為基本等長的兩個子陣列,重複這個過程,直到兩個子陣列都只有一個元素,歸併的過程是演算法的核心,前面已經提到過。歸併排序的Java實現以及測試程式碼如下:
public class MergeSort { public static void main(String[] args) { int[] array = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3 }; System.out.println("Before sort:"); ArrayUtils.printArray(array); mergeSort(array); System.out.println("After sort:"); ArrayUtils.printArray(array); } public static void mergeSort(int[] array) { sortArray(array, 0, array.length - 1); } private static void sortArray(int[] array, int start, int end) { // 單個元素不需要排序,直接返回 if (start == end) { return; } int sortSize = end - start + 1; int seperate; if (sortSize % 2 == 0) { seperate = start + sortSize / 2 - 1; } else { seperate = start + sortSize / 2; } sortArray(array, start, seperate); sortArray(array, seperate + 1, end); mergeArray(array, start, seperate, end); } private static void mergeArray(int[] array, int start, int seperate, int end) { int totalSize = end - start + 1; int size1 = seperate - start + 1; int size2 = end - seperate; int[] array1 = new int[size1]; int[] array2 = new int[size2]; for (int i = 0; i < size1; i++) { array1[i] = array[start + i]; } for (int i = 0; i < size2; i++) { array2[i] = array[seperate + 1 + i]; } int mergeCount = 0; int index1 = 0; int index2 = 0; while (mergeCount < totalSize) { // 先檢查有沒有其中的一個數組已經處理完 if (index1 == size1) { for (int i = index2; i < size2; i++) { array[start + mergeCount] = array2[i]; mergeCount++; index2++; } } else if (index2 == size2) { for (int i = index1; i < size1; i++) { array[start + mergeCount] = array1[i]; mergeCount++; index1++; } } else { int value1 = array1[index1]; int value2 = array2[index2]; if (value1 == value2) { array[start + mergeCount] = value1; array[start + mergeCount + 1] = value1; mergeCount += 2; index1++; index2++; } else if (value1 < value2) { array[start + mergeCount] = value1; mergeCount++; index1++; } else if (value1 > value2) { array[start + mergeCount] = value2; mergeCount++; index2++; } } } } }