堆排序(Heap Sort)是一种基于二叉堆这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组来模拟一个堆的结构。堆排序可以分为两个主要阶段:建堆和堆调整排序。

原理

堆排序利用了堆(heap)这一数据结构所设计。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

  • 建堆:将待排序的序列构造成一个大顶堆(或小顶堆)。此时,整个序列的最大值(或最小值)就是堆顶的根节点。

  • 堆调整排序:将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个序列重新构造成一个堆,这样会得到n个元素中的次大值。如此反复执行,便能得到一个有序序列了。

实现

以下是堆排序的Python实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
def heapify(arr, n, i):
largest = i # 初始化largest为根
l = 2 * i + 1 # 左 = 2*i + 1
r = 2 * i + 2 # 右 = 2*i + 2

# 如果左子节点大于根
if l < n and arr[i] < arr[l]:
largest = l

# 如果右子节点大于目前已知的最大值
if r < n and arr[largest] < arr[r]:
largest = r

# 如果最大值不是根
if largest != i:
arr[i], arr[largest] = arr[largest], arr[i] # 交换

# 递归地调整受影响的子堆
heapify(arr, n, largest)

def heapSort(arr):
n = len(arr)

# 构建大顶堆
for i in range(n, -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 = [12, 11, 13, 5, 6, 7]
heapSort(arr)
n = len(arr)
print("排序后的数组:")
for i in range(n):
print("%d" % arr[i]),

在这个实现中,heapify函数用于维护堆的性质,它确保以i为根的子树是一个大顶堆。heapSort函数首先构建一个大顶堆,然后依次将堆顶元素(即当前最大值)与末尾元素交换,并重新调整堆,直到整个数组有序。

注意

  1. 堆排序的时间复杂度是O(n log n),其中n是待排序元素的数量。它相对稳定,并且空间复杂度较低,除了隐式使用的调用栈外,不需要额外的空间。

  2. 堆排序不是稳定的排序算法,即如果序列中存在两个相等的元素,堆排序可能会改变它们的相对位置。

  3. 堆排序在构建初始堆时,需要从最后一个非叶子节点开始向上进行调整,因此其建堆的时间复杂度是O(n)。而整个排序过程包括建堆和n-1次堆调整,所以总的时间复杂度是O(n log n)。