分治法的基本思想 高階排序演算法 分治法與歸併排序

2021-10-11 23:21:39 字數 2232 閱讀 6839

很多有用的演算法結構上是遞迴的,為了解決乙個特定問題,演算法一次或者多次遞迴呼叫其自身以解決若干子問題。 這些演算法典型地遵循分治法的思想:將原問題分解為幾個規模較小但是類似於原問題的子問題,遞迴求解這些子問題, 然後再合併這些問題的解來建立原問題的解。

分治法在每層遞迴時有三個步驟:

現在我們就來看下歸併排序是是如何利用分治法解決問題的。

考慮我們排序這個陣列:[10,23,51,18,4,31,13,5] ,我們遞迴地將陣列進行分解

當陣列被完全分隔成只有單個元素的陣列時,我們需要把它們合併回去,每次兩兩合併成乙個有序的序列。

用遞迴**來描述這個問題:

def merge_sort(seq):

if len(seq) <= 1: # 只有乙個元素是遞迴出口

return seq

else:

mid = int(len(seq)/2)

left_half = merge_sort(seq[:mid])

right_half = merge_sort(seq[mid:])

# 合併兩個有序的陣列

new_seq = merge_sorted_list(left_half, right_half)

return new_seq

注意我們這裡有乙個函式沒實現,就是如何合併兩個有序陣列 merge_sorted_list。其實你在紙上畫一畫, 合併兩個有序陣列並不難實現。

""" 合併兩個有序序列,返回乙個新的有序序列

:param sorted_a:

:param sorted_b:

"""length_a, length_b = len(sorted_a), len(sorted_b)

a = b = 0

new_sorted_seq = list()

while a < length_a and b < length_b:

if sorted_a[a] < sorted_b[b]:

a += 1

else:

b += 1

# 最後別忘記把多餘的都放到有序陣列裡

if a < length_a:

new_sorted_seq.extend(sorted_a[a:])

else:

new_sorted_seq.extend(sorted_b[b:])

return new_sorted_seq

這樣就實現了歸併排序,並且你會發現它返回乙個新的陣列而不是修改原有陣列。

我們來簡單看下它歸併排序的時間複雜度,假設排序 n 個數字時間複雜度是 t(n),這裡為了方便假設 n 是 2 的冪

總的代價是 cnlg(n)+cncnlg(n)+cn ,忽略常數項可以認為是 o(nlg(n))。如果這個圖看不懂,我們自己求解下也不難,首先我們簡化一下, 把常數係數當成 1,得到以下遞迴式:

希爾排序法基本思想

希爾排序 shell sort 又稱為 縮小增量排序 是1959年由d.l.shell提出來的。該方法的基本思想是 先將整個待排元素序列分割成若干個子串行 由相隔某個 增量 的元素組成的 分別進行直接插入排序,然後依次縮減增量再進行排序,待整個序列中的元素基本有序 增量足夠小 時,再對全體元素進行一...

氣泡排序演算法的基本思想

1 氣泡排序的基本思想 氣泡排序是交換排序中一種簡單的排序方法。它的基本思想是對所有相鄰記錄的關鍵字值進行比效,如果是逆順 a j a j 1 則將其交換,最終達到有 序化 其處理過程為 1 將整個待排序的記錄序列劃分成有序區和無序區,初始狀態有序區為空,無序區包括所有待排序的記 錄。2 對無序區從...

氣泡排序的基本思想

1 氣泡排序的基本思想 氣泡排序是交換排序中一種簡單的排序方法。它的基本思想是對所有相鄰記錄的關鍵字值進行比效,如果是逆順 a j a j 1 則將其交換,最終達到有序化 其處理過程為 1 將整個待排序的記錄序列劃分成有序區和無序區,初始狀態有序區為空,無序區包括所有待排序的記錄。2 對無序區從前向...