Using Scala 2.9 to implement a kind of Dijkstra algorithm (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)
}
}
I'd like to change priority of an item in Scala's collection.mutable.PriorityQueue
.
Therefore tried to
But I can't find a method to either update priority or remove a specific item (not
necessarily head element) like java.util.PriorityQueue#remove(Object)
as apposed in
Removing an item from a priority queue.
How this task can be done with scala.collection.mutable.PriorityQueue
or do I have to use java.util.PriorityQueue
instead?
Does anyone know whether lack of such a method is by design and it would be recommended to rebuild the queue after changing priority of some items (maybe take a look at discussion about Priority queue with dynamic item priorities)?
There is an obvious way to do sorting with priority queues: Take the items that you want to sort, and insert them into the priority queue (using the item itself as its own priority). Then remove items from the priority queue until it is empty. The items will come off the queue in order from largest to smallest.
A Priority Queue is like a queue, except that each element is inserted according a given priority. The simplest example is provided by real numbers and ≤ or ≥ relations over them. We can say that the smallest (or the largest) numerical value has the highest priority.
This priority queue will be sorted according to the same comparator as the given collection, or according to its elements' natural order if the collection is sorted according to its elements' natural order. Parameters: c - the collection whose elements are to be placed into this priority queue.
A PriorityQueue in Java does not have any restriction with regard to duplicate elements. If you want to ensure that two identical items are never present in the priority queue at the same time the simplest way would be to maintain a separate Set in parallel with the priority queue.
Priority Queue is an extension of queue with following properties. 1) Every item has a priority associated with it. 2) An element with high priority is dequeued before an element with low priority. 3) If two elements have the same priority, they are served according to their order in the queue.
How do I explicitly order the PriorityQueue to sort itself again, given that the priority of an element has changed? Remove the element, change its priority value, re-add it. possible duplicate of stackoverflow.com/questions/1871253/… Remove the object, change its priority, and re-add it to the queue.
Defining a case class for the PriorityQueue type to use with var for priority allows you to find it and mutate the priority. The PriorityQueue then has this new value. To get the ordering correct I had to clone it which reorders/forces the ordering. There might be a better way to do this without cloning.
We can use heap implementation of Priority Queue to get value at an index. Create a heap first, then push items into the heap. An item in the Priority Queue will have a key and a value. This key is not the index of the heap. This key quantifies the priority. The index is the location where the item (key, value) of the Priority Queue is stored.
Defining a case class for the PriorityQueue type to use with var for priority allows you to find it and mutate the priority. The PriorityQueue then has this new value. To get the ordering correct I had to clone it which reorders/forces the ordering. There might be a better way to do this without cloning.
case class Elem(var priority: Int, i: Int)
def MyOrdering = new Ordering[Elem] {
def compare(a : Elem, b : Elem) = a.priority.compare(b.priority)
}
val pq = new scala.collection.mutable.PriorityQueue[Elem]()(MyOrdering) ++ List(Elem(1,1), Elem(0,0), Elem(2,2))
pq.find(x => x.priority == 0) match {
case Some(elem: Elem) => elem.priority = 3
case None => println("Not found")
}
val pq2 = pq.clone
println(pq2)
println(pq2.dequeue)
println(pq2.dequeue)
println(pq2.dequeue)
:load SO.scala
Loading SO.scala...
defined class Elem
PileOrdering: java.lang.Object with Ordering[Elem]
pq: scala.collection.mutable.PriorityQueue[Elem] = PriorityQueue(Elem(2,2), Elem(0,0), Elem(1,1))
pq2: scala.collection.mutable.PriorityQueue[Elem] = PriorityQueue(Elem(3,0), Elem(2,2), Elem(1,1))
PriorityQueue(Elem(3,0), Elem(2,2), Elem(1,1))
Elem(3,0)
Elem(2,2)
Elem(1,1)
Priority queues are commonly implemented with heaps. Binary heaps are commonly implemented using arrays, and if the element you want to remove is not on the path between the root of the heap and its last element in the array ordering, then there is no obvious way to remove it. I assume that this is why Scala doesn't offer removal of arbitrary elements. However, if you implement your own heap, it's easy enough to implement decrease-key for a binary (min-)heap: you just compare the new priority for a node N
to its parent's priority, and if necessary exchange the two. Do this repeatedly until N
is at the top or N
's parent has lower priority than N
itself.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With