本节书摘来自异步社区《Python Cookbook(第3版)中文版》一书中的第1章,第1.5节,作者[美]David Beazley , Brian K.Jones,陈舸 译,更多章节内容可以访问云栖社区“异步社区”公众号查看。

1.5 实现优先级队列

1.5.1 问题

我们想要实现一个队列,它能够以给定的优先级来对元素排序,且每次pop操作时都会返回优先级最高的那个元素。

1.5.2 解决方案

下面的类利用heapq模块实现了一个简单的优先级队列:

import heapq
class PriorityQueue:def __init__(self):self._queue = []self._index = 0def push(self, item, priority):heapq.heappush(self._queue, (-priority, self._index, item))self._index += 1def 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)返回的顺序同它们插入到队列时的顺序相同。

1.5.3 讨论

上面的代码片段的核心在于heapq模块的使用。函数heapq.heappush()以及heapq.heappop()分别实现将元素从列表_queue中插入和移除,且保证列表中第一个元素的优先级最低(如1.4节所述)。heappop()方法总是返回“最小”的元素,因此这就是让队列能弹出正确元素的关键。此外,由于push和pop操作的复杂度都是O(logN),其中N代表堆中元素的数量,因此就算N的值很大,这些操作的效率也非常高。

在这段代码中,队列以元组(-priority, index, item)的形式组成。把priority取负值是为了让队列能够按元素的优先级从高到低的顺序排列。这和正常的堆排列顺序相反,一般情况下堆是按从小到大的顺序排序的。

变量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()
>>>

通过引入额外的索引值,以(prioroty, 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 Cookbook(第3版)中文版》——1.5 实现优先级队列相关推荐

  1. python cookbook pdf下载-Python Cookbook 第3版 中文版.pdf

    作 者 :(美)比斯利,(美)琼斯著 出版发行 : 北京:人民邮电出版社 , 2015.05 ISBN号 :978-7-115-37959-7 页 数 : 684 原书定价 : 108.00 开本 : ...

  2. Python Cookbook(第3版)中文版:15.17 传递文件名给C扩展

    15.17 传递文件名给C扩展¶ 问题¶ 你需要向C库函数传递文件名,但是需要确保文件名根据系统期望的文件名编码方式编码过. 解决方案¶ 写一个接受一个文件名为参数的扩展函数,如下这样: static ...

  3. Python Cookbook(第3版)中文版:15.18 传递已打开的文件给C扩展

    15.18 传递已打开的文件给C扩展¶ 问题¶ 你在Python中有一个打开的文件对象,但是需要将它传给要使用这个文件的C扩展. 解决方案¶ 要将一个文件转换为一个整型的文件描述符,使用 PyFile ...

  4. python书籍推荐:Python Cookbook第三版中文

    所属网站分类: 资源下载 > python电子书 作者:熊猫烧香 链接:http://www.pythonheidong.com/blog/article/44/ 来源:python黑洞网 内容 ...

  5. python序列中各元素之间存在顺序关系_《Python Cookbook(第3版)中文版》——1.10 从序列中移除重复项且保持元素间顺序不变-阿里云开发者社区...

    本节书摘来自异步社区<Python Cookbook(第3版)中文版>一书中的第1章,第1.10节,作者[美]David Beazley , Brian K.Jones,陈舸 译,更多章节 ...

  6. 《Python Cookbook(第3版)中文版》——1.9 在两个字典中寻找相同点

    本节书摘来自异步社区<Python Cookbook(第3版)中文版>一书中的第1章,第1.9节,作者[美]David Beazley , Brian K.Jones,陈舸 译,更多章节内 ...

  7. 不属于python标准库的是_《Python Cookbook(第2版)中文版》——1.10 过滤字符串中不属于指定集合的字符-阿里云开发者社区...

    本节书摘来自异步社区<Python Cookbook(第2版)中文版>一书中的第1章,第1.10节,作者[美]Alex Martelli , Anna Martelli Ravenscro ...

  8. 【好书分享】《Python Cookbook》第三版 中文版(带书签)

    [书籍介绍] 带完整书签 书籍中的文字可复制 [获取方式] <Python Cookbook>第三版 中文版.rar: https://url00.ctfile.com/f/1936360 ...

  9. python cookbook 中文版 第 3 版-《Python Cookbook》第三版中文版

    人生苦短,我用 python! 我一直坚持使用 python3,因为它代表了python的未来.虽然向后兼容是它的硬伤,但是这个局面迟早会改变的, 而且python3的未来需要每个人的帮助和支持. 目 ...

最新文章

  1. STM32学习笔记9(SysTick滴答时钟)
  2. RHEL5 install
  3. 用python画图代码简单-【Matplotlib】利用Python进行绘图
  4. 【AI产品】超长文详解作业帮产品逻辑和技术原理
  5. shiro+springboot分析思路
  6. IntelliTrace 调试、定位异常
  7. `if __name__ == __main__`模块运行代码管理
  8. linux 关闭redis 命令_面试必问的 Redis:RDB、AOF、混合持久化
  9. Q91:真实地模拟透明材质(Realistic Transparency)(2)——Triangle Meshes
  10. RPC框架dubbo架构原理及使用说明
  11. 易语言使用超级模块 全局热键
  12. css 入场动画_进入css3动画世界(一)
  13. 知道君推荐给大家一些写论文、搞科研、读大学必备的30款软件。
  14. 苹果手机小圆点怎么设置?悬浮球设置,轻松学会
  15. Mac 超详细入门指南,备用!
  16. 题都城南庄---中华诗词-唐五代-崔护
  17. 制作ipad iphone充电线
  18. 什么是Nofollow
  19. 异或、异或和 的性质及应用总结
  20. 笔记 shell基础应用,texturePacker 命令批量打包打包

热门文章

  1. linux 路由访问不了php文件,linux系统nginx服务器不能访问php文件问题
  2. python 怎么样才有output_[学]Python用户手册笔记_4_Input and Output
  3. oracle24550,ORA-24550: signal received:这个问题的原因及解决办法
  4. oracle向右削减和补全,b操纵序列削减Oracle数据库开辟工作量-开辟技术/b[Oracle防范]...
  5. python中xlrd写操作_Python读写操作Excel模块_xlrd_xlwt_xlutils
  6. Vue3 插槽使用详解
  7. 工作占用了太多私人时间_一本正经聊驾驶 | 汽车真的为我们节约时间了吗
  8. 2020年9月北京计算机等级考试考点,2020年9月北京计算机等级考试考点设置
  9. python自动化测试学习有用吗_python自动化测试学习-UnitTest/PyUnit的用法介绍
  10. Android的Animator动画(平移,渐隐,旋转,缩放)