Concepts / Queues and Stacks

Queues and Stacks

A priority queue removes elements by priority, not by the order in which they were added.

  • Programming

Predicting the First Element Out

Imagine adding the numbers 5, 2, 8, and 1 to a collection, in that order, and then calling remove once. Which number comes back? The answer depends on the kind of collection you are using. This article looks at the priority queue, a collection in which elements leave in order of priority rather than in the order they arrived. Making a prediction before you read the trace is the fastest way to check whether the priority rule is clear to you.

What do you think happens?

You add 5, then 2, then 8, then 1 to a priority queue of integers. What does a single call to remove return?

  • 5

  • 2

  • 8

  • 1

Reveal answer
Answer:

1

remove takes out the element of minimal priority among those still in the queue. For integers, the smallest value has the minimal priority in this example, so 1 is returned even though it was the last element added.

Why Arrival Order Stops Mattering

A regular queue works like a line at a checkout. The first element added is the first element removed. A priority queue replaces that arrival-order rule with a priority rule. Each element you add competes with the others on priority, and the queue always hands back the one with the minimal priority among those still waiting.

This changes the question you ask while reading a priority queue program. You no longer ask only what came in first. At each step you ask two questions: what was just added, and which element now has the minimal priority. The answer to the second question is the one that will leave next.

The add and remove Methods

Definition

A priority queue removes elements by priority, not by the order in which they were added.

A priority queue offers two methods that the course focuses on. The add method places an object into the queue. The object must be of the element type T that the queue was declared with. The remove method takes no arguments, removes the element of minimal priority, and returns it. The returned value is also of type T.

The source also mentions addAll, which adds every element of a collection named coll to the queue in one call. It is a convenience for loading many elements at once; the add and remove rules stay the same.

Notes on the code
  • add places each value into the queue; it does not return a removed item
  • remove takes no arguments and returns the element of minimal priority
  • The value returned by remove is of the same element type T as the queue

Tracing the Contents Step by Step

The easiest way to see the rule at work is to track what the queue holds after each call. Start with an empty queue and apply the four add calls from the prediction, then one remove. The diagram shows the set of stored elements after each step. Notice that the diagram lists the contents as a set; it does not claim anything about the order the queue keeps them internally.

Startempty queueAfter add 5holds 5After add 2holds 2, 5After add 8holds 2, 5, 8After add 1holds 1, 2, 5, 8After removeholds 2, 5, 8add 5add 2add 8add 1remove returns 1
After each add, the queue holds one more element. The single remove call takes out 1, the element with minimal priority, and leaves the others waiting.
Worked example

Predicting the removal sequence for a short queue

A priority queue of integers receives 7, 3, 9 in that order. Then remove is called twice. Which two values are returned?

  1. 1
    Identify the elements present

    After the three adds, the queue holds 7, 3, and 9. Arrival order is 7, then 3, then 9.

  2. 2
    Find the minimal priority element

    For integers, the smallest value has the minimal priority. Among 7, 3, and 9, the smallest is 3, so the first remove returns 3.

  3. 3
    Remove it and repeat

    After 3 leaves, the queue holds 7 and 9. The minimal priority element now is 7, so the second remove returns 7.

Result

The first remove returns 3 and the second returns 7, even though 7 was added first.

Insertion Order Versus Priority Order

The same four values can leave the queue in a completely different sequence from the one they arrived in. The comparison below lines up the order of additions against the order of removals. Each removal takes the smallest value still waiting, so the removal column is always sorted from smallest to largest, while the addition column follows the order of the add calls.

5first added1first removed2second added2second removed8third added5third removed1fourth added8fourth removed
Values were added as 5, 2, 8, 1. Repeated remove calls return them as 1, 2, 5, 8, which is the priority order rather than the arrival order.

The source uses the phrase minimal priority, and it notes that for integers the smallest value is the one with minimal priority in this example. The rule that the removed element has minimal priority stays the same for any element type. Only the meaning of minimal depends on how the elements are compared. So if you change the element type, you must ask what minimal means for that type before predicting the output.

Draining a Queue Without the Empty Error

The source states that remove throws an exception if the queue is empty. That means you cannot call remove as many times as you like. If you call it when nothing is left, the program fails. The guard against this is the isEmpty check, which reports whether any elements remain. Each remove should happen only while isEmpty says there is at least one element left.

Begin drainingQueue empty?Remove and processitemStop loopno, elements remaincheck againyes, nothing left
The loop checks isEmpty before every remove. While elements remain, it removes and processes one element and checks again. When the queue is empty, the loop stops without calling remove.
Notes on the code
  • The isEmpty check runs before every remove call
  • remove is called only when at least one element is present
  • When the queue is empty the loop ends without calling remove

This is the standard pattern for draining a priority queue: keep calling remove until isEmpty reports that nothing is left. The source's own loop guards every call this way, so each removal happens only while there is at least one element.

Mistakes Beginners Make with Removal

  • Common mistake

    Predicting the first removal by arrival order

    What it looks like

    After adding 5, 2, 8, and 1, the learner says the first remove returns 5 because 5 was added first.

    Why it fails

    A priority queue removes the element of minimal priority, not the earliest arrival.

    Do this instead

    Find the smallest value currently in the queue. Here that is 1, so remove returns 1.

  • Common mistake

    Calling remove without checking whether elements remain

    What it looks like

    A loop calls remove a fixed number of times, such as four, on a queue that was only given three elements.

    Why it fails

    The source states that remove throws an exception on an empty queue, so the extra call fails.

    Do this instead

    Use a loop guarded by isEmpty, calling remove only while isEmpty reports that elements remain.

  • Common mistake

    Assuming minimal always means the smallest number

    What it looks like

    A learner uses the integer rule for a queue of a different element type and predicts the wrong removal.

    Why it fails

    The rule that minimal priority leaves first stays the same, but what minimal means depends on how the elements are compared.

    Do this instead

    Before predicting, decide what minimal means for the element type in use.

Practice: Tracing a Queue

MEDIUM

A priority queue of integers receives the values 9, 4, 6, and 3, in that order. Trace the contents after each add. Then predict the value returned by each of the next two remove calls, using the state you traced. Finally, write a guarded loop that removes and prints every remaining element.

Hints
  • After each add, list every element still in the queue, not only the newest one.
  • For integers, the element with minimal priority is the smallest value currently waiting.
  • Remove the element you identified, then repeat the minimal-priority check on what is left.
  • Put the isEmpty check at the top of the loop so remove is never called on an empty queue.

Key Takeaways from Queue Removal

  1. 1
    A priority queue removes the element of minimal priority, not the element that was added first.
  2. 2
    add places an object of the element type T into the queue, and remove takes no arguments and returns the minimal priority element.
  3. 3
    To predict the next removal, track which elements are currently waiting and find the minimal priority among them.
  4. 4
    remove throws an exception on an empty queue, so guard each call with isEmpty and loop only while elements remain.

At a glance

  • A priority queue removes elements by priority, not by the order in which they were added.
  • add places an element of type T into the queue, and remove returns the element of minimal priority.
  • Predict removal order by finding the minimal priority element among those still in the queue at each step.
  • remove throws an exception on an empty queue, so drain the queue with a loop guarded by isEmpty.