算法之堆排序(python)

树基础知识

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
子节点(i)找父节点:(i-1)//2

堆排序过程

在这里插入图片描述

代码实现

本文以大根堆(从小到大排序)为例。

向下调整的条件:节点的左右子树都是堆,但整体(包括自身)不是堆。

建堆过程:先找到最后一个非叶子节点,与其叶子节点,先向下调整形成一个小堆。再往前倒二个非叶子节点,也向下调整形成一个小堆…最后整体满足向下调整条件,进行一次向下调整,建堆完成。

堆排序过程:用i指向堆的最后一个叶子节点,与堆顶交换位置。接下来对除了最大值的其他数进行向下调整(因为是与最后一个叶子节点交换,所以不影响堆的结构,依然满足向下调整的条件)。经过一次调整,第二大的数在堆顶,并且指向最后一个叶子节点的i-1,与堆顶交换位置…最后全部交换过后,形成从小到大排序的列表。

def sift(li,low,high):  # 向下调整
    i = low             # 指向父节点
    j = 2 * i + 1       # 指向左子节点
    tmp = li[low]       # 对堆顶进行向下调整
    while j<=high:      # 子节点要存在
        if j+1 <= high and li[j+1] > li[j]:  # 右子节点存在 且 大于左子节点则指向右子节点
            j = j+1     # 用两个子节点较大的与tmp比较(大根堆)
        if li[j] > tmp: # 子节点大于tmp
            li[i] = li[j]  # 则子节点向上移动
            i = j
            j = 2 * i + 1  # 继续向下查找调整
        else:              # 直到两个子节点都小于tmp,所以tmp可以放这
            li[i] = tmp
            break
    else:  # 若i已指向叶子节点跳出循环,tmp就放这
        li[i] = tmp

def heap_sort(li):
    n = len(li)
    for i in range((n-1-1)//2,-1,-1):  # 建堆,n-1指最后一个叶子节点,(叶子节点-1)//2找到父节点。
        sift(li,i,n-1)  # i是所有小堆父节点,这边统一用n-1可以省去每次求小堆的high
    for i in range(n-1,-1,-1):  # 排序,i指向当前堆最后一个叶子节点
        li[0],li[i] = li[i],li[0]  # 最后一个叶子节点和堆顶交换
        sift(li,0,i-1)          # 现在节点左右均为堆,进行一次向下调整

li = [9,5,2,4,1,7,6,3,8]
print(li)
heap_sort(li)
print(li)

在这里插入图片描述
堆排序时间复杂度:O(nlogn)

Python堆的内置模块

在这里插入图片描述
heapq.heapify(li) 建(小根)堆
heapq.heappop(li) 弹出最小值(堆顶)

heapq相关函数:

heapify’:将一个列表转化为堆 (Transform list into a heap)

heappop’:pop最小的item,保持堆不变(Pop the smallest item off the heap, maintaining the heap invariant.)

heappush’:heappush(heap, item) 压入item,保持堆不变( Push item onto heap, maintaining the heap invariant.)

heappushpop’:heappushpop(heap, item),先heappush(item),再headpop最小元素

heapreplace’:heapreplace(heap, item) ,返回最小元素,添加item

merge’:heapq.merge(*iterables, key=None, reverse=False) ,合并多个列表为有序列表

nlargest’:heapq.nlargest(n, iterable, key=None),寻找列表中最大的n个元素

nsmallest’:heapq.nsmallest(n, iterable, key=None),寻找列表中最小的n个元素
————————————————
版权声明:本文为CSDN博主「frostjsy」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u013069552/article/details/107350595

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值