Remove an element from any position in a max heap

I have a Point object that just has an x and y, and I have a Heap data structure that looks like so:

class MaxHeap{
public Point[] heap;
public int size;
public int maxsize;

public MaxHeap(int maxsize){
    this.maxsize = maxsize;
    this.size = 0;
    heap = new Point[this.maxsize+1];
    heap[0] = new Point(-1,-1); //Heap is empty
}

public int parent(int pos){
    return pos /2;
}

public int leftChild(int pos){
    return (2 * pos);
}

public int rightChild(int pos){
    return (2 * pos) +1;
}

public boolean isLeaf(int pos){
    if (pos >= (size / 2) && pos <= size){
        return true;
    }
    return false;
}

public void swap (int fpos, int spos){
    Point tmp;
    tmp = heap[fpos];
    heap[fpos] = heap[spos];
    heap[spos] = tmp;
}

public void maxHeapify(int pos){
    if (!isLeaf(pos)){
        if (heap[pos].getY() < heap[leftChild(pos)].getY() || heap[pos].getY() < heap[rightChild(pos)].getY()){
            swap(pos, leftChild(pos));
            maxHeapify(leftChild(pos));
        }
        else{
            swap(pos, rightChild(pos));
            maxHeapify(rightChild(pos));
        }
    }
}

public void insert (Point p){
    heap[++size] = p;
    int current = size;
    while (heap[current].getY() > heap[parent(current)].getY()){
        swap(current, parent(current));
        current = parent(current);
    }
}

I am trying to implement a way to remove any Point from the Heap, instead of the traditional remove where it just removes the top. I’m not entirely sure how to go about doing this. I was thinking I could store the index of the Point in the heap inside of the Point. I’m not sure if this would help or not.

Answer

Just is case, are you aware that there is standard heap implementation in Java called PriorityQueue? You can use it as the reference of how removeAt(int i) is implemented.

Back to your question.

In order to remove intermediate element from the queue, you need to replace it with the last element of the queue (shrinking the queue by one element) and try to “heapify” this element down. If element is still in place (both children were bigger than the element) you need to “heapify” it up.

Regarding second part of your question. I’d not recommend storing queue indices inside Point class and hence making points queue-aware. The better way is to maintain Map from point to its index inside the queue (this map can be represented by IdentityHashMap[Point, Integer]). Just don’t forget to make appropriate changes in this map when you are making changes in the queue, such as inserting, removing elements, swapping them and so on.

Leave a Reply

Your email address will not be published. Required fields are marked *