Projektstart
This commit is contained in:
576
backend/node_modules/mnemonist/heap.js
generated
vendored
Normal file
576
backend/node_modules/mnemonist/heap.js
generated
vendored
Normal file
@@ -0,0 +1,576 @@
|
||||
/**
|
||||
* Mnemonist Binary Heap
|
||||
* ======================
|
||||
*
|
||||
* Binary heap implementation.
|
||||
*/
|
||||
var forEach = require('obliterator/foreach'),
|
||||
comparators = require('./utils/comparators.js'),
|
||||
iterables = require('./utils/iterables.js');
|
||||
|
||||
var DEFAULT_COMPARATOR = comparators.DEFAULT_COMPARATOR,
|
||||
reverseComparator = comparators.reverseComparator;
|
||||
|
||||
/**
|
||||
* Heap helper functions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Function used to sift down.
|
||||
*
|
||||
* @param {function} compare - Comparison function.
|
||||
* @param {array} heap - Array storing the heap's data.
|
||||
* @param {number} startIndex - Starting index.
|
||||
* @param {number} i - Index.
|
||||
*/
|
||||
function siftDown(compare, heap, startIndex, i) {
|
||||
var item = heap[i],
|
||||
parentIndex,
|
||||
parent;
|
||||
|
||||
while (i > startIndex) {
|
||||
parentIndex = (i - 1) >> 1;
|
||||
parent = heap[parentIndex];
|
||||
|
||||
if (compare(item, parent) < 0) {
|
||||
heap[i] = parent;
|
||||
i = parentIndex;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
heap[i] = item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to sift up.
|
||||
*
|
||||
* @param {function} compare - Comparison function.
|
||||
* @param {array} heap - Array storing the heap's data.
|
||||
* @param {number} i - Index.
|
||||
*/
|
||||
function siftUp(compare, heap, i) {
|
||||
var endIndex = heap.length,
|
||||
startIndex = i,
|
||||
item = heap[i],
|
||||
childIndex = 2 * i + 1,
|
||||
rightIndex;
|
||||
|
||||
while (childIndex < endIndex) {
|
||||
rightIndex = childIndex + 1;
|
||||
|
||||
if (
|
||||
rightIndex < endIndex &&
|
||||
compare(heap[childIndex], heap[rightIndex]) >= 0
|
||||
) {
|
||||
childIndex = rightIndex;
|
||||
}
|
||||
|
||||
heap[i] = heap[childIndex];
|
||||
i = childIndex;
|
||||
childIndex = 2 * i + 1;
|
||||
}
|
||||
|
||||
heap[i] = item;
|
||||
siftDown(compare, heap, startIndex, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to push an item into a heap represented by a raw array.
|
||||
*
|
||||
* @param {function} compare - Comparison function.
|
||||
* @param {array} heap - Array storing the heap's data.
|
||||
* @param {any} item - Item to push.
|
||||
*/
|
||||
function push(compare, heap, item) {
|
||||
heap.push(item);
|
||||
siftDown(compare, heap, 0, heap.length - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to pop an item from a heap represented by a raw array.
|
||||
*
|
||||
* @param {function} compare - Comparison function.
|
||||
* @param {array} heap - Array storing the heap's data.
|
||||
* @return {any}
|
||||
*/
|
||||
function pop(compare, heap) {
|
||||
var lastItem = heap.pop();
|
||||
|
||||
if (heap.length !== 0) {
|
||||
var item = heap[0];
|
||||
heap[0] = lastItem;
|
||||
siftUp(compare, heap, 0);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
return lastItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to pop the heap then push a new value into it, thus "replacing"
|
||||
* it.
|
||||
*
|
||||
* @param {function} compare - Comparison function.
|
||||
* @param {array} heap - Array storing the heap's data.
|
||||
* @param {any} item - The item to push.
|
||||
* @return {any}
|
||||
*/
|
||||
function replace(compare, heap, item) {
|
||||
if (heap.length === 0)
|
||||
throw new Error('mnemonist/heap.replace: cannot pop an empty heap.');
|
||||
|
||||
var popped = heap[0];
|
||||
heap[0] = item;
|
||||
siftUp(compare, heap, 0);
|
||||
|
||||
return popped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to push an item in the heap then pop the heap and return the
|
||||
* popped value.
|
||||
*
|
||||
* @param {function} compare - Comparison function.
|
||||
* @param {array} heap - Array storing the heap's data.
|
||||
* @param {any} item - The item to push.
|
||||
* @return {any}
|
||||
*/
|
||||
function pushpop(compare, heap, item) {
|
||||
var tmp;
|
||||
|
||||
if (heap.length !== 0 && compare(heap[0], item) < 0) {
|
||||
tmp = heap[0];
|
||||
heap[0] = item;
|
||||
item = tmp;
|
||||
siftUp(compare, heap, 0);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts and array into an abstract heap in linear time.
|
||||
*
|
||||
* @param {function} compare - Comparison function.
|
||||
* @param {array} array - Target array.
|
||||
*/
|
||||
function heapify(compare, array) {
|
||||
var n = array.length,
|
||||
l = n >> 1,
|
||||
i = l;
|
||||
|
||||
while (--i >= 0)
|
||||
siftUp(compare, array, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fully consumes the given heap.
|
||||
*
|
||||
* @param {function} compare - Comparison function.
|
||||
* @param {array} heap - Array storing the heap's data.
|
||||
* @return {array}
|
||||
*/
|
||||
function consume(compare, heap) {
|
||||
var l = heap.length,
|
||||
i = 0;
|
||||
|
||||
var array = new Array(l);
|
||||
|
||||
while (i < l)
|
||||
array[i++] = pop(compare, heap);
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to retrieve the n smallest items from the given iterable.
|
||||
*
|
||||
* @param {function} compare - Comparison function.
|
||||
* @param {number} n - Number of top items to retrieve.
|
||||
* @param {any} iterable - Arbitrary iterable.
|
||||
* @param {array}
|
||||
*/
|
||||
function nsmallest(compare, n, iterable) {
|
||||
if (arguments.length === 2) {
|
||||
iterable = n;
|
||||
n = compare;
|
||||
compare = DEFAULT_COMPARATOR;
|
||||
}
|
||||
|
||||
var reverseCompare = reverseComparator(compare);
|
||||
|
||||
var i, l, v;
|
||||
|
||||
var min = Infinity;
|
||||
|
||||
var result;
|
||||
|
||||
// If n is equal to 1, it's just a matter of finding the minimum
|
||||
if (n === 1) {
|
||||
if (iterables.isArrayLike(iterable)) {
|
||||
for (i = 0, l = iterable.length; i < l; i++) {
|
||||
v = iterable[i];
|
||||
|
||||
if (min === Infinity || compare(v, min) < 0)
|
||||
min = v;
|
||||
}
|
||||
|
||||
result = new iterable.constructor(1);
|
||||
result[0] = min;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
forEach(iterable, function(value) {
|
||||
if (min === Infinity || compare(value, min) < 0)
|
||||
min = value;
|
||||
});
|
||||
|
||||
return [min];
|
||||
}
|
||||
|
||||
if (iterables.isArrayLike(iterable)) {
|
||||
|
||||
// If n > iterable length, we just clone and sort
|
||||
if (n >= iterable.length)
|
||||
return iterable.slice().sort(compare);
|
||||
|
||||
result = iterable.slice(0, n);
|
||||
heapify(reverseCompare, result);
|
||||
|
||||
for (i = n, l = iterable.length; i < l; i++)
|
||||
if (reverseCompare(iterable[i], result[0]) > 0)
|
||||
replace(reverseCompare, result, iterable[i]);
|
||||
|
||||
// NOTE: if n is over some number, it becomes faster to consume the heap
|
||||
return result.sort(compare);
|
||||
}
|
||||
|
||||
// Correct for size
|
||||
var size = iterables.guessLength(iterable);
|
||||
|
||||
if (size !== null && size < n)
|
||||
n = size;
|
||||
|
||||
result = new Array(n);
|
||||
i = 0;
|
||||
|
||||
forEach(iterable, function(value) {
|
||||
if (i < n) {
|
||||
result[i] = value;
|
||||
}
|
||||
else {
|
||||
if (i === n)
|
||||
heapify(reverseCompare, result);
|
||||
|
||||
if (reverseCompare(value, result[0]) > 0)
|
||||
replace(reverseCompare, result, value);
|
||||
}
|
||||
|
||||
i++;
|
||||
});
|
||||
|
||||
if (result.length > i)
|
||||
result.length = i;
|
||||
|
||||
// NOTE: if n is over some number, it becomes faster to consume the heap
|
||||
return result.sort(compare);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to retrieve the n largest items from the given iterable.
|
||||
*
|
||||
* @param {function} compare - Comparison function.
|
||||
* @param {number} n - Number of top items to retrieve.
|
||||
* @param {any} iterable - Arbitrary iterable.
|
||||
* @param {array}
|
||||
*/
|
||||
function nlargest(compare, n, iterable) {
|
||||
if (arguments.length === 2) {
|
||||
iterable = n;
|
||||
n = compare;
|
||||
compare = DEFAULT_COMPARATOR;
|
||||
}
|
||||
|
||||
var reverseCompare = reverseComparator(compare);
|
||||
|
||||
var i, l, v;
|
||||
|
||||
var max = -Infinity;
|
||||
|
||||
var result;
|
||||
|
||||
// If n is equal to 1, it's just a matter of finding the maximum
|
||||
if (n === 1) {
|
||||
if (iterables.isArrayLike(iterable)) {
|
||||
for (i = 0, l = iterable.length; i < l; i++) {
|
||||
v = iterable[i];
|
||||
|
||||
if (max === -Infinity || compare(v, max) > 0)
|
||||
max = v;
|
||||
}
|
||||
|
||||
result = new iterable.constructor(1);
|
||||
result[0] = max;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
forEach(iterable, function(value) {
|
||||
if (max === -Infinity || compare(value, max) > 0)
|
||||
max = value;
|
||||
});
|
||||
|
||||
return [max];
|
||||
}
|
||||
|
||||
if (iterables.isArrayLike(iterable)) {
|
||||
|
||||
// If n > iterable length, we just clone and sort
|
||||
if (n >= iterable.length)
|
||||
return iterable.slice().sort(reverseCompare);
|
||||
|
||||
result = iterable.slice(0, n);
|
||||
heapify(compare, result);
|
||||
|
||||
for (i = n, l = iterable.length; i < l; i++)
|
||||
if (compare(iterable[i], result[0]) > 0)
|
||||
replace(compare, result, iterable[i]);
|
||||
|
||||
// NOTE: if n is over some number, it becomes faster to consume the heap
|
||||
return result.sort(reverseCompare);
|
||||
}
|
||||
|
||||
// Correct for size
|
||||
var size = iterables.guessLength(iterable);
|
||||
|
||||
if (size !== null && size < n)
|
||||
n = size;
|
||||
|
||||
result = new Array(n);
|
||||
i = 0;
|
||||
|
||||
forEach(iterable, function(value) {
|
||||
if (i < n) {
|
||||
result[i] = value;
|
||||
}
|
||||
else {
|
||||
if (i === n)
|
||||
heapify(compare, result);
|
||||
|
||||
if (compare(value, result[0]) > 0)
|
||||
replace(compare, result, value);
|
||||
}
|
||||
|
||||
i++;
|
||||
});
|
||||
|
||||
if (result.length > i)
|
||||
result.length = i;
|
||||
|
||||
// NOTE: if n is over some number, it becomes faster to consume the heap
|
||||
return result.sort(reverseCompare);
|
||||
}
|
||||
|
||||
/**
|
||||
* Binary Minimum Heap.
|
||||
*
|
||||
* @constructor
|
||||
* @param {function} comparator - Comparator function to use.
|
||||
*/
|
||||
function Heap(comparator) {
|
||||
this.clear();
|
||||
this.comparator = comparator || DEFAULT_COMPARATOR;
|
||||
|
||||
if (typeof this.comparator !== 'function')
|
||||
throw new Error('mnemonist/Heap.constructor: given comparator should be a function.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to clear the heap.
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
Heap.prototype.clear = function() {
|
||||
|
||||
// Properties
|
||||
this.items = [];
|
||||
this.size = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to push an item into the heap.
|
||||
*
|
||||
* @param {any} item - Item to push.
|
||||
* @return {number}
|
||||
*/
|
||||
Heap.prototype.push = function(item) {
|
||||
push(this.comparator, this.items, item);
|
||||
return ++this.size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to retrieve the "first" item of the heap.
|
||||
*
|
||||
* @return {any}
|
||||
*/
|
||||
Heap.prototype.peek = function() {
|
||||
return this.items[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to retrieve & remove the "first" item of the heap.
|
||||
*
|
||||
* @return {any}
|
||||
*/
|
||||
Heap.prototype.pop = function() {
|
||||
if (this.size !== 0)
|
||||
this.size--;
|
||||
|
||||
return pop(this.comparator, this.items);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to pop the heap, then push an item and return the popped
|
||||
* item.
|
||||
*
|
||||
* @param {any} item - Item to push into the heap.
|
||||
* @return {any}
|
||||
*/
|
||||
Heap.prototype.replace = function(item) {
|
||||
return replace(this.comparator, this.items, item);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to push the heap, the pop it and return the pooped item.
|
||||
*
|
||||
* @param {any} item - Item to push into the heap.
|
||||
* @return {any}
|
||||
*/
|
||||
Heap.prototype.pushpop = function(item) {
|
||||
return pushpop(this.comparator, this.items, item);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to consume the heap fully and return its items as a sorted array.
|
||||
*
|
||||
* @return {array}
|
||||
*/
|
||||
Heap.prototype.consume = function() {
|
||||
this.size = 0;
|
||||
return consume(this.comparator, this.items);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to convert the heap to an array. Note that it basically clone
|
||||
* the heap and consumes it completely. This is hardly performant.
|
||||
*
|
||||
* @return {array}
|
||||
*/
|
||||
Heap.prototype.toArray = function() {
|
||||
return consume(this.comparator, this.items.slice());
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience known methods.
|
||||
*/
|
||||
Heap.prototype.inspect = function() {
|
||||
var proxy = this.toArray();
|
||||
|
||||
// Trick so that node displays the name of the constructor
|
||||
Object.defineProperty(proxy, 'constructor', {
|
||||
value: Heap,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return proxy;
|
||||
};
|
||||
|
||||
if (typeof Symbol !== 'undefined')
|
||||
Heap.prototype[Symbol.for('nodejs.util.inspect.custom')] = Heap.prototype.inspect;
|
||||
|
||||
/**
|
||||
* Binary Maximum Heap.
|
||||
*
|
||||
* @constructor
|
||||
* @param {function} comparator - Comparator function to use.
|
||||
*/
|
||||
function MaxHeap(comparator) {
|
||||
this.clear();
|
||||
this.comparator = comparator || DEFAULT_COMPARATOR;
|
||||
|
||||
if (typeof this.comparator !== 'function')
|
||||
throw new Error('mnemonist/MaxHeap.constructor: given comparator should be a function.');
|
||||
|
||||
this.comparator = reverseComparator(this.comparator);
|
||||
}
|
||||
|
||||
MaxHeap.prototype = Heap.prototype;
|
||||
|
||||
/**
|
||||
* Static @.from function taking an arbitrary iterable & converting it into
|
||||
* a heap.
|
||||
*
|
||||
* @param {Iterable} iterable - Target iterable.
|
||||
* @param {function} comparator - Custom comparator function.
|
||||
* @return {Heap}
|
||||
*/
|
||||
Heap.from = function(iterable, comparator) {
|
||||
var heap = new Heap(comparator);
|
||||
|
||||
var items;
|
||||
|
||||
// If iterable is an array, we can be clever about it
|
||||
if (iterables.isArrayLike(iterable))
|
||||
items = iterable.slice();
|
||||
else
|
||||
items = iterables.toArray(iterable);
|
||||
|
||||
heapify(heap.comparator, items);
|
||||
heap.items = items;
|
||||
heap.size = items.length;
|
||||
|
||||
return heap;
|
||||
};
|
||||
|
||||
MaxHeap.from = function(iterable, comparator) {
|
||||
var heap = new MaxHeap(comparator);
|
||||
|
||||
var items;
|
||||
|
||||
// If iterable is an array, we can be clever about it
|
||||
if (iterables.isArrayLike(iterable))
|
||||
items = iterable.slice();
|
||||
else
|
||||
items = iterables.toArray(iterable);
|
||||
|
||||
heapify(heap.comparator, items);
|
||||
heap.items = items;
|
||||
heap.size = items.length;
|
||||
|
||||
return heap;
|
||||
};
|
||||
|
||||
/**
|
||||
* Exporting.
|
||||
*/
|
||||
Heap.siftUp = siftUp;
|
||||
Heap.siftDown = siftDown;
|
||||
Heap.push = push;
|
||||
Heap.pop = pop;
|
||||
Heap.replace = replace;
|
||||
Heap.pushpop = pushpop;
|
||||
Heap.heapify = heapify;
|
||||
Heap.consume = consume;
|
||||
|
||||
Heap.nsmallest = nsmallest;
|
||||
Heap.nlargest = nlargest;
|
||||
|
||||
Heap.MinHeap = Heap;
|
||||
Heap.MaxHeap = MaxHeap;
|
||||
|
||||
module.exports = Heap;
|
||||
Reference in New Issue
Block a user