Désolé pour une question aussi stupide mais Python sont déroutants ...
Lien 1: mise en œuvre de la file d'attente http://docs.python.org/library/queue.html
Il indique que la file d'attente a une structure pour la file d'attente prioritaire. Mais je n'ai pas trouvé comment l'appliquer.
class Queue.PriorityQueue(maxsize=0)
Lien 2: implémentation du tas http://docs.python.org/library/heapq.html
Ici, ils disent que nous pouvons implémenter indirectement des files d'attente prioritaires en utilisant 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'
Quelle est l'implémentation de file d'attente prioritaire la plus efficace en python? Et comment le mettre en œuvre?
La version du module Queue est implémentée à l'aide du tas , ils ont donc une efficacité égale pour les opérations de tas sous-jacentes.
Cela dit, la version Queue est plus lente car elle ajoute des verrous, l'encapsulation et une API orientée objet Nice.
Les suggestions de file d'attente prioritaire présentées dans les documents heapq sont destinées à montrer comment ajouter des fonctionnalités supplémentaires à une file d'attente prioritaire (telles que la stabilité du tri et la possibilité de modifier la priorité d'une tâche précédemment mise en file d'attente). Si vous n'avez pas besoin de ces capacités, alors le heappush de base et heappop vous donnera les performances les plus rapides.
Il n'y a rien de tel qu'une "implémentation de file d'attente prioritaire la plus efficace" dans n'importe quelle langue .
Une file d'attente prioritaire est tout au sujet des compromis. Voir http://en.wikipedia.org/wiki/Priority_queue
Vous devez choisir l'un de ces deux, en fonction de la façon dont vous prévoyez de l'utiliser:
O(log(N))
temps d'insertion et O(1)
findMin + deleteMin temps, ouO(1)
temps d'insertion et O(log(N))
findMin + deleteMin tempsDans ce dernier cas, vous pouvez choisir d'implémenter une file d'attente prioritaire avec un tas Fibonacci: http://en.wikipedia.org/wiki/Heap_ (data_structure) #Comparison_of_theoretic_bounds_for_variants (comme vous pouvez le voir, heapq
qui est essentiellement un arbre binaire, doit nécessairement avoir O(log(N))
pour l'insertion et findMin + deleteMin)
Si vous traitez des données avec des propriétés spéciales (telles que des données délimitées), vous pouvez réaliser l'insertion de O(1)
et O(1)
findMin + deleteMin time. Vous ne pouvez le faire qu'avec certains types de données, sinon vous pourriez abuser de votre file d'attente prioritaire pour violer la limite O(N log(N))
lors du tri.
Pour implémenter n'importe quelle file d'attente dans n'importe quelle langue, il vous suffit de définir les opérations insert(value)
et extractMin() -> value
. Cela implique généralement juste un habillage minimal du tas sous-jacent; voir http://en.wikipedia.org/wiki/Fibonacci_heap pour implémenter le vôtre, ou utiliser une bibliothèque standard d'un tas similaire comme un tas d'association (une recherche Google a révélé - http://svn.python.org/projects/sandbox/trunk/collections/pairing_heap.py )
Si vous ne vous souciez que des deux que vous avez référencés sont les plus efficaces (le code basé sur heapq
de http://docs.python.org/library/heapq.html#priority-queue- notes d'implémentation que vous avez inclus ci-dessus, contre Queue.PriorityQueue
), puis:
Il ne semble pas y avoir de discussion facile à trouver sur le Web quant à ce que Queue.PriorityQueue
est en train de faire; vous devriez plonger dans le code source, qui est lié à partir de la documentation d'aide: 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)
Comme on peut le voir, Queue.PriorityQueue
utilise également heapq
comme mécanisme sous-jacent. Par conséquent, ils sont également mauvais (asymptotiquement parlant). Queue.PriorityQueue
peut permettre des requêtes parallèles, donc je parierais qu'il pourrait y avoir un facteur de surcharge très légèrement constant. Mais comme vous savez que l'implémentation sous-jacente (et le comportement asymptotique) doivent être les mêmes, la manière la plus simple serait simplement de les exécuter sur le même grand ensemble de données.
(Notez que Queue.PriorityQueue
ne semble pas avoir de moyen de supprimer les entrées, contrairement à heapq
. Cependant, il s'agit d'une arme à double tranchant: de bonnes implémentations de files d'attente prioritaires peuvent éventuellement vous permettre de supprimer des éléments dans O(1) ou O(log(N)) = heure, mais si vous utilisez le remove_task
fonction que vous mentionnez, et laissez ces tâches zombies s'accumuler dans votre file d'attente parce que vous ne les extrayez pas du min, vous verrez alors un ralentissement asymptotique que vous ne verriez pas autrement. Bien sûr, vous ne pouvez pas faire cela avec Queue.PriorityQueue
en premier lieu, donc aucune comparaison ne peut être faite ici.)
Bien que cette question ait été répondue et marquée comme acceptée, voici encore une implémentation personnalisée simple de Priority Queue sans utiliser de module pour comprendre comment cela fonctionne.
# 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)
Trouvez le code complet et l'explication ici: https://www.studytonight.com/code/python/ds/priority-queue-in-python.php