目录
概要
堆排序算法是一种基于二叉堆数据结构的排序算法,它的时间复杂度为 O(nlogn)。(其中,n 表示待排序序列的长度)
堆排序采用的是一种选择排序的思想,具体地说,堆排序处理过程分为两个阶段:
- 建立堆。
- 堆顶元素与堆底元素交换位置后进行调整堆的操作(交换堆顶元素和堆尾元素对答案数组排序)。
这里的“堆”是指“完全二叉树”,且此完全二叉树中任何一个非叶子节点值都不大于并且不小于其左右节点所记录的值。那么建立堆的过程就是将未排序序列构建成一个堆,堆化的过程是从最后一个非叶子节点开始向前遍历整个堆结构,依次对各个子树进行堆化操作。完成堆化之后,堆顶元素就是序列的最大值(或者最小值),把其与序列的最后一个元素交换位置再重新调整堆,即可得到次大值,以此类推,直到所有元素均排好序为止。
在排序算法中,堆排序的时间复杂度为 O(nlogn),具有稳定性、高效性、既可以进行升序又可以进行降序排序等优点,被广泛运用在计算机科学中的各种领域。与快速排序等其他常见的 O(nlogn) 排序算法相比,堆排序适用于内存小、外存大的场景,或者要求稳定性和排序结果不依赖于初始数据顺序的场合,如解决前 K 大问题等。
算法实现之Python
Python实现堆排序算法的代码:
def heap_sort(arr):
n = len(arr) # 数组长度
# 构建大根堆
# 从最后一个非叶子节点开始向前构建
for i in range(n // 2 - 1, -1, -1):
heapify(arr, n, i)
# 排序
# 依次从堆中取出最大值并放在数组的尾部
# 堆的大小每次减少1,再重新堆化剩下的元素
for i in range(n - 1, 0, -1):
arr[0], arr[i] = arr[i], arr[0] # 将最大值和末尾元素交换
# 将最大值和末尾元素交换
heapify(arr, i, 0)
def heapify(arr, n, i):
# 初始化根、左孩子和右孩子的索引
largest = i
l = 2 * i + 1
r = 2 * i + 2
# 如果左孩子比根节点大,则将largest设置为左孩子的索引
if l < n and arr[l] > arr[largest]:
largest = l
# 如果右孩子比根节点大,则将largest设置为右孩子的索引
if r < n and arr[r] > arr[largest]:
largest = r
# 如果最大值不是当前节点,则交换并递归地堆化被影响的子树
if largest != i:
arr[i], arr[largest] = arr[largest], arr[i]
heapify(arr, n, largest)
arr = [1,4,2,8,9,6]
heap_sort(arr)
print("排好序的数组:")
for i in arr:
print(i, end=" ")
运行结果:
排好序的数组:
1 2 4 6 8 9
heap_sort()
函数接收一个待排序的数组arr
作为输入,并实现了堆排序算法。该函数又调用了heapify()
函数来保持二叉堆的性质,在每次迭代中,在堆顶找到最大的元素进行交换,同时将剩余元素重新堆化。
heapify()
函数也非常重要,它用于维护二叉堆的性质。函数接收三个参数:数组arr
、堆的大小(即在递归过程中被排除的元素数)n
和当前节点的索引i
。函数首先使用左儿子和右儿子中的最大值与父节点比较从而找到最大值。如果存在任何修改,则对影响的子树进行递归性地堆化,以确保最大值沉入堆中。