问题

怎样实现一个按优先级排序的队列? 并且在这个队列上面每次 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 "", line 1, in

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 "", line 1, in

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实现优先级队列的资料请关注脚本之家其它相关文章!

python优先级排序_Python实现一个优先级队列的方法相关推荐

  1. python实现排序_python实现以及所有排序大总结【转】

    原址 一.概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存. 我们这里说说八大排序就是内部排序. ...

  2. python set 排序_python set 排序_如何在Python中使用sorted()和sort()

    点击"蓝字"关注我们 ?"Python基础知识" 大卫·丰达科夫斯基  著 18财税3班 李潇潇    译 日期:2019年5月6日 一. 使用sorted() ...

  3. python数字排序_python按照列表元素中的数字大小排序

    [Human Sorting] 常见的python排序只需要一个sort或者sorted函数即可.但是默认采用的是字典序,这会带来一个问题,如果列表中的元素是字符串+数字组合,往往无法得到我们想要的排 ...

  4. python dict排序_python 字典(dict)按键和值排序

    python 字典(dict)的特点就是无序的,按照键(key)来提取相应值(value),如果我们需要字典按值排序的话,那可以用下面的方法来进行: 1 下面的是按照value的值从大到小的顺序来排序 ...

  5. python结构排序_Python数据结构(七)排序算法 上

    Python数据结构(七)排序算法 上 上回: 本文的重点不是代码,而是带着大家分析每一个排序算法背后的思想以及使用到的数据结构.很多时候不是我们想不出算法该如何去写,而是题目并没有指定特定的数据结构 ...

  6. python 拓扑排序_Python 拓扑排序

    Python 拓扑排序 对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G) ...

  7. python 列表排序_python列表排序有哪些

    python列表排序:1.冒泡排序,是一种简单的排序算法,它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来:2.插入排序,通过构建有序序列,对于未排序数据,在已排序序列中 ...

  8. python子进程通信_python执行子进程实现进程间通信的方法

    本文实例讲述了python执行子进程实现进程间通信的方法.分享给大家供大家参考.具体实现方法如下: a.py: import subprocess, time subproc = subprocess ...

  9. python打印日历_python输出指定月份日历的方法

    python输出指定月份日历的方法 本文实例讲述了python输出指定月份日历的方法.分享给大家供大家参考.具体实现方法如下: #!/usr/bin/python import calendar ca ...

最新文章

  1. Go 变量及基本数据类型1
  2. linux下tomcat6无法显示图片验证码 少了图形插件
  3. 长期价值三重进阶,同程艺龙加速“破局”OTA
  4. C++学习之路 | PTA乙级—— 1048 数字加密 (20 分)(精简)
  5. 【数据库系统】数据模型、模式、数据的概念辨析
  6. 1313 质因数分解
  7. js之数据类型的比较
  8. 【kafka】 kafka如何设置指定分区进行发送和消费
  9. 《Python Enhancement Proposal #8》要点 学习摘录
  10. jquery实现app开发闹钟功能_商城app开发价格及功能列表
  11. 2021必收藏!Java编程技巧之单元测试用例编写流程
  12. Educoder 二维码名片制作
  13. 用python对我和女票的聊天记录生成心形词云
  14. 3分钟教你如何用代码向心爱的女生表白
  15. html表格如何创建搜索,6.如何创建HTML表格
  16. HDU - 胜利大逃亡(搜索)
  17. 前端设置div的显示与隐藏
  18. BI工具调研之——帆软
  19. 写作三件套(VScode Miktex Latex Workshop)入门三大坑
  20. java 科学计数法转换为普通数字_如何将计算器上的科学记数法转换为普通记数法?...

热门文章

  1. Python进程multiprocessing. Process()的使用
  2. 精致全景图 | 程序是如何运行起来的
  3. 面试官问:ZooKeeper是强一致的吗?怎么实现的?
  4. 如何学习 Go 语言的核心知识
  5. Python中的高阶变量
  6. 编解码再进化:Ali266与下一代视频技术
  7. 腾讯云快直播——超低延迟直播技术方案及应用
  8. VVC专利池最新进展:MC-IF正在召集专利拥有者
  9. 效能优化实践:C/C++单元测试万能插桩工具
  10. 正式启动|2020腾讯犀牛鸟云开发校园技术布道师养成计划