python 优先队列_python中使用优先队列

相信对于队列的概念大家都不会陌生,这种先入先出的数据结构应用很广泛,像一般的生产消费都会用到队列,关于Queue的用法介绍可以参考我之前的文章 python中的Queue与多进程(multiprocessing)还有栈,栈是一种先入后出的数据结构,面优先队列有别于普通的队列与栈,在实现上,它一般通过堆这一数据结构,而堆其实是一种完全二叉树,它会对进入容器的元素进行排序(根据事先指定的规则),出队的顺序则会是二叉树的根结点代表的元素。接下来介绍几种优先队列的实现。

通过heapq模块

heapq是一个二叉堆的实现,它内部使用内置的list对象,它无论插入还是获取最小元素复杂度都在O(log n)。这里主要用到它的heappushheappop方法,heappush 方法需要传入两个参数,一个是列表(list),另外是一个对象,这里的对象须是可比较对象,就是它可以通过cmp方法来比较大小,以下是在 python2 中的代码实现

#coding:gbk
import heapqtasks = []
heapq.heappush(tasks,(10,'aaa'))
heapq.heappush(tasks,(40,'bbb'))
heapq.heappush(tasks,(30,'ccc'))
heapq.heappush(tasks,(20,'ddd'))while tasks:task = heapq.heappop(tasks)print(task)

运行结果如下

(10, 'aaa')
(20, 'ddd')
(30, 'ccc')
(40, 'bbb')

可以看到,我放入 tasks 列表里的元素是个 set 对象,对象第一个元素是个 int 类型的数字,如果使用cmp方法进行比较的话

>>> cmp(10,20)
-1
>>> cmp(10,10)
0
>>> cmp(10,5)
1

对于小于,等于,大于分别返回的是-1,0,1,其实这也是在定义sorted的实现方法,

>>> sorted([(10,'aaaa'),(30,'bbbb')])
[(10, 'aaaa'), (30, 'bbbb')]
>>> sorted([(40,'aaaa'),(30,'bbbb')])
[(30, 'bbbb'), (40, 'aaaa')]
>>> sorted([(30,'aaaa'),(30,'bbbb')])
[(30, 'aaaa'), (30, 'bbbb')]
>>> sorted([(30,'bbbb'),(30,'abbb')])
[(30, 'abbb'), (30, 'bbbb')]

可以看到在sorted方法里,它的排序算法是通过比较第一个元素的大小,小的排在前面,第一个元素相同再比较第二个元素,看返回之前的代码,heapq.heappush 将 set 元素添加到列表元素以后,将对其进行重新排序,将最小的放在前面,于是就得到了上面的打印结果。

上面是使用python自带的 set 数据结构,可否自定义一种类型呢,比较在实现生活中,在上班的第一件事是给自已写一下今天要完成哪些事情,其实哪些事情的优先级比较高就是先做哪些事情,其实在上面也说到 sorted 方法,这个方法其实就是在调用对象的 __cmp__ 方法,好么我可以单独定义一个带有 __cmp__ 方法的对象则可以实现优先队列中的对象排序。

#coding:gbk
import heapq# 使用heapq实现优先队列
#定义一个可比较对象
class CompareAble:def __init__(self,priority,jobname):self.priority = priorityself.jobname = jobnamedef __cmp__(self, other):if self.priority < other.priority:return -1elif self.priority == other.priority:return 0else:return 1joblist = []heapq.heappush(joblist,CompareAble(80,'eat'))
heapq.heappush(joblist,CompareAble(70,'a write plan2'))
heapq.heappush(joblist,CompareAble(70,'write plan'))
heapq.heappush(joblist,CompareAble(90,'sleep'))
heapq.heappush(joblist,CompareAble(100,'write code'))while joblist:task = heapq.heappop(joblist)print(task.priority,task.jobname)

运行结果:

(70, 'write plan')
(70, 'a write plan2')
(80, 'eat')
(90, 'sleep')
(100, 'write code')

上面的compareAble 类初始化有两个参数,一个是优先级,一个是事情的名字,我这里定义的是优先级数值越小排序越靠前,也可以定义成数值越大越靠前。如果优先级相同,则按照插入顺序来排序。

通过Queue,PriorityQueue类型实现

