# -*- coding: utf-8 -*-
"""
@File : heap_sort.py
@Author: Zhang_San
@Time : 2020/7/20 17:51
@des : 堆排序:基于大根堆或者小根堆的一种排序,每次通过大/小根堆得特点,找出堆顶的元素,并跟当前子堆的最后一个元素交换,排除最后一个元素后,
新的子树重新形成堆,依次交换堆顶和最后当前堆的最后一个叶子元素,直到排序完成。
实现过程:
(1)根据堆的有序性,使用下沉(sink)的方法,建立一个大/小根堆
(2)交换堆顶和最后一个叶子节点的值,删除最后一个叶子节点,形成一个新的完全二叉树
(3)对于新的二叉树,重复(1)和(2)两步
(4)直到最后树只有一个节点为止,所有删除的元素形成的有序序列即为排序后的序列
"""
def build_heap(arr, i, arr_len):
left_index = 2*i + 1
right_index = 2*i + 2
while left_index < arr_len:
# 如果该节点只有左子节点,则根据堆的性质,该左子节点是最后一个节点
if left_index == arr_len - 1:
if arr[i] > arr[left_index]:
arr[i], arr[left_index] = arr[left_index], arr[i]
break
# 如果该节点有左右两个子节点,则进行三个元素的大小比较,然后决定要不要下沉
if arr[left_index] < arr[right_index]:
small_index = left_index
else:
small_index = right_index
# 对比根节点与子节点中比较小的那个节点的值
if arr[small_index] < arr[i]:
arr[i], arr[small_index] = arr[small_index], arr[i]
i = small_index
left_index = 2 * i + 1
right_index = 2 * i + 2
else:
break
def heapSort(arr):
# 初始化堆,构建小根堆
arr_len = len(arr)
for i in range(arr_len - 1, -1, -1):
build_heap(arr, i, arr_len)
# 堆排序就是每次在一个有序堆得基础上删掉堆顶的元素,然后重新构建一个堆,依次循环操作
for i in range(arr_len - 1, 0, -1):
arr[0], arr[i] = arr[i], arr[0]
build_heap(arr, 0, i)
print(arr)
arr = [3, 44, 38, 5, 47, 38, 36, 26, -7, 2, 46, 4, 19, 50]
heapSort(arr)
[50, 47, 46, 44, 38, 38, 36, 26, 19, 5, 4, 3, 2, -7]
参考资料: