Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change priority of items in a priority queue

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

  • remove item
  • change priority
  • reinsert into queue.

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)?

like image 351
binuWADa Avatar asked Feb 01 '12 21:02

binuWADa


People also ask

How do I sort a priority queue?

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.

What is highest priority in priority queue?

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.

Is priority queue always sorted?

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.

How do I avoid duplicates in 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.

What is the use of 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?

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.

How do I change the priority of a PriorityQueue?

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.

How to get value at an index in Java priority queue?

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.


2 Answers

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)
like image 128
Brian Avatar answered Sep 23 '22 12:09

Brian


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.

like image 25
Erik P. Avatar answered Sep 23 '22 12:09

Erik P.