这个优先级队列内部使用了heapq,不同的是PriorityQueue的操作是同步的,提供锁操作,支持并发的生产者和消费者,而且它的接口更加友好,它继承自Queue,所以好多Queue的方法可以直接使用

#coding:gbk
import heapq
from queue import Queue,PriorityQueue# 使用heapq实现优先队列
#定义一个可比较对象
class CompareAble:def __init__(self,priority,jobname):self.priority = priorityself.jobname = jobnamedef __cmp__(self, other):if self.priority < other.priority:return -1elif self.priority == other.priority:return 0else:return 1pq = PriorityQueue()
pq.put(CompareAble(80,'eat'))
pq.put(CompareAble(70,'a write plan2'))
pq.put(CompareAble(70,'write plan'))
pq.put(CompareAble(90,'sleep'))
pq.put(CompareAble(100,'write code'))while pq.qsize()!= 0:task = pq.get_nowait()print(task.jobname,task.priority)

接下来通过一个生产消费的实例来说明优先队列的使用

有三个生产者和二个消费者,生产者向队列中生产有优先级的任务,消费者也是优先消费高级别的任务

#coding:gbk
from queue import PriorityQueue
import time
import random
import threading# 使用heapq实现优先队列
#定义一个可比较对象
class CompareAble:def __init__(self,priority,jobname):self.priority = priorityself.jobname = jobnamedef __cmp__(self, other):if self.priority < other.priority:return -1elif self.priority == other.priority:return 0else:return 1tasks = [(i, "do task %s"%i) for i in range(10,100,5)]
def produce(pq,lock):while True:lock.acquire()task = tasks[random.randint(0,len(tasks)-1)]print('put %s %s in pq'%(task[0],task[1]))pq.put(CompareAble(task[0],task[1]))time.sleep(1)lock.release()def consumer(pq,lock):while True:lock.acquire()task = pq.get_nowait()if task:print(task.priority, task.jobname)else:time.sleep(1)lock.release()if __name__ == '__main__':task_queue = PriorityQueue()task_lock = threading.Lock()for i in range(3):t = threading.Thread(target=produce,args=(task_queue,task_lock))t.setDaemon(False)t.start()for i in range(2):t = threading.Thread(target=consumer,args=(task_queue,task_lock))t.setDaemon(False)t.start()

运行结果:

put 30 do task 30 in pq
put 20 do task 20 in pq
put 75 do task 75 in pq
(20, 'do task 20')
(30, 'do task 30')
put 20 do task 20 in pq
put 15 do task 15 in pq
put 70 do task 70 in pq
(15, 'do task 15')
(20, 'do task 20')
put 85 do task 85 in pq
put 10 do task 10 in pq
put 30 do task 30 in pq
(10, 'do task 10')
(30, 'do task 30')
put 70 do task 70 in pq
put 10 do task 10 in pq
put 55 do task 55 in pq
(10, 'do task 10')
(55, 'do task 55')
put 20 do task 20 in pq
put 45 do task 45 in pq
put 75 do task 75 in pq
(20, 'do task 20')
(45, 'do task 45')
put 40 do task 40 in pq
put 40 do task 40 in pq 
...

可以看出,每次取出来的都是当前队列中 priority 最小的数

python3 中的使用方法

上面的代码无法在python3中运行,主要是因为python3没有cmp方法,运行得到的异常信息是

TypeError: unorderable types: CompareAble() < CompareAble()

就是没有一个cmp 的操作

需要在上面定义一个 __lt__ 方法

#coding:gbk
from queue import PriorityQueue
import time
import random
import threading# 使用heapq实现优先队列
#定义一个可比较对象
class CompareAble:def __init__(self,priority,jobname):self.priority = priorityself.jobname = jobname# def __cmp__(self, other):#     if self.priority < other.priority:#         return -1#     elif self.priority == other.priority:#         return 0#     else:#         return 1def __lt__(self, other):if self.priority <= other.priority:return Falseelse:return Truetasks = [(i, "do task %s"%i) for i in range(10,100,5)]
def produce(pq,lock):while True:lock.acquire()task = tasks[random.randint(0,len(tasks)-1)]print('put %s %s in pq'%(task[0],task[1]))pq.put(CompareAble(task[0],task[1]))lock.release()time.sleep(1)def consumer(pq,lock):while True:lock.acquire()try:if pq.empty():continuetask = pq.get_nowait()if task:print(task.priority, task.jobname)finally:lock.release()time.sleep(1)if __name__ == '__main__':task_queue = PriorityQueue()task_lock = threading.Lock()for i in range(3):t = threading.Thread(target=produce,args=(task_queue,task_lock))t.setDaemon(False)t.start()for i in range(2):t = threading.Thread(target=consumer,args=(task_queue,task_lock))t.setDaemon(False)t.start()

