Skip to content

Instantly share code, notes, and snippets.

@whiler
Created April 24, 2018 08:32
Show Gist options
  • Save whiler/67668f14c0466eca081a203d5655f779 to your computer and use it in GitHub Desktop.
Save whiler/67668f14c0466eca081a203d5655f779 to your computer and use it in GitHub Desktop.
Binary Heap implementation in JavaScript language
"use strict";
function BinaryHeap(keyFunction, scoreFunction) {
this.content = [];
this.map = {};
this.keyFunction = keyFunction || function (e) {
return e;
};
this.scoreFunction = scoreFunction || function (e) {
return e;
};
}
BinaryHeap.prototype = {
push: function (node) {
this.content.push(node);
this.map[this.keyFunction(node)] = this.bubbleUp(this.content.length - 1, node,
this.scoreFunction(node));
return true;
},
pop: function () {
var result = this.content[0], end = this.content.pop();
if (this.content.length > 0) {
this.content[0] = end;
this.map[this.keyFunction(end)] = this.sinkDown(0, end, this.scoreFunction(end));
}
delete this.map[this.keyFunction(result)];
return result;
},
get: function (key) {
return this.map.hasOwnProperty(key) ? this.content[this.map[key]] : null;
},
size: function () {
return this.content.length;
},
update: function (key) {
var idx = this.map[key], node = this.content[idx], score = this.scoreFunction(node);
idx = this.bubbleUp(idx, node, score);
this.map[key] = this.sinkDown(idx, node, score);
return true;
},
bubbleUp: function (n, node, score) {
var parentIdx = null, parent = null;
while (n > 0) {
parentIdx = ((n + 1) >> 1) - 1;
parent = this.content[parentIdx];
if (score < this.scoreFunction(parent)) {
this.content[parentIdx] = node;
this.content[n] = parent;
this.map[this.keyFunction(parent)] = n;
n = parentIdx;
} else {
break;
}
}
return n;
},
sinkDown: function (n, node, score) {
var length = this.content.length,
left = null, leftIdx = null, leftScore = null,
right = null, rightIdx = null, rightScore = null,
swap = null, swapKey = null;
while (true) {
rightIdx = (n + 1) << 1;
leftIdx = rightIdx - 1;
swap = null;
swapKey = null;
if (leftIdx < length) {
left = this.content[leftIdx];
leftScore = this.scoreFunction(left);
if (leftScore < score) {
swap = leftIdx;
swapKey = this.keyFunction(left);
}
}
if (rightIdx < length) {
right = this.content[rightIdx];
rightScore = this.scoreFunction(right);
if (rightScore < (swap === null ? score : leftScore)) {
swap = rightIdx;
swapKey = this.keyFunction(right);
}
}
if (swap !== null) {
this.content[n] = this.content[swap];
this.content[swap] = node;
this.map[swapKey] = n;
n = swap;
} else {
break;
}
}
return n;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment