Block(array) implementation of a priority queue?

665 views Asked by At

I'm just studying for exams right now, and came across this question in the sample exam:

Block Implementation of a Priority Queue

If we know in advance that a priority queue will only ever need to cater for a small number of discrete priorities (say 10), we can implement all operations of the priority queue in constant time by representing the priority queue as an array of queues - each queue storing the elements of a single priority. Note that while an operation may be linear in the number of priorities in the priority queue, the operation is still constant with respect to the size of the overall data structure.

The Objects stored in this priority queue is not comparable.

I have attempted it but I am lost as to how I am supposed to assign priority with a array implementation priority queue.

I have also tried looking for solutions, but all I've managed to find are examples that used Comparable, which we did not learn in this course.

Question: https://i.stack.imgur.com/5F4YS.jpg

2

There are 2 answers

5
lmcphers On

Each of the arrays will correspond to a different priority. Your lowest level priority array will deal only with objects of that priority level. Your highest level priority array will deal with objects of highest priority level, and so on. When you receive a new object, you place it into the array that corresponds to its priority.

It doesn't matter, then, that objects are not comparable since they are sorted by priority based on the stratification of the arrays. Then, when you are looking for next elements to execute, you check the highest priority array and see if there are any elements; if not, move to the next priority, and so on through each array.

I'm hoping I understood the problem and your question correctly; let me know if you have any additional questions in regards to my answer.

0
tucuxi On

Following on Imcphers' answer, this would be a simple implementation in Java. Note that you do not need Comparable because enqueue takes an extra parameter, namely the discrete priority of the newly-added element:

public class PQueue<T> {
     public static final int MAX_PRIORITIES = 10;
     private ArrayList<ArrayDeque<T> > queues = new ArrayList<>();
     public PQueue() {
         for (int i=0; i<MAX_PRIORITIES; i++) {
             queues.add(new ArrayDeque<T>());
         }
     }
     public void enqueue(int priority, T element) {
         // ... add element to the end of queues[priority]
     }
     public T dequeue() { 
         // ... find first non-empty queue and pop&return its first element
     }
     // ... other methods
}

Here, enqueue() and dequeue() are both O(1), because you know in advance how many priorities there can be, and what their values are (0 to MAX_PRIORITIES-1) so that no sorting is required, and search of a non-empty queue is constant-time (at most, MAX_PRIORITIES queues will have to be tested for emptyness). If these parameters are not known, the best implementation would use

 private TreeSet<ArrayDeque<T extends Comparable> > queues 
      = new TreeSet<>(CustomComparator);

Where the CustomComparator asks queues to sort themselves depending on the natural order of their first elements, and which needs to keep these internal queues sorted after each call to enqueue --- this ups the complexity of enqueue/dequeue to O(log p), where p is the number of distinct priorities (and therefore, internal queues).

Note that Java's PriorityQueue belongs to the same complexity class, but avoids all that object overhead contributed by the TreeSet / ArrayDeque wrappers by implementing its own internal priorty heap.