Skip to content

Instantly share code, notes, and snippets.

@johannes-weber
Created January 17, 2018 15:25
Show Gist options
  • Save johannes-weber/f5806e922cc707b5d159baa4860df090 to your computer and use it in GitHub Desktop.
Save johannes-weber/f5806e922cc707b5d159baa4860df090 to your computer and use it in GitHub Desktop.
JavaScript implementation of a Min and Max Heap
function Heap (compareFunc) {
var _self = this;
this.elements = [];
this.compareFunc = compareFunc;
_self.swap = function(aIdx, bIdx) {
var a = _self.elements[aIdx];
var b = _self.elements[bIdx];
var tmp = a;
_self.elements[aIdx] = b;
_self.elements[bIdx] = tmp;
if((a instanceof Object) && (b instanceof Object)) {
a['_index'] = bIdx;
b['_index'] = aIdx;
}
};
_self.set = function(element, i) {
if ((i < 0) || i >= _self.elements.length) {
throw "index out of range."
}
_self.elements[i] = element;
if(element instanceof Object) {
element['_index'] = i;
}
};
_self.parent = function(i) {
if (i == 0) {
return 0;
}
var idx = Math.floor((i - 1) / 2);
return idx;
};
_self.leftChild = function(i) {
var idx = (2 * i) + 1;
if (_self.elements.length <= idx) {
return -1;
}
return idx;
};
_self.rightChild = function(i) {
var idx = (2 * i) + 2;
if (_self.elements.length <= idx) {
return -1;
}
return idx;
};
_self.upHeap = function(i) {
var child = _self.elements[i];
var parentIdx = _self.parent(i);
if(parentIdx === -1) {
// No parent.
return;
}
if (i === parentIdx) {
return;
}
var parent = _self.elements[parentIdx];
if (compareFunc(child, parent)) {
// Swap.
_self.swap(i, parentIdx);
_self.upHeap(parentIdx);
}
};
_self.downHeap = function(i) {
var node = _self.elements[i];
var rightChildIdx = _self.rightChild(i);
var leftChildIdx = _self.leftChild(i);
var rightChild = null;
var leftChild = null;
var minIdx = -1;
var min = null;
if ((rightChildIdx === -1) && (leftChildIdx === -1)) {
return
}
if (rightChildIdx !== -1) {
rightChild = _self.elements[rightChildIdx];
minIdx = rightChildIdx;
min = rightChild;
}
if (leftChildIdx !== -1) {
leftChild = _self.elements[leftChildIdx];
minIdx = leftChildIdx;
min = leftChild;
}
if ((rightChild !== null) && (leftChild !== null)) {
if(compareFunc(rightChild, leftChild)) {
minIdx = rightChildIdx;
min = rightChild;
}
else {
minIdx = leftChildIdx;
min = leftChild;
}
}
if (compareFunc(min, node)) {
// Swap.
_self.swap(minIdx, i);
_self.downHeap(minIdx);
}
};
_self.heapify = function(i) {
if ((i < 0) || (i >= _self.elements.length)) {
throw "index out of range.";
}
var node = _self.elements[i];
var parent = _self.elements[_self.parent(i)];
if (_self.compareFunc(node, parent)) {
_self.upHeap(i);
}
else {
_self.downHeap(i);
}
};
_self.Peek = function() {
if (_self.elements.length == 0) {
return null;
}
return _self.elements[0];
};
_self.Pop = function() {
if (_self.elements.length == 0) {
return null;
}
var result = _self.elements[0];
// Place last element on root and heapify.
var last = _self.elements.splice(_self.elements.length-1, 1)[0];
if (_self.elements.length > 0) {
_self.set(last, 0);
_self.downHeap(0);
}
return result;
};
_self.Push = function(element) {
_self.elements.push(element);
var idx = _self.elements.length - 1;
if(element instanceof Object) {
element['_index'] = idx;
if('on' in element) {
element.on('change', function(value) {
_self.heapify(element['_index']);
});
}
}
_self.upHeap(idx);
};
};
// max heap compare
var maxHeapCompareFunc = function(a, b) { return a > b; };
// min heap compare function.
var minHeapCompareFunc = function(a, b) { return a < b; };
var maxHeap = new Heap(maxHeapCompareFunc);
maxHeap.Push(1);
maxHeap.Peek(1);
maxHeap.Pop(1);
var minHeap = new Heap(maxHeapCompareFunc);
minHeap.Push(1);
minHeap.Peek(1);
minHeap.Pop(1);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment