I have an Indexed Minimum Priority Queue implemented as a heap. When deleting an indexed element, the code is:
public void delete(int i) {
if (i < 0 || i >= maxN) throw new IllegalArgumentException();
if (!contains(i)) throw new NoSuchElementException("index is not in the priority queue");
int index = qp[i];
exch(index, n--);
swim(index); // Why is this needed?
sink(index);
keys[i] = null;
qp[i] = -1;
}
The rest of the code can be found here: https://algs4.cs.princeton.edu/24pq/IndexMinPQ.java.html
Since pq[N
] is the last element in pq[]
, and this is swapped with the element at pq[i]
(which is to be deleted), wouldn't this mean that the value at pq[i]
after the swap is larger or equal to pq[i]
before the swap? The question is why do we have to call swim(i)
at all and not just sink(i)
alone? Under which specific conditions is there a need to call swim(i)
after the swap?
(There are 3 arrays, qp[]
and keys[]
with corresponding indexes, and pq[]
such that qp[pq[i]]
= pq[qp[i]]
= i
.)
Since pq[N] is the last element in pq[], and this is swapped with the element at pq[i] (which is to be deleted), wouldn't this mean that the value at pq[i] after the swap is larger or equal to pq[i] before the swap?
No, that is not necessarily true. The only requirement for a valid min-heap is that a child cannot be smaller than its parent. While this means that the element in the first position is the smallest, it does not mean that the element in the last position is the largest. Consider the following heap:
1
10 2
15 18 5 3
16 17 19 20 7 8 6 4
pq[N]
is 4
and yet there are lots of elements in that heap that are larger than it. Suppose we wanted to remove 15
by replacing it with 4
. 4
is smaller than 10
and so would have to be moved up the tree (using swim
).