上面的代码我修改了一点对于大小的判断,与之前的是反的,这里 priority 越大则越先返回,上面的代码在 python2 中也可以运行,所有如果为了兼容性可以选择定义使用 __lt__ 方法。

参考文章
用Python实现优先级队列的3种方法
python的优先队列示例

更多文章请点击查看我的个人博客

杨彦星 | 序语程言​www.yangyanxing.com
6ca4259d80ffc35724beb2ebc2e09a4a.png

也欢迎关注我的个人公众账号 序语程言

8176b36b5cd315c2714ed764e6d6c93b.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/352176.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JHipster入门,第2部分

所以你回来了&#xff01; 在本系列的最后一部分中 &#xff0c;我们采用了单片路线创建了一个JHipster应用程序。 这是红色药丸路线&#xff1b; 生活与您习惯的差不多。 但是也许您喜欢挑战。 也许您想超越红色药丸并尝试蓝色药丸。 在这种情况下&#xff0c;Blue Pill是微服…

由于html元素加载导致的问题

js中要求执行的事件是在完全加载完&#xff0c;但由于本地环境测试一直没发现出问题&#xff0c;在上线后由于网络延迟导致元素加载慢&#xff0c;而事件执行完&#xff0c;没达到预期目标。 这时就需要用到属性 readyState readyState 属性返回当前文档的状态&#xff08;载入…

Linux下MySQL数据库常用基本操作 一

1、显示数据库 show databases; 2、选择数据库 use 数据库名; 3、显示数据库中的表 show tables; 4、显示数据表的结构 describe 表名; 5、显示表中记录 SELECT * FROM 表名 6、建库 create databse 库名; 7、建表 create table 表名 (字段设定列表)&#xff1b;mysql> cr…

C语言读取txt文档中的数据

1.说明 txt文档中的数据格式&#xff1a;前后数据用空格隔开&#xff1b;数据来源&#xff1a;matlab读取彩图的R、G、B三层的像素值&#xff0c;分别存放在三个txt文档中&#xff0c;用C读取到一维数组。动态申请数组&#xff0c;还是需要预先知道数组的大小&#xff0c;比静态…

cpickle支持的python版本_Python序列化模块pickle和cPickle

Python的序列化是指把变量从内存中变为可以储存/传输的数据/文件的过程. 在Python中叫pickling&#xff0c;在其他语言中也被称之为serialization&#xff0c;marshalling&#xff0c;flattening等等&#xff0c;都是一个意思。序列化之后&#xff0c;就可以把序列化后的内容写…

Intellij IDEA 4种配置热部署的方法

Intellij IDEA 4种配置热部署的方法 热部署可以使的修改代码后&#xff0c;无须重启服务器&#xff0c;就可以加载更改的代码。 第1种&#xff1a;修改服务器配置&#xff0c;使得IDEA窗口失去焦点时&#xff0c;更新类和资源 菜单Run -> EditConfiguration , 然后配置指定服…

mysql启动报错:Another MySQL daemon already running with the same unix socket.

[rootlocalhost ~]#/etc/init.d/mysqld restart Stopping mysqld: [ OK ] Another MySQL daemon already running with the same unix socket. Starting mysqld: [FAILED] 原因多个Mys…

malloc申请一维动态数组的错误

正确写法&#xff1a;int *tmp ( int * )malloc( H*W*sizeof(int) ); float *tmp ( float * )malloc( H*W*sizeof(float) ); double *tmp ( double * )malloc( H*W*sizeof(double) ); 错误写法&#xff1a;double *tmp ( double * )malloc( H*W*sizeof(double * ) ); 错…

java检查注入sql框架_Java:检查器框架

