data-structure-typed 2.2.8 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/.github/workflows/ci.yml +9 -0
  2. package/CHANGELOG.md +1 -1
  3. package/README.md +1 -1
  4. package/README_CN.md +1 -1
  5. package/dist/cjs/index.cjs +584 -76
  6. package/dist/cjs/index.cjs.map +1 -1
  7. package/dist/cjs-legacy/index.cjs +588 -79
  8. package/dist/cjs-legacy/index.cjs.map +1 -1
  9. package/dist/esm/index.mjs +584 -76
  10. package/dist/esm/index.mjs.map +1 -1
  11. package/dist/esm-legacy/index.mjs +588 -79
  12. package/dist/esm-legacy/index.mjs.map +1 -1
  13. package/dist/types/data-structures/base/linear-base.d.ts +6 -6
  14. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +3 -4
  15. package/dist/types/data-structures/binary-tree/bst.d.ts +2 -1
  16. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +150 -20
  17. package/dist/types/data-structures/binary-tree/tree-counter.d.ts +3 -3
  18. package/dist/types/interfaces/binary-tree.d.ts +1 -1
  19. package/dist/umd/data-structure-typed.js +588 -79
  20. package/dist/umd/data-structure-typed.js.map +1 -1
  21. package/dist/umd/data-structure-typed.min.js +3 -3
  22. package/dist/umd/data-structure-typed.min.js.map +1 -1
  23. package/package.json +4 -3
  24. package/src/data-structures/base/linear-base.ts +2 -12
  25. package/src/data-structures/binary-tree/binary-tree.ts +5 -6
  26. package/src/data-structures/binary-tree/bst.ts +79 -4
  27. package/src/data-structures/binary-tree/red-black-tree.ts +583 -73
  28. package/src/data-structures/binary-tree/tree-counter.ts +21 -9
  29. package/src/data-structures/queue/deque.ts +10 -0
  30. package/src/interfaces/binary-tree.ts +1 -1
  31. package/test/unit/data-structures/base/iterable-element-base.coverage.test.ts +106 -0
  32. package/test/unit/data-structures/base/iterable-element-base.more-branches.coverage.test.ts +61 -0
  33. package/test/unit/data-structures/base/linear-base.array.coverage.test.ts +168 -0
  34. package/test/unit/data-structures/base/linear-base.concat-else.coverage.test.ts +82 -0
  35. package/test/unit/data-structures/base/linear-base.coverage.test.ts +72 -0
  36. package/test/unit/data-structures/base/linear-base.more-branches.coverage.test.ts +417 -0
  37. package/test/unit/data-structures/binary-tree/avl-tree-counter.more-branches-3.coverage.test.ts +146 -0
  38. package/test/unit/data-structures/binary-tree/avl-tree-counter.more-branches.coverage.test.ts +93 -0
  39. package/test/unit/data-structures/binary-tree/avl-tree-multi-map.coverage.test.ts +108 -0
  40. package/test/unit/data-structures/binary-tree/avl-tree-multi-map.more-branches-2.coverage.test.ts +85 -0
  41. package/test/unit/data-structures/binary-tree/avl-tree-node.familyPosition-root-left.coverage.test.ts +17 -0
  42. package/test/unit/data-structures/binary-tree/avl-tree.more-branches-2.coverage.test.ts +99 -0
  43. package/test/unit/data-structures/binary-tree/binary-indexed-tree.more-branches.coverage.test.ts +18 -0
  44. package/test/unit/data-structures/binary-tree/binary-tree.more-branches.coverage.test.ts +56 -0
  45. package/test/unit/data-structures/binary-tree/binary-tree.remaining-branches.coverage.test.ts +229 -0
  46. package/test/unit/data-structures/binary-tree/bst.bound-by-predicate.coverage.test.ts +33 -0
  47. package/test/unit/data-structures/binary-tree/bst.coverage.test.ts +94 -0
  48. package/test/unit/data-structures/binary-tree/bst.deletebykey.coverage.test.ts +70 -0
  49. package/test/unit/data-structures/binary-tree/bst.deletewhere.coverage.test.ts +37 -0
  50. package/test/unit/data-structures/binary-tree/bst.floor-lower-predicate.coverage.test.ts +29 -0
  51. package/test/unit/data-structures/binary-tree/bst.floor-setmany.coverage.test.ts +72 -0
  52. package/test/unit/data-structures/binary-tree/bst.getnode.range-ensure.coverage.test.ts +22 -0
  53. package/test/unit/data-structures/binary-tree/bst.misc-branches.coverage.test.ts +100 -0
  54. package/test/unit/data-structures/binary-tree/bst.more-branches-2.coverage.test.ts +133 -0
  55. package/test/unit/data-structures/binary-tree/bst.more-branches-3.coverage.test.ts +45 -0
  56. package/test/unit/data-structures/binary-tree/bst.more-branches-4.coverage.test.ts +36 -0
  57. package/test/unit/data-structures/binary-tree/bst.more-branches-5.coverage.test.ts +40 -0
  58. package/test/unit/data-structures/binary-tree/bst.more.coverage.test.ts +39 -0
  59. package/test/unit/data-structures/binary-tree/bst.node-family.coverage.test.ts +29 -0
  60. package/test/unit/data-structures/binary-tree/bst.range-pruning.coverage.test.ts +43 -0
  61. package/test/unit/data-structures/binary-tree/bst.search-fastpath.coverage.test.ts +30 -0
  62. package/test/unit/data-structures/binary-tree/bst.test.ts +25 -55
  63. package/test/unit/data-structures/binary-tree/red-black-tree.boundary-corruption-repair.coverage.test.ts +66 -0
  64. package/test/unit/data-structures/binary-tree/red-black-tree.boundary-max-update.coverage.test.ts +18 -0
  65. package/test/unit/data-structures/binary-tree/red-black-tree.boundary-null.coverage.test.ts +53 -0
  66. package/test/unit/data-structures/binary-tree/red-black-tree.boundary-stale-cache.coverage.test.ts +25 -0
  67. package/test/unit/data-structures/binary-tree/red-black-tree.boundary-update.coverage.test.ts +23 -0
  68. package/test/unit/data-structures/binary-tree/red-black-tree.cache-delete.coverage.test.ts +49 -0
  69. package/test/unit/data-structures/binary-tree/red-black-tree.cache-edge.coverage.test.ts +37 -0
  70. package/test/unit/data-structures/binary-tree/red-black-tree.cache-stale-insert.coverage.test.ts +39 -0
  71. package/test/unit/data-structures/binary-tree/red-black-tree.coverage.test.ts +334 -0
  72. package/test/unit/data-structures/binary-tree/red-black-tree.delete-fixup.coverage.test.ts +68 -0
  73. package/test/unit/data-structures/binary-tree/red-black-tree.delete-successor.coverage.test.ts +75 -0
  74. package/test/unit/data-structures/binary-tree/red-black-tree.factories.coverage.test.ts +26 -0
  75. package/test/unit/data-structures/binary-tree/red-black-tree.hint-cache-compare-update.coverage.test.ts +74 -0
  76. package/test/unit/data-structures/binary-tree/red-black-tree.hint-cache-no-update.coverage.test.ts +44 -0
  77. package/test/unit/data-structures/binary-tree/red-black-tree.hint-cache-nullish.coverage.test.ts +61 -0
  78. package/test/unit/data-structures/binary-tree/red-black-tree.hint-mapmode-defined.coverage.test.ts +35 -0
  79. package/test/unit/data-structures/binary-tree/red-black-tree.hint-mapmode-undefined.coverage.test.ts +43 -0
  80. package/test/unit/data-structures/binary-tree/red-black-tree.hint-more.coverage.test.ts +99 -0
  81. package/test/unit/data-structures/binary-tree/red-black-tree.hint.coverage.test.ts +60 -0
  82. package/test/unit/data-structures/binary-tree/red-black-tree.insert-cache-nullish.coverage.test.ts +29 -0
  83. package/test/unit/data-structures/binary-tree/red-black-tree.insert-header-parent-nullish.coverage.test.ts +17 -0
  84. package/test/unit/data-structures/binary-tree/red-black-tree.internal-walk.coverage.test.ts +57 -0
  85. package/test/unit/data-structures/binary-tree/red-black-tree.minmax-cache.test.ts +65 -0
  86. package/test/unit/data-structures/binary-tree/red-black-tree.misc-inputs.coverage.test.ts +17 -0
  87. package/test/unit/data-structures/binary-tree/red-black-tree.more-branches-2.coverage.test.ts +121 -0
  88. package/test/unit/data-structures/binary-tree/red-black-tree.more-branches-3.coverage.test.ts +55 -0
  89. package/test/unit/data-structures/binary-tree/red-black-tree.more-branches-4.coverage.test.ts +44 -0
  90. package/test/unit/data-structures/binary-tree/red-black-tree.predsucc.coverage.test.ts +40 -0
  91. package/test/unit/data-structures/binary-tree/red-black-tree.remaining-branches.coverage.test.ts +123 -0
  92. package/test/unit/data-structures/binary-tree/red-black-tree.set-inputs.coverage.test.ts +64 -0
  93. package/test/unit/data-structures/binary-tree/red-black-tree.setkvnode-parent-cache.coverage.test.ts +79 -0
  94. package/test/unit/data-structures/binary-tree/red-black-tree.setkvnode-remaining.coverage.test.ts +44 -0
  95. package/test/unit/data-structures/binary-tree/red-black-tree.setkvnode-uncovered.coverage.test.ts +74 -0
  96. package/test/unit/data-structures/binary-tree/red-black-tree.update-branches.coverage.test.ts +30 -0
  97. package/test/unit/data-structures/binary-tree/segment-tree.more-branches.coverage.test.ts +31 -0
  98. package/test/unit/data-structures/binary-tree/tree-counter.coverage.test.ts +115 -0
  99. package/test/unit/data-structures/binary-tree/tree-counter.more-branches.coverage.test.ts +244 -0
  100. package/test/unit/data-structures/binary-tree/tree-counter.test.ts +4 -2
  101. package/test/unit/data-structures/binary-tree/tree-multi-map.coverage.test.ts +104 -0
  102. package/test/unit/data-structures/binary-tree/tree-multi-map.more-branches-2.coverage.test.ts +59 -0
  103. package/test/unit/data-structures/graph/abstract-graph.more-branches-2.coverage.test.ts +40 -0
  104. package/test/unit/data-structures/graph/abstract-graph.more-branches-3.coverage.test.ts +65 -0
  105. package/test/unit/data-structures/graph/abstract-graph.more-branches-4.coverage.test.ts +98 -0
  106. package/test/unit/data-structures/graph/abstract-graph.more-branches-5.coverage.test.ts +51 -0
  107. package/test/unit/data-structures/graph/abstract-graph.more-branches.coverage.test.ts +62 -0
  108. package/test/unit/data-structures/graph/directed-graph.more-branches-2.coverage.test.ts +38 -0
  109. package/test/unit/data-structures/graph/directed-graph.more-branches-3.coverage.test.ts +25 -0
  110. package/test/unit/data-structures/graph/directed-graph.more-branches.coverage.test.ts +82 -0
  111. package/test/unit/data-structures/graph/map-graph.more-branches.coverage.test.ts +22 -0
  112. package/test/unit/data-structures/graph/undirected-graph.more-branches-2.coverage.test.ts +35 -0
  113. package/test/unit/data-structures/graph/undirected-graph.more-branches.coverage.test.ts +87 -0
  114. package/test/unit/data-structures/hash/hash-map.more-branches.coverage.test.ts +64 -0
  115. package/test/unit/data-structures/hash/hash-map.toEntryFn-branch.coverage.test.ts +9 -0
  116. package/test/unit/data-structures/heap/heap.misc-branches.coverage.test.ts +110 -0
  117. package/test/unit/data-structures/heap/heap.remaining-branches.coverage.test.ts +22 -0
  118. package/test/unit/data-structures/heap/max-heap.coverage.test.ts +29 -0
  119. package/test/unit/data-structures/linked-list/doubly-linked-list.more-branches.coverage.test.ts +72 -0
  120. package/test/unit/data-structures/linked-list/linked-list.unshiftMany-else.coverage.test.ts +15 -0
  121. package/test/unit/data-structures/linked-list/singly-linked-list.coverage.test.ts +221 -0
  122. package/test/unit/data-structures/linked-list/singly-linked-list.more-branches.coverage.test.ts +86 -0
  123. package/test/unit/data-structures/linked-list/skip-linked-list.more-branches.coverage.test.ts +31 -0
  124. package/test/unit/data-structures/matrix/matrix.more-branches.coverage.test.ts +81 -0
  125. package/test/unit/data-structures/matrix/matrix.pivotElement-nullish.coverage.test.ts +28 -0
  126. package/test/unit/data-structures/priority-queue/max-priority-queue.more-branches.coverage.test.ts +10 -0
  127. package/test/unit/data-structures/priority-queue/priority-queue.coverage.test.ts +21 -0
  128. package/test/unit/data-structures/queue/deque.coverage.test.ts +173 -0
  129. package/test/unit/data-structures/queue/deque.more-branches-2.coverage.test.ts +39 -0
  130. package/test/unit/data-structures/queue/deque.more-branches-3.coverage.test.ts +9 -0
  131. package/test/unit/data-structures/queue/deque.more-branches.coverage.test.ts +95 -0
  132. package/test/unit/data-structures/queue/queue.coverage.test.ts +138 -0
  133. package/test/unit/data-structures/queue/queue.more-branches-2.coverage.test.ts +27 -0
  134. package/test/unit/data-structures/stack/stack.coverage.test.ts +112 -0
  135. package/test/unit/data-structures/tree/tree.more-branches.coverage.test.ts +9 -0
  136. package/test/unit/data-structures/trie/trie.more-branches-2.coverage.test.ts +51 -0
  137. package/test/utils/patch.ts +33 -0
