解锁Python优先队列----堆

        首先,堆是一种优先队列,能够以任意顺序添加对象,并随时(可能是在两次添加对象之间)找出(并删除)最小的元素。类似于列表方法min,但效率要高很多。

        其实在python中没有独立的堆类型,而只有一个包含一些堆操作函数的模块。这个模块名为heapq。

        堆特征 -> 元素不是严格,但必须保证一点:位置i处的元素总是大于位置 i // 2处的元素(反过来就是小于位置2 * i 和 2 * i + 1处的元素,i从1开始计数,即heap[0]为第一个元素)。


1.堆的主要函数及详解

In [34]: import heapq

In [35]: heapq.__all__

Out[35]: 

['heappush', 'heappop', 'heapify', 'heapreplace', 'merge', 'nlargest', 'nsmallest', 'heappushpop']


函数描述

heappush(heap, item, /)

将item压入堆中

heappop(heap, /)

从堆中弹出最小的元素

heapify(heap, /)

让列表具有堆的特性,线性时间复杂度

heapreplace(heap, item, /)

弹出最小的元素,并将item压入堆中

merge(*iterables, key=None, reverse=False)

将多个排序的输入合并为一个排序的输出。

nlargest(n, iterable, key=None)

返回iterable中n个最大的元素

nsmallest(n, iterable, key=None)

返回iterable中n个最小的元素

2.堆函数的应用

heappush && heappop:压入和弹出元素

heappop弹出最小的元素,并确保剩余元素中最小的那个位于索引0处(保持堆特征)

from heapq import *
from random import shuffle

data = list(range(10))
shuffle(data)
heap = []
for n in data:
    heappush(heap, n)

print(heap)  # [0, 1, 3, 4, 2, 8, 6, 7, 5, 9],严格满足heap[i] > heap[i//2]

print(heappop(heap))    # 0
print(heappop(heap))    # 1
print(heappop(heap))    # 2

print(heap)    # [3, 6, 4, 7, 8, 9, 5],移除元素的堆仍然具有堆特征

heapify :将列表变为合法堆

如果你的堆不是通过heappush创建的,而是自己手动构造的,请在heappush和heappop之前使用这个函数

from heapq import *

heap1 = [3, 4, 2, 6, 7, 1, 0, 9]
heapify(heap1)
print(heap1)    # [0, 4, 1, 6, 7, 3, 2, 9]

heaprepalce:从堆中弹出最小的元素,并压入一个元素

相比于依次执行函数heappop和heappush,这个函数的效率更高

from heapq import *

heap2 = [3, 4, 2, 6, 7, 1, 0, 9]
heapreplace(heap2, 8)
print(heap2)    # [1, 4, 2, 6, 7, 3, 8, 9]

nlargest && nsmallest

这两个函数分别用于找出可迭代对象iter中最大和最小的n个元素。这种任务也可通过先排序(如使用函数sorted)再切片再完成,但堆算法的速度更快,使用的内存更少(而且使用起来也更容易)。

L = [3, 4, 2, 7, 8, 0, 11, 5]
print(sorted(L))    # [0, 2, 3, 4, 5, 7, 8, 11]
print(nlargest(3, L))    # [11, 8, 7] 从大到小的顺序
print(nsmallest(3, L))    # [0, 2, 3]

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值