5 歸併排序
歸併排序的思路是將數據表持續分裂成爲兩半,分別對兩半進行歸併排序,然後在合併,其過程爲遞歸算法。每個步驟爲:
歸併排序實例
python實現源碼
## 歸併算法
def merge_sort (lst):
if len(lst)<=1: #遞歸結束條件
return lst
#分解問題,並遞歸調用
middle=len(lst)//2
left=merge_sort(lst[:middle])
right=merge_sort(lst[middle:])
#合併左右部分,完成排序
merged=[]
while left and right:
if left[0]<=right[0]:
merged.append(left.pop(0))
else:
merged.append(right.pop(0))
merged.extend(right if right else left)
return merged
alist5=[0,1,17,7,9,3,18,25,8]
merge_sort(alist5)
print(alist5)
算法分析:
歸併排序分爲兩個過程:分裂和歸併
- 分裂過程與二分查找結果類似,時間複雜度爲O(log n);
- 歸併過程爲對分裂的各部分,其所有數據項均會被比較和放置一次,是線性複雜度,其時間複雜度爲O(n),;
- 每次分裂都會進行一次歸併,因此,總的時間複雜度是O(n log n)
注意: 歸併排序使用了額外1倍的存儲空間用於歸併,在處理大數據集需要額外考慮空間複雜度。
6 快速排序
求解思路:依據一個“中值”數據項來把列表分爲兩半:小於中值和大於中值的一半(不一定均分),然後對每部分分別進行快速排序(遞歸)
注:若想均分數據,則該“中值”爲列表的“中位數”!此時有計算開銷,
最簡便的中值爲隨意一個數,如第1個數。
遞歸調用過程與上面的歸併排序一致,
排序過程:
python實現:
def quicksort(a, left, right):
# 確定基條件
if left>right:
return
# 申明需要用到的變量
temp = a[left]
i = left
j = right
# 交換中間變量
t = temp
# 縮小問題規模
# 在左右指針相遇之前完成所有交換,用基準將數組分爲兩組
while i != j:
# 先從右往左掃描,遇到比基準小的便停下來
while a[j]>=temp and i<j:
j -= 1
# 在從左往右掃描,遇到比基準大的數便停下來
while a[i]<=temp and i<j:
i += 1
# 左右交換
t = a[j]
a[j] = a[i]
a[i] = t
# 左右指針相遇,將基準放到數組中間將數組劃分爲兩塊
a[left] = a[i]
a[i] = temp
# print(a)
# 調用遞歸
quicksort(a, left, i-1)
quicksort(a, i+1, right)
# 測試實例
if __name__ == "__main__":
a = [6,8,2,3,4,5,7]
quicksort(a,0,len(a)-1)
print(a) # [2, 3, 4, 5, 6, 7, 8]
算法分析:
快速排序過程分爲兩部分:分裂和移動:若分裂將數據表分爲相等的兩部分,那麼久有O(log n)的複雜度,而移動需要每數據與中值對比,還是O(n),綜合起來算法複雜度就是O(n log n)。
注:快速排序過程中不需要額外的存儲空間。但是中值不能太偏離中心,極端情況下算法複雜度爲O(n^2)。需要探討選取中值的方法,如:三點取樣,
歡迎留言與評論,交流如何改進快速排序算法