假設如今的列表分兩段有序,如何將其合成爲一個有序列表。這種操做稱爲一次歸併。python
當一個列表兩段有序合併爲一個有序列表的一次歸併的過程以下:算法
將列表分爲兩段,兩個箭頭分別指向每段的第一個:app
比較兩段中最小的數2和1,將最小的那個值,箭頭後移:dom
接着比較兩段中最小的數,將2取出,箭頭後移,以此類推:ide
def merge(li, low, mid, high): """ 歸併過程 :param li:列表 :param low:第一段第一個元素 :param mid:第一段最後一個元素 :param high:第二段最後一個元素 :return: """ i = low j = mid + 1 # 第二段第一個元素 ltmp = [] # 新列表 while i <= mid and j<= high: # 只要左右兩邊都有數 if li[i] < li[j]: ltmp.append(li[i]) i += 1 else: ltmp.append(li[j]) j += 1 # while執行完,確定會有一部分沒數了 while i<= mid : # 若是是第一部分仍有數 ltmp.append(li[i]) i += 1 while j <= high: # 若是是第二部分仍有數 ltmp.append(li[j]) j += 1 # 將ltmp的值寫回到li li[low:high+1] = ltmp # 切片往回寫 li = [2, 4, 5, 7, 1, 3, 6, 8] merge(li, 0, 3, 7) print(li) """ [1, 2, 3, 4, 5, 6, 7, 8] """
歸併排序(MERGE-SORT)是利用歸併的思想實現的排序方法,該算法採用經典的分治(divide-and-conquer)策略(分治法將問題分(divide)成一些小的問題而後遞歸求解,而治(conquer)的階段則將分的階段獲得的各答案"修補"在一塊兒,即分而治之)。
函數
分解:將列表越分越小,直至分紅一個元素。spa
終止條件:一個元素是有序的。blog
合併:將兩個有序列表歸併,列表愈來愈大。排序
def merge(li, low, mid, high): """ 歸併過程 :param li:列表 :param low:第一段第一個元素 :param mid:第一段最後一個元素 :param high:第二段最後一個元素 :return: """ i = low j = mid + 1 # 第二段第一個元素 ltmp = [] # 新列表 while i <= mid and j<= high: # 只要左右兩邊都有數 if li[i] < li[j]: ltmp.append(li[i]) i += 1 else: ltmp.append(li[j]) j += 1 # while執行完,確定會有一部分沒數了 while i<= mid : # 若是是第一部分仍有數 ltmp.append(li[i]) i += 1 while j <= high: # 若是是第二部分仍有數 ltmp.append(li[j]) j += 1 # 將ltmp的值寫回到li li[low:high+1] = ltmp # 切片往回寫 def _merge_sort(li, low, high): # 遞歸函數 """歸併排序""" if low < high: # 翟少有兩個元素,遞歸 mid = (low + high) // 2 _merge_sort(li, low, mid) # 把左邊排好序 _merge_sort(li, mid+1, high) # 把右邊排好序 merge(li, low, mid, high) print(li[low: high+1]) def merge_sort(li): return _merge_sort(li, 0, len(li)-1) li = list(range(10)) import random random.shuffle(li) print(li) merge_sort(li) print(li) """ [6, 2, 8, 3, 1, 9, 7, 5, 4, 0] [2, 6] [2, 6, 8] [1, 3] [1, 2, 3, 6, 8] [7, 9] [5, 7, 9] [0, 4] [0, 4, 5, 7, 9] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] """
每一層的時間複雜度是O(n),層數是logn。所以總的時間複雜度是O(nlogn)。遞歸
因爲merge函數建立了一個ltmp的臨時空間,到最大的時候長度是n,空間複雜度是O(n)。再也不是原地排序。