堆的介绍
参考 https://blog.csdn.net/qq_34270874/article/details/113091364
代码
def heap_sort(nums: list):
"""
:param nums: 无序数组
:return: None
"""
def heapify(nums: list, heap_len: int, index: int):
"""
:param nums: 维护的堆
:param heap_len: 当前堆的长度
:param index: 当前节点的下标
:return:
"""
big_index = index
# 满二叉树的左右子节点的下标
l_son = big_index * 2 + 1
r_son = big_index * 2 + 2
# 当当前节点的值小于左子树的节点就交换
# 注意这个l_son < heap_len这个条件非常重要可以避免我们产生长度溢出和在重建堆时可以避免我们和已经排好序的数字对比
#
if l_son < heap_len and nums[big_index] < nums[l_son]:
big_index = l_son
if r_son < heap_len and nums[big_index] < nums[r_son]:
big_index = r_son
# 当节点和初始值不一样的话说明有下标交换,
# 此时我们对数组的值进行交换并且进入递归继续比较
# 直到当前节点是最大的
if (big_index != index):
nums[big_index], nums[index] = nums[index], nums[big_index]
heapify(nums, heap_len, big_index)
# 从最后一个非子叶节点开始建堆
cur_index = int(len(nums)/2 - 1)
while cur_index >= 0:
heapify(nums, len(nums), cur_index)
cur_index -= 1
# 进行堆排序,循环次数为N-1
cycle_index = len(nums) - 1
while cycle_index > 0:
# 将堆顶的节点下沉到尾部
nums[cycle_index], nums[0] = nums[0], nums[cycle_index]
# 此时重新建堆每次都是从堆顶节点开始建
heapify(nums, cycle_index, 0)
cycle_index -= 1
if __name__ == "__main__":
mylist = [12, 33, 199, 0, 54, 11, 299,-1]
heap_sort(mylist)
print(f'堆排序后:{mylist}')
自己的画图过程
如果你觉得我画的难看的话可以参考https://www.cnblogs.com/sunshineliulu/p/12995910.html,电脑画的图还是比手画的好啊
时间复杂度分析
建堆时间复杂度为O(n),调整堆为O(logn),即为O(nlogn)
参考
https://www.cnblogs.com/sunshineliulu/p/12995910.html
https://github.com/imxtx/algorithms/blob/main/01-sort/05-heap/heap.c
https://www.bilibili.com/video/BV1fp4y1D7cj
https://blog.csdn.net/qq_34270874/article/details/113091364