| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 | import Check from "./Check.js";import defaultValue from "./defaultValue.js";import defined from "./defined.js";/** * Array implementation of a heap. * * @alias Heap * @constructor * @private * * @param {Object} options Object with the following properties: * @param {Heap.ComparatorCallback} options.comparator The comparator to use for the heap. If comparator(a, b) is less than 0, sort a to a lower index than b, otherwise sort to a higher index. */function Heap(options) {  //>>includeStart('debug', pragmas.debug);  Check.typeOf.object("options", options);  Check.defined("options.comparator", options.comparator);  //>>includeEnd('debug');  this._comparator = options.comparator;  this._array = [];  this._length = 0;  this._maximumLength = undefined;}Object.defineProperties(Heap.prototype, {  /**   * Gets the length of the heap.   *   * @memberof Heap.prototype   *   * @type {Number}   * @readonly   */  length: {    get: function () {      return this._length;    },  },  /**   * Gets the internal array.   *   * @memberof Heap.prototype   *   * @type {Array}   * @readonly   */  internalArray: {    get: function () {      return this._array;    },  },  /**   * Gets and sets the maximum length of the heap.   *   * @memberof Heap.prototype   *   * @type {Number}   */  maximumLength: {    get: function () {      return this._maximumLength;    },    set: function (value) {      //>>includeStart('debug', pragmas.debug);      Check.typeOf.number.greaterThanOrEquals("maximumLength", value, 0);      //>>includeEnd('debug');      const originalLength = this._length;      if (value < originalLength) {        const array = this._array;        // Remove trailing references        for (let i = value; i < originalLength; ++i) {          array[i] = undefined;        }        this._length = value;        array.length = value;      }      this._maximumLength = value;    },  },  /**   * The comparator to use for the heap. If comparator(a, b) is less than 0, sort a to a lower index than b, otherwise sort to a higher index.   *   * @memberof Heap.prototype   *   * @type {Heap.ComparatorCallback}   */  comparator: {    get: function () {      return this._comparator;    },  },});function swap(array, a, b) {  const temp = array[a];  array[a] = array[b];  array[b] = temp;}/** * Resizes the internal array of the heap. * * @param {Number} [length] The length to resize internal array to. Defaults to the current length of the heap. */Heap.prototype.reserve = function (length) {  length = defaultValue(length, this._length);  this._array.length = length;};/** * Update the heap so that index and all descendants satisfy the heap property. * * @param {Number} [index=0] The starting index to heapify from. */Heap.prototype.heapify = function (index) {  index = defaultValue(index, 0);  const length = this._length;  const comparator = this._comparator;  const array = this._array;  let candidate = -1;  let inserting = true;  while (inserting) {    const right = 2 * (index + 1);    const left = right - 1;    if (left < length && comparator(array[left], array[index]) < 0) {      candidate = left;    } else {      candidate = index;    }    if (right < length && comparator(array[right], array[candidate]) < 0) {      candidate = right;    }    if (candidate !== index) {      swap(array, candidate, index);      index = candidate;    } else {      inserting = false;    }  }};/** * Resort the heap. */Heap.prototype.resort = function () {  const length = this._length;  for (let i = Math.ceil(length / 2); i >= 0; --i) {    this.heapify(i);  }};/** * Insert an element into the heap. If the length would grow greater than maximumLength * of the heap, extra elements are removed. * * @param {*} element The element to insert * * @return {*} The element that was removed from the heap if the heap is at full capacity. */Heap.prototype.insert = function (element) {  //>>includeStart('debug', pragmas.debug);  Check.defined("element", element);  //>>includeEnd('debug');  const array = this._array;  const comparator = this._comparator;  const maximumLength = this._maximumLength;  let index = this._length++;  if (index < array.length) {    array[index] = element;  } else {    array.push(element);  }  while (index !== 0) {    const parent = Math.floor((index - 1) / 2);    if (comparator(array[index], array[parent]) < 0) {      swap(array, index, parent);      index = parent;    } else {      break;    }  }  let removedElement;  if (defined(maximumLength) && this._length > maximumLength) {    removedElement = array[maximumLength];    this._length = maximumLength;  }  return removedElement;};/** * Remove the element specified by index from the heap and return it. * * @param {Number} [index=0] The index to remove. * @returns {*} The specified element of the heap. */Heap.prototype.pop = function (index) {  index = defaultValue(index, 0);  if (this._length === 0) {    return undefined;  }  //>>includeStart('debug', pragmas.debug);  Check.typeOf.number.lessThan("index", index, this._length);  //>>includeEnd('debug');  const array = this._array;  const root = array[index];  swap(array, index, --this._length);  this.heapify(index);  array[this._length] = undefined; // Remove trailing reference  return root;};/** * The comparator to use for the heap. * @callback Heap.ComparatorCallback * @param {*} a An element in the heap. * @param {*} b An element in the heap. * @returns {Number} If the result of the comparison is less than 0, sort a to a lower index than b, otherwise sort to a higher index. */export default Heap;
 |