As I understand, binary heap
does not support removing random elements. What if I need to remove random elements from a binary heap
?
Obviously, I can remove an element and re-arrange the entire heap in O(N)
. Can I do better?
As I understand, binary heap
does not support removing random elements. What if I need to remove random elements from a binary heap
?
Obviously, I can remove an element and re-arrange the entire heap in O(N)
. Can I do better?
Yes and no.
The problem is a binary heap does not support search for an arbitrary element. Finding it is itself O(n)
.
However, if you have a pointer to the element (and not only its value) - you can swap the element with the rightest leaf, remove this leaf, and than re-heapify the relevant sub-heap (by sifting down the newly placed element as much as needed). This results in O(logn)
removal, but requires a pointer to the actual element you are looking for.
Amit is right in his answer but here is one more nuance:
the position of the removed item (where you put the right-most leaf) can be required to be bubbled up (compare with parent and move up until parent is larger than you). Sometimes it is required to bubble down (compare with children and move down until all children are smaller than you). It all depends on the case.
Depends on what is meant by "random element." If it means that the heap contains elements [e1, e2, ..., eN] and one wants to delete some ei (1 <= i <= N), then this is possible.
If you are using a binary heap implementation from some library, it might be that it doesn't provide you with the API that you need. In that case, you should look for another library that has it.
If you were to implement it yourself, you would need two additional calls:
A procedure deleteAtIndex(heap, i) that deletes the node at index i by positioning the last element in the heap array at i, decrementing the element count, and finally shuffling down/up the new ith element to maintain the heap invariant. The most common use of this procedure is to "pop" the heap by calling deleteAtIndex(heap, 1) -- assuming 1-origin indexing. This operation will run O(log n) (though, to be complete, I'll note that the highest bound can be improved up to O(log(log n)) depending on some assumptions about your elements' keys).
A procedure deleteElement(heap, e) that deletes the element e (your arbitrary element). Your heap algorithm would maintain an array ElementIndex such that ElementIndex[e] returns the current index of element e: calling deleteAtIndex(heap, ElementIndex[e]) will then do what you want. It will also run in O(log n) because the array access is constant.
Since binary heaps are often used in algorithms that merely pop the highest (or lowest) priority element (rather than deleting arbitrary elements), I imagine that some libraries might miss on the deleteAtIndex API to save space (the extra ElementIndex array mentioned above).