堆排序
(1)基本概念
堆排序(Heap Sort)是基于二叉堆的一种排序算法。二叉堆分为两种:最大堆和最小堆。在最大堆中,父节点的值总是大于或等于其子节点的值;而在最小堆中,父节点的值总是小于或等于其子节点的值。
堆排序的核心思想是将一个无序数组构建成一个大顶堆(或小顶堆),然后将堆顶元素(最大值或最小值)与堆尾元素互换,之后将剩余元素重新调整为大顶堆(或小顶堆),以此类推,直到整个数组有序。
堆排序的核心是堆的调整操作,即将一个无序数组构建成一个大顶堆(或小顶堆)。这个过程可以通过自上而下、自下而上的方式进行。自上而下方式是从上到下遍历数组,依次将每个元素插入到合适的位置,使得整个数组满足大顶堆(或小顶堆)的性质。自下而上方式是从下到上遍历数组,每次将当前未调整的元素中最大的(或最小的)元素调整到合适的位置,直到整个数组有序。
(2)代码示例
"""堆排序"""
#函数目的:找到当前子数组中的最大值,确保给定的子树满足堆的性质(父节点>=子节点)
def heapify(arr, n, i):#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:#如果largest不是i,则交换arr[i]和arr[largest]
arr[i], arr[largest] = arr[largest], arr[i] # 交换
heapify(arr, n, largest) #递归地对交换后的子树调用heapify函数,以保持堆的性质
#函数目的:使用堆排序算法对数组进行排序
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[i], arr[0] = arr[0], arr[i] #交换
heapify(arr, i, 0)
return arr
if __name__ == '__main__':
arr = [5, 7, 3, 7, 2, 3, 2, 5, 9, 5, 7, 8]
print(heap_sort(arr))
(3)算法分析
时间复杂度:最佳情况下,堆排序的时间复杂度为 O(nlogn)。在最坏情况下,如果输入数组已经是有序的,其时间复杂度退化为 O(n^2)。
空间复杂度:堆排序是原地排序算法,不需要额外的存储空间,因此其空间复杂度为 O(1)。
稳定性:堆排序是稳定的排序算法,因为相等的元素在交换过程中不会被交换。
适用场景:对于处理中小规模数据集的排序场景,堆排序是一个高效的选择。但对于大规模数据集或者含有大量重复元素的数组,其他排序算法如归并排序或快速排序可能更为合适。
局限性:由于堆排序需要构建和调整堆,因此对于非常大的数组,可能会占用大量内存。此外,如果输入数据不满足堆的性质,排序结果可能不正确。