1 概述
堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
2 算法流程
- 首先构建最大堆,要求是每个非叶节点的值大于其左右子节点的值,构建过程从非叶节点最大序号开始,根据【父节点是
i
,则其左子节点是2*i+1
,其右子节点是2*i+2
】的规律,进行检查,如果不满足则需要做交换 - 根据最大堆,将根节点的最大值与末尾叶节点交换,将最大值取出,实质上是选择过程,然后重新检查堆,调整为最大堆
- 循环步骤2,直至取出序列中所有的值
3 代码/Python
def buildMaxHeap(arr):
import math
# 最大堆构建过程,主要需要检查所有父节点是否大于子节点
# 二叉树的非叶节点最大序号只能是floor(len(arr)/2),降序检查
for i in range(math.floor(len(arr)/2),-1,-1):
heapify(arr,i)
def heapify(arr, i):
# 设定最大节点是父节点
largest = i
# 对应的两个子节点(可能不存在)
left = 2*i+1
right = 2*i+2
# 如果子节点大于父节点,则需要交换
if left < arrLen and arr[left] > arr[largest]:
largest = left
if right < arrLen and arr[right] > arr[largest]:
largest = right
if largest != i:
swap(arr, i, largest)
# 交换之后要检查被交换的节点作为父节点是否满足最大堆要求
heapify(arr, largest)
def swap(arr, i, j):
arr[i], arr[j] = arr[j], arr[i]
def heapSort(arr):
global arrLen
arrLen = len(arr)
buildMaxHeap(arr) # 构建最大堆
for i in range(len(arr)-1,0,-1):
# 每次循环将最大值交换到最后位置
swap(arr,0,i)
arrLen -=1
# 检查根节点是否满足最大堆要求
heapify(arr, 0)
return arr
# 算法调用
import random
nums = [random.randint(0,100) for i in range(10)]
print('随机生成10个数字:', nums)
print('排序后输出结果为:', heapSort(nums))
4 算法解释
- 堆排序是利用完全二叉树性质,进行数值交换和最大值选择
- 时间复杂度:构建初始堆经推导复杂度为 O ( n ) O(n) O(n),在交换并重建堆的过程中,需交换n-1次,而重建堆的过程中,根据完全二叉树的性质, [ log 2 ( n − 1 ) , log 2 ( n − 2 ) . . . , 1 ] [\log_2(n-1),\log_2(n-2)...,1] [log2(n−1),log2(n−2)...,1]逐步递减,近似为) n log n n\log n nlogn。所以堆排序时间复杂度一般认为就是 O ( n log n ) O(n\log n) O(nlogn)级。,因此最坏,最好,平均时间复杂度均为 O ( n l o g n ) O(nlogn) O(nlogn)
- 空间复杂度:由于堆排序是原地进行交换,所以空间复杂度是 O ( 1 ) O(1) O(1)
- 稳定性:在排序过程,需要大范围替换元素,存在相等元素替换之后顺序颠倒,所以是不稳定的