首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Python实现优先队列

Python实现优先队列

作者头像
bear_fish
发布2018-09-20 15:45:07
发布2018-09-20 15:45:07
8760
举报

Python有队列类Queue,为啥就不提供个PriorityQueue类呢?

写优先队列也是在写爬虫的时候想到的,当时没想用PageRank算法(最终也没用),就直接用优先队列来放URL,但是发现Python没有优先队列。

网上我看到一哥们用Python的bisect包来实现优先队列的

具体的网址:http://www.kgblog.net/2009/04/25/pythonSpider.html

我们就来分析下他的优先队列算法复杂度吧,这仅仅是学术探讨,没有任何别的意思。

首先在元素插入队列的时候,bisect的原理是用二分来搜索需要插入的位置,然后将后面的元素平移一个位置,将该位置空出来给需要插入的元素

看bisect包的源码:

[python] view plaincopyprint?

  1. def insort_right(a, x, lo=0, hi=None):  
  2. """Insert item x in list a, and keep it sorted assuming a is sorted.
  3.     If x is already in a, insert it to the right of the rightmost x.
  4.     Optional args lo (default 0) and hi (default len(a)) bound the
  5.     slice of a to be searched.
  6.     """
  7. if lo < 0:  
  8. raise ValueError('lo must be non-negative')  
  9. if hi is None:  
  10.         hi = len(a)  
  11. while lo < hi:  
  12.         mid = (lo+hi)//2
  13. if x < a[mid]: hi = mid  
  14. else: lo = mid+1
  15.     a.insert(lo, x)  
  16. insort = insort_right   

具体我不知道Python的list是怎么个机制来平移的,但怎么平移又要保证大小的顺序不变,那么复杂度也是O(n)吧。

再次,当我们需要pop出一个元素的时候同样他的方法是直接用list.pop(item),这样也需要list自己来平移元素位置,复杂度也是O(n)

而实际上C++ STL中的优先队列的插入和删除的复杂度是O(logn)

对于Python list的机制我不了解,如果和C++中的数组平移是一样的话,那么这种优先队列的方法是不可取的。

那么就需要自己写堆了,说白了就是堆的Insert和Adjust两个函数就搞定了

需要说明的是:此代码中我没有使用list[0]这个位置,这样再写代码的时候比较直观,我是这样认为的,大家可以把root=0和root=1的两种堆画一画就知道我说的了(子节点)

[python] view plaincopyprint?

  1. #-*-coding:utf-8-*-
  2. """
  3. class PriorityQueue:
  4. """
  5. class PriorityQueue:  
  6. def __init__(self):  
  7. self.queue = []  
  8. self.length = 0
  9. self.queue.insert(0, self.length)  
  10. #队列中元素的个数
  11. def count(self):  
  12. return self.length  
  13. #判断队列是否为空
  14. def empty(self):  
  15. if self.count() == 0:  
  16. return True
  17. else :  
  18. return False
  19. #取队列首元素,但是此时没有删除该元素
  20. def top(self):  
  21. return self.queue[1]  
  22. #删除队首元素
  23. def pop(self):  
  24.         bEmpty = self.empty()  
  25. if bEmpty == False:  
  26. self.queue[1] = self.queue[self.length]  
  27. self.length -= 1
  28. self._adjust()  
  29. #插入一个元素
  30. def push(self,item):  
  31. self.length += 1
  32. self.queue.insert(self.length, item)  
  33. #插入元素后对堆进行调整,使其满足最大顶堆的性质
  34.         i = self.length  
  35. while i >= 2 and self.queue[i][1] > self.queue[i/2][1]:  
  36. self.queue[i] , self.queue[i/2] = self.queue[i/2] , self.queue[i]  
  37.             i = i / 2
  38. #堆的调整函数
  39. def _adjust(self):  
  40.         root = 1
  41.         j = root << 1
  42.         temp = self.queue[root]  
  43. while j <= self.length:  
  44. if j < self.length and self.queue[j][1] < self.queue[j+1][1]:  
  45.                 j += 1
  46. if self.queue[j] <= temp:  
  47. break
  48. self.queue[j],self.queue[root] = self.queue[root],self.queue[j]  
  49.             root = j  
  50.             j = j << 1
  51. self.queue[root] = temp  
  52. if __name__ == '__main__':  
  53.     pq = PriorityQueue()  
  54.     pq.push(15)  
  55.     pq.push(8)  
  56.     pq.push(9)  
  57.     pq.push(3)  
  58.     pq.push(7)  
  59.     pq.push(6)  
  60. print pq.queue    
  61. while pq.empty() == False:  
  62. print "Value = ",pq.top()  
  63. print pq.queue,pq.length  
  64.         pq.pop()  

代码我自己验证过了,应该是没有问题的

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2015年02月02日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档