很抱歉这个愚蠢的问题,但Python文档令人困惑。
链接1:队列实施 http://docs.python.org/library/queue.html
它表示该队列具有优先级队列的构造。但我找不到如何实现它。
class Queue.PriorityQueue(maxsize=0)
链接2:堆实施 http://docs.python.org/library/heapq.html
他们说我们可以使用heapq
间接实现优先级队列pq = [] # list of entries arranged in a heap
entry_finder = {} # mapping of tasks to entries
REMOVED = '<removed-task>' # placeholder for a removed task
counter = itertools.count() # unique sequence count
def add_task(task, priority=0):
'Add a new task or update the priority of an existing task'
if task in entry_finder:
remove_task(task)
count = next(counter)
entry = [priority, count, task]
entry_finder[task] = entry
heappush(pq, entry)
def remove_task(task):
'Mark an existing task as REMOVED. Raise KeyError if not found.'
entry = entry_finder.pop(task)
entry[-1] = REMOVED
def pop_task():
'Remove and return the lowest priority task. Raise KeyError if empty.'
while pq:
priority, count, task = heappop(pq)
if task is not REMOVED:
del entry_finder[task]
return task
raise KeyError('pop from an empty priority queue'
哪个是python中最有效的优先级队列实现?以及如何实现它?
答案 0 :(得分:28)
没有&#34;最有效的优先级队列实现&#34;在任何语言。
优先级队列都是权衡取舍。见http://en.wikipedia.org/wiki/Priority_queue
您应根据计划使用方式选择其中一种:
O(log(N))
插入时间和O(1)
findMin + deleteMin时间,或O(1)
插入时间和O(log(N))
findMin + deleteMin time 在后一种情况下,您可以选择使用Fibonacci堆实现优先级队列:http://en.wikipedia.org/wiki/Heap_(data_structure)#Comparison_of_theoretic_bounds_for_variants(如您所见,heapq
基本上是二叉树,必须具有{{1}对于插入和findMin + deleteMin)
如果您正在处理具有特殊属性(例如有界数据)的数据,那么您可以实现O(log(N))
插入和O(1)
findMin + deleteMin时间。您只能对某些类型的数据执行此操作,否则您可能会滥用您的优先级队列以违反排序中的O(1)
限制。
要使用任何语言实现任何队列,您只需要定义O(N log(N))
和insert(value)
操作。这通常只涉及底层堆的最小包装;请参阅http://en.wikipedia.org/wiki/Fibonacci_heap以实现您自己的,或使用类似堆的现成库,如配对堆(Google搜索显示http://svn.python.org/projects/sandbox/trunk/collections/pairing_heap.py)
如果您只关心您引用的两个中的哪一个效率更高(上面包含的基于extractMin() -> value
的{{3}}代码,而不是heapq
),那么:
在网络上似乎没有任何关于Queue.PriorityQueue
实际在做什么的容易找到的讨论;您需要深入了解代码,该代码链接到帮助文档:http://docs.python.org/library/heapq.html#priority-queue-implementation-notes
Queue.PriorityQueue
我们可以看到, 224 def _put(self, item, heappush=heapq.heappush):
225 heappush(self.queue, item)
226
227 def _get(self, heappop=heapq.heappop):
228 return heappop(self.queue)
也使用Queue.PriorityQueue
作为底层机制。因此它们同样糟糕(渐近地说)。 heapq
可能允许并行查询,所以我会打赌它可能会有一个非常小的常数因子更多的开销。但是因为你知道底层实现(和渐近行为)必须是相同的,最简单的方法就是在同一个大型数据集上运行它们。
(请注意,Queue.PriorityQueue
似乎没有办法删除条目,而Queue.PriorityQueue
则这样做。但这是一把双刃剑:优先级高的队列实现可能允许您删除在O(1)或O(log(N))时间内的元素,但是如果你使用你提到的heapq
函数,并让那些僵尸任务在你的队列中累积,因为你没有从它们中提取它们min,然后你会看到渐渐减速,你不会看到它。当然,你首先不能用remove_task
来做这个,所以这里不能进行比较。)< / p>
答案 1 :(得分:27)
Queue 模块中的版本使用 heapq 模块implemented,因此它们对底层堆操作具有相同的效率。
也就是说, Queue 版本较慢,因为它增加了锁,封装和一个很好的面向对象的API。
priority queue suggestions shown in the heapq docs旨在说明如何向优先级队列添加其他功能(例如排序稳定性和更改先前排队任务的优先级的能力)。如果您不需要这些功能,那么基本的 heappush 和 heappop 功能将为您提供最快的性能。
答案 2 :(得分:1)
虽然这个问题已被回答并被标记为已接受,但仍然是一个简单的自定义优先级队列实现,而不使用任何模块来理解它是如何工作的。
# class for Node with data and priority
class Node:
def __init__(self, info, priority):
self.info = info
self.priority = priority
# class for Priority queue
class PriorityQueue:
def __init__(self):
self.queue = list()
# if you want you can set a maximum size for the queue
def insert(self, node):
# if queue is empty
if self.size() == 0:
# add the new node
self.queue.append(node)
else:
# traverse the queue to find the right place for new node
for x in range(0, self.size()):
# if the priority of new node is greater
if node.priority >= self.queue[x].priority:
# if we have traversed the complete queue
if x == (self.size()-1):
# add new node at the end
self.queue.insert(x+1, node)
else:
continue
else:
self.queue.insert(x, node)
return True
def delete(self):
# remove the first node from the queue
return self.queue.pop(0)
def show(self):
for x in self.queue:
print str(x.info)+" - "+str(x.priority)
def size(self):
return len(self.queue)
在此处查找完整的代码和说明:https://www.studytonight.com/code/python/ds/priority-queue-in-python.php