Python学习算法系列(5):归并排序与堆排序
1. 引言
在前几篇博客中,我们学习了插入排序和快速排序。本篇博客将继续介绍两种常见的排序算法:
- 归并排序(Merge Sort)
- 堆排序(Heap Sort)
我们将介绍它们的基本原理、代码实现以及性能分析。
2. 归并排序(Merge Sort)
2.1 归并排序原理
归并排序是一种采用分治法的排序算法,其基本思想是:
- 将数组分为两部分,分别进行排序。
- 将已排序的两部分合并成一个有序数组。
归并排序的关键在于“合并”操作,即将两个已排序的子数组合并成一个有序数组。
2.2 归并排序代码实现
def merge_sort(arr):
if len(arr) <= 1:
return arr
mid = len(arr) // 2 # 找到中间位置
left = merge_sort(arr[:mid]) # 对左半部分递归排序
right = merge_sort(arr[mid:]) # 对右半部分递归排序
return merge(left, right) # 合并排序结果
def merge(left, right):
result = []
i = j = 0
# 合并左右两部分
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
# 测试归并排序
arr = [64, 34, 25, 12, 22, 11, 90]
sorted_arr = merge_sort(arr)
print("排序后的数组:", sorted_arr) # 输出 [11, 12, 22, 25, 34, 64, 90]
2.3 归并排序时间复杂度
归并排序的时间复杂度为:
- 最好情况:O(n log n)
- 最坏情况:O(n log n)
- 平均情况:O(n log n)
归并排序的空间复杂度是 O(n),因为需要额外的空间来存储合并后的数组。
3. 堆排序(Heap Sort)
3.1 堆排序原理
堆排序是一种基于堆数据结构的排序算法,堆是一个完全二叉树,其每个父节点都大于或小于其子节点(最大堆或最小堆)。堆排序的过程如下:
- 构建最大堆(或最小堆),使得根节点是最大(或最小)元素。
- 将根节点(最大元素)与堆的最后一个元素交换,然后重新调整堆。
- 重复该过程,直到所有元素排序完成。
3.2 堆排序代码实现
def heapify(arr, n, i):
largest = i
left = 2 * i + 1 # 左子节点
right = 2 * i + 2 # 右子节点
# 判断左子节点是否比根节点大
if left < n and arr[left] > arr[largest]:
largest = left
# 判断右子节点是否比当前最大值大
if right < n and arr[right] > arr[largest]:
largest = right
# 如果最大值不是根节点,则交换并继续调整堆
if largest != i:
arr[i], arr[largest] = arr[largest], arr[i]
heapify(arr, n, largest)
def heap_sort(arr):
n = len(arr)
# 建立最大堆
for i in range(n//2 - 1, -1, -1):
heapify(arr, n, i)
# 逐个交换根节点与最后一个元素,并调整堆
for i in range(n-1, 0, -1):
arr[i], arr[0] = arr[0], arr[i]
heapify(arr, i, 0)
# 测试堆排序
arr = [64, 34, 25, 12, 22, 11, 90]
heap_sort(arr)
print("排序后的数组:", arr) # 输出 [11, 12, 22, 25, 34, 64, 90]
3.3 堆排序时间复杂度
堆排序的时间复杂度为:
- 最好情况:O(n log n)
- 最坏情况:O(n log n)
- 平均情况:O(n log n)
堆排序的空间复杂度是 O(1),因为堆排序是原地排序,不需要额外的空间。
4. 排序算法的性能比较
以下是 归并排序 和 堆排序 与其他常见排序算法的时间复杂度比较:
| 算法 | 时间复杂度(最好情况) | 时间复杂度(最坏情况) | 空间复杂度 |
|---|---|---|---|
| 冒泡排序 | O(n) | O(n^2) | O(1) |
| 选择排序 | O(n^2) | O(n^2) | O(1) |
| 插入排序 | O(n) | O(n^2) | O(1) |
| 快速排序 | O(n log n) | O(n^2) | O(log n) |
| 归并排序 | O(n log n) | O(n log n) | O(n) |
| 堆排序 | O(n log n) | O(n log n) | O(1) |
5. 总结
- 归并排序:是一种稳定的排序算法,适用于大规模数据,时间复杂度为 O(n log n),但需要额外的空间来存储中间数组。
- 堆排序:是一种原地排序算法,空间复杂度 O(1),适用于大规模数据,尽管时间复杂度也是 O(n log n),但性能通常不如快速排序。
- 排序算法优化:对于大规模数据,归并排序和堆排序是非常有效的选择。
📢 下一篇 Python学习算法系列(6):基数排序与计数排序,敬请期待!🚀
💡 如果你喜欢这篇文章,欢迎点赞、收藏,并关注本系列!
105

被折叠的 条评论
为什么被折叠?



