图解-排序算法-堆排序

堆的介绍

参考 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值