堆排序
外观
堆排序(Heap Sort)是一种基于二叉堆数据结构的比较排序算法。它通过构建最大堆(或最小堆)并反复提取堆顶元素实现排序,时间复杂度为,且具有原地排序的特性。
算法原理[编辑 | 编辑源代码]
堆排序的核心分为两步: 1. 建堆:将无序数组调整为满足堆性质的完全二叉树(最大堆中父节点≥子节点,最小堆反之)。 2. 排序:反复将堆顶元素(最大值或最小值)与末尾元素交换,并重新调整堆,直到所有元素有序。
堆的性质[编辑 | 编辑源代码]
- 完全二叉树结构,可用数组表示。
- 对于索引的节点:
* 父节点: * 左子节点: * 右子节点:
- 图:最大堆示例(数组表示:[7,3,8,1,2,5,4])*
算法步骤[编辑 | 编辑源代码]
1. 构建最大堆:从最后一个非叶子节点开始,自底向上调用`heapify`。 2. 交换与调整:
- 将堆顶元素(最大值)与末尾元素交换。 - 缩小堆范围,对剩余部分重新`heapify`。
3. 重复步骤2直到堆大小为1。
伪代码[编辑 | 编辑源代码]
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[0], arr[i] = arr[i], arr[0]
heapify(arr, i, 0)
示例分析[编辑 | 编辑源代码]
输入数组: [12, 11, 13, 5, 6, 7] 1. 建堆后(最大堆): [13, 11, 12, 5, 6, 7] 2. 第一次交换后: [12, 11, 7, 5, 6, 13] 3. 最终结果: [5, 6, 7, 11, 12, 13]
时间复杂度与空间复杂度[编辑 | 编辑源代码]
- 时间复杂度:
* 建堆: * 每次`heapify`:,共次 * 总计:
- 空间复杂度:(原地排序)
实际应用[编辑 | 编辑源代码]
- 优先级队列:操作系统任务调度、图算法(如Dijkstra)。
- Top-K问题:只需构建大小为K的堆,无需全排序。
- 嵌入式系统:因原地排序特性,适合内存受限场景。
与其他排序算法对比[编辑 | 编辑源代码]
算法 | 平均时间复杂度 | 空间复杂度 | 稳定性 |
---|---|---|---|
堆排序 | 不稳定 | ||
快速排序 | 不稳定 | ||
归并排序 | 稳定 |
常见问题[编辑 | 编辑源代码]
Q: 为什么堆排序不稳定? A: 交换堆顶与末尾元素时,可能破坏相同键值的原始顺序(例如[3a, 3b, 2] → [2, 3b, 3a])。
Q: 如何优化堆排序的常数因子? A: 使用Floyd的建堆算法(自底向上`heapify`),减少比较次数。