堆排序算法
堆排序算法是一种高效的排序算法,它利用了堆这种数据结构来实现排序。堆是一种完全二叉树,并且满足堆的性质:对于每个节点i,其父节点的值大于(或小于)其子节点的值。堆排序算法可以分为两个阶段:建立堆和排序。
建立堆
在建立堆的阶段,我们需要将待排序的数组构建成一个堆。在堆中,根节点是最大(或最小)的元素。我们可以通过从最后一个非叶子节点开始,自底向上地调整每个节点,使其满足堆的性质。
首先,我们定义一个函数heapify
,用来调整某个节点以满足堆的性质。我们将其实现为一个递归函数,它首先找到当前节点的左子节点和右子节点中的最大值(或最小值),然后将当前节点与其交换。然后,递归地调用heapify
函数来继续调整被交换的子节点。
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)
接下来,我们定义一个函数build_heap
,用来建立堆。它从最后一个非叶子节点开始,依次调用heapify
函数来调整每个节点。
def build_heap(arr):
n = len(arr)
# 从最后一个非叶子节点开始调整
for i in range(n // 2 - 1, -1, -1):
heapify(arr, n, i)
排序
在建立堆之后,我们可以通过重复从堆中取出最大(或最小)值,并将其放置到已排序的部分中来实现排序。具体步骤如下:
- 将堆的根节点与最后一个元素交换;
- 从根节点开始调用
heapify
函数,将堆的大小减一,并调整堆; - 重复步骤1和2,直到堆的大小为1。
下面是完整的堆排序算法的实现:
def heap_sort(arr):
n = len(arr)
# 建立堆
build_heap(arr)
# 重复从堆中取出最大值,并将其放置到已排序的部分中
for i in range(n - 1, 0, -1):
arr[i], arr[0] = arr[0], arr[i]
heapify(arr, i, 0)
示例
假设我们有一个待排序的数组[4, 2, 9, 6, 5]
,我们可以使用堆排序算法来排序它。
首先,我们建立堆:
arr = [4, 2, 9, 6, 5]
build_heap(arr)
print(arr) # 输出:[9, 6, 4, 2, 5]
然后,我们进行排序:
heap_sort(arr)
print(arr) # 输出:[2, 4, 5, 6, 9]
通过以上示例,我们可以看到,使用堆排序算法可以将一个无序的数组按照升序(或降序)进行排序。
堆排序算法的时间复杂度为O(nlogn),其中n是数组的长度。由于堆排序算法是原地排序算法,它不需要额外的空间来存储临时变量,因此空间复杂度为O(1)。
总结起来,堆排序算法是一种