问题
怎样实现一个按优先级排序的队列? 并且在这个队列上面每次 pop 操作总是返回优先级最高的那个元素
解决方案
下面的类利用 heapq
模块实现了一个简单的优先级队列:
import heapq class PriorityQueue: def __init__(self): self._queue = [] self._index = 0 def push(self, item, priority): heapq.heappush(self._queue, (-priority, self._index, item)) self._index += 1 def pop(self): return heapq.heappop(self._queue)[-1]
下面是它的使用方式:
> class Item: ... def __init__(self, name): ... self.name = name ... def __repr__(self): ... return 'Item({!r})'.format(self.name) ... > q = PriorityQueue() > q.push(Item('foo'), 1) > q.push(Item('bar'), 5) > q.push(Item('spam'), 4) > q.push(Item('grok'), 1) > q.pop() Item('bar') > q.pop() Item('spam') > q.pop() Item('foo') > q.pop() Item('grok') >
仔细观察可以发现,第一个 pop()
操作返回优先级最高的元素。 另外注意到如果两个有着相同优先级的元素( foo
和 grok
),pop 操作按照它们被插入到队列的顺序返回的。
讨论
这一小节我们主要关注 heapq
模块的使用。 函数 heapq.heappush()
和 heapq.heappop()
分别在队列 _queue
上插入和删除第一个元素, 并且队列 _queue
保证第一个元素拥有最高优先级( 1.4 节已经讨论过这个问题)。 heappop()
函数总是返回”最小的”的元素,这就是保证队列pop操作返回正确元素的关键。 另外,由于 push 和 pop 操作时间复杂度为 O(log N),其中 N 是堆的大小,因此就算是 N 很大的时候它们运行速度也依旧很快。
在上面代码中,队列包含了一个 (-priority, index, item)
的元组。 优先级为负数的目的是使得元素按照优先级从高到低排序。 这个跟普通的按优先级从低到高排序的堆排序恰巧相反。
index
变量的作用是保证同等优先级元素的正确排序。 通过保存一个不断增加的 index
下标变量,可以确保元素按照它们插入的顺序排序。 而且, index
变量也在相同优先级元素比较的时候起到重要作用。
为了阐明这些,先假定 Item
实例是不支持排序的:
> a = Item('foo') > b = Item('bar') > a < b Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unorderable types: Item() < Item() >
如果你使用元组 (priority, item)
,只要两个元素的优先级不同就能比较。 但是如果两个元素优先级一样的话,那么比较操作就会跟之前一样出错:
> a = (1, Item('foo')) > b = (5, Item('bar')) > a < b True > c = (1, Item('grok')) > a < c Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unorderable types: Item() < Item() >
通过引入另外的 index
变量组成三元组 (priority, index, item)
,就能很好的避免上面的错误, 因为不可能有两个元素有相同的 index
值。Python 在做元组比较时候,如果前面的比较已经可以确定结果了, 后面的比较操作就不会发生了:
> a = (1, 0, Item('foo')) > b = (5, 1, Item('bar')) > c = (1, 2, Item('grok')) > a < b True > a < c True >
如果你想在多个线程中使用同一个队列,那么你需要增加适当的锁和信号量机制。 可以查看 12.3 小节的例子演示是怎样做的。
heapq
模块的官方文档有更详细的例子程序以及对于堆理论及其实现的详细说明。
以上就是Python实现一个优先级队列的方法的详细内容,更多关于Python实现优先级队列的资料请关注其它相关文章!
RTX 5090要首发 性能要翻倍!三星展示GDDR7显存
三星在GTC上展示了专为下一代游戏GPU设计的GDDR7内存。
首次推出的GDDR7内存模块密度为16GB,每个模块容量为2GB。其速度预设为32 Gbps(PAM3),但也可以降至28 Gbps,以提高产量和初始阶段的整体性能和成本效益。
据三星表示,GDDR7内存的能效将提高20%,同时工作电压仅为1.1V,低于标准的1.2V。通过采用更新的封装材料和优化的电路设计,使得在高速运行时的发热量降低,GDDR7的热阻比GDDR6降低了70%。
更新日志
- 群星《前途海量 电影原声专辑》[FLAC/分轨][227.78MB]
- 张信哲.1992-知道新曲与精丫巨石】【WAV+CUE】
- 王翠玲.1995-ANGEL【新艺宝】【WAV+CUE】
- 景冈山.1996-我的眼里只有你【大地唱片】【WAV+CUE】
- 群星《八戒 电影原声带》[320K/MP3][188.97MB]
- 群星《我的阿勒泰 影视原声带》[320K/MP3][139.47MB]
- 纪钧瀚《胎教古典音乐 钢琴与大提琴的沉浸时光》[320K/MP3][148.91MB]
- 刘雅丽.2001-丽花皇后·EMI精选王【EMI百代】【FLAC分轨】
- 齐秦.1994-黄金十年1981-1990CHINA.TOUR.LIVE精丫上华】【WAV+CUE】
- 群星.2008-本色·百代音乐人创作专辑【EMI百代】【WAV+CUE】
- 群星.2001-同步过冬AVCD【环球】【WAV+CUE】
- 群星.2020-同步过冬2020冀待晴空【环球】【WAV+CUE】
- 沈雁.1986-四季(2012梦田复刻版)【白云唱片】【WAV+CUE】
- 纪钧瀚《胎教古典音乐 钢琴与大提琴的沉浸时光》[FLAC/分轨][257.88MB]
- 《国语老歌 怀旧篇 3CD》[WAV/分轨][1.6GB]