@@ -1396,6 +1396,12 @@ var _LinearLinkedBase = class _LinearLinkedBase extends LinearBase {
1396
1396
  }
1397
1397
  return -1;
1398
1398
  }
1399
+ /**
1400
+ * Concatenate lists/elements preserving order.
1401
+ * @param items - Elements or `LinearBase` instances.
1402
+ * @returns New list with combined elements (`this` type).
1403
+ * @remarks Time O(sum(length)), Space O(sum(length))
1404
+ */
1399
1405
  concat(...items) {
1400
1406
  const newList = this.clone();
1401
1407
  for (const item of items) {
@@ -4218,6 +4224,12 @@ var _Deque = class _Deque extends LinearBase {
4218
4224
  */
4219
4225
  _setBucketSize(size) {
4220
4226
  this._bucketSize = size;
4227
+ if (this._length === 0) {
4228
+ this._buckets = [new Array(this._bucketSize)];
4229
+ this._bucketCount = 1;
4230
+ this._bucketFirst = this._bucketLast = 0;
4231
+ this._firstInBucket = this._lastInBucket = this._bucketSize >> 1;
4232
+ }
4221
4233
  }
4222
4234
  /**
4223
4235
  * (Protected) Iterate elements from front to back.
@@ -7270,7 +7282,6 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
7270
7282
  * @remarks Time O(N * M), where N is the number of items to set and M is the size of the tree at insertion (due to O(M) `set` operation). Space O(M) (from `set`) + O(N) (for the `inserted` array).
7271
7283
  *
7272
7284
  * @param keysNodesEntriesOrRaws - An iterable of items to set.
7273
- * @param [values] - An optional parallel iterable of values.
7274
7285
  * @returns An array of booleans indicating the success of each individual `set` operation.
7275
7286
  */
7276
7287
  addMany(keysNodesEntriesOrRaws) {
@@ -7327,13 +7338,13 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
7327
7338
  * Deletes a node from the tree.
7328
7339
  * @remarks Time O(log N), For BST, Red-Black Tree, and AVL Tree subclasses, the worst-case time is O(log N). This implementation finds the node, and if it has two children, swaps it with the rightmost node of its left subtree (in-order predecessor) before deleting. Time O(N) in the worst case. O(N) to find the node (`getNode`) and O(H) (which is O(N) worst-case) to find the rightmost node. Space O(1) (if `getNode` is iterative, which it is).
7329
7340
  *
7330
- * @param keyNodeOrEntry - The node to delete.
7341
+ * @param keyNodeEntryRawOrPredicate - The node to delete.
7331
7342
  * @returns An array containing deletion results (for compatibility with self-balancing trees).
7332
7343
  */
7333
- delete(keyNodeOrEntry) {
7344
+ delete(keyNodeEntryRawOrPredicate) {
7334
7345
  const deletedResult = [];
7335
7346
  if (!this._root) return deletedResult;
7336
- const curr = this.getNode(keyNodeOrEntry);
7347
+ const curr = this.getNode(keyNodeEntryRawOrPredicate);
7337
7348
  if (!curr) return deletedResult;
7338
7349
  const parent = curr == null ? void 0 : curr.parent;
7339
7350
  let needBalanced;
@@ -7517,7 +7528,7 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
7517
7528
  }
7518
7529
  return true;
7519
7530
  }, "checkBST");
7520
- const isStandardBST = checkBST(false);
7531
+ const isStandardBST = checkBST();
7521
7532
  const isInverseBST = checkBST(true);
7522
7533
  return isStandardBST || isInverseBST;
7523
7534
  }
@@ -8748,8 +8759,40 @@ var _BST = class _BST extends BinaryTree {
8748
8759
  * @returns The first matching node, or undefined if not found.
8749
8760
  */
8750
8761
  getNode(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
8751
- var _a;
8752
- return (_a = this.getNodes(keyNodeEntryOrPredicate, true, startNode, iterationType)[0]) != null ? _a : void 0;
8762
+ var _a, _b;
8763
+ if (keyNodeEntryOrPredicate === null || keyNodeEntryOrPredicate === void 0) return void 0;
8764
+ if (this._isPredicate(keyNodeEntryOrPredicate)) {
8765
+ return (_a = this.getNodes(keyNodeEntryOrPredicate, true, startNode, iterationType)[0]) != null ? _a : void 0;
8766
+ }
8767
+ if (keyNodeEntryOrPredicate instanceof Range) {
8768
+ return (_b = this.getNodes(
8769
+ keyNodeEntryOrPredicate,
8770
+ true,
8771
+ startNode,
8772
+ iterationType
8773
+ )[0]) != null ? _b : void 0;
8774
+ }
8775
+ let targetKey;
8776
+ if (this.isNode(keyNodeEntryOrPredicate)) {
8777
+ targetKey = keyNodeEntryOrPredicate.key;
8778
+ } else if (this.isEntry(keyNodeEntryOrPredicate)) {
8779
+ const k = keyNodeEntryOrPredicate[0];
8780
+ if (k === null || k === void 0) return void 0;
8781
+ targetKey = k;
8782
+ } else {
8783
+ targetKey = keyNodeEntryOrPredicate;
8784
+ }
8785
+ const start = this.ensureNode(startNode);
8786
+ if (!start) return void 0;
8787
+ const NIL = this._NIL;
8788
+ let cur = start;
8789
+ const cmpFn = this._comparator;
8790
+ while (cur && cur !== NIL) {
8791
+ const c = cmpFn(targetKey, cur.key);
8792
+ if (c === 0) return cur;
8793
+ cur = c < 0 ? cur._left : cur._right;
8794
+ }
8795
+ return void 0;
8753
8796
  }
8754
8797
  /**
8755
8798
  * Searches the tree for nodes matching a predicate, key, or range.
@@ -8770,8 +8813,30 @@ var _BST = class _BST extends BinaryTree {
8770
8813
  if (keyNodeEntryOrPredicate === null) return [];
8771
8814
  startNode = this.ensureNode(startNode);
8772
8815
  if (!startNode) return [];
8773
- let predicate;
8774
8816
  const isRange = this.isRange(keyNodeEntryOrPredicate);
8817
+ const isPred = !isRange && this._isPredicate(keyNodeEntryOrPredicate);
8818
+ if (!isRange && !isPred) {
8819
+ let targetKey;
8820
+ if (this.isNode(keyNodeEntryOrPredicate)) {
8821
+ targetKey = keyNodeEntryOrPredicate.key;
8822
+ } else if (this.isEntry(keyNodeEntryOrPredicate)) {
8823
+ const k = keyNodeEntryOrPredicate[0];
8824
+ if (k !== null && k !== void 0) targetKey = k;
8825
+ } else {
8826
+ targetKey = keyNodeEntryOrPredicate;
8827
+ }
8828
+ if (targetKey === void 0) return [];
8829
+ const NIL = this._NIL;
8830
+ const cmpFn = this._comparator;
8831
+ let cur = startNode;
8832
+ while (cur && cur !== NIL) {
8833
+ const c = cmpFn(targetKey, cur.key);
8834
+ if (c === 0) return [callback(cur)];
8835
+ cur = c < 0 ? cur._left : cur._right;
8836
+ }
8837
+ return [];
8838
+ }
8839
+ let predicate;
8775
8840
  if (isRange) {
8776
8841
  predicate = /* @__PURE__ */ __name((node) => {
8777
8842
  if (!node) return false;
@@ -9658,7 +9723,6 @@ var _BST = class _BST extends BinaryTree {
9658
9723
  * @returns True if the node was found and deleted, false otherwise.
9659
9724
  */
9660
9725
  _deleteByKey(key) {
9661
- var _a;
9662
9726
  let node = this._root;
9663
9727
  while (node) {
9664
9728
  const cmp = this._compare(node.key, key);
@@ -9697,7 +9761,7 @@ var _BST = class _BST extends BinaryTree {
9697
9761
  succ.left = node.left;
9698
9762
  if (succ.left) succ.left.parent = succ;
9699
9763
  }
9700
- this._size = Math.max(0, ((_a = this._size) != null ? _a : 0) - 1);
9764
+ this._size = Math.max(0, this._size - 1);
9701
9765
  return true;
9702
9766
  }
9703
9767
  };
@@ -10804,12 +10868,11 @@ var AVLTree = _AVLTree;
10804
10868
  // src/data-structures/binary-tree/red-black-tree.ts
10805
10869
  var _RedBlackTreeNode = class _RedBlackTreeNode {
10806
10870
  /**
10807
- * Create a Red-Black Tree and optionally bulk-insert items.
10808
- * @remarks Time O(n log n), Space O(n)
10809
- * @param key - See parameter type for details.
10810
- * @param [value]- See parameter type for details.
10811
- * @param color - See parameter type for details.
10812
- * @returns New RedBlackTree instance.
10871
+ * Create a Red-Black Tree node.
10872
+ * @remarks Time O(1), Space O(1)
10873
+ * @param key - Node key.
10874
+ * @param [value] - Node value (unused in map mode trees).
10875
+ * @param color - Node color.
10813
10876
  */
10814
10877
  constructor(key, value, color = "BLACK") {
10815
10878
  __publicField(this, "key");
@@ -10942,7 +11005,29 @@ var _RedBlackTree = class _RedBlackTree extends BST {
10942
11005
  constructor(keysNodesEntriesOrRaws = [], options) {
10943
11006
  super([], options);
10944
11007
  __publicField(this, "_root");
11008
+ /**
11009
+ * (Internal) Header sentinel:
11010
+ * - header.parent -> root
11011
+ * - header._left -> min (or NIL)
11012
+ * - header._right -> max (or NIL)
11013
+ *
11014
+ * IMPORTANT:
11015
+ * - This header is NOT part of the actual tree.
11016
+ * - Do NOT use `header.left` / `header.right` accessors for wiring: those setters update `NIL.parent`
11017
+ * and can corrupt sentinel invariants / cause hangs. Only touch `header._left/_right`.
11018
+ */
11019
+ __publicField(this, "_header");
11020
+ /**
11021
+ * (Internal) Cache of the current minimum and maximum nodes.
11022
+ * Used for fast-path insert/update when keys are monotonic or near-boundary.
11023
+ */
11024
+ __publicField(this, "_minNode");
11025
+ __publicField(this, "_maxNode");
10945
11026
  this._root = this.NIL;
11027
+ this._header = new RedBlackTreeNode(void 0, void 0, "BLACK");
11028
+ this._header.parent = this.NIL;
11029
+ this._header._left = this.NIL;
11030
+ this._header._right = this.NIL;
10946
11031
  if (keysNodesEntriesOrRaws) {
10947
11032
  this.setMany(keysNodesEntriesOrRaws);
10948
11033
  }
@@ -10980,18 +11065,390 @@ var _RedBlackTree = class _RedBlackTree extends BST {
10980
11065
  * @remarks Time O(n), Space O(1)
10981
11066
  * @returns void
10982
11067
  */
11068
+ /**
11069
+ * Remove all nodes and clear internal caches.
11070
+ * @remarks Time O(n) average, Space O(1)
11071
+ */
10983
11072
  clear() {
10984
11073
  super.clear();
10985
11074
  this._root = this.NIL;
11075
+ this._header.parent = this.NIL;
11076
+ this._setMinCache(void 0);
11077
+ this._setMaxCache(void 0);
10986
11078
  }
10987
11079
  /**
10988
- * Insert or replace an entry using BST order and red-black fix-up.
10989
- * @remarks Time O(log n), Space O(1)
10990
- * @param keyNodeOrEntry - Key, node, or [key, value] entry to insert.
10991
- * @param [value]- See parameter type for details.
10992
- * @returns True if inserted or updated; false if ignored.
11080
+ * (Internal) Find a node by key using a tight BST walk (no allocations).
11081
+ *
11082
+ * NOTE: This uses `header.parent` as the canonical root pointer.
11083
+ * @remarks Time O(log n) average, Space O(1)
11084
+ */
11085
+ _findNodeByKey(key) {
11086
+ var _a, _b, _c;
11087
+ const NIL = this.NIL;
11088
+ const cmp = this._compare.bind(this);
11089
+ let cur = (_a = this._header.parent) != null ? _a : NIL;
11090
+ while (cur !== NIL) {
11091
+ const c = cmp(key, cur.key);
11092
+ if (c < 0) cur = (_b = cur.left) != null ? _b : NIL;
11093
+ else if (c > 0) cur = (_c = cur.right) != null ? _c : NIL;
11094
+ else return cur;
11095
+ }
11096
+ return void 0;
11097
+ }
11098
+ /**
11099
+ * (Internal) In-order predecessor of a node in a BST.
11100
+ * @remarks Time O(log n) average, Space O(1)
11101
+ */
11102
+ _predecessorOf(node) {
11103
+ const NIL = this.NIL;
11104
+ if (node.left && node.left !== NIL) {
11105
+ let cur2 = node.left;
11106
+ while (cur2.right && cur2.right !== NIL) cur2 = cur2.right;
11107
+ return cur2;
11108
+ }
11109
+ let cur = node;
11110
+ let p = node.parent;
11111
+ while (p && cur === p.left) {
11112
+ cur = p;
11113
+ p = p.parent;
11114
+ }
11115
+ return p;
11116
+ }
11117
+ /**
11118
+ * (Internal) In-order successor of a node in a BST.
11119
+ * @remarks Time O(log n) average, Space O(1)
11120
+ */
11121
+ _successorOf(node) {
11122
+ const NIL = this.NIL;
11123
+ if (node.right && node.right !== NIL) {
11124
+ let cur2 = node.right;
11125
+ while (cur2.left && cur2.left !== NIL) cur2 = cur2.left;
11126
+ return cur2;
11127
+ }
11128
+ let cur = node;
11129
+ let p = node.parent;
11130
+ while (p && cur === p.right) {
11131
+ cur = p;
11132
+ p = p.parent;
11133
+ }
11134
+ return p;
11135
+ }
11136
+ /**
11137
+ * (Internal) Attach a new node directly under a known parent/side (no search).
11138
+ *
11139
+ * This is a performance-oriented helper used by boundary fast paths and hinted insertion.
11140
+ * It will:
11141
+ * - wire parent/child pointers (using accessors, so parent pointers are updated)
11142
+ * - initialize children to NIL
11143
+ * - mark the new node RED, then run insert fix-up
11144
+ *
11145
+ * Precondition: the chosen slot (parent.left/parent.right) is empty (NIL/null/undefined).
11146
+ * @remarks Time O(log n) average, Space O(1)
11147
+ */
11148
+ _attachNewNode(parent, side, node) {
11149
+ const NIL = this.NIL;
11150
+ node.parent = parent;
11151
+ if (side === "left") parent.left = node;
11152
+ else parent.right = node;
11153
+ node.left = NIL;
11154
+ node.right = NIL;
11155
+ node.color = "RED";
11156
+ this._insertFixup(node);
11157
+ if (this.isRealNode(this._root)) this._root.color = "BLACK";
11158
+ }
11159
+ /**
11160
+ * (Internal) a single source of truth for min/max is header._left/_right.
11161
+ * Keep legacy _minNode/_maxNode mirrored for compatibility.
11162
+ * @remarks Time O(1), Space O(1)
11163
+ */
11164
+ /**
11165
+ * (Internal) Update min cache pointers (header._left is the canonical min pointer).
11166
+ * @remarks Time O(1), Space O(1)
11167
+ */
11168
+ _setMinCache(node) {
11169
+ this._minNode = node;
11170
+ this._header._left = node != null ? node : this.NIL;
11171
+ }
11172
+ /**
11173
+ * (Internal) Update max cache pointers (header._right is the canonical max pointer).
11174
+ * @remarks Time O(1), Space O(1)
11175
+ */
11176
+ _setMaxCache(node) {
11177
+ this._maxNode = node;
11178
+ this._header._right = node != null ? node : this.NIL;
11179
+ }
11180
+ /**
11181
+ * (Internal) Core set implementation returning the affected node.
11182
+ *
11183
+ * Hot path goals:
11184
+ * - Avoid double walks (search+insert): do a single traversal that either updates or inserts.
11185
+ * - Use header min/max caches to fast-path boundary inserts.
11186
+ * - Keep header._left/_right as canonical min/max pointers.
11187
+ *
11188
+ * Return value:
11189
+ * - `{ node, created:false }` when an existing key is updated
11190
+ * - `{ node, created:true }` when a new node is inserted
11191
+ * - `undefined` only on unexpected internal failure.
11192
+ * @remarks Time O(log n) average, Space O(1)
11193
+ */
11194
+ _setKVNode(key, nextValue) {
11195
+ var _a, _b, _c, _d, _e, _f, _g;
11196
+ const NIL = this.NIL;
11197
+ const comparator = this._comparator;
11198
+ const header = this._header;
11199
+ const minN = (_a = header._left) != null ? _a : NIL;
11200
+ if (minN !== NIL) {
11201
+ const cMin = comparator(key, minN.key);
11202
+ if (cMin === 0) {
11203
+ if (this._isMapMode) {
11204
+ if (nextValue !== void 0) this._store.set(key, nextValue);
11205
+ else this._setValue(key, nextValue);
11206
+ } else minN.value = nextValue;
11207
+ return { node: minN, created: false };
11208
+ }
11209
+ const minL = minN.left;
11210
+ if (cMin < 0 && (minL === NIL || minL === null || minL === void 0)) {
11211
+ const newNode2 = this.createNode(key, nextValue);
11212
+ this._attachNewNode(minN, "left", newNode2);
11213
+ if (this._isMapMode) {
11214
+ if (nextValue !== void 0) this._store.set(newNode2.key, nextValue);
11215
+ else this._setValue(newNode2.key, nextValue);
11216
+ }
11217
+ this._size++;
11218
+ this._setMinCache(newNode2);
11219
+ if (header._right === NIL) this._setMaxCache(newNode2);
11220
+ return { node: newNode2, created: true };
11221
+ }
11222
+ if (cMin > 0) {
11223
+ const maxN = (_b = header._right) != null ? _b : NIL;
11224
+ const cMax = comparator(key, maxN.key);
11225
+ if (cMax === 0) {
11226
+ if (this._isMapMode) {
11227
+ if (nextValue !== void 0) this._store.set(key, nextValue);
11228
+ else this._setValue(key, nextValue);
11229
+ } else maxN.value = nextValue;
11230
+ return { node: maxN, created: false };
11231
+ }
11232
+ const maxR = maxN.right;
11233
+ if (cMax > 0 && (maxR === NIL || maxR === null || maxR === void 0)) {
11234
+ const newNode2 = this.createNode(key, nextValue);
11235
+ this._attachNewNode(maxN, "right", newNode2);
11236
+ if (this._isMapMode) {
11237
+ if (nextValue !== void 0) this._store.set(newNode2.key, nextValue);
11238
+ else this._setValue(newNode2.key, nextValue);
11239
+ }
11240
+ this._size++;
11241
+ this._setMaxCache(newNode2);
11242
+ if (header._left === NIL) this._setMinCache(newNode2);
11243
+ return { node: newNode2, created: true };
11244
+ }
11245
+ }
11246
+ }
11247
+ const cmp = comparator;
11248
+ const isMapMode = this._isMapMode;
11249
+ const store = this._store;
11250
+ let current = (_c = this._header.parent) != null ? _c : NIL;
11251
+ let parent;
11252
+ let lastCompared = 0;
11253
+ while (current !== NIL) {
11254
+ parent = current;
11255
+ lastCompared = cmp(key, current.key);
11256
+ if (lastCompared < 0) current = (_d = current.left) != null ? _d : NIL;
11257
+ else if (lastCompared > 0) current = (_e = current.right) != null ? _e : NIL;
11258
+ else {
11259
+ if (isMapMode) {
11260
+ if (nextValue !== void 0) store.set(key, nextValue);
11261
+ else this._setValue(key, nextValue);
11262
+ } else {
11263
+ current.value = nextValue;
11264
+ }
11265
+ return { node: current, created: false };
11266
+ }
11267
+ }
11268
+ const newNode = this.createNode(key, nextValue);
11269
+ newNode.parent = parent;
11270
+ if (!parent) {
11271
+ this._setRoot(newNode);
11272
+ } else if (lastCompared < 0) {
11273
+ parent.left = newNode;
11274
+ } else {
11275
+ parent.right = newNode;
11276
+ }
11277
+ newNode.left = NIL;
11278
+ newNode.right = NIL;
11279
+ newNode.color = "RED";
11280
+ this._insertFixup(newNode);
11281
+ if (this.isRealNode(this._root)) this._root.color = "BLACK";
11282
+ else return void 0;
11283
+ if (isMapMode) {
11284
+ if (nextValue !== void 0) store.set(newNode.key, nextValue);
11285
+ else this._setValue(newNode.key, nextValue);
11286
+ }
11287
+ this._size++;
11288
+ const hMin = (_f = this._header._left) != null ? _f : NIL;
11289
+ const hMax = (_g = this._header._right) != null ? _g : NIL;
11290
+ if (hMin === NIL || hMax === NIL) {
11291
+ this._setMinCache(newNode);
11292
+ this._setMaxCache(newNode);
11293
+ } else if (parent === hMax && lastCompared > 0) {
11294
+ this._setMaxCache(newNode);
11295
+ } else if (parent === hMin && lastCompared < 0) {
11296
+ this._setMinCache(newNode);
11297
+ } else {
11298
+ if (cmp(newNode.key, hMin.key) < 0) this._setMinCache(newNode);
11299
+ if (cmp(newNode.key, hMax.key) > 0) this._setMaxCache(newNode);
11300
+ }
11301
+ return { node: newNode, created: true };
11302
+ }
11303
+ /**
11304
+ * (Internal) Boolean wrapper around `_setKVNode`.
11305
+ *
11306
+ * Includes a map-mode update fast-path:
11307
+ * - If `isMapMode=true` and the key already exists in `_store`, then updating the value does not
11308
+ * require any tree search/rotation (tree shape depends only on key).
11309
+ * - This path is intentionally limited to `nextValue !== undefined` to preserve existing
11310
+ * semantics for `undefined` values.
11311
+ * @remarks Time O(log n) average, Space O(1)
11312
+ */
11313
+ _setKV(key, nextValue) {
11314
+ if (this._isMapMode && nextValue !== void 0) {
11315
+ const store = this._store;
11316
+ if (store.has(key)) {
11317
+ store.set(key, nextValue);
11318
+ return true;
11319
+ }
11320
+ }
11321
+ return this._setKVNode(key, nextValue) !== void 0;
11322
+ }
11323
+ /**
11324
+ * Insert/update using a hint node to speed up nearby insertions.
11325
+ *
11326
+ * close to the expected insertion position (often the previously returned node in a loop).
11327
+ *
11328
+ * When the hint is a good fit (sorted / nearly-sorted insertion), this can avoid most of the
11329
+ * normal root-to-leaf search and reduce constant factors.
11330
+ *
11331
+ * When the hint does not match (random workloads), this will fall back to the normal set path.
11332
+ * @remarks Time O(log n) average, Space O(1)
11333
+ */
11334
+ setWithHintNode(key, value, hint) {
11335
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
11336
+ if (!hint || !this.isRealNode(hint)) {
11337
+ return (_a = this._setKVNode(key, value)) == null ? void 0 : _a.node;
11338
+ }
11339
+ const cmp = this._compare.bind(this);
11340
+ const c0 = cmp(key, hint.key);
11341
+ if (c0 === 0) {
11342
+ if (this._isMapMode) {
11343
+ if (value !== void 0) this._store.set(key, value);
11344
+ else this._setValue(key, value);
11345
+ } else hint.value = value;
11346
+ return hint;
11347
+ }
11348
+ if (c0 < 0) {
11349
+ if (!this.isRealNode(hint.left)) {
11350
+ const newNode = this.createNode(key, value);
11351
+ if (!this.isRealNode(newNode)) return void 0;
11352
+ this._attachNewNode(hint, "left", newNode);
11353
+ if (this._isMapMode) {
11354
+ if (value !== void 0) this._store.set(key, value);
11355
+ else this._setValue(key, value);
11356
+ }
11357
+ this._size++;
11358
+ const NIL = this.NIL;
11359
+ const hMin = (_b = this._header._left) != null ? _b : NIL;
11360
+ if (hMin === NIL || this._compare(newNode.key, hMin.key) < 0) this._setMinCache(newNode);
11361
+ const hMax = (_c = this._header._right) != null ? _c : NIL;
11362
+ if (hMax === NIL || this._compare(newNode.key, hMax.key) > 0) this._setMaxCache(newNode);
11363
+ return newNode;
11364
+ }
11365
+ const pred = this._predecessorOf(hint);
11366
+ if (pred && cmp(pred.key, key) >= 0) {
11367
+ return (_d = this._setKVNode(key, value)) == null ? void 0 : _d.node;
11368
+ }
11369
+ if (pred && !this.isRealNode(pred.right)) {
11370
+ const newNode = this.createNode(key, value);
11371
+ if (!this.isRealNode(newNode)) return void 0;
11372
+ this._attachNewNode(pred, "right", newNode);
11373
+ if (this._isMapMode) {
11374
+ if (value !== void 0) this._store.set(key, value);
11375
+ else this._setValue(key, value);
11376
+ }
11377
+ this._size++;
11378
+ const NIL = this.NIL;
11379
+ const hMin = (_e = this._header._left) != null ? _e : NIL;
11380
+ if (hMin === NIL || this._compare(newNode.key, hMin.key) < 0) this._setMinCache(newNode);
11381
+ const hMax = (_f = this._header._right) != null ? _f : NIL;
11382
+ if (hMax === NIL || this._compare(newNode.key, hMax.key) > 0) this._setMaxCache(newNode);
11383
+ return newNode;
11384
+ }
11385
+ return (_g = this._setKVNode(key, value)) == null ? void 0 : _g.node;
11386
+ }
11387
+ if (!this.isRealNode(hint.right)) {
11388
+ const newNode = this.createNode(key, value);
11389
+ if (!this.isRealNode(newNode)) return void 0;
11390
+ this._attachNewNode(hint, "right", newNode);
11391
+ if (this._isMapMode) {
11392
+ if (value !== void 0) this._store.set(key, value);
11393
+ else this._setValue(key, value);
11394
+ }
11395
+ this._size++;
11396
+ const NIL = this.NIL;
11397
+ const hMin = (_h = this._header._left) != null ? _h : NIL;
11398
+ if (hMin === NIL || this._compare(newNode.key, hMin.key) < 0) this._setMinCache(newNode);
11399
+ const hMax = (_i = this._header._right) != null ? _i : NIL;
11400
+ if (hMax === NIL || this._compare(newNode.key, hMax.key) > 0) this._setMaxCache(newNode);
11401
+ return newNode;
11402
+ }
11403
+ const succ = this._successorOf(hint);
11404
+ if (succ && cmp(succ.key, key) <= 0) {
11405
+ return (_j = this._setKVNode(key, value)) == null ? void 0 : _j.node;
11406
+ }
11407
+ if (succ && !this.isRealNode(succ.left)) {
11408
+ const newNode = this.createNode(key, value);
11409
+ if (!this.isRealNode(newNode)) return void 0;
11410
+ this._attachNewNode(succ, "left", newNode);
11411
+ if (this._isMapMode) {
11412
+ if (value !== void 0) this._store.set(key, value);
11413
+ else this._setValue(key, value);
11414
+ }
11415
+ this._size++;
11416
+ const NIL = this.NIL;
11417
+ const hMin = (_k = this._header._left) != null ? _k : NIL;
11418
+ if (hMin === NIL || this._compare(newNode.key, hMin.key) < 0) this._setMinCache(newNode);
11419
+ const hMax = (_l = this._header._right) != null ? _l : NIL;
11420
+ if (hMax === NIL || this._compare(newNode.key, hMax.key) > 0) this._setMaxCache(newNode);
11421
+ return newNode;
11422
+ }
11423
+ return (_m = this._setKVNode(key, value)) == null ? void 0 : _m.node;
11424
+ }
11425
+ /**
11426
+ * Boolean wrapper for setWithHintNode.
11427
+ * @remarks Time O(log n) average, Space O(1)
11428
+ */
11429
+ setWithHint(key, value, hint) {
11430
+ return this.setWithHintNode(key, value, hint) !== void 0;
11431
+ }
11432
+ /**
11433
+ * Insert or update a key/value (map mode) or key-only (set mode).
11434
+ *
11435
+ * This method is optimized for:
11436
+ * - monotonic inserts via min/max boundary fast paths
11437
+ * - updates via a single-pass search (no double walk)
11438
+ *
11439
+ * @remarks Time O(log n) average, Space O(1)
10993
11440
  */
10994
11441
  set(keyNodeOrEntry, value) {
11442
+ if (!this.isNode(keyNodeOrEntry)) {
11443
+ if (keyNodeOrEntry === null || keyNodeOrEntry === void 0) return false;
11444
+ if (this.isEntry(keyNodeOrEntry)) {
11445
+ const key = keyNodeOrEntry[0];
11446
+ if (key === null || key === void 0) return false;
11447
+ const nextValue = value != null ? value : keyNodeOrEntry[1];
11448
+ return this._setKV(key, nextValue);
11449
+ }
11450
+ return this._setKV(keyNodeOrEntry, value);
11451
+ }
10995
11452
  const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
10996
11453
  if (!this.isRealNode(newNode)) return false;
10997
11454
  const insertStatus = this._insert(newNode);
@@ -11013,19 +11470,23 @@ var _RedBlackTree = class _RedBlackTree extends BST {
11013
11470
  }
11014
11471
  /**
11015
11472
  * Delete a node by key/node/entry and rebalance as needed.
11016
- * @remarks Time O(log n), Space O(1)
11017
- * @param keyNodeOrEntry - Key, node, or [key, value] entry identifying the node to delete.
11473
+ * @remarks Time O(log n) average, Space O(1)
11474
+ * @param keyNodeEntryRawOrPredicate - Key, node, or [key, value] entry identifying the node to delete.
11018
11475
  * @returns Array with deletion metadata (removed node, rebalancing hint if any).
11019
11476
  */
11020
- delete(keyNodeOrEntry) {
11021
- if (keyNodeOrEntry === null) return [];
11477
+ delete(keyNodeEntryRawOrPredicate) {
11478
+ if (keyNodeEntryRawOrPredicate === null) return [];
11022
11479
  const results = [];
11023
11480
  let nodeToDelete;
11024
- if (this._isPredicate(keyNodeOrEntry)) nodeToDelete = this.getNode(keyNodeOrEntry);
11025
- else nodeToDelete = this.isRealNode(keyNodeOrEntry) ? keyNodeOrEntry : this.getNode(keyNodeOrEntry);
11481
+ if (this._isPredicate(keyNodeEntryRawOrPredicate)) nodeToDelete = this.getNode(keyNodeEntryRawOrPredicate);
11482
+ else nodeToDelete = this.isRealNode(keyNodeEntryRawOrPredicate) ? keyNodeEntryRawOrPredicate : this.getNode(keyNodeEntryRawOrPredicate);
11026
11483
  if (!nodeToDelete) {
11027
11484
  return results;
11028
11485
  }
11486
+ const willDeleteMin = nodeToDelete === this._minNode;
11487
+ const willDeleteMax = nodeToDelete === this._maxNode;
11488
+ const nextMin = willDeleteMin ? this._successorOf(nodeToDelete) : void 0;
11489
+ const nextMax = willDeleteMax ? this._predecessorOf(nodeToDelete) : void 0;
11029
11490
  let originalColor = nodeToDelete.color;
11030
11491
  let replacementNode;
11031
11492
  if (!this.isRealNode(nodeToDelete.left)) {
@@ -11064,6 +11525,19 @@ var _RedBlackTree = class _RedBlackTree extends BST {
11064
11525
  }
11065
11526
  if (this._isMapMode) this._store.delete(nodeToDelete.key);
11066
11527
  this._size--;
11528
+ if (this._size <= 0) {
11529
+ this._setMinCache(void 0);
11530
+ this._setMaxCache(void 0);
11531
+ } else {
11532
+ if (willDeleteMin) this._setMinCache(nextMin);
11533
+ if (willDeleteMax) this._setMaxCache(nextMax);
11534
+ if (!this._minNode || !this.isRealNode(this._minNode)) {
11535
+ this._setMinCache(this.isRealNode(this._root) ? this.getLeftMost((n) => n, this._root) : void 0);
11536
+ }
11537
+ if (!this._maxNode || !this.isRealNode(this._maxNode)) {
11538
+ this._setMaxCache(this.isRealNode(this._root) ? this.getRightMost((n) => n, this._root) : void 0);
11539
+ }
11540
+ }
11067
11541
  if (originalColor === "BLACK") {
11068
11542
  this._deleteFixup(replacementNode);
11069
11543
  }
@@ -11072,7 +11546,7 @@ var _RedBlackTree = class _RedBlackTree extends BST {
11072
11546
  }
11073
11547
  /**
11074
11548
  * Transform entries into a like-kind red-black tree with possibly different key/value types.
11075
- * @remarks Time O(n), Space O(n)
11549
+ * @remarks Time O(n) average, Space O(n)
11076
11550
  * @template MK
11077
11551
  * @template MV
11078
11552
  * @template MR
@@ -11089,41 +11563,62 @@ var _RedBlackTree = class _RedBlackTree extends BST {
11089
11563
  }
11090
11564
  return out;
11091
11565
  }
11566
+ /**
11567
+ * (Internal) Create an empty instance of the same concrete tree type.
11568
+ * @remarks Time O(1) average, Space O(1)
11569
+ */
11092
11570
  _createInstance(options) {
11093
11571
  const Ctor = this.constructor;
11094
11572
  return new Ctor([], { ...this._snapshotOptions(), ...options != null ? options : {} });
11095
11573
  }
11574
+ /**
11575
+ * (Internal) Create a like-kind tree (same concrete class) populated from an iterable.
11576
+ * @remarks Time O(m log m) average (m = iterable length), Space O(m)
11577
+ */
11096
11578
  _createLike(iter = [], options) {
11097
11579
  const Ctor = this.constructor;
11098
11580
  return new Ctor(iter, { ...this._snapshotOptions(), ...options != null ? options : {} });
11099
11581
  }
11582
+ /**
11583
+ * (Internal) Set the root pointer and keep header.parent in sync.
11584
+ * @remarks Time O(1), Space O(1)
11585
+ */
11100
11586
  _setRoot(v) {
11587
+ const NIL = this.NIL;
11101
11588
  if (v) {
11102
11589
  v.parent = void 0;
11103
11590
  }
11104
11591
  this._root = v;
11592
+ this._header.parent = v != null ? v : NIL;
11105
11593
  }
11594
+ /**
11595
+ * (Internal) Replace a node in place while preserving its color.
11596
+ * @remarks Time O(1) average, Space O(1)
11597
+ */
11106
11598
  _replaceNode(oldNode, newNode) {
11107
11599
  newNode.color = oldNode.color;
11108
11600
  return super._replaceNode(oldNode, newNode);
11109
11601
  }
11110
11602
  /**
11111
11603
  * (Protected) Standard BST insert followed by red-black fix-up.
11112
- * @remarks Time O(log n), Space O(1)
11604
+ * @remarks Time O(log n) average, Space O(1)
11113
11605
  * @param node - Node to insert.
11114
11606
  * @returns Status string: 'CREATED' or 'UPDATED'.
11115
11607
  */
11116
11608
  _insert(node) {
11117
11609
  var _a, _b, _c;
11118
- let current = (_a = this.root) != null ? _a : this.NIL;
11119
- let parent = void 0;
11120
- while (current !== this.NIL) {
11610
+ const NIL = this.NIL;
11611
+ const cmp = this._compare.bind(this);
11612
+ let current = (_a = this._header.parent) != null ? _a : NIL;
11613
+ let parent;
11614
+ let lastCompared = 0;
11615
+ while (current !== NIL) {
11121
11616
  parent = current;
11122
- const compared = this._compare(node.key, current.key);
11123
- if (compared < 0) {
11124
- current = (_b = current.left) != null ? _b : this.NIL;
11125
- } else if (compared > 0) {
11126
- current = (_c = current.right) != null ? _c : this.NIL;
11617
+ lastCompared = cmp(node.key, current.key);
11618
+ if (lastCompared < 0) {
11619
+ current = (_b = current.left) != null ? _b : NIL;
11620
+ } else if (lastCompared > 0) {
11621
+ current = (_c = current.right) != null ? _c : NIL;
11127
11622
  } else {
11128
11623
  this._replaceNode(current, node);
11129
11624
  return "UPDATED";
@@ -11132,13 +11627,13 @@ var _RedBlackTree = class _RedBlackTree extends BST {
11132
11627
  node.parent = parent;
11133
11628
  if (!parent) {
11134
11629
  this._setRoot(node);
11135
- } else if (this._compare(node.key, parent.key) < 0) {
11630
+ } else if (lastCompared < 0) {
11136
11631
  parent.left = node;
11137
11632
  } else {
11138
11633
  parent.right = node;
11139
11634
  }
11140
- node.left = this.NIL;
11141
- node.right = this.NIL;
11635
+ node.left = NIL;
11636
+ node.right = NIL;
11142
11637
  node.color = "RED";
11143
11638
  this._insertFixup(node);
11144
11639
  return "CREATED";
@@ -11164,56 +11659,66 @@ var _RedBlackTree = class _RedBlackTree extends BST {
11164
11659
  }
11165
11660
  /**
11166
11661
  * (Protected) Restore red-black properties after insertion (recolor/rotate).
11167
- * @remarks Time O(log n), Space O(1)
11662
+ * @remarks Time O(log n) average, Space O(1)
11168
11663
  * @param z - Recently inserted node.
11169
11664
  * @returns void
11170
11665
  */
11171
11666
  _insertFixup(z) {
11172
- var _a, _b, _c, _d, _e;
11173
- while (((_a = z == null ? void 0 : z.parent) == null ? void 0 : _a.color) === "RED") {
11174
- if (z.parent === ((_b = z.parent.parent) == null ? void 0 : _b.left)) {
11175
- const y = z.parent.parent.right;
11667
+ const leftRotate = this._leftRotate.bind(this);
11668
+ const rightRotate = this._rightRotate.bind(this);
11669
+ while (z) {
11670
+ const p = z.parent;
11671
+ if (!p || p.color !== "RED") break;
11672
+ const gp = p.parent;
11673
+ if (!gp) break;
11674
+ if (p === gp.left) {
11675
+ const y = gp.right;
11176
11676
  if ((y == null ? void 0 : y.color) === "RED") {
11177
- z.parent.color = "BLACK";
11677
+ p.color = "BLACK";
11178
11678
  y.color = "BLACK";
11179
- z.parent.parent.color = "RED";
11180
- z = z.parent.parent;
11181
- } else {
11182
- if (z === z.parent.right) {
11183
- z = z.parent;
11184
- this._leftRotate(z);
11185
- }
11186
- if (z && z.parent && z.parent.parent) {
11187
- z.parent.color = "BLACK";
11188
- z.parent.parent.color = "RED";
11189
- this._rightRotate(z.parent.parent);
11190
- }
11679
+ gp.color = "RED";
11680
+ z = gp;
11681
+ continue;
11682
+ }
11683
+ if (z === p.right) {
11684
+ z = p;
11685
+ leftRotate(z);
11686
+ }
11687
+ const p2 = z == null ? void 0 : z.parent;
11688
+ const gp2 = p2 == null ? void 0 : p2.parent;
11689
+ if (p2 && gp2) {
11690
+ p2.color = "BLACK";
11691
+ gp2.color = "RED";
11692
+ rightRotate(gp2);
11191
11693
  }
11192
11694
  } else {
11193
- const y = (_e = (_d = (_c = z == null ? void 0 : z.parent) == null ? void 0 : _c.parent) == null ? void 0 : _d.left) != null ? _e : void 0;
11695
+ const y = gp.left;
11194
11696
  if ((y == null ? void 0 : y.color) === "RED") {
11195
- z.parent.color = "BLACK";
11697
+ p.color = "BLACK";
11196
11698
  y.color = "BLACK";
11197
- z.parent.parent.color = "RED";
11198
- z = z.parent.parent;
11199
- } else {
11200
- if (z === z.parent.left) {
11201
- z = z.parent;
11202
- this._rightRotate(z);
11203
- }
11204
- if (z && z.parent && z.parent.parent) {
11205
- z.parent.color = "BLACK";
11206
- z.parent.parent.color = "RED";
11207
- this._leftRotate(z.parent.parent);
11208
- }
11699
+ gp.color = "RED";
11700
+ z = gp;
11701
+ continue;
11702
+ }
11703
+ if (z === p.left) {
11704
+ z = p;
11705
+ rightRotate(z);
11706
+ }
11707
+ const p2 = z == null ? void 0 : z.parent;
11708
+ const gp2 = p2 == null ? void 0 : p2.parent;
11709
+ if (p2 && gp2) {
11710
+ p2.color = "BLACK";
11711
+ gp2.color = "RED";
11712
+ leftRotate(gp2);
11209
11713
  }
11210
11714
  }
11715
+ break;
11211
11716
  }
11212
11717
  if (this.isRealNode(this._root)) this._root.color = "BLACK";
11213
11718
  }
11214
11719
  /**
11215
11720
  * (Protected) Restore red-black properties after deletion (recolor/rotate).
11216
- * @remarks Time O(log n), Space O(1)
11721
+ * @remarks Time O(log n) average, Space O(1)
11217
11722
  * @param node - Child that replaced the deleted node (may be undefined).
11218
11723
  * @returns void
11219
11724
  */
@@ -12116,16 +12621,16 @@ var _TreeCounter = class _TreeCounter extends RedBlackTree {
12116
12621
  /**
12117
12622
  * Delete a node (or decrement its count) and rebalance if needed.
12118
12623
  * @remarks Time O(log N), Space O(1)
12119
- * @param keyNodeOrEntry - Key, node, or [key, value] entry identifying the node.
12624
+ * @param keyNodeEntryRawOrPredicate - Key, node, or [key, value] entry identifying the node.
12120
12625
  * @param [ignoreCount] - If true, remove the node regardless of its count.
12121
12626
  * @returns Array of deletion results including deleted node and a rebalance hint when present.
12122
12627
  */
12123
- delete(keyNodeOrEntry, ignoreCount = false) {
12124
- if (keyNodeOrEntry === null) return [];
12628
+ delete(keyNodeEntryRawOrPredicate, ignoreCount = false) {
12629
+ if (keyNodeEntryRawOrPredicate === null) return [];
12125
12630
  const results = [];
12126
12631
  let nodeToDelete;
12127
- if (this._isPredicate(keyNodeOrEntry)) nodeToDelete = this.getNode(keyNodeOrEntry);
12128
- else nodeToDelete = this.isRealNode(keyNodeOrEntry) ? keyNodeOrEntry : this.getNode(keyNodeOrEntry);
12632
+ if (this._isPredicate(keyNodeEntryRawOrPredicate)) nodeToDelete = this.getNode(keyNodeEntryRawOrPredicate);
12633
+ else nodeToDelete = this.isRealNode(keyNodeEntryRawOrPredicate) ? keyNodeEntryRawOrPredicate : this.getNode(keyNodeEntryRawOrPredicate);
12129
12634
  if (!nodeToDelete) {
12130
12635
  return results;
12131
12636
  }
@@ -12168,7 +12673,6 @@ var _TreeCounter = class _TreeCounter extends RedBlackTree {
12168
12673
  if (ignoreCount || nodeToDelete.count <= 1) {
12169
12674
  if (successor.right !== null) {
12170
12675
  this._transplant(successor, successor.right);
12171
- this._count -= nodeToDelete.count;
12172
12676
  }
12173
12677
  } else {
12174
12678
  nodeToDelete.count--;
@@ -12271,6 +12775,11 @@ var _TreeCounter = class _TreeCounter extends RedBlackTree {
12271
12775
  const out = this._createInstance();
12272
12776
  this._clone(out);
12273
12777
  out._count = this._count;
12778
+ for (const node of this.dfs((n) => n, "IN")) {
12779
+ if (!node) continue;
12780
+ const outNode = out.getNode(node.key);
12781
+ if (outNode) outNode.count = node.count;
12782
+ }
12274
12783
  return out;
12275
12784
  }
12276
12785
  /**