以前只瞭解了冒泡排序、選擇排序、快速排序等排序演算法,今天學習了一下歸併排序,記錄在此。
歸併排序,其實就是先遞迴將序列拆分成兩個有序的序列,然後將其合并成一個有序的序列,那麼首先來看一下如何將兩個有序的序列合并成一個有序的序列。這個比較簡單,我們可以比較兩個序列中的第一個數,哪個小就將其取出來放進新的序列,然後在該序列中將其刪除;繼續比較取出刪除直至其中一個序列為空白為止,這時將另一個序列中的數全部拷貝到新的序列中(如果還有元素的話),這樣新的序列就是二者的並集,並且是有序的。
那麼如何將一個序列拆分成兩個有序的序列?我們可以將序列拆分成A、B兩個序列,再遞迴將A、B序列拆分直至序列裡只有一個元素,可認為其是有序的,然後將兩個只含一個元素的序列合并成一個有序的兩元素序列,兩個有序序列合并成一個有序的四元素序列,以此類推,直到合并到原來的數組長度。
排序完畢!
範例程式碼:
static int [] gbSort(int [] arr) {// 如果數組元素為1, 直接返回if (arr.length < 2) {return arr;}// 將數組拆分兩個int middle = arr.length/2;int [] left = Arrays.copyOfRange(arr, 0, middle);int [] right = Arrays.copyOfRange(arr, middle, arr.length);left = gbSort(left);right = gbSort(right);// 返回合并結果return merge(left, right);}static int [] merge(int [] left, int [] right) {// 臨時大數組, 長度是兩個數組長度之和int [] result = new int[left.length + right.length];int index = 0;// 兩個數組都有元素時, 迴圈比較取兩數組第一個元素的較小值, 放入臨時數組, 然後將其刪除while (left.length > 0 && right.length > 0) {if (left[0] > right[0]) {result[index++] = right[0];right = Arrays.copyOfRange(right, 1, right.length);} else {result[index++] = left[0];left = Arrays.copyOfRange(left, 1, left.length);}}// 迴圈結束後有可能某個數組還有元素, 將其整個拷貝到臨時大數組中.if (left.length > 0) {System.arraycopy(left, 0, result, index, left.length);} else if (right.length > 0) {System.arraycopy(right, 0, result, index, right.length);}return result;}