python之堆heapq模块
堆是一种特殊的树形结构,通常我们所说的堆的数据结构指的是完全二叉树,并且根节点的值小于等于该节点所有子节点的值。
堆是非线性的树形的数据结构,有两种堆,最大堆与最小堆。( heapq库中的堆默认是最小堆)
- 最大堆,树种各个父节点的值总是大于或等于任何一个子节点的值。
- 最小堆,树种各个父节点的值总是小于或等于任何一个子节点的值。
我们一般使用二叉堆来实现优先级队列,它的内部调整算法复杂度为logN。
堆是一个二叉树,其中最小堆每个父节点的值都小于或等于其所有子节点的值。
整个最小堆的最小元素总是位于二叉树的根节点。
常用方法 heappush(heap,item)往堆中插入一条新的值heappop(heap)从堆中弹出最小值heapreplace(heap,item)从堆中弹出最小值,并往堆中插入item 【注意:与heappushpop(heap,item)的区别在于,顺序不同,这里是先进行删除,后压入堆】heappushpop(heap,item)Python3中的heappushpop更高级 【注意:相当于先操作了heappush(heap,item),然后操作heappop(heap)】heapify(x)以线性时间将一个列表转化为堆 【直接会对列表进行排序变成堆排序】merge(*iterables,key=None,reverse=False)合并对个堆,然后输出nlargest(n,iterable,key=None)返回可枚举对象中的n个最大值并返回一个结果集listnsmallest(n,iterable,key=None)返回可枚举对象中的n个最小值并返回一个结果集list 常用方法示例:import heapq
import random
def test():
li = list(random.sample(range(100), 6))
print(li)
n = len(li)
# nlargest
print("nlargest:", heapq.nlargest(n, li))
# nsmallest
print("nsmallest:", heapq.nsmallest(n, li))
# heapify
print('original list is', li)
heapq.heapify(li)
print('heapify list is', li)
# heappush & heappop
heapq.heappush(li, 105)
print('pushed heap is', li)
heapq.heappop(li)
print('popped heap is', li)
# heappushpop & heapreplace
heapq.heappushpop(li, 130) # heappush -> heappop
print('heappushpop', li)
heapq.heapreplace(li, 2) # heappop -> heappush
print('heapreplace', li)
test()
运行结果:
heapq模块中有几张方法进行排序:
方法一:
import heapq
def heap_sort(iterable):
heap = []
for i in iterable:
heapq.heappush(heap, i)
return [heapq.heappop(heap) for _ in range(len(heap))]
if __name__ == '__main__':
li = [30, 40, 60, 10, 20, 50]
print(heap_sort(li))
运行结果:
方法二(使用nlargest或nsmallest):
import heapq
li = [30, 40, 60, 10, 20, 50]
# nlargest
n = len(li)
print("nlargest:", heapq.nlargest(n, li))
# nsmallest
print("nsmallest:", heapq.nsmallest(n, li))
运行结果:
方法三(使用heapify):
import heapq
def heap_sort(list):
print(list)
heapq.heapify(list)
print(list)
heap = []
while (list):
heap.append(heapq.heappop(list))
print(heap)
li[:] = heap
print(li)
if __name__ == '__main__':
li = [30, 40, 60, 10, 20, 50]
heap_sort(li)
运行结果:
需求:实现任务的添加,删除(相当于任务的执行),修改任务优先级
from heapq import *
import itertools
pq = [] # list of entries arranged in a heap
entry_finder = {} # mapping of tasks to entries
REMOVED = '' # placeholder for a removed task
counter = itertools.count() # unique sequence count
def add_task(task, priority=0):
'Add a new task or update the priority of an existing task'
if task in entry_finder:
remove_task(task)
count = next(counter)
entry = [priority, count, task]
entry_finder[task] = entry
heappush(pq, entry)
def remove_task(task):
'Mark an existing task as REMOVED. Raise KeyError if not found.'
entry = entry_finder.pop(task)
entry[-1] = REMOVED
def pop_task():
'Remove and return the lowest priority task. Raise KeyError if empty.'
while pq:
priority, count, task = heappop(pq)
if task is not REMOVED:
del entry_finder[task]
return task
raise KeyError('pop from an empty priority queue')