返回

堆排序:一种高效的原地排序算法

Android

堆排序原理

堆排序的基本思想是将待排序序列转化为一个大顶堆 (堆中每个节点的值都大于或等于其子节点的值),然后依次弹出堆顶元素,并将其插入到已排序序列的末尾。这个过程不断重复,直到堆中只剩下一个元素。

堆化 是堆排序的核心步骤,它将一个无序序列转化为一个大顶堆。具体操作如下:

  1. 将待排序序列的最后一个元素与根节点交换位置。
  2. 调整根节点,使其满足大顶堆性质(父节点的值大于等于子节点的值)。
  3. 重复步骤2和步骤3,直到调整完毕。

与选择排序的比较

堆排序与选择排序都属于原地排序算法,它们的元素交换次数相同,但它们在效率上有显着差异。堆排序的平均时间复杂度为O(n log n),而选择排序的时间复杂度为O(n^2)。

堆排序优于选择排序的原因在于:

  • 堆排序对数据进行了部分排序,而选择排序每次只能找出序列中的一个最小(或最大)元素。
  • 堆排序在堆化过程中利用了堆的特性,可以高效地找到要交换的元素。

代码实现

def heap_sort(arr):
    """堆排序算法"""

    # 1. 构建大顶堆
    for i in range(len(arr) // 2 - 1, -1, -1):
        heapify(arr, i, len(arr))

    # 2. 依次弹出堆顶元素
    for i in range(len(arr) - 1, 0, -1):
        # 交换堆顶元素和最后一个元素
        arr[0], arr[i] = arr[i], arr[0]
        # 重新堆化
        heapify(arr, 0, i)

def heapify(arr, i, n):
    """维护堆性质"""

    # 左子节点的索引
    left = 2 * i + 1
    # 右子节点的索引
    right = 2 * i + 2

    # 寻找最大值索引
    max_index = i
    if left < n and arr[left] > arr[max_index]:
        max_index = left
    if right < n and arr[right] > arr[max_index]:
        max_index = right

    # 若最大值索引不是根节点,则交换并继续堆化
    if max_index != i:
        arr[i], arr[max_index] = arr[max_index], arr[i]
        heapify(arr, max_index, n)

总结

堆排序是一种高效的原地排序算法,它利用堆的特性进行排序。它在效率上优于选择排序,并且在实际应用中得到了广泛的应用。