但是在n較小的時候插入排序可能運行的會更快點。因此在歸并排序中當子問題變得足夠小時,采用插入排序來使得遞歸的葉子變粗可以加快排序速度。那么這個足夠小到底怎么去衡量呢? 請看下面:
這么幾個我不證明了,比較簡單:
A,插入排序最壞情況下可以在O(nk)時間內排序每個長度為k的n/k個子列表
B,在最壞情況下可在O(nlg(n/k))的時間內合并這些子表
C,修訂后的算法的最壞情況運行時間復雜度是O(nk + nlg(n/k))
那么,O(nk+nlg(n/k))=O(nlgn).只能最大是k=O(lgn).等式左邊中第一項是高階項。k如果大于lgn,則比歸并排序復雜度大了。左邊可以寫成nk+nlgn-nlgk,k等于lgn時,就是2nlgn-nlglgn.忽略恒定系數,則與歸并排序是一樣的。
最后結論: k < lg(n)的時候,使用插入排序
from at003_insertsort import insertSort from math import log __author__ = 'Xiong Neng' def mergeSort(seq): mergeSortRange(seq, 0, len(seq) - 1, log(len(seq)) - 1) def mergeOrderedSeq(seq, left, middle, right): """ seq: 待排序序列 left <= middle <= right 子數組seq[left..middle]和seq[middle+1..right]都是排好序的 該排序的時間復雜度為O(n) """ tempSeq = [] i = left j = middle + 1 while i <= middle and j <= right: if seq[i] <= seq[j]: tempSeq.append(seq[i]) i += 1 else: tempSeq.append(seq[j]) j += 1 if i <= middle: tempSeq.extend(seq[i:middle + 1]) else: tempSeq.extend(seq[j:right + 1]) seq[left:right + 1] = tempSeq[:] def mergeSortRange(seq, start, end, threshold): """ 歸并排序一個序列的子序列 start: 子序列的start下標 end: 子序列的end下標 threshold: 待排序長度低于這個值,就采用插入排序 """ if end - start < threshold: tempSeq = seq[start: end + 1] insertSort(tempSeq) seq[start: end + 1] = tempSeq[:] elif start < end: # 如果start >= end就終止遞歸調用 middle = (start + end) / 2 mergeSortRange(seq, start, middle, threshold) # 排好左邊的一半 mergeSortRange(seq, middle + 1, end, threshold) # 再排好右邊的一半 mergeOrderedSeq(seq, start, middle, end) # 最后合并排序結果 if __name__ == '__main__': aa = [4, 2, 5, 1, 6, 3, 7, 9, 8] mergeSort(aa) print(aa)
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com