python 歸並排序


歸並排序仍然是利用完全二叉樹實現,它是建立在歸並操作上的一種有效的排序算法,該算法是采用分治法(Divide and Conquer)的一個非常典型的應用。將已有序的子序列合並,得到完全有序的序列。

基本過程:假設初始序列含有n個記錄,則可以看成是n個有序的子序列,每個子序列的長度為1,然后兩兩歸並,得到n/2個長度為2或1的有序子序列,再兩兩歸並,最終得到一個長度為n的有序序列為止,這稱為2路歸並排序。

下面的截圖來自《大話數據結構》相關章節,便於理解整個代碼的實現過程。

                               

圖中主要表明了實例代碼中的兩部分,分別為原始序列的拆分和合並兩部分。

下面是實例代碼:

# -*- coding:utf-8 -*-
__author__ = 'webber'
import random, time

def merge_sort(lst):
    if len(lst) <= 1:
        return lst          # 從遞歸中返回長度為1的序列

    middle = len(lst) / 2
    left = merge_sort(lst[:middle])     # 通過不斷遞歸,將原始序列拆分成n個小序列
    right = merge_sort(lst[middle:])
    return merge(left, right)

def merge(left, right):
    i, j = 0, 0
    result = []
    while i < len(left) and j < len(right):  # 比較傳入的兩個子序列,對兩個子序列進行排序
        if left[i] <= right[j]:
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            j += 1
    result.extend(left[i:])         # 將排好序的子序列合並
    result.extend(right[j:])
    return result

if __name__ == "__main__":
    start = time.clock()

    rand_lst = []
    for i in range(6):
        rand_lst.append(round(random.random()*100, 2))
    lst = merge_sort(rand_lst)

    end = time.clock()
    print lst
    print "done  ", (end-start)

 

性能方面:

由於和堆排序類似,都是利用完全二叉樹的相關性質,所以它在時間復雜度方面,最好、最壞和平均的時間復雜度都是O(nlogn);但是,在空間復雜度方面,由於它開辟了一塊新的內存空間用來存放left和right子序列,而兩個子序列的總大小其實和lst是一樣的,為n,所以它的空間復雜度為O(n),這是歸並排序的主要弱點,犧牲了空間復雜度來換取時間復雜度的減少。穩定性方面,只要在關鍵碼相同時采用左序列元素先行的原則,就能保證算法的穩定性,另一方面,歸並排序算法沒有適應性,無論對於什么樣的序列它都要做logn遍的遞歸。在《大話數據結構》一書中,對於歸並排序,作者提倡盡量考慮非遞歸的方法(在c中)。

 

這里記錄一下,python有一個模塊,專門提供了歸並排序的方法,叫做“heapq”模塊,因此我們只要將分解后的結果導入該方法即可。例如:

from heapq import merge def merge_sort(lst):
    if len(lst) <= 1:
        return lst          # 從遞歸中返回長度為1的序列
    middle = len(lst) / 2
    left = merge_sort(lst[:middle])     # 通過不斷遞歸,將原始序列拆分成n個小序列
    right = merge_sort(lst[middle:])
    return list(merge(left, right))

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM