Changer la priorité d'éléments dans une file d'attente de priorité
À l'aide de la Scala de 2,9 à mettre en œuvre une sorte de Dijkstra algorithme (en pseudo-code)
val queue = new PriorityQueue
queue.insert(...)
while (!queue.isEmpty) {
val u = queue.extractMin
queue.foreach { v =>
if (condition(u, v))
queue.decreaseKey(v, newPriority)
}
}
J'aimerais changer la priorité d'un élément dans Scala collection.mutable.PriorityQueue
.
Donc essayé de
- supprimer l'élément
- changer la priorité
- réinsérez-la dans la file d'attente.
Mais je ne peux pas trouver une méthode pour priorité de mise à jour ou de supprimer un élément spécifique (pas
nécessairement l'élément de tête) comme java.util.PriorityQueue#remove(Object)
rien gagné dans
Suppression d'un élément dans une file d'attente de priorité.
- Comment cette tâche peut être fait avec
scala.collection.mutable.PriorityQueue
ou dois-je utiliserjava.util.PriorityQueue
à la place? - Personne ne sait si l'absence d'une telle méthode est, par conception, et il serait recommandé
pour reconstruire la file d'attente après la modification de la priorité de certains articles (peut-être jeter un oeil à la discussion sur File d'attente de priorité avec élément dynamique priorités)?
Je ne suis pas un Scala utilisateur, mais je sais que
BTW, Êtes-vous sûr que
Vous connaissez un remplacement pour
PriorityQueue sera parfaitement apte à extractMin-diminution-enqueueBack, j'ai été dérangée par des ce n'est pas nécessairement l'élément de tête
Après chaque extractMin étape il y a peut-être quelques decreaseKey (cela signifie que certains (et donc pas en tête) des éléments prioritaires de changement de la valeur (diminue)).
java.util.PriorityQueue
manque de soutien pour diminuer-clé. Je crois que c'est parce que, pour soutenir efficacement diminuer-clé, vous devez être en mesure d'accéder de manière aléatoire les éléments de la PriorityQueue
, quelque chose que Java version ne prend pas en charge.BTW, Êtes-vous sûr que
PriorityQueue
est la bonne solution pour votre problème, puisque je vois que vous ne l'utilisez pas des avantages directs et autant que je sache, l'accès aléatoire opérations sur les Files d'attente sera O(n)?Vous connaissez un remplacement pour
PriorityQueue
dans Dijkstra comme des algorithmes (insert, extractMin et decreaseKey sont utilisés)? Et j'ai lu que l'accès aléatoire pourrait être O(1) pour le stockage de position d'insertion d'éléments - mais je crains que ce n'est pas réalisée par la norme impl.PriorityQueue sera parfaitement apte à extractMin-diminution-enqueueBack, j'ai été dérangée par des ce n'est pas nécessairement l'élément de tête
Après chaque extractMin étape il y a peut-être quelques decreaseKey (cela signifie que certains (et donc pas en tête) des éléments prioritaires de changement de la valeur (diminue)).
OriginalL'auteur binuWADa | 2012-02-01
Vous devez vous connecter pour publier un commentaire.
La définition d'une classe de cas pour la PriorityQueue type à utiliser avec la var pour priorité vous permet de le trouver et de le muter à la priorité. Le PriorityQueue a alors cette nouvelle valeur. Pour obtenir la commande correcte, j'ai eu pour le clone qui réorganise/forces de l'ordre. Il pourrait y avoir une meilleure façon de le faire sans le clonage.
case class Elem(var priority: Int, i: Int) extends Ordering[Elem] { def compare(that : Elem) = that.priority.compare(priority) }
et puis il suffit d'utilisernew PriorityQueue[Elem](Elem(1,1), Elem(0,0), Elem(2,2))
Si je vous ai bien compris, vous proposez de créer simplement de la file d'attente à nouveau (pour re-trier) après la modification de la priorité de certains éléments.
Eh bien, je ne dirais pas depuis qu'il est inefficace, mais le clonage ne réorganiser l'altération de la file d'attente. Je pense qu'il y peut-être une meilleure façon d'atteindre cet objectif sans le clonage de la file d'attente. Si vous dequeue x 3 sur pq après le changement de priorité de la commande n'est pas correcte.
OriginalL'auteur Brian
Files d'attente de priorité sont couramment mis en œuvre avec des tas. Binaire tas sont souvent mise en œuvre à l'aide de tableaux, et si l'élément que vous souhaitez supprimer n'est pas sur le chemin entre la racine du tas et de son dernier élément dans le tableau de commande, alors il n'est pas évident de trouver un moyen de l'éliminer. Je suppose que c'est pourquoi Scala n'offre pas de suppression de l'arbitraire des éléments. Toutefois, si vous implémentez votre propre tas, c'est assez facile à mettre en œuvre diminuer-clé pour un binaire (min)tas: il vous suffit de comparer la nouvelle priorité pour un nœud
N
pour l'un de ses parents priorité, et, si nécessaire, change les deux. Répéter cette opération jusqu'à ce queN
est en haut ou enN
parent a une priorité plus faible queN
lui-même.OriginalL'auteur Erik P.
Je n'ai pas d'expérience avec Scala, mais le problème que je vois est qu'une simple file d'attente de priorité n'est pas assez pour Dijkstra, car vous avez besoin de savoir où un vertex est stocké dans la file d'attente avant de pouvoir faire une diminution de la clé. En d'autres mots, un dictionnaire (table de hachage) est nécessaire pour la carte id de sommet d'indices dans le tas, prévue dans les temps constant. Ensuite, vous obtenez un ensemble O(log n) pour la diminution de la clé. Il me semble improbable qu'une telle fonctionnalité peut être trouvé dans une bibliothèque standard. L'écriture d'un convenable de la classe à partir de zéro devrait être facile, cependant.
Le code à la fin de cette conférence explique l'idée (mais en python.. désolé).
OriginalL'auteur sumx
Pas un Scala utilisateur, mais jusqu'à présent je n'ai jamais vu un intégré/pré-faites Tas de mise en œuvre qui permet de Diminuer la Clé, parce que la Diminution de la Clé n'est efficace que si vous pouvez fournir (l'emplacement) de l'élément en cours de DK.
La façon la plus simple d'obtenir le DK opération est de mettre en œuvre le Tas vous-même. Ma méthode est généralement de garder mes Éléments séparés (non organisés matrice/vecteur/liste chaînée) et de construire un Segment de mémoire de pointeurs-à-Éléments (ou d'une matrice (indices). Alors, étant donné un Tas de nœud, vous pouvez rechercher l'élément en y accédant dans le tableau (déréférencement ou de l'index de recherche). À l'appui de DK et/ou Aléatoire Supprimer, vous pouvez ajouter une variable supplémentaire à l'Élément qui pointe vers le Tas de nœud (ou continue de l'indice, si la matrice de base du Tas). Cela vous permet d'avoir O(1) l'accès dans les deux sens.
Si votre pré-faites Tas est livré avec un DK opération qui accepte un pointeur vers le Nœud, vous pouvez simplement construire un Tas de self-made, Objets de Nœud, qui enroulez simplement le Pointeur dans une classe de sorte que vous pouvez fournir à des opérateurs de comparaison (nécessaire pour construire un Tas d'entre eux).
OriginalL'auteur Gaminic
J'ai mis en place un classe pour faire exactement ce dont vous avez besoin:
enqueue
dequeue
putValue
OriginalL'auteur Leonardo