Chapter 11: Priority Queues and Heaps

Chapter 11: Priority Queues and Heaps · Study Questions
The priority queue ADTList-based implementationsBinary heaps and the array representationUp-heap and down-heapAdaptable priority queuesHeap construction and heap sortJava PriorityQueue
Sercan KÜLCÜ · Giresun University · Computer Engineering

Multiple Choice · The Priority Queue ADT

Question 1: Equal Priorities

In a min-priority queue, Eve and Nina have the same priority (1), and Eve arrived first. What must be done to guarantee that Eve leaves before Nina?

Correct: B. Sequence numbers are always distinct, so they break every tie: when priorities are equal, the smaller sequence number (the earlier arrival) leaves first. A is the strongest distractor: a heap (and Java's PriorityQueue) gives no FIFO guarantee for equal keys.

Short Answer · The Priority Queue ADT

Question 2: A Sequence of Operations

The operations below are applied in order to an empty min-priority queue. For each operation that returns a value, give the result and the queue contents at that moment.

insert(8, P)
insert(3, Q)
insert(6, R)
min()
removeMin()
insert(2, S)
removeMin()
removeMin()
size()
removeMin()
removeMin()
Show answer
OperationReturnsQueue
min()(3,Q){(3,Q), (6,R), (8,P)}
removeMin()(3,Q){(6,R), (8,P)}
removeMin()(2,S){(6,R), (8,P)}
removeMin()(6,R){(8,P)}
size()1{(8,P)}
removeMin()(8,P){ }
removeMin()null{ } (empty queue)

min() returns the entry without removing it; removeMin() removes it. (2,S) arrives late, but as the smallest key it goes straight to the front. On an empty queue removeMin() returns null.

Code Trace · List-Based Implementations

Question 3: removeMin on an Unsorted Array

removeMin() is called on an unsorted array. What value is returned, and what does the array look like afterward?

First candidate: index 0 (7). In an unsorted array the minimum could be anywhere.

a[1] = 4 < a[0] = 7 → new minimum, minIdx = 1.

a[2] = 9 ≥ 4 → minIdx stays.

a[3] = 2 < 4 → minIdx = 3.

a[4] = 6 ≥ 2 → minIdx stays.

k = 5 = n → scan done: 4 comparisons. Every removeMin scans the whole array → O(n).

min = a[3] = 2 is saved.

The last item (6) fills the gap, n = 4. Order doesn't matter, so no shifting: O(1).

return 2. The remaining array [7, 4, 9, 6] is still unsorted.

public int removeMin() {
  int minIdx = 0;
  for (int k = 1; k < n; k++)
    if (a[k] < a[minIdx]) minIdx = k;
  int min = a[minIdx];
  a[minIdx] = a[n - 1];  n--;
  return min;
}
// a = [7, 4, 9, 2, 6], n = 5

Multiple Choice · List-Based Implementations

Question 4: n Insertions + n Removals

n items are inserted into an empty priority queue, followed by n calls to removeMin(). What is the total cost with an unsorted list, a sorted list, and a binary heap, respectively?

Correct: C. Unsorted: n·O(1) + n·O(n) = O(n²). Sorted: n·O(n) + n·O(1) = O(n²). Heap: 2n·O(log n) = O(n log n). A is the distractor: insertion into an unsorted list is cheap, but every removeMin scans the whole list. For n = 10⁶ the difference is a factor of about 50,000.

Short Answer · List-Based Implementations

Question 5: Tracing a Priority Queue

A max-priority queue is implemented with a sorted array (a larger number means higher priority; ties keep arrival order). The calls insert(A,3), insert(B,1), insert(C,4), insert(D,3), remove(), insert(E,4), remove(), remove() are made in order. What do the remove() calls return, and what is the final array?

Show answer
OperationArray (data:priority)
insert(A,3)A:3
insert(B,1)A:3, B:1
insert(C,4)C:4, A:3, B:1
insert(D,3)C:4, A:3, D:3, B:1
remove → CA:3, D:3, B:1
insert(E,4)E:4, A:3, D:3, B:1
remove → EA:3, D:3, B:1
remove → AD:3, B:1

Removed: C, E, A; final array [D:3, B:1]. D lines up behind A, which has the same priority (3 < 3 is false). E leaves before A even though it arrived later: priority, not arrival, decides the order.

Multiple Choice · List-Based Implementations

Question 6: Equal Priority

In the priority queue's insert() method, the condition < is changed to <=. After insert(X,3), insert(Y,3), insert(Z,1) on an empty queue, what does remove() return?

int i = size;
while (i > 0 && items[i-1].priority <= p) {
    items[i] = items[i - 1];  // shift right
    i--;
}
items[i] = new Item<>(data, p);
size++;

With <=, X, which has the same priority, is shifted right as well: [Y:3, X:3, Z:1]. The array is still sorted from largest to smallest (so C is wrong), but FIFO order among ties is lost. With the original <, X would have stayed in front; A describes the original code.

Short Answer · Binary Heaps

Question 7: Heap or Not?

In the tree below, every parent is larger than its children. Is this tree a max-heap? If not, which property fails?

2015189107
Show answer

It is not a max-heap. Heap order holds (20 ≥ 15, 18; 15 ≥ 9; 18 ≥ 10, 7), but the complete binary tree property fails: the last level is not filled from left to right, since 15 has no right child while 18 has children.

In the array representation, this means index 4 is empty: [20, 15, 18, 9, _, 10, 7]. A heap's array must have no gaps; a new item always goes into the first free slot (index n).

Heap = complete binary tree and heap order; both are required.

Multiple Choice · Binary Heaps

Question 8: A Valid Min-Heap Array

Which of these is a valid min-heap array (0-based)?

Correct: C. Every i must satisfy a[(i−1)/2] ≤ a[i]: 1 ≤ 3, 2; 3 ≤ 6, 4; 2 ≤ 5. In A, the 4 at index 1 is larger than its child 3 (index 3); having the smallest item at the root is not enough. In B the root 2 > 1, and in D the 2 at index 1 is larger than its child 0 (index 4).

Multiple Choice · Binary Heaps

Question 9: The Result of isHeap

What does the call below return?

static boolean isHeap(int[] a) {
  for (int i = 1; i < a.length; i++) {
    int p = (i - 1) / 2;
    if (a[p] < a[i]) return false;
  }
  return true;
}
isHeap(new int[]{9, 6, 8, 3, 7, 8, 1});

Correct: D. i = 1…3 pass (9 ≥ 6, 8; 6 ≥ 3). At i = 4: p = 1, a[1] = 6 < a[4] = 7 → false. C is wrong: the test is strict (<), so equality does not break a heap, and the loop never gets that far anyway. The check takes at most n − 1 comparisons: O(n).

Code Trace · Insertion and Removal

Question 10: Inserting into a Max-Heap

insert(45) is called on the max-heap heap = [50, 30, 40, 10, 20, 35] (n = 6, capacity 8). How many levels does 45 rise, and what is the final array?

503040102035
503040102035

n = 6 ≠ 8 → the array is not full, so resize is not called.

50304010203545

45 goes into the first free slot, heap[6]; n = 7. The tree stays complete.

50304010203545

swim(6): i = 6 > 0 → enter the loop.

50304010203545

parent = (6 − 1)/2 = 2. heap[2] = 40 < 45 → no return.

50304510203540

Swap (6 ↔ 2): 45 rises one level, i = 2.

50304510203540

parent = 0: heap[0] = 50 ≥ 45 → return.

50304510203540

Done: 45 rose one level. Final array [50, 30, 45, 10, 20, 35, 40]. At most h swaps → O(log n).

public void insert(int x) {
  if (n == heap.length) resize(2 * n);
  heap[n] = x;  n++;
  swim(n - 1);
}
private void swim(int i) {
  while (i > 0) {
    int parent = (i - 1) / 2;
    if (heap[parent] >= heap[i]) return;
    swap(i, parent); i = parent;
  }
}

Short Answer · Insertion and Removal

Question 11: Successive Insertions

4, 9, 2, 7, 11, 5, 8 are inserted in this order into an empty max-heap of capacity 4. What is the array after each insertion, and when does the capacity grow?

Show answer
insertArraySwaps
4[4]-
9[9, 4]9↔4
2[9, 4, 2]-
7[9, 7, 2, 4]7↔4
11[11, 9, 2, 4, 7]11↔7, 11↔9
5[11, 9, 5, 4, 7, 2]5↔2
8[11, 9, 8, 4, 7, 2, 5]8↔5

When 11 is inserted, n = 4 = capacity, so resize(8) runs first (copying 4 items).

11984725

Multiple Choice · Insertion and Removal

Question 12: Why the Larger Child?

After removeMax on a max-heap, the 3 moved to the root has left child 8 and right child 9. Which child should down-heap swap the 3 with?

Correct: B. If 9 moves up, the new root 9 has children 8 and 3, and the order holds. If 8 moved up (A, C), the root 8 would have the child 9: 8 < 9, so heap order breaks. In a min-heap, pick the smaller child instead.

Code Trace · Insertion and Removal

Question 13: removeMax and Down-Heap

removeMax() is called on the max-heap heap = [12, 10, 8, 4, 9, 7, 3] (n = 7). What is returned, and what is the final array?

121084973
121084973

The largest is always at the root: max = 12.

310849712

Swap the root with the last item (0 ↔ 6), n = 6: 12 is outside the heap. The new root 3 breaks the order.

310849712

sink(0): children 10 and 8 → the larger is 10, j = 1.

103849712

3 < 10 → swap (0 ↔ 1), i = 1.

103849712

Children 4 (index 3) and 9 (index 4) → j = 4.

109843712

3 < 9 → swap (1 ↔ 4), i = 4.

109843712

2·4 + 1 = 9 ≥ n = 6 → a leaf, so the loop ends.

109843712

return 12. The new heap is [10, 9, 8, 4, 3, 7]; at most ⌊log₂ n⌋ levels → O(log n).

public int removeMax() {
  int max = heap[0];
  swap(0, n - 1);  n--;
  sink(0);
  return max;
}
private void sink(int i) {
  while (2 * i + 1 < n) {
    int j = 2 * i + 1;
    if (j+1 < n && heap[j+1] > heap[j]) j++;
    if (heap[i] >= heap[j]) return;
    swap(i, j);  i = j;
  }
}

Short Answer · Insertion and Removal

Question 14: Forgetting the Right-Child Bound

This sink forgets the j + 1 < n check. If removeMax() is called on the max-heap [9, 8, 3, 5, 4] (n = 5), what do the first n items of the heap become?

private void sink(int i) {
  while (2 * i + 1 < n) {
    int j = 2 * i + 1;
    if (heap[j + 1] > heap[j]) j++;
    if (heap[i] >= heap[j]) return;
    swap(i, j);  i = j;
  }
}
Show answer
  • max = 9; 9 ↔ 4, n = 4: [4, 8, 3, 5 | 9].
  • i = 0: j = 1 (8 > 3); 4 < 8 → swap: [8, 4, 3, 5 | 9].
  • i = 1: j = 3; because heap[4] = 9 > 5, the buggy code picks j = 4 (a removed item!); 4 < 9 → swap: [8, 9, 3, 5 | 4].

Result [8, 9, 3, 5]: the removed 9 is back, 4 is lost, and 9 > its parent 8 → the heap is broken. The correct result is [8, 5, 3, 4].

Fix: if (j + 1 < n && heap[j + 1] > heap[j]) j++; (when sink is called without first decreasing n, as in buildHeap, the buggy code can also throw ArrayIndexOutOfBoundsException if the array is completely full).

Short Answer · Heap Construction and Heap Sort

Question 15: Bottom-Up Heap Construction

Turn the array [2, 9, 4, 7, 1, 8, 5, 3] into a max-heap bottom-up. At which k does the loop start, and what is the array after each sink(k)?

Show answer

n = 8 → the first k = n/2 − 1 = 3 (the last internal node); indices 4–7 are leaves, each already a heap on its own.

kStepArray
37 ≥ 3, no swap[2, 9, 4, 7, 1, 8, 5, 3]
24 ↔ 8[2, 9, 8, 7, 1, 4, 5, 3]
19 ≥ 7, 1, no swap[2, 9, 8, 7, 1, 4, 5, 3]
02 ↔ 9, 2 ↔ 7, 2 ↔ 3[9, 7, 8, 3, 1, 4, 5, 2]

Result: [9, 7, 8, 3, 1, 4, 5, 2]. Whenever sink(k) is called, the subtrees of k are already heaps. Total O(n); n insertions would cost O(n log n).

Multiple Choice · Heap Construction and Heap Sort

Question 16: Why O(n)?

In a complete binary tree with 15 nodes (h = 3), how many swaps does bottom-up heap construction make in the worst case?

Correct: D. In down-heap, the number of swaps is at most the node's height: 8 leaves·0 + 4·1 + 2·2 + 1·3 = 11 ≤ n. A (34) is the worst case for n insertions into the same tree: the cost of up-heap depends on depth, and most nodes are deep: 2·1 + 4·2 + 8·3 = 34. Still, when items arrive one at a time (online), insertion is the only option.

Short Answer · Heap Construction and Heap Sort

Question 17: Heap Sort by Hand

Sort the array [3, 7, 2, 9, 5] into ascending order with heap sort. Write the array after building the max-heap and after each “move the root to the end + sink” step.

Show answer
StepArray (sorted to the right of |)
Build (k = 1, 0)[9, 7, 2, 3, 5]
last = 4: 9 to the end[7, 5, 2, 3 | 9]
last = 3: 7 to the end[5, 3, 2 | 7, 9]
last = 2: 5 to the end[3, 2 | 5, 7, 9]
last = 1: 3 to the end[2 | 3, 5, 7, 9]

Result: [2, 3, 5, 7, 9]. Building: at k = 1, 7 ↔ 9; at k = 0, 3 ↔ 9, 3 ↔ 7. Then the root moves to the end n − 1 times, and the heap shrinks by one each time. Building O(n) + n − 1 sinks at O(log n) = O(n log n), with no extra array.

Multiple Choice · Heap Construction and Heap Sort

Question 18: Properties of Heap Sort

Which statement about heap sort is false?

Answer: C (the false statement). Long-distance swaps between the root and the last item can reorder equal keys; heap sort is not stable. D is true: at every step the largest item goes to the end of the array, so a max-heap gives ascending order (a min-heap, descending). A is true: heap sort has no O(n²) worst case like quick sort's.

Short Answer · Heap Construction and Heap Sort

Question 19: PriorityQueue Output

What does the following program print?

PriorityQueue<Integer> pq = new PriorityQueue<>();
for (int x : new int[]{7, 2, 9, 4, 1})
    pq.offer(x);
System.out.println(pq);
System.out.print(pq.poll() + " ");
System.out.println(pq.poll());
pq.offer(3);
System.out.println(pq.peek() + " " + pq.size());
PriorityQueue<Integer> mx = new
    PriorityQueue<>(Comparator.reverseOrder());
mx.addAll(Arrays.asList(7, 2, 9));
System.out.println(mx.poll());
Show answer
[1, 2, 9, 7, 4]
1 2
3 4
9
  • println(pq) prints the internal array in heap order, not sorted order: inserting 4 swaps it with 7, and inserting 1 swaps it with 4 and then 2 → [1, 2, 9, 7, 4].
  • PriorityQueue is a min-heap by default: poll → 1, poll → 2.
  • {4, 7, 9} remain; after inserting 3, peek → 3 (without removing it), size → 4.
  • With reverseOrder() it is a max-heap: poll → 9.

Multiple Choice · Heap Construction and Heap Sort

Question 20: The PriorityQueue Class

Which statement about Java's PriorityQueue class is true?

Correct: A. A heap is not sorted, so finding a particular item means a linear search of the array. B is false and a common mistake: the default is a min-heap; for a max-heap use Comparator.reverseOrder(). There is no FIFO guarantee among ties, and the class is not thread-safe (use PriorityBlockingQueue). offer/poll are O(log n), peek is O(1).

Short Answer · Heap Construction and Heap Sort

Question 21: The k-th Largest

With the a and k given in the comment, what does the call return, and which items are left in pq when the loop ends? What does the method cost?

static int kthLargest(int[] a, int k) {
  PriorityQueue<Integer> pq =
      new PriorityQueue<>();
  for (int x : a) {
    pq.offer(x);
    if (pq.size() > k) pq.poll();
  }
  return pq.peek();
}
// a = {4, 8, 1, 7, 3, 9, 2}, k = 3
Show answer
xafter offerpollpq
4, 8, 1{1, 4, 8}-{1, 4, 8}
7{1, 4, 7, 8}1{4, 7, 8}
3{3, 4, 7, 8}3{4, 7, 8}
9{4, 7, 8, 9}4{7, 8, 9}
2{2, 7, 8, 9}2{7, 8, 9}

pq = {7, 8, 9} (the three largest items); peek() → 7 (the 3rd largest).

The root of the min-heap is the smallest of the k largest, so small items are dropped right away. The heap never holds more than k + 1 items: O(n log k) time, O(k) memory.

Short Answer · Insertion and Removal

Question 22: Tracing changeKey

The deck's changeKey(i, key) (swim if the key increased, sink if it decreased) is called on the max-heap [30, 24, 28, 9, 20, 26, 11], first as changeKey(3, 29) and then as changeKey(0, 7). Which swaps does each call make, and what is the resulting array?

Show answer
  • changeKey(3, 29): 9 → 29, the key increased → swim(3). Parent (3 − 1)/2 = 1: 24 < 29 → swap. Parent 0: 30 ≥ 29 → stop. Array [30, 29, 28, 24, 20, 26, 11].
  • changeKey(0, 7): 30 → 7, the key decreased → sink(0). Children 29, 28 → swap with 29; i = 1: children 24, 20 → swap with 24; i = 3 is a leaf. Array [29, 24, 28, 7, 20, 26, 11].

Each call follows a single root-to-leaf path: O(log n). The item's index is read from its locator in O(1); without a locator, just finding the item would take O(n). In a location-aware heap, every swap updates the indices of both items.

Multiple Choice · Insertion and Removal

Question 23: The Heap after remove(e)

In the max-heap [50, 20, 40, 10, 15, 35, 38], the entry at position 3 (10) is deleted with remove(e): swap with the last item, n − 1, then up-heap or down-heap the item that took its place. What is the final array?

Correct: A. 38 lands at index 3; its parent (index 1) is 20 < 38, so it needs an up-heap: 38 ↔ 20; 50 ≥ 38 → stop. B tries only a down-heap: index 3 is a leaf, so nothing happens and the 20 < 38 violation remains. C shifts the array left, which takes O(n) and breaks the order (20 gets the child 35). D forgets the n − 1, so the deleted 10 is still in the heap.

Short Answer · Heap Construction and Heap Sort

Question 24: Heap Sort Is Not Stable

Records have the form (key, label), and the deck's heapSort compares keys only. When [(4,a), (4,b), (2,c), (1,d)] is sorted, what is the array after each step? Do a and b, which have equal keys, keep their relative order?

Show answer
StepArray (sorted to the right of |)
Build (k = 1, 0)[(4,a), (4,b), (2,c), (1,d)]: no swaps (a[i] ≥ a[j] stops on a tie)
last = 3: (4,a) to the end, (4,b) to the root[(4,b), (1,d), (2,c) | (4,a)]
last = 2: (4,b) to the end[(2,c), (1,d) | (4,b), (4,a)]
last = 1: (2,c) to the end[(1,d) | (2,c), (4,b), (4,a)]

Result: (1,d), (2,c), (4,b), (4,a). In the input a came before b; in the output it comes after: heap sort is not stable. The reason: the root (4,a) travels to the very end in one long-distance swap, while (4,b), with the same key, rises to the root and settles in the slot before it.

If stability matters, add an arrival sequence number to the key or use a stable sort (merge sort, say).

The End

Chapter 11: Priority Queues and Heaps: Study Questions
Lecture slides: Chapter 11: Priority Queues and Heaps
1 / 1 Sercan KÜLCÜ. All rights reserved.