Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating Java PriorityQueue when its elements change priority

I'm trying to use a PriorityQueue to order objects using a Comparator.

This can be achieved easily, but the objects class variables (with which the comparator calculates priority) may change after the initial insertion. Most people have suggested the simple solution of removing the object, updating the values and reinserting it again, as this is when the priority queue's comparator is put into action.

Is there a better way other than just creating a wrapper class around the PriorityQueue to do this?

like image 471
Marcus Whybrow Avatar asked Dec 09 '09 02:12

Marcus Whybrow


People also ask

How do you change the priority of a priority queue in Java?

Now when you need to change the priority of an item, simply add the same item to the queue with a different priority (and update the map of course). When you poll an item from the queue, check if its priority is the same than in your map. If not, then ditch it and poll again.

How do I change the value of priority queue?

To update priority in Priority Queue, get the index of the element that you want to update the priority of and assign a new key to the element. After updating the priority of an element, we need to heapify the heap to maintain the heap data structure.

What happens if two elements have the same priority in priority queue?

An element with high priority is dequeued before an element with low priority. If two elements have the same priority, they are served according to their order in the queue.

How can you set the priority for the elements in a priority queue?

1. Adding Elements: In order to add an element in a priority queue, we can use the add() method. The insertion order is not retained in the PriorityQueue. The elements are stored based on the priority order which is ascending by default.


2 Answers

You have to remove and re-insert, as the queue works by putting new elements in the appropriate position when they are inserted. This is much faster than the alternative of finding the highest-priority element every time you pull out of the queue. The drawback is that you cannot change the priority after the element has been inserted. A TreeMap has the same limitation (as does a HashMap, which also breaks when the hashcode of its elements changes after insertion).

If you want to write a wrapper, you can move the comparison code from enqueue to dequeue. You would not need to sort at enqueue time anymore (because the order it creates would not be reliable anyway if you allow changes).

But this will perform worse, and you want to synchronize on the queue if you change any of the priorities. Since you need to add synchronization code when updating priorities, you might as well just dequeue and enqueue (you need the reference to the queue in both cases).

like image 142
Thilo Avatar answered Oct 24 '22 05:10

Thilo


I don't know if there is a Java implementation, but if you're changing key values alot, you can use a Fibonnaci heap, which has O(1) amortized cost to decrease a key value of an entry in the heap, rather than O(log(n)) as in an ordinary heap.

like image 32
Jon McCaffrey Avatar answered Oct 24 '22 05:10

Jon McCaffrey