このような馬鹿げた質問は申し訳ありませんが、Python docs is confusing .。
リンク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で最も効率的な優先キューの実装はどれですか?そして、それを実装する方法は?
Queueモジュールのバージョンは 実装済みheapqモジュールを使用しているため、基礎となるヒープ操作。
ただし、Queueバージョンは、ロック、カプセル化、およびNiceオブジェクト指向APIを追加するため、低速です。
heapqドキュメントに示されている優先度キューの提案 は、優先度キューに追加機能を追加する方法(並べ替えの安定性、以前にキューに入れられたタスクの優先度を変更する機能など)を示すためのものです。これらの機能が必要ない場合は、基本的なheappushおよびheappop関数が最速のパフォーマンスを提供します。
任意の言語に「最も効率的な優先度キュー実装」などはありません。
優先度キューは、トレードオフに関するものです。 http://en.wikipedia.org/wiki/Priority_queue を参照してください
使用方法に基づいて、次の2つのいずれかを選択する必要があります。
O(log(N))
挿入時間およびO(1)
findMin + deleteMin時間、またはO(1)
挿入時間およびO(log(N))
findMin + deleteMin時間後者の場合、フィボナッチヒープで優先度キューを実装することを選択できます。 http://en.wikipedia.org/wiki/Heap_(data_structure)#Comparison_of_theoretic_bounds_for_variants 基本的にバイナリツリーであるheapq
は、挿入とfindMin + deleteMinの両方に必ずO(log(N))
が必要です。
特別なプロパティ(制限されたデータなど)を持つデータを扱う場合、O(1)
挿入とO(1)
findMin + deleteMin時間を達成できます。特定の種類のデータでのみこれを行うことができます。そうしないと、優先キューを乱用して、ソートのO(N log(N))
バインドに違反する可能性があります。
任意の言語で任意のキューを実装するには、insert(value)
およびextractMin() -> value
操作を定義するだけです。通常、これには、基礎となるヒープの最小限のラップが含まれます。 http://en.wikipedia.org/wiki/Fibonacci_heap を参照して独自の実装を行うか、ペアリングヒープ(Googleのような類似のヒープの既製ライブラリを使用してください検索結果 http://svn.python.org/projects/sandbox/trunk/collections/pairing_heap.py )
参照した2つのうちどちらがより効率的かだけを気にする場合( 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)) time、ただし、言及したremove_task
関数を使用し、それらのゾンビタスクをキューに蓄積する場合それらを最小値から抽出していないので、他の方法では見られない漸近的なスローダウンが表示されます。もちろん、最初に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/code/python/ds/priority-queue-in-python.php