[英]How to implement Priority Queues in Python?
抱歉問了這么愚蠢的問題,但 Python 文檔令人困惑......
鏈接 1:隊列實現http://docs.python.org/library/queue.html
它說 Queue 有一個優先級隊列的類。 但我找不到如何實現它。
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 中最有效的優先級隊列實現? 以及如何實施?
在任何語言中都不存在“最有效的優先級隊列實現”這樣的東西。
優先級隊列就是權衡取舍。 見http://en.wikipedia.org/wiki/Priority_queue
您應該根據您打算如何使用它來選擇這兩個之一:
O(log(N))
插入時間和O(1)
findMin+deleteMin 時間,或O(1)
插入時間和O(log(N))
findMin+deleteMin 時間在后一種情況下,您可以選擇使用斐波那契堆實現優先級隊列: http : //en.wikipedia.org/wiki/Heap_ ( heapq
(如您所見, heapq
基本上是一個二叉樹,必須有O(log(N))
插入和 findMin+deleteMin)
如果你在處理具有特殊屬性的數據(比如有界數據),那么你可以實現O(1)
插入和O(1)
findMin+deleteMin 時間。 您只能對某些類型的數據執行此操作,否則您可能會濫用優先級隊列來違反排序時的O(N log(N))
界限。
要以任何語言實現任何隊列,您只需要定義insert(value)
和extractMin() -> value
操作。 這通常只涉及底層堆的最小包裝; 參見http://en.wikipedia.org/wiki/Fibonacci_heap來實現你自己的,或者使用一個像配對堆這樣的類似堆的現成庫(谷歌搜索顯示http://svn.python.org /projects/sandbox/trunk/collections/pairing_heap.py )
如果您只關心您引用的兩個中的哪一個更有效(您在上面包含的http://docs.python.org/library/heapq.html#priority-queue-implementation-notes中的基於heapq
的代碼,而不是Queue.PriorityQueue
),然后:
關於Queue.PriorityQueue
實際上在做什么,網絡上似乎沒有任何容易找到的討論; 您必須深入了解代碼,該代碼鏈接到幫助文檔: http : //hg.python.org/cpython/file/2.7/Lib/Queue.py
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
似乎沒有刪除條目的方法,而heapq
有。但是這是一把雙刃劍:好的優先級隊列實現可能允許您刪除 O(1) 或 O( log(N)) 時間,但是如果你使用你提到的remove_task
函數,並讓那些僵屍任務在你的隊列中累積,因為你沒有從 min 中提取它們,那么你會看到漸近減速,否則你不會看到.當然,首先你不能用Queue.PriorityQueue
來做這個,所以這里不能做比較。)
盡管此問題已得到回答並標記為已接受,但這里仍然是 Priority Queue 的一個簡單自定義實現,無需使用任何模塊來了解其工作原理。
# 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/post/implementing-priority-queue-in-python (更新的 URL)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.