java检查注入sql框架我在JavaOne 2012上 了解的有趣的工具之一是Checker Framework 。 Checker Framework的网页之一 指出 &#xff0c;Checker Framework“增强了Java的类型系统&#xff0c;使其更加强大和有用”&#xff0c;从而使软件开发人员“能够检测并防止Java程序中的错…

jqc3ff继电器引脚图_电气元件中间继电器的知识全面解读,欢迎电工朋友收藏!...

继电器(英文&#xff1a;Relay)&#xff0c;也称电驿&#xff0c;是一种电子控制器件&#xff0c;它具有控制系统(又称输入回路)和被控制系统(又称输出回路)&#xff0c;通常应用于自动控制电路中&#xff0c;它实际上是用较小的电流去控制较大电流的一种“自动开关”。故在电路…

]remove-duplicates-from-sorted-list-ii (删除)

题意略&#xff1a; 思路都在注解里&#xff1a; #include<iostream> #include<cstdio> using namespace std;struct ListNode {int val;ListNode *next;ListNode(int x) : val(x), next(NULL) {}};class Solution {public:ListNode *deleteDuplicates(ListNode *h…

C语言动态数组建立方法

动态数组是指在声明时没有确定数组大小的数组&#xff0c;即忽略圆括号中的下标&#xff1b;当要用它时&#xff0c;可随时用ReDim语句&#xff08;C语言中用malloc语句&#xff09;重新指出数组的大小。使用动态数组的优点是可以根据用户需要&#xff0c;有效利用存储空间。 动…

Linux小宝典之理解Chroot模式

Chroot 在 Linux 系统中发挥了根目录的切换工作&#xff0c;同时带来了系统的安全性等好处。本文通过编写 chroot 来理解 chroot 的作用和好处&#xff0c;这不仅有助于更好的使用 chroot&#xff0c;同时加深了对 Linix 系统初始 RAM 磁盘工作的认识。 chroot&#xff0c;即 …

jHipster入门,第1部分

因此&#xff0c;您想保持技术的领先地位&#xff0c;但对所有活动部件感到不知所措。 你真幸运&#xff01; 这是jHipster发光的地方。 如果您喜欢Ruby on Rails或Grails的方法来快速启动和运行应用程序&#xff0c;那么这可能是适合您的选择。 jHipster旨在使设置应用程序变…

python每隔30s检查一次_用Python写一个“离线语音提示器”来提醒我们别忘记了时间...

前言本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理。环境&#xff1a;Win7系统&#xff0c;外网未连接&#xff0c;主机接有返听音箱。准备&#xff1a;这里明显要用语音合成&#xff0c;既然是离线状态…

vue中map组件

分享一个比较好用的基于百度地图的vue组件。也有react版本的&#xff0c;可以自行选择。 分享链接&#xff1a;点击转载于:https://www.cnblogs.com/yunnex-xw/p/9996600.html

MATLAB中mean的用法

1、函数功能 求数组的平均数或者均值 2、使用方法 ① M mean(A) 返回沿数组中不同维的元素的平均值。 如果A是一个向量&#xff0c;mean(A)返回A中元素的平均值。 如果A是一个矩阵&#xff0c;mean(A)将其中的各列视为向量&#xff0c;把矩阵中的每列…

Linux中profile、bashrc、bash_profile之间的区别和联系

/etc/profile:此文件为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行.并从/etc/profile.d目录的配置文件中搜集shell的设置. 英文描述为&#xff1a; # /etc/profile # System wide environment and startup programs, for login setup # Functions and alias…

python selenium 等待元素出现_Python Selenium等待加载几个元素

考虑到Mr.E.和Arran的评论&#xff0c;我在CSS选择器上完全遍历了列表。棘手的部分是关于我自己的列表结构和标记(更改类等)&#xff0c;以及动态创建所需的选择器并在遍历期间将它们保存在内存中。我通过搜索任何未加载状态的内容来处理等待几个元素的问题。您也可以使用“&am…

网络操作系统第242页作业

1.简述电子邮件的工作原理。 答&#xff1a;用户编辑的E mail被转换成一个标准的邮件格式&#xff0c;这个邮件格式中可以包含各种样式的文件&#xff0c;如图像&#xff0c;声音&#xff0c;可执行程序等。邮件的内容以各种编码方式转换成ASCII码的形式&#xff0c;以便在网络…