个人主页:丷从心·
系列专栏:分治算法
学习指南:算法学习指南
递归算法
Python实现
def merge(left_sorted, right_sorted):
merged = []
# 比较左右两个数组的元素, 按顺序合并到结果数组中
i = j = 0
while i < len(left_sorted) and j < len(right_sorted):
if left_sorted[i] <= right_sorted[j]:
merged.append(left_sorted[i])
i += 1
else:
merged.append(right_sorted[j])
j += 1
# 将剩余的元素添加到结果数组中
merged.extend(left_sorted[i:])
merged.extend(right_sorted[j:])
return merged
def merge_sort(arr):
# 基本情况: 当数组长度为 1 或 0 时, 直接返回
if len(arr) <= 1:
return arr
# 将数组分成两半
mid = len(arr) // 2
left = arr[:mid]
right = arr[mid:]
# 递归地对左右两半进行排序
left_sorted = merge_sort(left)
right_sorted = merge_sort(right)
# 合并已排序的左右两半
merged = merge(left_sorted, right_sorted)
return merged
arr = [5, 3, 8, 4, 2, 1, 6, 7]
sorted_arr = merge_sort(arr)
print(f'sorted_arr: {sorted_arr}')
sorted_arr: [1, 2, 3, 4, 5, 6, 7, 8]
时间复杂性
T ( n ) = { O ( 1 ) n ≤ 1 2 T ( n / 2 ) + O ( n ) n > 1 T(n) = \begin{cases} O(1) & n \leq 1 \\ 2 T(n / 2) + O(n) & n > 1 \end{cases} T(n)={O(1)2T(n/2)+O(n)n≤1n>1
T ( n ) = O ( n log n ) T(n) = O(n \log{n}) T(n)=O(nlogn)
- 由于排序问题的计算时间下界为 Ω ( n log n ) \Omega(n \log{n}) Ω(nlogn),故归并排序算法是一个渐进最优算法
非递归算法
Python实现
def merge(left_sorted, right_sorted):
merged = []
# 比较左右两个数组的元素, 按顺序合并到结果数组中
i = j = 0
while i < len(left_sorted) and j < len(right_sorted):
if left_sorted[i] <= right_sorted[j]:
merged.append(left_sorted[i])
i += 1
else:
merged.append(right_sorted[j])
j += 1
# 将剩余的元素添加到结果数组中
merged.extend(left_sorted[i:])
merged.extend(right_sorted[j:])
return merged
def merge_sort(arr):
# 将列表中的每个元素转换为单个元素的子列表
sublists = [[val] for val in arr]
# 依次合并相邻的子列表, 直到只剩下一个排序好的列表
while len(sublists) > 1:
merged_sublists = []
# 两两合并相邻的子列表
for i in range(0, len(sublists), 2):
sublist_1 = sublists[i]
sublist_2 = sublists[i + 1] if i + 1 < len(sublists) else []
merged = merge(sublist_1, sublist_2)
merged_sublists.append(merged)
sublists = merged_sublists
# 返回最终的排序结果
return sublists[0] if sublists else []
arr = [5, 3, 8, 4, 2, 1, 6, 7]
sorted_arr = merge_sort(arr)
print(f'sorted_arr: {sorted_arr}')
sorted_arr: [1, 2, 3, 4, 5, 6, 7, 8]
自然归并排序
- 用 1 1 1次对数组的线性扫描找出所有排好序的子数组段,然后将相邻的排好序的子数组段两两合并,构成更大的排好序的子数组段
Python实现
def find_sorted_sublists(arr):
sorted_sublists = []
left, right = 0, 1
while right < len(arr):
if arr[right] >= arr[right - 1]:
right += 1
else:
sorted_sublists.append(arr[left:right])
left = right
right += 1
sorted_sublists.append(arr[left:right])
return sorted_sublists
def merge(left_sorted, right_sorted):
merged = []
# 比较左右两个数组的元素, 按顺序合并到结果数组中
i = j = 0
while i < len(left_sorted) and j < len(right_sorted):
if left_sorted[i] <= right_sorted[j]:
merged.append(left_sorted[i])
i += 1
else:
merged.append(right_sorted[j])
j += 1
# 将剩余的元素添加到结果数组中
merged.extend(left_sorted[i:])
merged.extend(right_sorted[j:])
return merged
def natural_merge_sort(arr):
sublists = find_sorted_sublists(arr)
# 依次合并相邻的子列表, 直到只剩下一个排序好的列表
while len(sublists) > 1:
merged_sublists = []
# 两两合并相邻的子列表
for i in range(0, len(sublists), 2):
sublist_1 = sublists[i]
sublist_2 = sublists[i + 1] if i + 1 < len(sublists) else []
merged = merge(sublist_1, sublist_2)
merged_sublists.append(merged)
sublists = merged_sublists
# 返回最终的排序结果
return sublists[0] if sublists else []
arr = [5, 3, 8, 4, 2, 1, 6, 7]
sorted_arr = natural_merge_sort(arr)
print(f'sorted_arr: {sorted_arr}')
sorted_arr: [1, 2, 3, 4, 5, 6, 7, 8]