Heap.js 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. var Class = require('./Class');
  2. var swap = require('./swap');
  3. var isSorted = require('./isSorted');
  4. exports = Class({
  5. initialize: function Heap() {
  6. var cmp =
  7. arguments.length > 0 && arguments[0] !== undefined
  8. ? arguments[0]
  9. : isSorted.defComparator;
  10. this._cmp = cmp;
  11. this.clear();
  12. },
  13. clear: function() {
  14. this._data = [];
  15. this.size = 0;
  16. },
  17. add: function(item) {
  18. this._data.push(item);
  19. this.size++;
  20. this._heapifyUp(this.size - 1);
  21. return this.size;
  22. },
  23. poll: function() {
  24. var data = this._data;
  25. if (this.size > 0) {
  26. var item = data[0];
  27. data[0] = data[this.size - 1];
  28. this.size--;
  29. this._heapifyDown(0);
  30. return item;
  31. }
  32. },
  33. peek: function() {
  34. if (this.size > 0) {
  35. return this._data[0];
  36. }
  37. },
  38. _heapifyUp: function(idx) {
  39. var data = this._data;
  40. var parent = parentIdx(idx);
  41. while (idx > 0 && this._cmp(data[parent], data[idx]) > 0) {
  42. swap(data, parent, idx);
  43. idx = parent;
  44. parent = parentIdx(idx);
  45. }
  46. },
  47. _heapifyDown: function(idx) {
  48. var size = this.size;
  49. var cmp = this._cmp;
  50. var data = this._data;
  51. while (leftChildIdx(idx) < size) {
  52. var smallerIdx = leftChildIdx(idx);
  53. var rightChild = rightChildIdx(idx);
  54. if (
  55. rightChild < size &&
  56. cmp(data[rightChildIdx], data[smallerIdx]) < 0
  57. ) {
  58. smallerIdx = rightChild;
  59. }
  60. if (cmp(data[idx], data[smallerIdx]) < 0) {
  61. break;
  62. } else {
  63. swap(data, idx, smallerIdx);
  64. }
  65. idx = smallerIdx;
  66. }
  67. }
  68. });
  69. function parentIdx(idx) {
  70. return Math.floor((idx - 1) / 2);
  71. }
  72. function leftChildIdx(idx) {
  73. return 2 * idx + 1;
  74. }
  75. function rightChildIdx(idx) {
  76. return 2 * idx + 2;
  77. }
  78. module.exports = exports;