Python实现优先队列

原创 2012年03月24日 17:05:26

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

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

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

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

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

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

看bisect包的源码:

def insort_right(a, x, lo=0, hi=None):
    """Insert item x in list a, and keep it sorted assuming a is sorted.

    If x is already in a, insert it to the right of the rightmost x.

    Optional args lo (default 0) and hi (default len(a)) bound the
    slice of a to be searched.
    """

    if lo < 0:
        raise ValueError('lo must be non-negative')
    if hi is None:
        hi = len(a)
    while lo < hi:
        mid = (lo+hi)//2
        if x < a[mid]: hi = mid
        else: lo = mid+1
    a.insert(lo, x)

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的两种堆画一画就知道我说的了(子节点)

#-*-coding:utf-8-*-
"""
class PriorityQueue:
"""

class PriorityQueue:
    def __init__(self):
        self.queue = []
        self.length = 0
        self.queue.insert(0, self.length)
    
	#队列中元素的个数
    def count(self):
        return self.length
    
	#判断队列是否为空
    def empty(self):
        if self.count() == 0:
            return True
        else :
            return False
    
	#取队列首元素,但是此时没有删除该元素
    def top(self):
        return self.queue[1]
    
	#删除队首元素
    def pop(self):
        bEmpty = self.empty()
        if bEmpty == False:
            self.queue[1] = self.queue[self.length]
            self.length -= 1
            self._adjust()
    
	#插入一个元素
    def push(self,item):
        self.length += 1
        self.queue.insert(self.length, item)
        
		#插入元素后对堆进行调整,使其满足最大顶堆的性质
        i = self.length
        while i >= 2 and self.queue[i][1] > self.queue[i/2][1]:
            self.queue[i] , self.queue[i/2] = self.queue[i/2] , self.queue[i]
            i = i / 2
    
    #堆的调整函数
    def _adjust(self):
        root = 1
        j = root << 1
        temp = self.queue[root]
        while j <= self.length:
            if j < self.length and self.queue[j][1] < self.queue[j+1][1]:
                j += 1
            if self.queue[j] <= temp:
                break
            self.queue[j],self.queue[root] = self.queue[root],self.queue[j]
            root = j
            j = j << 1
            
        self.queue[root] = temp
        
if __name__ == '__main__':
    pq = PriorityQueue()
    pq.push(15)
    pq.push(8)
    pq.push(9)
    pq.push(3)
    pq.push(7)
    pq.push(6)
    print pq.queue  
    while pq.empty() == False:
        print "Value = ",pq.top()
        print pq.queue,pq.length
        pq.pop()

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

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Python 使用list实现无边际优先队列 (基于class, 包含迭代器)

Python 使用list实现无边际优先队列 (基于class, 包含迭代器)

优先队列算法实现(Java)

  • 2009年06月01日 12:49
  • 4KB
  • 下载

python 堆和优先队列的使用

1.heapqpython里面的堆是通过在列表中维护堆的性质实现的。这一点与C++中heap一系列的算法类似,底层是通过堆vector的维护获取堆的性质。 python堆的部分API,其他API查阅...

优先队列C++实现哈夫曼树

  • 2012年02月13日 10:23
  • 2KB
  • 下载

优先队列操作

  • 2013年04月12日 15:59
  • 3KB
  • 下载

HDU 4006 The kth great number(优先队列、堆实现)

/* 题意:"I"表示输入数据,"Q"表示输出第k大数据 题解:优先队列,从大到小,队列中只需要k个元素。每次输出最小的即可 我用小顶堆实现,如果插入元素比tree[1]小,则直接舍掉。否则,更新。...

关于STL中优先队列的用法

  • 2010年01月02日 12:20
  • 2KB
  • 下载

C-优先队列

  • 2016年12月08日 21:08
  • 5KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Python实现优先队列
举报原因:
原因补充:

(最多只允许输入30个字)