1. 堆: 是一种顺序结构存储的完全二叉树。
2. 大根堆: 根结点的关键字不小于孩子结点的关键字。(从小到大排序)
小根堆:根结点的关键字不大于孩子结点的关键字。 (从大到小排序)
3. 堆的构建:
从最后一个非叶子结点(数组中编号为 i= len(arr)//2 -1 )开始,从下到上,从右到左开始调整。以大根堆为例,如果第i 个结点的孩子结点(左孩子结点的编号为k=2*i+1, 右孩子结点的编号为k+1)比它大,则进行交换;否则,不交换。再从第二个非叶子结点开始,进行调整,直到调整到根结点为止。
4. 堆排序:
先将待排记录调整为堆,再将堆顶元素与末尾元素进行交换,将交换后的末尾元素沉到待排序的末尾;然后,将剩余元素调整为堆,将堆顶元素与末尾元素进行交换,如此反复,直到最后两个待排元素交换为止。
5. 复杂度
平均时间 | 最好 | 最差 | 空间复杂度 | 稳定性 |
O(nlogn) | O(nlogn) | O(nlogn) | O(1) | 不稳定 |
6. Python实现
def HeapSort(arr):
s = len(arr)
i = len(arr)//2 - 1 # 非叶子结点的位置
# 初次建立堆
for k in range(i,-1, -1):
ajustHeap(arr, k, s)
# 交换元素和调整堆
for j in range(s-1, 0, -1):
arr[j], arr[0] = arr[0], arr[j]
adjustHeap(arr, 0, j)
# 定义adjustHeap函数
def adjustHeap(arr, cur, heaplen):
temp = arr[cur] # 记录当前位置的值
k = cur*2+1 #当前位置的左孩子结点
while k < heaplen:
# 左孩子结点的值小于右孩子结点的值,指向右孩子结点
if k+1 < heaplen and arr[k] < arr[k+1]:
k += 1
# 当前位置的值小于孩子结点进行交换
if arr[cur] < arr[k]:
arr[cur] = arr[k]
cur = k
k = k*2 + 1
arr[cur] = temp