index.js 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. export default class TinyQueue {
  2. constructor(data = [], compare = defaultCompare) {
  3. this.data = data;
  4. this.length = this.data.length;
  5. this.compare = compare;
  6. if (this.length > 0) {
  7. for (let i = (this.length >> 1) - 1; i >= 0; i--) this._down(i);
  8. }
  9. }
  10. push(item) {
  11. this.data.push(item);
  12. this.length++;
  13. this._up(this.length - 1);
  14. }
  15. pop() {
  16. if (this.length === 0) return undefined;
  17. const top = this.data[0];
  18. const bottom = this.data.pop();
  19. this.length--;
  20. if (this.length > 0) {
  21. this.data[0] = bottom;
  22. this._down(0);
  23. }
  24. return top;
  25. }
  26. peek() {
  27. return this.data[0];
  28. }
  29. _up(pos) {
  30. const {data, compare} = this;
  31. const item = data[pos];
  32. while (pos > 0) {
  33. const parent = (pos - 1) >> 1;
  34. const current = data[parent];
  35. if (compare(item, current) >= 0) break;
  36. data[pos] = current;
  37. pos = parent;
  38. }
  39. data[pos] = item;
  40. }
  41. _down(pos) {
  42. const {data, compare} = this;
  43. const halfLength = this.length >> 1;
  44. const item = data[pos];
  45. while (pos < halfLength) {
  46. let left = (pos << 1) + 1;
  47. let best = data[left];
  48. const right = left + 1;
  49. if (right < this.length && compare(data[right], best) < 0) {
  50. left = right;
  51. best = data[right];
  52. }
  53. if (compare(best, item) >= 0) break;
  54. data[pos] = best;
  55. pos = left;
  56. }
  57. data[pos] = item;
  58. }
  59. }
  60. function defaultCompare(a, b) {
  61. return a < b ? -1 : a > b ? 1 : 0;
  62. }