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

通过heapq模块

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

1

2

3

4

5

6

7

8

9

10

11

12#coding:gbk

import heapq

tasks = []

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)

运行结果如下

1

2

3

4(10, 'aaa')

(20, 'ddd')

(30, 'ccc')

(40, 'bbb')

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

1

2

3

4

5

6>>>cmp(10,20)

-1

>>>cmp(10,10)

0

>>>cmp(10,5)

1

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

1

2

3

4

5

6

7

8>>>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__ 方法的对象则可以实现优先队列中的对象排序。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30#coding:gbk

import heapq

# 使用heapq实现优先队列

#定义一个可比较对象

class CompareAble:

def __init__(self,priority,jobname):

self.priority = priority

self.jobname = jobname

def __cmp__(self, other):

if self.priority < other.priority:

return -1

elif self.priority == other.priority:

return 0

else:

return 1

joblist = []

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)

运行结果:

1

2

3

4

5(70, 'write plan')

(70, 'a write plan2')

(80, 'eat')

(90, 'sleep')

(100, 'write code')

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

通过Queue,PriorityQueue类型实现

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30#coding:gbk

import heapq

from queue import Queue,PriorityQueue

# 使用heapq实现优先队列

#定义一个可比较对象

class CompareAble:

def __init__(self,priority,jobname):

self.priority = priority

self.jobname = jobname

def __cmp__(self, other):

if self.priority < other.priority:

return -1

elif self.priority == other.priority:

return 0

else:

return 1

pq = 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)

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

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52#coding:gbk

from queue import PriorityQueue

import time

import random

import threading

# 使用heapq实现优先队列

#定义一个可比较对象

class CompareAble:

def __init__(self,priority,jobname):

self.priority = priority

self.jobname = jobname

def __cmp__(self, other):

if self.priority < other.priority:

return -1

elif self.priority == other.priority:

return 0

else:

return 1

tasks = [(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()

运行结果:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28put 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方法,运行得到的异常信息是

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

就是没有一个 < 的操作

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61#coding:gbk

from queue import PriorityQueue

import time

import random

import threading

# 使用heapq实现优先队列

#定义一个可比较对象

class CompareAble:

def __init__(self,priority,jobname):

self.priority = priority

self.jobname = jobname

# def __cmp__(self, other):

# if self.priority < other.priority:

# return -1

# elif self.priority == other.priority:

# return 0

# else:

# return 1

def __lt__(self, other):

if self.priority <= other.priority:

return False

else:

return True

tasks = [(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():

continue

task = 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优先级排序_python中使用优先队列相关推荐

  1. python优先级排序_Python实现一个优先级队列的方法

    问题 怎样实现一个按优先级排序的队列? 并且在这个队列上面每次 pop 操作总是返回优先级最高的那个元素 解决方案 下面的类利用 heapq 模块实现了一个简单的优先级队列: import heapq ...

  2. python优先级排序_Python实现优先级队列结构的方法详解

    最简单的实现一个队列至少满足2个方法,put和get. 借助最小堆来实现. 这里按"值越大优先级越高"的顺序. #coding=utf-8 from heapq import he ...

  3. python优先级排序_Python Numpy重新排列双向排序

    我有一个结构化的numpy数组,我按顺序对它进行排序. 它工作得很好,但只是一个方向! 降: sort(myStructuredArray,order=my_order)[::-1] 和 上升: so ...

  4. python数字排序_python中如何对数字排序

    python中对数字进行排序的方法: 1.使用sorted()函数对数字排序 sorted() 函数对所有可迭代的对象进行排序操作. sorted 语法:sorted(iterable, cmp=No ...

  5. python list排序_Python中字符串List按照长度排序

    下面看下字符串List按照长度排序(python)的实现方法 myList = ['青海省','内蒙古自治区','西藏自治区','新疆维吾尔自治区','广西壮族自治区'] 1.首先得到每个字符串长度 ...

  6. python常用排序_python中的各种排序

    #encoding=utf-8 import random from copy import copy def directInsertSort(seq): """ 直接 ...

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

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

  8. python list排序_python里对list中的整数求平均并排序

    python里对list中的整数求平均并排序 本文主要记述了使用Python将list重点整数求平均值之后在进行排列的过程,并把代码分享给大家, 问题 定义一个int型的一维数组,包含40个元素,用来 ...

  9. python列表数据排序_Python中,如何将列表中数据排序给列表排序?

    在程序中使用字典进行数据信息統计时由于字典是无序的所以打印字典时内容也是无序的.因此为了使统计得到的结果更方便查看需要进行排序.Python中字典的排序分为按"键"排序和按&quo ...

最新文章

  1. 【mysql】Mac下安装mysql5.7 完整步骤,大坑已解决
  2. @ConfigurationProperties和@Value 注入
  3. 禁止用户复制网页的内容
  4. Eclipse的maven插件最新地址
  5. 我两小时学完指针,你学会数组/指针与函数需要多久?
  6. mysql 判断 字母大写_MySQL中查询时对字母大小写的区分
  7. oracle 表名拼接_Oracle之3种表连接方式(排序合并连接、嵌套循环、哈希连接)...
  8. python ljust函数,Python 字符串左对齐-Python 指定字符串左对齐-python ljust() 函数-python ljust() 函数用法-嗨客网...
  9. 阿里巴巴副总裁陈丽娟:我对阿里云产品生态的思考
  10. 分享76网络科技88教育教学47公司企业PPT模板
  11. Proface触摸屏与三菱PLC软件仿真(或连接实体PLC)
  12. [Windows] 翻页时钟Fliqlo 1.4 — 无需Flash Player,2021年官网最新更新 ,fliqlo 时钟屏保不显示了怎么办?已解决!
  13. java和vue实现拖拽可视化_可视化拖拽页面编辑器 一__Vue.js
  14. MySQL报Out of sort memory, consider increasing server sort buffer size的两种情况
  15. vscode 移动到末尾并且换行快捷键
  16. 算法导论 — 比较排序算法对比实验
  17. c语言实现简单的24点游戏
  18. RGB和HSV颜色空间
  19. 阿里面试其实也没想象中的那么难,秋招提前批4面拿到21K
  20. C++解析JSON格式数据

热门文章

  1. linux打包/解压-tar
  2. PHP 显示信息到控制台console
  3. layout文件夹中activity_main.xml与fragment_main.xml文件的处理记录
  4. getHibernateTemplate()(Spring中常用的hql查询方法)
  5. WPF 学习笔记 路由事件
  6. JQuery - Animate
  7. 清掉数据_值得收藏!面试中有哪些经典的数据库问题?
  8. 使用glbindbuffers产生访问冲突_预防IP地址冲突的应对方案,你知道吗?
  9. tomcat命令linux,Linux下一些操作Tomcat的命令
  10. java中为什么还要防止内存泄露_JAVA防止内存的泄漏什么意思,内存还能泄露?...