UNPKG

heapster

Version:

Heap data structure so hype it's using ES 2015. Gluten and dependency free.

374 lines (323 loc) 8.89 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var comparator = function comparator(a, b) { if (a < b) return -1; if (a > b) return 1; return 0; }; var symbols = { index: Symbol && Symbol('index') }; function isNumber(value) { return typeof value === 'number'; } function indexOf(arr, elem, sym) { if (sym && isNumber(elem[sym])) { return elem[sym]; } else { return arr.indexOf(elem); } } function updateIndexAt(arr, index, sym) { if (sym && typeof arr[index] === 'object') { arr[index][sym] = index; } } // O(log(n)) function siftUp(arr, comp, pos, sym) { var elem = arr[pos]; while (pos > 0) { var parentPos = pos - 1 >> 1; var _parent = arr[parentPos]; if (pos > 0 && comp(elem, _parent) > 0) { arr[pos] = _parent; updateIndexAt(arr, pos, sym); pos = parentPos; } else { break; } } arr[pos] = elem; updateIndexAt(arr, pos, sym); return arr; } // O(log(n)) function siftDown(_x, _x2, _x3, _x4, _x5) { var _again = true; _function: while (_again) { var arr = _x, comp = _x2, pos = _x3, end = _x4, sym = _x5; _again = false; if (!isNumber(end)) { sym = end; end = arr.length; } var largest = undefined; var left = 2 * pos + 1, right = 2 * pos + 2; if (left < end && comp(arr[left], arr[pos]) > 0) { largest = left; } else { largest = pos; } if (right < end && comp(arr[right], arr[largest]) > 0) { largest = right; } if (largest === pos) { updateIndexAt(arr, pos, sym); return arr; } else { var tmp = arr[pos]; arr[pos] = arr[largest]; arr[largest] = tmp; updateIndexAt(arr, pos, sym); updateIndexAt(arr, largest, sym); _x = arr; _x2 = comp; _x3 = largest; _x4 = end; _x5 = sym; _again = true; largest = left = right = tmp = undefined; continue _function; } } } var Heapster = (function () { function Heapster(elems, comp, opts) { _classCallCheck(this, Heapster); if (!Array.isArray(elems)) { opts = comp; comp = elems; elems = []; } if (typeof comp !== 'function') { opts = comp; comp = comparator; } if (opts === undefined) { opts = {}; } this.comparator = comp; this.symbols = {}; if (opts.indexed) { this.symbols.index = symbols.index; } this.elements = Heapster.heapify(elems.slice(0), this.comparator, this.symbols.index); } // O(n.log(n)) _createClass(Heapster, [{ key: 'size', // O(1) value: function size() { return this.elements.length; } // O(1) }, { key: 'isEmpty', value: function isEmpty() { return this.size() === 0; } // O(1) }, { key: 'clean', value: function clean(elem) { return Heapster.clean(elem); } // get: O(1) // set: O(log(n)) }, { key: 'root', value: function root(elem) { if (elem !== undefined) { var first = this.root(); if (first === undefined || this.comparator(first, elem) < 0) { return elem; } else { this.elements[0] = elem; siftDown(this.elements, this.comparator, 0, this.symbols.index); return first; } } return this.elements[0]; } // O(log(n)) for each element }, { key: 'push', value: function push() { var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _len = arguments.length, elems = Array(_len), _key = 0; _key < _len; _key++) { elems[_key] = arguments[_key]; } for (var _iterator = elems[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var elem = _step.value; this.elements.push(elem); siftUp(this.elements, this.comparator, this.size() - 1, this.symbols.index); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator['return']) { _iterator['return'](); } } finally { if (_didIteratorError) { throw _iteratorError; } } } return this.size(); } // O(log(n)) }, { key: 'add', value: function add(elem) { this.push(elem); return this; } // O(log(n)) }, { key: 'pop', value: function pop() { return this.root(this.elements.pop()); } // O(1) }, { key: 'clone', value: function clone() { var result = new Heapster(this.comparator); result.elements = this.elements.slice(0); return result; } // O(n) or O(1) }, { key: 'has', value: function has(elem) { if (this.symbols.index && typeof elem === 'object') { return isNumber(elem[this.symbols.index]) && elem === this.elements[elem[this.symbols.index]]; } else { return this.elements.indexOf(elem) > -1; } } // O(n) or O(log(n)) if indexed }, { key: 'update', value: function update(elem) { return this.updateAt(indexOf(this.elements, elem, this.symbols.index), elem); } // O(log(n)) }, { key: 'updateAt', value: function updateAt(index, value) { if (index > -1 && index < this.size()) { if (this.elements[index] !== value) { this.elements[index] = value; } siftUp(this.elements, this.comparator, index, this.symbols.index); siftDown(this.elements, this.comparator, index, this.symbols.index); } return this; } // O(n) or O(log(n)) if indexed }, { key: 'remove', value: function remove(elem) { return this.removeAt(indexOf(this.elements, elem, this.symbols.index)); } // O(log(n)) }, { key: 'removeAt', value: function removeAt(index) { if (index > -1 && index < this.size()) { if (index === this.size() - 1) { this.elements.pop(); } else { this.elements[index] = this.elements.pop(); siftUp(this.elements, this.comparator, index, this.symbols.index); siftDown(this.elements, this.comparator, index, this.symbols.index); } return true; } return false; } }, { key: 'merge', value: function merge(heap) { var result = this.clone(); result.push.apply(result, heap.elements); return result; } }, { key: 'meld', value: function meld(heap) { this.push.apply(this, heap.elements); return this; } // O(n.log(n)) }, { key: 'sort', value: function sort() { var result = this.elements.slice(0); for (var i = result.length - 1; i > 0; --i) { var tmp = result[0]; result[0] = result[i]; result[i] = tmp; siftDown(result, this.comparator, 0, i, this.symbols.index); } return result; } }, { key: 'toArray', value: function toArray() { return this.elements.slice(0); } }], [{ key: 'heapify', value: function heapify(arr, comp, sym) { if (comp === undefined) comp = comparator; if (!Array.isArray(arr)) { return arr; } var pivot = arr.length - 1 >> 1; if (sym) { for (var i = arr.length - 1; i > pivot; --i) { updateIndexAt(arr, i, sym); } } for (var i = pivot; i >= 0; --i) { siftDown(arr, comp, i, sym); } return arr; } // O(n.log(n)) }, { key: 'sort', value: function sort(arr, comp, opts) { return new Heapster(arr, comp, opts).sort(); } // O(1) }, { key: 'clean', value: function clean(elem) { if (symbols.index) { delete elem[symbols.index]; } return elem; } }]); return Heapster; })(); exports['default'] = Heapster; module.exports = exports['default'];