Heap.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /**
  2. * Copyright (c) 2013-present, Facebook, Inc.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. *
  7. * @typechecks
  8. * @preventMunge
  9. */
  10. 'use strict';
  11. /*
  12. * @param {*} a
  13. * @param {*} b
  14. * @return {boolean}
  15. */
  16. function defaultComparator(a, b) {
  17. return a < b;
  18. }
  19. var Heap =
  20. /*#__PURE__*/
  21. function () {
  22. function Heap(items, comparator) {
  23. this._items = items || [];
  24. this._size = this._items.length;
  25. this._comparator = comparator || defaultComparator;
  26. this._heapify();
  27. }
  28. /*
  29. * @return {boolean}
  30. */
  31. var _proto = Heap.prototype;
  32. _proto.empty = function empty() {
  33. return this._size === 0;
  34. };
  35. /*
  36. * @return {*}
  37. */
  38. _proto.pop = function pop() {
  39. if (this._size === 0) {
  40. return;
  41. }
  42. var elt = this._items[0];
  43. var lastElt = this._items.pop();
  44. this._size--;
  45. if (this._size > 0) {
  46. this._items[0] = lastElt;
  47. this._sinkDown(0);
  48. }
  49. return elt;
  50. };
  51. /*
  52. * @param {*} item
  53. */
  54. _proto.push = function push(item) {
  55. this._items[this._size++] = item;
  56. this._bubbleUp(this._size - 1);
  57. };
  58. /*
  59. * @return {number}
  60. */
  61. _proto.size = function size() {
  62. return this._size;
  63. };
  64. /*
  65. * @return {*}
  66. */
  67. _proto.peek = function peek() {
  68. if (this._size === 0) {
  69. return;
  70. }
  71. return this._items[0];
  72. };
  73. _proto._heapify = function _heapify() {
  74. for (var index = Math.floor((this._size + 1) / 2); index >= 0; index--) {
  75. this._sinkDown(index);
  76. }
  77. };
  78. /*
  79. * @parent {number} index
  80. */
  81. _proto._bubbleUp = function _bubbleUp(index) {
  82. var elt = this._items[index];
  83. while (index > 0) {
  84. var parentIndex = Math.floor((index + 1) / 2) - 1;
  85. var parentElt = this._items[parentIndex]; // if parentElt < elt, stop
  86. if (this._comparator(parentElt, elt)) {
  87. return;
  88. } // swap
  89. this._items[parentIndex] = elt;
  90. this._items[index] = parentElt;
  91. index = parentIndex;
  92. }
  93. };
  94. /*
  95. * @parent {number} index
  96. */
  97. _proto._sinkDown = function _sinkDown(index) {
  98. var elt = this._items[index];
  99. while (true) {
  100. var leftChildIndex = 2 * (index + 1) - 1;
  101. var rightChildIndex = 2 * (index + 1);
  102. var swapIndex = -1;
  103. if (leftChildIndex < this._size) {
  104. var leftChild = this._items[leftChildIndex];
  105. if (this._comparator(leftChild, elt)) {
  106. swapIndex = leftChildIndex;
  107. }
  108. }
  109. if (rightChildIndex < this._size) {
  110. var rightChild = this._items[rightChildIndex];
  111. if (this._comparator(rightChild, elt)) {
  112. if (swapIndex === -1 || this._comparator(rightChild, this._items[swapIndex])) {
  113. swapIndex = rightChildIndex;
  114. }
  115. }
  116. } // if we don't have a swap, stop
  117. if (swapIndex === -1) {
  118. return;
  119. }
  120. this._items[index] = this._items[swapIndex];
  121. this._items[swapIndex] = elt;
  122. index = swapIndex;
  123. }
  124. };
  125. return Heap;
  126. }();
  127. module.exports = Heap;