Last active
May 29, 2022 07:15
-
-
Save fazeelanizam13/67126de1ec4021542e5031acb89a4e45 to your computer and use it in GitHub Desktop.
Implementation of a (min) heap data structure in JavaScript
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class MinHeap { | |
// creates an array of given length | |
constructor(length) { | |
this.data = new Array(length) | |
this.size = 0 | |
} | |
// helpers | |
rehash = () => { | |
// create a new array that is twice the size of current array | |
let newData = new Array(this.data.length * 2) | |
// copy all values in current array to new array | |
// not going through whole array as only .75 array should have values at the point of rehashing | |
let i = 0 | |
while (this.data[i] !== undefined) { | |
newData[i] = this.data[i] | |
i++ | |
} | |
// assign new array to current array | |
this.data = newData | |
} | |
// moves a smaller value up to right place | |
bubbleUp = valueIndex => { | |
// get new value from index | |
let value = this.data[valueIndex] | |
let parentIndex = Math.floor((valueIndex - 1) / 2) | |
let parentValue = this.data[parentIndex] | |
// if new value is less than parent value | |
// (as this is a min heap, smaller values should be moved up) | |
if (value < parentValue) { | |
// swap spots of parent and new value | |
let temp = parentValue | |
this.data[parentIndex] = value | |
this.data[valueIndex] = temp | |
// perform same operation from the current spot | |
this.bubbleUp(parentIndex) | |
// if at right place, return | |
} else return | |
} | |
// moves a larger value down to right place | |
bubbleDown = valueIndex => { | |
// get new value from index | |
let value = this.data[valueIndex] | |
let leftChildIndex = 2 * valueIndex + 1 // 7 | |
let leftChildValue = this.data[leftChildIndex] // x | |
let rightChildIndex = 2 * valueIndex + 2 // 8 | |
let rightChildValue = this.data[rightChildIndex] // x | |
// if not any of children are undefined | |
if (leftChildValue && rightChildValue) { | |
// if either of children are smaller | |
if (value > leftChildValue || value > rightChildValue) { | |
// get smaller of two children | |
let smallerChildValue = Math.min(leftChildValue, rightChildValue) | |
let smallerChildIndex = smallerChildValue === leftChildValue ? leftChildIndex : rightChildIndex | |
// swap spots with smaller child | |
let temp = smallerChildValue | |
this.data[smallerChildIndex] = value | |
this.data[valueIndex] = temp | |
// continue same from current spot | |
this.bubbleDown(smallerChildIndex) | |
} else return | |
// if right child is undefined and left child is smaller, we need to swap one last time | |
} else if (rightChildValue === undefined && value > leftChildValue) { | |
let temp = leftChildValue | |
this.data[leftChildIndex] = value | |
this.data[valueIndex] = temp | |
// perform same operation from the current spot | |
this.bubbleDown(valueIndex) | |
// if both are undefined, return. | |
// they are vacant spots | |
} else return | |
} | |
// helper functions end | |
insert = value => { | |
// if array empty, just insert at root, | |
// increase size | |
// and return | |
if (this.size === 0) { | |
this.data[0] = value | |
this.size++ | |
return | |
} | |
// load factor = filled slots / total slots | |
let loadFactor = this.size / this.data.length | |
// if gte to .75, increase (double) the size | |
if (loadFactor >= .75) this.rehash() | |
// insert new value at the end | |
this.data[this.size] = value | |
// move new value up the tree to the right place from current spot | |
this.bubbleUp(this.size) | |
this.size++ | |
} | |
removeRoot = () => { | |
// get the lowest, right-most value and | |
// assign to root | |
this.data[0] = this.data[this.size - 1] | |
this.data[this.size - 1] = undefined | |
// move new root value down the tree to the right place | |
// swapping with the smaller of two children | |
this.bubbleDown(0) | |
this.size-- | |
} | |
getMin = () => { | |
return this.data[0] | |
} | |
} | |
// tests | |
// let heap = new MinHeap(10) | |
// heap.insert(1) | |
// heap.insert(9) | |
// heap.insert(13) | |
// heap.insert(8) | |
// heap.insert(20) | |
// heap.insert(2) | |
// heap.insert(2) | |
// heap.insert(2) | |
// console.log(heap.size) | |
// console.log(heap.data) | |
// heap.removeRoot() | |
// console.log('size', heap.size) | |
// console.log(heap.data) | |
// heap.removeRoot() | |
// console.log('size', heap.size) | |
// console.log(heap.data) | |
// heap.removeRoot() | |
// console.log('size', heap.size) | |
// console.log(heap.data) | |
// heap.insert(26) | |
// heap.insert(76) | |
// heap.insert(90) | |
// heap.insert(-90) | |
// console.log(heap.data) | |
// console.log(heap.getMin()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment