Python内置的heapq模块
Python3.4版本中heapq包含了几个有用的方法:
heapq.heappush(heap,item):将item,推入heap
>>> items = [1,2,9,7,3]
>>> heapq.heappush(items,10)
>>> items
[1, 2, 9, 7, 3, 10]
>>>
heapq.heappop(heap):将heap的最小值pop出heap,heap为空时报IndexError错误
>>> heapq.heappop(items)#heap在pop时总是将最小值首先pop出
1
>>> items
[2, 3, 9, 7, 10]
>>>
heapq.heappushpop(heap,item):pop出heap中最小的元素,推入item
>>> items
[2, 3, 9, 7, 10]
>>> heapq.heappushpop(items,11)
2
>>> items
[3, 7, 9, 11, 10]
>>>
heapq.heapify(x):将list X转换为heap
>>> nums = [1,10,9,8]
>>> heap = list(nums)
>>> heapq.heapify(heap)
>>> heap
[1, 8, 9, 10]
>>>
heapq.heapreplace(heap,item):pop出最小值,推入item,heap的size不变
>>> heap
[1, 8, 9, 10]
>>> heapq.heapreplace(heap,100)
1
>>> heap
[8, 10, 9, 100]
>>
heapq.merge(*iterable):将多个可迭代合并,并且排好序,返回一个iterator
>>> heap
[8, 10, 9, 100]
>>> heap1 = [10,67,56,80,79]
>>> h = heapq.merge(heap,heap1)
>>> list(h)
[8, 10, 9, 10, 67, 56, 80, 79, 100]#需要 说明的是这里所谓的排序不是完全排序,只是两个list对应位置比较,
#将小的值先push,然后大的值再与另外一个list的下一个值比较
heapq.nlargest(n,iterable,key):返回item中大到小顺序的前N个元素,key默认为空,可以用来指定规则如:function等来处理特定的排序
itemsDict=[
{'name':'dgb1','age':23,'salary':10000},
{'name':'dgb2','age':23,'salary':15000},
{'name':'dgb3','age':23,'salary':80000},
{'name':'dgb4','age':23,'salary':80000}
]
itemsDictlarge = heapq.nlargest(3,itemsDict,lambda s:s['salary'])
print(itemsDictlarge)
[{'name': 'dgb3', 'age': 23, 'salary': 80000}, {'name': 'dgb4', 'age': 23, 'salary': 80000}, {'name': 'dgb2', 'age': 23, 'salary': 15000}]
如果没有指定key,那么就按照第一个字段来排序
heapq.nsmallest(n,iterable,key):返回item中小到大顺序的前N个元素,key默认为空,可以用来指定规则如:function等来处理特定的排序
这个函数的用法与上一个nlargest是一样的。
To create a heap, use a list initialized to[], or you can transform a populated list into a heap via functionheapify().
创建heap可以通过创建list,和使用heapify方法来实现。
这边先将基本用法罗列出来记录下,下一篇再写稍微复杂场景的程序。
1. heapq.heappush(heap, item)
将值item插入堆,并执行sift-up维持堆特性(列表末尾元素按规则向上移动)
2. heapq.heappop(heap)
将堆顶元素弹出,并执行sift-down位置堆特性(列表末尾元素赋值给list[0],并按规则向下移动)
3. heapq.heappushpop(heap, item)
相当于heappush和heappop的命令结合,先push item入堆,然后pop堆顶元素
4. heapq.heapreplace(heap, item)
和3的顺序相反,先pop堆顶元素,然后push item入堆
5. heapq.heapify(x)
将列表x转换为heap对象(inplace,线性时间)
6. heapq.merge(*iterables, key=None, reverse=False)
返回: 一个iterable可迭代对象
操作: 将可迭代对象列表*iterables合并, 相当于对一个大文件分解的多个小文件组合排序(具体原理见下方的磁盘排序)
参数:
iterables: 多个输入对象(已经从小到大排序), 例如多个已排序的小文件
key: 用于比较大小的关键字字段, 默认为None
reverse: 默认输出是从小到大, 设置为True后逆序输出
7. heapq.nlargest(n, iterable, key=None)
返回一个列表, 为根据key作为筛选条件从可迭代对象iterable中筛选的最大的n个元素
8. heapq.nsmallest(n, iterable, key=None)
返回一个列表, 为根据key作为筛选条件从可迭代对象iterable中筛选的最小的n个元素
python的heapq模块可以快速构建堆。只是heapq只能构建小根堆,不能构建大根堆。
import heapq
data2 = [1,5,3,2,9,5]
heapq.heapify(data2)
print(data2)
#输出:[1, 2, 3, 5, 9, 5]
大根堆的做法:
import heapq
ll=[1,4,2,3,5]
print(ll,'原始数组')
heapq.heapify(ll)
print(ll,'小根堆')
# 此时若想得到大顶堆
newl = [(-i, ll[i]) for i in range(len(ll))]
print(newl,'插入负数后的小根堆')
heapq.heapify(newl) #以插入的负数做小根堆,越大的数字插入的负数就越小,所以这样就相当于做了大根堆
# 此时已经按照第一个值变成了小顶堆,即变成了逆序
max_heap = list()
while newl:
_, s = heapq.heappop(newl) #删除并返回 newl中的最小元素
max_heap.append(s)
print(max_heap,'输出的大根堆')