天天看點

【資料結構與算法】歸并排序的原理及算法實作歸并排序

歸并排序

歸并排序是采用分治法的一個非常典型的應用。歸并排序的思想就是先遞歸分解數組,再合并數組

将數組分解到最小之後,合并兩個有序的數組,基本思路就是比較兩個數組最前面的數字,誰小就先取誰,取了後相應的指針就往後移動一位。然後再比較,知道一個數組為空,最後把一個數組的剩餘部分複制過來即可

文章目錄

  • 歸并排序
        • 基本實作
          • 這個就是歸并算法的思想:把一組元素一直拆分到隻有一個子元素,之後開始合并,通過Left與Right進行排序。
        • 歸并算法代碼實作
        • 時間複雜度

基本實作

1.有一串數組如下,将其對半分成兩個數組。

【資料結構與算法】歸并排序的原理及算法實作歸并排序

2.左右繼續拆分到每一個子部分隻有一個元素,如下,拆分到隻有一個子元素的之後拆分結束

【資料結構與算法】歸并排序的原理及算法實作歸并排序

3,拆分完之後進行合并,56跟26是上面綠色框拆出來的,合并的時候采用小的在前,大的在後。

【資料結構與算法】歸并排序的原理及算法實作歸并排序

4.把兩個綠色塊進行合并,這個時候就要借助定義的遊标了,一個指的是左邊大部分Left ,一個是右邊的Right.合并的時候采用的方式是,對于左邊的部分有一個遊标,右邊的部分也有一個遊标,然後對于所指的兩個部分進行比較換位。

【資料結構與算法】歸并排序的原理及算法實作歸并排序

5.經過比較17比較小,拿出來,之後Right向後移動一位。

【資料結構與算法】歸并排序的原理及算法實作歸并排序

6.之後繼續比較Right的指向比26大,取出26,Left繼續向後移動一位。之後比較發現Right指向比Left大,取出54,最後把Right放到後面,得到下面的一個有序數列。

【資料結構與算法】歸并排序的原理及算法實作歸并排序

7.右邊繼續采用相同的方式,的得到兩個部分,之後現在對于整個序列來說就隻有兩個部分了。

【資料結構與算法】歸并排序的原理及算法實作歸并排序

8.按照上面相同的方式對兩個綠色框的資料進行合并。依舊是左邊的遊标Left,右邊的右邊Right對比。得到了一個有序的數列

【資料結構與算法】歸并排序的原理及算法實作歸并排序

這個就是歸并算法的思想:把一組元素一直拆分到隻有一個子元素,之後開始合并,通過Left與Right進行排序。

那麼對于奇數個也是一樣的,隻不過拆分的時候最後的的一組多出來一個。合并的時候也是,先把最後那個灰色框那兩個合并到一起,再跟44合并成3個,怎麼拆的就怎麼合并。
【資料結構與算法】歸并排序的原理及算法實作歸并排序

歸并算法代碼實作

'''
Create by YO
@Time:  2020/4/22
'''

#相除的時候兩個斜杠無小數部分。向下取整
def merge_sort(alist):
    '''歸并排序'''
    n=len(alist)
    if n<=1:
        return alist
    mid=n//2    #中間值
    left_li=merge_sort(alist[:mid])
    #right   采用歸并排序後形成的新的清單
    right_li=merge_sort(alist[mid:])
    #将兩個有序的子序列合并成一個新的整體  merge(left,right)  左邊的指針跟右邊的指針都指向兩個子序列的第一個元素
    left_pointer,right_pointer=0,0
    result=[]

    while left_pointer<len(left_li) and right_pointer<len(right_li):
        if left_li[left_pointer]<right_li[right_pointer]:
            result.append(left_li[left_pointer])
            left_pointer+=1   #移動完向後一位移動
        else:
          result.append(right_li[right_pointer])
          right_pointer+=1
    result+=left_li[left_pointer:]
    result+=right_li[right_pointer:]
    return result


if __name__ == "__main__":
    li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
    print(li)
    sorted_li=merge_sort(li)
    print(li)
    print(sorted_li)

輸出:
[54, 26, 93, 17, 77, 31, 44, 55, 20]
[54, 26, 93, 17, 77, 31, 44, 55, 20]
[17, 20, 26, 31, 44, 54, 55, 77, 93]           

複制

時間複雜度

最優時間複雜度:O(nlogn)

最壞時間複雜度:O(nlogn)

穩定性:穩定