因為上個星期leetcode的一道題(Median of Two Sorted Arrays)所以想仔細了解一下歸並排序的實現。
還是先闡述一下排序思路:
首先歸並排序使用了二分法,歸根到底的思想還是分而治之。拿到一個長數組,將其不停的分為左邊和右邊兩份,然后以此遞歸分下去。然后再將她們按照兩個有序數組的樣子合並起來。這樣說起來可能很難理解,於是給出一張我畫的圖。
這里顯示了歸並排序的第一步,將數組按照middle進行遞歸拆分,最后分到最細之后再將其使用對兩個有序數組進行排序的方法對其進行排序。
兩個有序數組排序的方法則非常簡單,同時對兩個數組的第一個位置進行比大小,將小的放入一個空數組,然后被放入空數組的那個位置的指針往后 移一個,然后繼續和另外一個數組的上一個位置進行比較,以此類推。到最后任何一個數組先出棧完,就將另外i一個數組里的所有元素追加到新數組后面。
由於遞歸拆分的時間復雜度是logN 然而,進行兩個有序數組排序的方法復雜度是N該算法的時間復雜度是N*logN 所以是NlogN。
根據這波分析,我們可以看看對上圖的一個行為。
當最左邊的分到最細之后無法再划分左右然后開始進行合並。
第一次組合完成[4, 7]的合並
第二次組合完成[4, 7, 8]的合並
第三次組合完成[3, 5]的合並
第四次組合完成[3, 5, 9]的合並
第五次組合完成[3, 4, 5, 7, 8, 9]的合並結束排序。
下面放上python的代碼
def merge(a, b): c = [] h = j = 0 while j < len(a) and h < len(b): if a[j] < b[h]: c.append(a[j]) j += 1 else: c.append(b[h]) h += 1 if j == len(a): for i in b[h:]: c.append(i) else: for i in a[j:]: c.append(i) return c def merge_sort(lists): if len(lists) <= 1: return lists middle = len(lists)/2 left = merge_sort(lists[:middle]) right = merge_sort(lists[middle:]) return merge(left, right) if __name__ == '__main__': a = [4, 7, 8, 3, 5, 9] print merge_sort(a)
Java 實現
package com.geektime.SortQ; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class MergeSort { public void merge(List<Integer> arrays, List<Integer> pp, List<Integer> gg, int start, int end) { int pIndex = 0; int gIndex = 0; ArrayList<Integer> temp = new ArrayList<Integer>(); while (true) { if (pp.get(pIndex) >= gg.get(gIndex)) { temp.add(gg.get(gIndex)); gIndex++; } else { temp.add(pp.get(pIndex)); pIndex++; } if (gIndex == gg.size()) { for (int i = pIndex; i < pp.size(); i++) temp.add(pp.get(i)); break; } else if (pIndex == pp.size()) { for (int j = gIndex; j < gg.size(); j++) temp.add(gg.get(j)); break; } } for (int op = 0; op < temp.size(); op++) { arrays.set(start+op, temp.get(op)); } } public void mergeSort(ArrayList<Integer> arrays, int start, int end) { if (start >= end) return; int mid = (start + end) / 2; mergeSort(arrays, start, mid); mergeSort(arrays, mid+1, end); List<Integer> pp = arrays.subList(start, mid+1); List<Integer> gg = arrays.subList(mid+1, end+1); merge(arrays, pp, gg, start, end); } public static void main(String[] args) { MergeSort bb = new MergeSort(); ArrayList<Integer> arrayList = new ArrayList<Integer>(Arrays.asList(4, 5, 6, 3, 2, 1)); bb.mergeSort(arrayList,0, 5); System.out.println(arrayList); } }