You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					577 lines
				
				12 KiB
			
		
		
			
		
	
	
					577 lines
				
				12 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * 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;
							 |