Skip to main content

Heaps (priority queues)

Complete Binary Tree

Each level of a Complete Binary Tree contains the maximum number of nodes, except possibly the last layer, which must be filled from left to right.

Heap property

Heap property essentially means that for any given node C, if P is a parent node of C, then:

  • For a max heap: the key of P should be greater than or equal to the key of C.
  • For a min heap: the key of P should be less than or equal to the key of C.

Heaps are stored as arrays

If a node is placed at index i in array, then given that the resultant index lies within length of the array:

  • Left child would be at (2i+1)th position
  • Right child would be at (2i+2)the position

If a node is placed at index i in array, it's parent node would be located at floor((i-1)/2)th index.

Implementation (Min Heap)

heappush

adds the provided newKey into the min-heap named "heap"

function heappush(heap, newKey){
// push the new key
heap.push(newKey);

// get the current index of pushed key
let curr = heap.length-1;

// keep comparing till root is reached or we terminate in middle
while(curr > 0){
let parent = Math.floor((curr-1)/2)
if( heap[curr] < heap[parent] ){
// quick swap
[ heap[curr], heap[parent] ] = [ heap[parent], heap[curr] ]
// update the index of newKey
curr = parent
} else{
// if no swap, break, since we heap is stable now
break
}
}
}

heappop

removes the smallest key from the min-heap named "heap"

function heappop(heap){
// swap root with last node
const n = heap.length;
[heap[0], heap[n-1]] = [ heap[n-1], heap[0]]

// remove the root i.e. the last item (because of swap)
const removedKey = heap.pop();

let curr = 0;

// keep going till atleast left child is possible for current node
while(2*curr + 1 < heap.length){
const leftIndex = 2*curr+1;
const rightIndex = 2*curr+2;
const minChildIndex = (rightIndex < heap.length && heap[rightIndex] < heap[leftIndex] ) ? rightIndex :leftIndex;
if(heap[minChildIndex] < heap[curr]){
// quick swap, if smaller of two children is smaller than the parent (min-heap)
[heap[minChildIndex], heap[curr]] = [heap[curr], heap[minChildIndex]]
curr = minChildIndex
} else {
break
}
}

// finally return the removed key
return removedKey;
}

heapify

transforms a pre-existing array into a heap

function percolateDown(heap, index) {
let curr = index;
// keep going down till heap property is established
while (2 * curr + 1 < heap.length) {
const leftIndex = 2 * curr + 1;
const rightIndex = 2 * curr + 2;
const minChildIndex = (rightIndex < heap.length && heap[rightIndex] < heap[leftIndex]) ? rightIndex : leftIndex;
if (heap[minChildIndex] < heap[curr]) {
// quick swap, if smaller of two children is smaller than the parent (min-heap)
[heap[minChildIndex], heap[curr]] = [heap[curr], heap[minChildIndex]]
curr = minChildIndex
} else {
break
}
}
}

function heapify(heap){
const last = Math.floor(heap.length/2 - 1);
for(let i = 0; i <= last; i++){
percolateDown(heap, i)
}
return heap
}

How to make it into a Max Heap

Max heap is a min heap using negative keys.

Say we have an array const x = [23, 454, 54, 29]

const minHeap = [];
for(let el of x) heappush(minHeap, el);

// min value
const min = heappop(minHeap)
const maxHeap = [];
for(let el of x) heappush(maxHeap, el);

// max value
const max = -heappop(maxHeap)