python-歸併排序

代碼環境:python3.6

歸併排序採用分治法,思想是:先遞歸拆分數組,再合併數組。python

一、拆分數組

假設數組一共有 n 個元素,咱們遞歸對數組進行折半拆分即n//2,直到每組只有一個元素爲止。算法

二、合併數組

算法會從最小數組開始有序合併,這樣合併出來的數組一直是有序的,因此合併兩個有序數組是歸併算法的核心,這裏用兩個簡單數組示例:數組

  • 步驟1:新建一個空數組存放合併結果,用lr兩個輔助指針記錄兩個數組當前操做位置;

image.png

  • 步驟2:從左到右逐一比較兩個小數組中的元素,較小的元素先放入新數組,指針移位,直到lr指針超出尾部;

image.png

image.png

image.png

image.png

image.png

  • 步驟3:指針還沒有移到尾部的數組,說明還有剩餘元素,將剩餘元素合併到新數組尾部。

image.png

算法實現

def merge(list_left, list_right):
    """
    入參數組都是有序的,此處將兩個有序數組合併成一個大的有序數組
    """
    # 兩個數組的起始下標
    l, r = 0, 0

    new_list = []
    while l < len(list_left) and r < len(list_right):
        if list_left[l] < list_right[r]:
            new_list.append(list_left[l])
            l += 1
        else:
            new_list.append(list_right[r])
            r += 1
    new_list += list_left[l:]
    new_list += list_right[r:]
    return new_list


def merge_sort(mylist):
    """歸併排序
    mylist: 待排序數組
    return: 新數組list
    """
    if len(mylist) <= 1:
        return mylist

    mid = len(mylist) // 2
    list_left = merge_sort(mylist[:mid])
    list_right = merge_sort(mylist[mid:])
    return merge(list_left, list_right)


if __name__ == "__main__":
    mylist = [12, 33, 199, 0, 54, 33, 11]
    result = merge_sort(mylist)
    print(f'歸併排序後:{result}')

算法效率

  • 時間複雜度:O(nlogn)

歸併排序把數組一層層折半分組,長度爲 n 的數組,折半層數就是 logn,每一層進行操做的運算量是 n,得出時間複雜度 O(nlogn)。app

  • 空間複雜度:O(n)

每次歸併操做須要建立額外的新數組,佔用空間爲 n,但這部分額外空間會隨着方法的結束而釋放,因此只須要算單次歸併操做開闢的空間便可,得出空間複雜度 O(n)。spa

  • 穩定性:穩定

從算法中從左到右逐一比較,較小的先放入新數組,因此兩個值相同的元素,排序後依然保持原前後順序。指針

  • 非原地排序
相關文章
相關標籤/搜索