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
@@ -1398,6 +1398,12 @@ var _LinearLinkedBase = class _LinearLinkedBase extends LinearBase {
1398
1398
  }
1399
1399
  return -1;
1400
1400
  }
1401
+ /**
1402
+ * Concatenate lists/elements preserving order.
1403
+ * @param items - Elements or `LinearBase` instances.
1404
+ * @returns New list with combined elements (`this` type).
1405
+ * @remarks Time O(sum(length)), Space O(sum(length))
1406
+ */
1401
1407
  concat(...items) {
1402
1408
  const newList = this.clone();
1403
1409
  for (const item of items) {
@@ -4220,6 +4226,12 @@ var _Deque = class _Deque extends LinearBase {
4220
4226
  */
4221
4227
  _setBucketSize(size) {
4222
4228
  this._bucketSize = size;
4229
+ if (this._length === 0) {
4230
+ this._buckets = [new Array(this._bucketSize)];
4231
+ this._bucketCount = 1;
4232
+ this._bucketFirst = this._bucketLast = 0;
4233
+ this._firstInBucket = this._lastInBucket = this._bucketSize >> 1;
4234
+ }
4223
4235
  }
4224
4236
  /**
4225
4237
  * (Protected) Iterate elements from front to back.
@@ -7272,7 +7284,6 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
7272
7284
  * @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).
7273
7285
  *
7274
7286
  * @param keysNodesEntriesOrRaws - An iterable of items to set.
7275
- * @param [values] - An optional parallel iterable of values.
7276
7287
  * @returns An array of booleans indicating the success of each individual `set` operation.
7277
7288
  */
7278
7289
  addMany(keysNodesEntriesOrRaws) {
@@ -7329,13 +7340,13 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
7329
7340
  * Deletes a node from the tree.
7330
7341
  * @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).
7331
7342
  *
7332
- * @param keyNodeOrEntry - The node to delete.
7343
+ * @param keyNodeEntryRawOrPredicate - The node to delete.
7333
7344
  * @returns An array containing deletion results (for compatibility with self-balancing trees).
7334
7345
  */
7335
- delete(keyNodeOrEntry) {
7346
+ delete(keyNodeEntryRawOrPredicate) {
7336
7347
  const deletedResult = [];
7337
7348
  if (!this._root) return deletedResult;
7338
- const curr = this.getNode(keyNodeOrEntry);
7349
+ const curr = this.getNode(keyNodeEntryRawOrPredicate);
7339
7350
  if (!curr) return deletedResult;
7340
7351
  const parent = curr == null ? void 0 : curr.parent;
7341
7352
  let needBalanced;
@@ -7519,7 +7530,7 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
7519
7530
  }
7520
7531
  return true;
7521
7532
  }, "checkBST");
7522
- const isStandardBST = checkBST(false);
7533
+ const isStandardBST = checkBST();
7523
7534
  const isInverseBST = checkBST(true);
7524
7535
  return isStandardBST || isInverseBST;
7525
7536
  }
@@ -8750,8 +8761,40 @@ var _BST = class _BST extends BinaryTree {
8750
8761
  * @returns The first matching node, or undefined if not found.
8751
8762
  */
8752
8763
  getNode(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
8753
- var _a;
8754
- return (_a = this.getNodes(keyNodeEntryOrPredicate, true, startNode, iterationType)[0]) != null ? _a : void 0;
8764
+ var _a, _b;
8765
+ if (keyNodeEntryOrPredicate === null || keyNodeEntryOrPredicate === void 0) return void 0;
8766
+ if (this._isPredicate(keyNodeEntryOrPredicate)) {
8767
+ return (_a = this.getNodes(keyNodeEntryOrPredicate, true, startNode, iterationType)[0]) != null ? _a : void 0;
8768
+ }
8769
+ if (keyNodeEntryOrPredicate instanceof Range) {
8770
+ return (_b = this.getNodes(
8771
+ keyNodeEntryOrPredicate,
8772
+ true,
8773
+ startNode,
8774
+ iterationType
8775
+ )[0]) != null ? _b : void 0;
8776
+ }
8777
+ let targetKey;
8778
+ if (this.isNode(keyNodeEntryOrPredicate)) {
8779
+ targetKey = keyNodeEntryOrPredicate.key;
8780
+ } else if (this.isEntry(keyNodeEntryOrPredicate)) {
8781
+ const k = keyNodeEntryOrPredicate[0];
8782
+ if (k === null || k === void 0) return void 0;
8783
+ targetKey = k;
8784
+ } else {
8785
+ targetKey = keyNodeEntryOrPredicate;
8786
+ }
8787
+ const start = this.ensureNode(startNode);
8788
+ if (!start) return void 0;
8789
+ const NIL = this._NIL;
8790
+ let cur = start;
8791
+ const cmpFn = this._comparator;
8792
+ while (cur && cur !== NIL) {
8793
+ const c = cmpFn(targetKey, cur.key);
8794
+ if (c === 0) return cur;
8795
+ cur = c < 0 ? cur._left : cur._right;
8796
+ }
8797
+ return void 0;
8755
8798
  }
8756
8799
  /**
8757
8800
  * Searches the tree for nodes matching a predicate, key, or range.
@@ -8772,8 +8815,30 @@ var _BST = class _BST extends BinaryTree {
8772
8815
  if (keyNodeEntryOrPredicate === null) return [];
8773
8816
  startNode = this.ensureNode(startNode);
8774
8817
  if (!startNode) return [];
8775
- let predicate;
8776
8818
  const isRange = this.isRange(keyNodeEntryOrPredicate);
8819
+ const isPred = !isRange && this._isPredicate(keyNodeEntryOrPredicate);
8820
+ if (!isRange && !isPred) {
8821
+ let targetKey;
8822
+ if (this.isNode(keyNodeEntryOrPredicate)) {
8823
+ targetKey = keyNodeEntryOrPredicate.key;
8824
+ } else if (this.isEntry(keyNodeEntryOrPredicate)) {
8825
+ const k = keyNodeEntryOrPredicate[0];
8826
+ if (k !== null && k !== void 0) targetKey = k;
8827
+ } else {
8828
+ targetKey = keyNodeEntryOrPredicate;
8829
+ }
8830
+ if (targetKey === void 0) return [];
8831
+ const NIL = this._NIL;
8832
+ const cmpFn = this._comparator;
8833
+ let cur = startNode;
8834
+ while (cur && cur !== NIL) {
8835
+ const c = cmpFn(targetKey, cur.key);
8836
+ if (c === 0) return [callback(cur)];
8837
+ cur = c < 0 ? cur._left : cur._right;
8838
+ }
8839
+ return [];
8840
+ }
8841
+ let predicate;
8777
8842
  if (isRange) {
8778
8843
  predicate = /* @__PURE__ */ __name((node) => {
8779
8844
  if (!node) return false;
@@ -9660,7 +9725,6 @@ var _BST = class _BST extends BinaryTree {
9660
9725
  * @returns True if the node was found and deleted, false otherwise.
9661
9726
  */
9662
9727
  _deleteByKey(key) {
9663
- var _a;
9664
9728
  let node = this._root;
9665
9729
  while (node) {
9666
9730
  const cmp = this._compare(node.key, key);
@@ -9699,7 +9763,7 @@ var _BST = class _BST extends BinaryTree {
9699
9763
  succ.left = node.left;
9700
9764
  if (succ.left) succ.left.parent = succ;
9701
9765
  }
9702
- this._size = Math.max(0, ((_a = this._size) != null ? _a : 0) - 1);
9766
+ this._size = Math.max(0, this._size - 1);
9703
9767
  return true;
9704
9768
  }
9705
9769
  };
@@ -10806,12 +10870,11 @@ var AVLTree = _AVLTree;
10806
10870
  // src/data-structures/binary-tree/red-black-tree.ts
10807
10871
  var _RedBlackTreeNode = class _RedBlackTreeNode {
10808
10872
  /**
10809
- * Create a Red-Black Tree and optionally bulk-insert items.
10810
- * @remarks Time O(n log n), Space O(n)
10811
- * @param key - See parameter type for details.
10812
- * @param [value]- See parameter type for details.
10813
- * @param color - See parameter type for details.
10814
- * @returns New RedBlackTree instance.
10873
+ * Create a Red-Black Tree node.
10874
+ * @remarks Time O(1), Space O(1)
10875
+ * @param key - Node key.
10876
+ * @param [value] - Node value (unused in map mode trees).
10877
+ * @param color - Node color.
10815
10878
  */
10816
10879
  constructor(key, value, color = "BLACK") {
10817
10880
  __publicField(this, "key");
@@ -10944,7 +11007,29 @@ var _RedBlackTree = class _RedBlackTree extends BST {
10944
11007
  constructor(keysNodesEntriesOrRaws = [], options) {
10945
11008
  super([], options);
10946
11009
  __publicField(this, "_root");
11010
+ /**
11011
+ * (Internal) Header sentinel:
11012
+ * - header.parent -> root
11013
+ * - header._left -> min (or NIL)
11014
+ * - header._right -> max (or NIL)
11015
+ *
11016
+ * IMPORTANT:
11017
+ * - This header is NOT part of the actual tree.
11018
+ * - Do NOT use `header.left` / `header.right` accessors for wiring: those setters update `NIL.parent`
11019
+ * and can corrupt sentinel invariants / cause hangs. Only touch `header._left/_right`.
11020
+ */
11021
+ __publicField(this, "_header");
11022
+ /**
11023
+ * (Internal) Cache of the current minimum and maximum nodes.
11024
+ * Used for fast-path insert/update when keys are monotonic or near-boundary.
11025
+ */
11026
+ __publicField(this, "_minNode");
11027
+ __publicField(this, "_maxNode");
10947
11028
  this._root = this.NIL;
11029
+ this._header = new RedBlackTreeNode(void 0, void 0, "BLACK");
11030
+ this._header.parent = this.NIL;
11031
+ this._header._left = this.NIL;
11032
+ this._header._right = this.NIL;
10948
11033
  if (keysNodesEntriesOrRaws) {
10949
11034
  this.setMany(keysNodesEntriesOrRaws);
10950
11035
  }
@@ -10982,18 +11067,390 @@ var _RedBlackTree = class _RedBlackTree extends BST {
10982
11067
  * @remarks Time O(n), Space O(1)
10983
11068
  * @returns void
10984
11069
  */
11070
+ /**
11071
+ * Remove all nodes and clear internal caches.
11072
+ * @remarks Time O(n) average, Space O(1)
11073
+ */
10985
11074
  clear() {
10986
11075
  super.clear();
10987
11076
  this._root = this.NIL;
11077
+ this._header.parent = this.NIL;
11078
+ this._setMinCache(void 0);
11079
+ this._setMaxCache(void 0);
10988
11080
  }
10989
11081
  /**
10990
- * Insert or replace an entry using BST order and red-black fix-up.
10991
- * @remarks Time O(log n), Space O(1)
10992
- * @param keyNodeOrEntry - Key, node, or [key, value] entry to insert.
10993
- * @param [value]- See parameter type for details.
10994
- * @returns True if inserted or updated; false if ignored.
11082
+ * (Internal) Find a node by key using a tight BST walk (no allocations).
11083
+ *
11084
+ * NOTE: This uses `header.parent` as the canonical root pointer.
11085
+ * @remarks Time O(log n) average, Space O(1)
11086
+ */
11087
+ _findNodeByKey(key) {
11088
+ var _a, _b, _c;
11089
+ const NIL = this.NIL;
11090
+ const cmp = this._compare.bind(this);
11091
+ let cur = (_a = this._header.parent) != null ? _a : NIL;
11092
+ while (cur !== NIL) {
11093
+ const c = cmp(key, cur.key);
11094
+ if (c < 0) cur = (_b = cur.left) != null ? _b : NIL;
11095
+ else if (c > 0) cur = (_c = cur.right) != null ? _c : NIL;
11096
+ else return cur;
11097
+ }
11098
+ return void 0;
11099
+ }
11100
+ /**
11101
+ * (Internal) In-order predecessor of a node in a BST.
11102
+ * @remarks Time O(log n) average, Space O(1)
11103
+ */
11104
+ _predecessorOf(node) {
11105
+ const NIL = this.NIL;
11106
+ if (node.left && node.left !== NIL) {
11107
+ let cur2 = node.left;
11108
+ while (cur2.right && cur2.right !== NIL) cur2 = cur2.right;
11109
+ return cur2;
11110
+ }
11111
+ let cur = node;
11112
+ let p = node.parent;
11113
+ while (p && cur === p.left) {
11114
+ cur = p;
11115
+ p = p.parent;
11116
+ }
11117
+ return p;
11118
+ }
11119
+ /**
11120
+ * (Internal) In-order successor of a node in a BST.
11121
+ * @remarks Time O(log n) average, Space O(1)
11122
+ */
11123
+ _successorOf(node) {
11124
+ const NIL = this.NIL;
11125
+ if (node.right && node.right !== NIL) {
11126
+ let cur2 = node.right;
11127
+ while (cur2.left && cur2.left !== NIL) cur2 = cur2.left;
11128
+ return cur2;
11129
+ }
11130
+ let cur = node;
11131
+ let p = node.parent;
11132
+ while (p && cur === p.right) {
11133
+ cur = p;
11134
+ p = p.parent;
11135
+ }
11136
+ return p;
11137
+ }
11138
+ /**
11139
+ * (Internal) Attach a new node directly under a known parent/side (no search).
11140
+ *
11141
+ * This is a performance-oriented helper used by boundary fast paths and hinted insertion.
11142
+ * It will:
11143
+ * - wire parent/child pointers (using accessors, so parent pointers are updated)
11144
+ * - initialize children to NIL
11145
+ * - mark the new node RED, then run insert fix-up
11146
+ *
11147
+ * Precondition: the chosen slot (parent.left/parent.right) is empty (NIL/null/undefined).
11148
+ * @remarks Time O(log n) average, Space O(1)
11149
+ */
11150
+ _attachNewNode(parent, side, node) {
11151
+ const NIL = this.NIL;
11152
+ node.parent = parent;
11153
+ if (side === "left") parent.left = node;
11154
+ else parent.right = node;
11155
+ node.left = NIL;
11156
+ node.right = NIL;
11157
+ node.color = "RED";
11158
+ this._insertFixup(node);
11159
+ if (this.isRealNode(this._root)) this._root.color = "BLACK";
11160
+ }
11161
+ /**
11162
+ * (Internal) a single source of truth for min/max is header._left/_right.
11163
+ * Keep legacy _minNode/_maxNode mirrored for compatibility.
11164
+ * @remarks Time O(1), Space O(1)
11165
+ */
11166
+ /**
11167
+ * (Internal) Update min cache pointers (header._left is the canonical min pointer).
11168
+ * @remarks Time O(1), Space O(1)
11169
+ */
11170
+ _setMinCache(node) {
11171
+ this._minNode = node;
11172
+ this._header._left = node != null ? node : this.NIL;
11173
+ }
11174
+ /**
11175
+ * (Internal) Update max cache pointers (header._right is the canonical max pointer).
11176
+ * @remarks Time O(1), Space O(1)
11177
+ */
11178
+ _setMaxCache(node) {
11179
+ this._maxNode = node;
11180
+ this._header._right = node != null ? node : this.NIL;
11181
+ }
11182
+ /**
11183
+ * (Internal) Core set implementation returning the affected node.
11184
+ *
11185
+ * Hot path goals:
11186
+ * - Avoid double walks (search+insert): do a single traversal that either updates or inserts.
11187
+ * - Use header min/max caches to fast-path boundary inserts.
11188
+ * - Keep header._left/_right as canonical min/max pointers.
11189
+ *
11190
+ * Return value:
11191
+ * - `{ node, created:false }` when an existing key is updated
11192
+ * - `{ node, created:true }` when a new node is inserted
11193
+ * - `undefined` only on unexpected internal failure.
11194
+ * @remarks Time O(log n) average, Space O(1)
11195
+ */
11196
+ _setKVNode(key, nextValue) {
11197
+ var _a, _b, _c, _d, _e, _f, _g;
11198
+ const NIL = this.NIL;
11199
+ const comparator = this._comparator;
11200
+ const header = this._header;
11201
+ const minN = (_a = header._left) != null ? _a : NIL;
11202
+ if (minN !== NIL) {
11203
+ const cMin = comparator(key, minN.key);
11204
+ if (cMin === 0) {
11205
+ if (this._isMapMode) {
11206
+ if (nextValue !== void 0) this._store.set(key, nextValue);
11207
+ else this._setValue(key, nextValue);
11208
+ } else minN.value = nextValue;
11209
+ return { node: minN, created: false };
11210
+ }
11211
+ const minL = minN.left;
11212
+ if (cMin < 0 && (minL === NIL || minL === null || minL === void 0)) {
11213
+ const newNode2 = this.createNode(key, nextValue);
11214
+ this._attachNewNode(minN, "left", newNode2);
11215
+ if (this._isMapMode) {
11216
+ if (nextValue !== void 0) this._store.set(newNode2.key, nextValue);
11217
+ else this._setValue(newNode2.key, nextValue);
11218
+ }
11219
+ this._size++;
11220
+ this._setMinCache(newNode2);
11221
+ if (header._right === NIL) this._setMaxCache(newNode2);
11222
+ return { node: newNode2, created: true };
11223
+ }
11224
+ if (cMin > 0) {
11225
+ const maxN = (_b = header._right) != null ? _b : NIL;
11226
+ const cMax = comparator(key, maxN.key);
11227
+ if (cMax === 0) {
11228
+ if (this._isMapMode) {
11229
+ if (nextValue !== void 0) this._store.set(key, nextValue);
11230
+ else this._setValue(key, nextValue);
11231
+ } else maxN.value = nextValue;
11232
+ return { node: maxN, created: false };
11233
+ }
11234
+ const maxR = maxN.right;
11235
+ if (cMax > 0 && (maxR === NIL || maxR === null || maxR === void 0)) {
11236
+ const newNode2 = this.createNode(key, nextValue);
11237
+ this._attachNewNode(maxN, "right", newNode2);
11238
+ if (this._isMapMode) {
11239
+ if (nextValue !== void 0) this._store.set(newNode2.key, nextValue);
11240
+ else this._setValue(newNode2.key, nextValue);
11241
+ }
11242
+ this._size++;
11243
+ this._setMaxCache(newNode2);
11244
+ if (header._left === NIL) this._setMinCache(newNode2);
11245
+ return { node: newNode2, created: true };
11246
+ }
11247
+ }
11248
+ }
11249
+ const cmp = comparator;
11250
+ const isMapMode = this._isMapMode;
11251
+ const store = this._store;
11252
+ let current = (_c = this._header.parent) != null ? _c : NIL;
11253
+ let parent;
11254
+ let lastCompared = 0;
11255
+ while (current !== NIL) {
11256
+ parent = current;
11257
+ lastCompared = cmp(key, current.key);
11258
+ if (lastCompared < 0) current = (_d = current.left) != null ? _d : NIL;
11259
+ else if (lastCompared > 0) current = (_e = current.right) != null ? _e : NIL;
11260
+ else {
11261
+ if (isMapMode) {
11262
+ if (nextValue !== void 0) store.set(key, nextValue);
11263
+ else this._setValue(key, nextValue);
11264
+ } else {
11265
+ current.value = nextValue;
11266
+ }
11267
+ return { node: current, created: false };
11268
+ }
11269
+ }
11270
+ const newNode = this.createNode(key, nextValue);
11271
+ newNode.parent = parent;
11272
+ if (!parent) {
11273
+ this._setRoot(newNode);
11274
+ } else if (lastCompared < 0) {
11275
+ parent.left = newNode;
11276
+ } else {
11277
+ parent.right = newNode;
11278
+ }
11279
+ newNode.left = NIL;
11280
+ newNode.right = NIL;
11281
+ newNode.color = "RED";
11282
+ this._insertFixup(newNode);
11283
+ if (this.isRealNode(this._root)) this._root.color = "BLACK";
11284
+ else return void 0;
11285
+ if (isMapMode) {
11286
+ if (nextValue !== void 0) store.set(newNode.key, nextValue);
11287
+ else this._setValue(newNode.key, nextValue);
11288
+ }
11289
+ this._size++;
11290
+ const hMin = (_f = this._header._left) != null ? _f : NIL;
11291
+ const hMax = (_g = this._header._right) != null ? _g : NIL;
11292
+ if (hMin === NIL || hMax === NIL) {
11293
+ this._setMinCache(newNode);
11294
+ this._setMaxCache(newNode);
11295
+ } else if (parent === hMax && lastCompared > 0) {
11296
+ this._setMaxCache(newNode);
11297
+ } else if (parent === hMin && lastCompared < 0) {
11298
+ this._setMinCache(newNode);
11299
+ } else {
11300
+ if (cmp(newNode.key, hMin.key) < 0) this._setMinCache(newNode);
11301
+ if (cmp(newNode.key, hMax.key) > 0) this._setMaxCache(newNode);
11302
+ }
11303
+ return { node: newNode, created: true };
11304
+ }
11305
+ /**
11306
+ * (Internal) Boolean wrapper around `_setKVNode`.
11307
+ *
11308
+ * Includes a map-mode update fast-path:
11309
+ * - If `isMapMode=true` and the key already exists in `_store`, then updating the value does not
11310
+ * require any tree search/rotation (tree shape depends only on key).
11311
+ * - This path is intentionally limited to `nextValue !== undefined` to preserve existing
11312
+ * semantics for `undefined` values.
11313
+ * @remarks Time O(log n) average, Space O(1)
11314
+ */
11315
+ _setKV(key, nextValue) {
11316
+ if (this._isMapMode && nextValue !== void 0) {
11317
+ const store = this._store;
11318
+ if (store.has(key)) {
11319
+ store.set(key, nextValue);
11320
+ return true;
11321
+ }
11322
+ }
11323
+ return this._setKVNode(key, nextValue) !== void 0;
11324
+ }
11325
+ /**
11326
+ * Insert/update using a hint node to speed up nearby insertions.
11327
+ *
11328
+ * close to the expected insertion position (often the previously returned node in a loop).
11329
+ *
11330
+ * When the hint is a good fit (sorted / nearly-sorted insertion), this can avoid most of the
11331
+ * normal root-to-leaf search and reduce constant factors.
11332
+ *
11333
+ * When the hint does not match (random workloads), this will fall back to the normal set path.
11334
+ * @remarks Time O(log n) average, Space O(1)
11335
+ */
11336
+ setWithHintNode(key, value, hint) {
11337
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
11338
+ if (!hint || !this.isRealNode(hint)) {
11339
+ return (_a = this._setKVNode(key, value)) == null ? void 0 : _a.node;
11340
+ }
11341
+ const cmp = this._compare.bind(this);
11342
+ const c0 = cmp(key, hint.key);
11343
+ if (c0 === 0) {
11344
+ if (this._isMapMode) {
11345
+ if (value !== void 0) this._store.set(key, value);
11346
+ else this._setValue(key, value);
11347
+ } else hint.value = value;
11348
+ return hint;
11349
+ }
11350
+ if (c0 < 0) {
11351
+ if (!this.isRealNode(hint.left)) {
11352
+ const newNode = this.createNode(key, value);
11353
+ if (!this.isRealNode(newNode)) return void 0;
11354
+ this._attachNewNode(hint, "left", newNode);
11355
+ if (this._isMapMode) {
11356
+ if (value !== void 0) this._store.set(key, value);
11357
+ else this._setValue(key, value);
11358
+ }
11359
+ this._size++;
11360
+ const NIL = this.NIL;
11361
+ const hMin = (_b = this._header._left) != null ? _b : NIL;
11362
+ if (hMin === NIL || this._compare(newNode.key, hMin.key) < 0) this._setMinCache(newNode);
11363
+ const hMax = (_c = this._header._right) != null ? _c : NIL;
11364
+ if (hMax === NIL || this._compare(newNode.key, hMax.key) > 0) this._setMaxCache(newNode);
11365
+ return newNode;
11366
+ }
11367
+ const pred = this._predecessorOf(hint);
11368
+ if (pred && cmp(pred.key, key) >= 0) {
11369
+ return (_d = this._setKVNode(key, value)) == null ? void 0 : _d.node;
11370
+ }
11371
+ if (pred && !this.isRealNode(pred.right)) {
11372
+ const newNode = this.createNode(key, value);
11373
+ if (!this.isRealNode(newNode)) return void 0;
11374
+ this._attachNewNode(pred, "right", newNode);
11375
+ if (this._isMapMode) {
11376
+ if (value !== void 0) this._store.set(key, value);
11377
+ else this._setValue(key, value);
11378
+ }
11379
+ this._size++;
11380
+ const NIL = this.NIL;
11381
+ const hMin = (_e = this._header._left) != null ? _e : NIL;
11382
+ if (hMin === NIL || this._compare(newNode.key, hMin.key) < 0) this._setMinCache(newNode);
11383
+ const hMax = (_f = this._header._right) != null ? _f : NIL;
11384
+ if (hMax === NIL || this._compare(newNode.key, hMax.key) > 0) this._setMaxCache(newNode);
11385
+ return newNode;
11386
+ }
11387
+ return (_g = this._setKVNode(key, value)) == null ? void 0 : _g.node;
11388
+ }
11389
+ if (!this.isRealNode(hint.right)) {
11390
+ const newNode = this.createNode(key, value);
11391
+ if (!this.isRealNode(newNode)) return void 0;
11392
+ this._attachNewNode(hint, "right", newNode);
11393
+ if (this._isMapMode) {
11394
+ if (value !== void 0) this._store.set(key, value);
11395
+ else this._setValue(key, value);
11396
+ }
11397
+ this._size++;
11398
+ const NIL = this.NIL;
11399
+ const hMin = (_h = this._header._left) != null ? _h : NIL;
11400
+ if (hMin === NIL || this._compare(newNode.key, hMin.key) < 0) this._setMinCache(newNode);
11401
+ const hMax = (_i = this._header._right) != null ? _i : NIL;
11402
+ if (hMax === NIL || this._compare(newNode.key, hMax.key) > 0) this._setMaxCache(newNode);
11403
+ return newNode;
11404
+ }
11405
+ const succ = this._successorOf(hint);
11406
+ if (succ && cmp(succ.key, key) <= 0) {
11407
+ return (_j = this._setKVNode(key, value)) == null ? void 0 : _j.node;
11408
+ }
11409
+ if (succ && !this.isRealNode(succ.left)) {
11410
+ const newNode = this.createNode(key, value);
11411
+ if (!this.isRealNode(newNode)) return void 0;
11412
+ this._attachNewNode(succ, "left", newNode);
11413
+ if (this._isMapMode) {
11414
+ if (value !== void 0) this._store.set(key, value);
11415
+ else this._setValue(key, value);
11416
+ }
11417
+ this._size++;
11418
+ const NIL = this.NIL;
11419
+ const hMin = (_k = this._header._left) != null ? _k : NIL;
11420
+ if (hMin === NIL || this._compare(newNode.key, hMin.key) < 0) this._setMinCache(newNode);
11421
+ const hMax = (_l = this._header._right) != null ? _l : NIL;
11422
+ if (hMax === NIL || this._compare(newNode.key, hMax.key) > 0) this._setMaxCache(newNode);
11423
+ return newNode;
11424
+ }
11425
+ return (_m = this._setKVNode(key, value)) == null ? void 0 : _m.node;
11426
+ }
11427
+ /**
11428
+ * Boolean wrapper for setWithHintNode.
11429
+ * @remarks Time O(log n) average, Space O(1)
11430
+ */
11431
+ setWithHint(key, value, hint) {
11432
+ return this.setWithHintNode(key, value, hint) !== void 0;
11433
+ }
11434
+ /**
11435
+ * Insert or update a key/value (map mode) or key-only (set mode).
11436
+ *
11437
+ * This method is optimized for:
11438
+ * - monotonic inserts via min/max boundary fast paths
11439
+ * - updates via a single-pass search (no double walk)
11440
+ *
11441
+ * @remarks Time O(log n) average, Space O(1)
10995
11442
  */
10996
11443
  set(keyNodeOrEntry, value) {
11444
+ if (!this.isNode(keyNodeOrEntry)) {
11445
+ if (keyNodeOrEntry === null || keyNodeOrEntry === void 0) return false;
11446
+ if (this.isEntry(keyNodeOrEntry)) {
11447
+ const key = keyNodeOrEntry[0];
11448
+ if (key === null || key === void 0) return false;
11449
+ const nextValue = value != null ? value : keyNodeOrEntry[1];
11450
+ return this._setKV(key, nextValue);
11451
+ }
11452
+ return this._setKV(keyNodeOrEntry, value);
11453
+ }
10997
11454
  const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
10998
11455
  if (!this.isRealNode(newNode)) return false;
10999
11456
  const insertStatus = this._insert(newNode);
@@ -11015,19 +11472,23 @@ var _RedBlackTree = class _RedBlackTree extends BST {
11015
11472
  }
11016
11473
  /**
11017
11474
  * Delete a node by key/node/entry and rebalance as needed.
11018
- * @remarks Time O(log n), Space O(1)
11019
- * @param keyNodeOrEntry - Key, node, or [key, value] entry identifying the node to delete.
11475
+ * @remarks Time O(log n) average, Space O(1)
11476
+ * @param keyNodeEntryRawOrPredicate - Key, node, or [key, value] entry identifying the node to delete.
11020
11477
  * @returns Array with deletion metadata (removed node, rebalancing hint if any).
11021
11478
  */
11022
- delete(keyNodeOrEntry) {
11023
- if (keyNodeOrEntry === null) return [];
11479
+ delete(keyNodeEntryRawOrPredicate) {
11480
+ if (keyNodeEntryRawOrPredicate === null) return [];
11024
11481
  const results = [];
11025
11482
  let nodeToDelete;
11026
- if (this._isPredicate(keyNodeOrEntry)) nodeToDelete = this.getNode(keyNodeOrEntry);
11027
- else nodeToDelete = this.isRealNode(keyNodeOrEntry) ? keyNodeOrEntry : this.getNode(keyNodeOrEntry);
11483
+ if (this._isPredicate(keyNodeEntryRawOrPredicate)) nodeToDelete = this.getNode(keyNodeEntryRawOrPredicate);
11484
+ else nodeToDelete = this.isRealNode(keyNodeEntryRawOrPredicate) ? keyNodeEntryRawOrPredicate : this.getNode(keyNodeEntryRawOrPredicate);
11028
11485
  if (!nodeToDelete) {
11029
11486
  return results;
11030
11487
  }
11488
+ const willDeleteMin = nodeToDelete === this._minNode;
11489
+ const willDeleteMax = nodeToDelete === this._maxNode;
11490
+ const nextMin = willDeleteMin ? this._successorOf(nodeToDelete) : void 0;
11491
+ const nextMax = willDeleteMax ? this._predecessorOf(nodeToDelete) : void 0;
11031
11492
  let originalColor = nodeToDelete.color;
11032
11493
  let replacementNode;
11033
11494
  if (!this.isRealNode(nodeToDelete.left)) {
@@ -11066,6 +11527,19 @@ var _RedBlackTree = class _RedBlackTree extends BST {
11066
11527
  }
11067
11528
  if (this._isMapMode) this._store.delete(nodeToDelete.key);
11068
11529
  this._size--;
11530
+ if (this._size <= 0) {
11531
+ this._setMinCache(void 0);
11532
+ this._setMaxCache(void 0);
11533
+ } else {
11534
+ if (willDeleteMin) this._setMinCache(nextMin);
11535
+ if (willDeleteMax) this._setMaxCache(nextMax);
11536
+ if (!this._minNode || !this.isRealNode(this._minNode)) {
11537
+ this._setMinCache(this.isRealNode(this._root) ? this.getLeftMost((n) => n, this._root) : void 0);
11538
+ }
11539
+ if (!this._maxNode || !this.isRealNode(this._maxNode)) {
11540
+ this._setMaxCache(this.isRealNode(this._root) ? this.getRightMost((n) => n, this._root) : void 0);
11541
+ }
11542
+ }
11069
11543
  if (originalColor === "BLACK") {
11070
11544
  this._deleteFixup(replacementNode);
11071
11545
  }
@@ -11074,7 +11548,7 @@ var _RedBlackTree = class _RedBlackTree extends BST {
11074
11548
  }
11075
11549
  /**
11076
11550
  * Transform entries into a like-kind red-black tree with possibly different key/value types.
11077
- * @remarks Time O(n), Space O(n)
11551
+ * @remarks Time O(n) average, Space O(n)
11078
11552
  * @template MK
11079
11553
  * @template MV
11080
11554
  * @template MR
@@ -11091,41 +11565,62 @@ var _RedBlackTree = class _RedBlackTree extends BST {
11091
11565
  }
11092
11566
  return out;
11093
11567
  }
11568
+ /**
11569
+ * (Internal) Create an empty instance of the same concrete tree type.
11570
+ * @remarks Time O(1) average, Space O(1)
11571
+ */
11094
11572
  _createInstance(options) {
11095
11573
  const Ctor = this.constructor;
11096
11574
  return new Ctor([], { ...this._snapshotOptions(), ...options != null ? options : {} });
11097
11575
  }
11576
+ /**
11577
+ * (Internal) Create a like-kind tree (same concrete class) populated from an iterable.
11578
+ * @remarks Time O(m log m) average (m = iterable length), Space O(m)
11579
+ */
11098
11580
  _createLike(iter = [], options) {
11099
11581
  const Ctor = this.constructor;
11100
11582
  return new Ctor(iter, { ...this._snapshotOptions(), ...options != null ? options : {} });
11101
11583
  }
11584
+ /**
11585
+ * (Internal) Set the root pointer and keep header.parent in sync.
11586
+ * @remarks Time O(1), Space O(1)
11587
+ */
11102
11588
  _setRoot(v) {
11589
+ const NIL = this.NIL;
11103
11590
  if (v) {
11104
11591
  v.parent = void 0;
11105
11592
  }
11106
11593
  this._root = v;
11594
+ this._header.parent = v != null ? v : NIL;
11107
11595
  }
11596
+ /**
11597
+ * (Internal) Replace a node in place while preserving its color.
11598
+ * @remarks Time O(1) average, Space O(1)
11599
+ */
11108
11600
  _replaceNode(oldNode, newNode) {
11109
11601
  newNode.color = oldNode.color;
11110
11602
  return super._replaceNode(oldNode, newNode);
11111
11603
  }
11112
11604
  /**
11113
11605
  * (Protected) Standard BST insert followed by red-black fix-up.
11114
- * @remarks Time O(log n), Space O(1)
11606
+ * @remarks Time O(log n) average, Space O(1)
11115
11607
  * @param node - Node to insert.
11116
11608
  * @returns Status string: 'CREATED' or 'UPDATED'.
11117
11609
  */
11118
11610
  _insert(node) {
11119
11611
  var _a, _b, _c;
11120
- let current = (_a = this.root) != null ? _a : this.NIL;
11121
- let parent = void 0;
11122
- while (current !== this.NIL) {
11612
+ const NIL = this.NIL;
11613
+ const cmp = this._compare.bind(this);
11614
+ let current = (_a = this._header.parent) != null ? _a : NIL;
11615
+ let parent;
11616
+ let lastCompared = 0;
11617
+ while (current !== NIL) {
11123
11618
  parent = current;
11124
- const compared = this._compare(node.key, current.key);
11125
- if (compared < 0) {
11126
- current = (_b = current.left) != null ? _b : this.NIL;
11127
- } else if (compared > 0) {
11128
- current = (_c = current.right) != null ? _c : this.NIL;
11619
+ lastCompared = cmp(node.key, current.key);
11620
+ if (lastCompared < 0) {
11621
+ current = (_b = current.left) != null ? _b : NIL;
11622
+ } else if (lastCompared > 0) {
11623
+ current = (_c = current.right) != null ? _c : NIL;
11129
11624
  } else {
11130
11625
  this._replaceNode(current, node);
11131
11626
  return "UPDATED";
@@ -11134,13 +11629,13 @@ var _RedBlackTree = class _RedBlackTree extends BST {
11134
11629
  node.parent = parent;
11135
11630
  if (!parent) {
11136
11631
  this._setRoot(node);
11137
- } else if (this._compare(node.key, parent.key) < 0) {
11632
+ } else if (lastCompared < 0) {
11138
11633
  parent.left = node;
11139
11634
  } else {
11140
11635
  parent.right = node;
11141
11636
  }
11142
- node.left = this.NIL;
11143
- node.right = this.NIL;
11637
+ node.left = NIL;
11638
+ node.right = NIL;
11144
11639
  node.color = "RED";
11145
11640
  this._insertFixup(node);
11146
11641
  return "CREATED";
@@ -11166,56 +11661,66 @@ var _RedBlackTree = class _RedBlackTree extends BST {
11166
11661
  }
11167
11662
  /**
11168
11663
  * (Protected) Restore red-black properties after insertion (recolor/rotate).
11169
- * @remarks Time O(log n), Space O(1)
11664
+ * @remarks Time O(log n) average, Space O(1)
11170
11665
  * @param z - Recently inserted node.
11171
11666
  * @returns void
11172
11667
  */
11173
11668
  _insertFixup(z) {
11174
- var _a, _b, _c, _d, _e;
11175
- while (((_a = z == null ? void 0 : z.parent) == null ? void 0 : _a.color) === "RED") {
11176
- if (z.parent === ((_b = z.parent.parent) == null ? void 0 : _b.left)) {
11177
- const y = z.parent.parent.right;
11669
+ const leftRotate = this._leftRotate.bind(this);
11670
+ const rightRotate = this._rightRotate.bind(this);
11671
+ while (z) {
11672
+ const p = z.parent;
11673
+ if (!p || p.color !== "RED") break;
11674
+ const gp = p.parent;
11675
+ if (!gp) break;
11676
+ if (p === gp.left) {
11677
+ const y = gp.right;
11178
11678
  if ((y == null ? void 0 : y.color) === "RED") {
11179
- z.parent.color = "BLACK";
11679
+ p.color = "BLACK";
11180
11680
  y.color = "BLACK";
11181
- z.parent.parent.color = "RED";
11182
- z = z.parent.parent;
11183
- } else {
11184
- if (z === z.parent.right) {
11185
- z = z.parent;
11186
- this._leftRotate(z);
11187
- }
11188
- if (z && z.parent && z.parent.parent) {
11189
- z.parent.color = "BLACK";
11190
- z.parent.parent.color = "RED";
11191
- this._rightRotate(z.parent.parent);
11192
- }
11681
+ gp.color = "RED";
11682
+ z = gp;
11683
+ continue;
11684
+ }
11685
+ if (z === p.right) {
11686
+ z = p;
11687
+ leftRotate(z);
11688
+ }
11689
+ const p2 = z == null ? void 0 : z.parent;
11690
+ const gp2 = p2 == null ? void 0 : p2.parent;
11691
+ if (p2 && gp2) {
11692
+ p2.color = "BLACK";
11693
+ gp2.color = "RED";
11694
+ rightRotate(gp2);
11193
11695
  }
11194
11696
  } else {
11195
- 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;
11697
+ const y = gp.left;
11196
11698
  if ((y == null ? void 0 : y.color) === "RED") {
11197
- z.parent.color = "BLACK";
11699
+ p.color = "BLACK";
11198
11700
  y.color = "BLACK";
11199
- z.parent.parent.color = "RED";
11200
- z = z.parent.parent;
11201
- } else {
11202
- if (z === z.parent.left) {
11203
- z = z.parent;
11204
- this._rightRotate(z);
11205
- }
11206
- if (z && z.parent && z.parent.parent) {
11207
- z.parent.color = "BLACK";
11208
- z.parent.parent.color = "RED";
11209
- this._leftRotate(z.parent.parent);
11210
- }
11701
+ gp.color = "RED";
11702
+ z = gp;
11703
+ continue;
11704
+ }
11705
+ if (z === p.left) {
11706
+ z = p;
11707
+ rightRotate(z);
11708
+ }
11709
+ const p2 = z == null ? void 0 : z.parent;
11710
+ const gp2 = p2 == null ? void 0 : p2.parent;
11711
+ if (p2 && gp2) {
11712
+ p2.color = "BLACK";
11713
+ gp2.color = "RED";
11714
+ leftRotate(gp2);
11211
11715
  }
11212
11716
  }
11717
+ break;
11213
11718
  }
11214
11719
  if (this.isRealNode(this._root)) this._root.color = "BLACK";
11215
11720
  }
11216
11721
  /**
11217
11722
  * (Protected) Restore red-black properties after deletion (recolor/rotate).
11218
- * @remarks Time O(log n), Space O(1)
11723
+ * @remarks Time O(log n) average, Space O(1)
11219
11724
  * @param node - Child that replaced the deleted node (may be undefined).
11220
11725
  * @returns void
11221
11726
  */
@@ -12118,16 +12623,16 @@ var _TreeCounter = class _TreeCounter extends RedBlackTree {
12118
12623
  /**
12119
12624
  * Delete a node (or decrement its count) and rebalance if needed.
12120
12625
  * @remarks Time O(log N), Space O(1)
12121
- * @param keyNodeOrEntry - Key, node, or [key, value] entry identifying the node.
12626
+ * @param keyNodeEntryRawOrPredicate - Key, node, or [key, value] entry identifying the node.
12122
12627
  * @param [ignoreCount] - If true, remove the node regardless of its count.
12123
12628
  * @returns Array of deletion results including deleted node and a rebalance hint when present.
12124
12629
  */
12125
- delete(keyNodeOrEntry, ignoreCount = false) {
12126
- if (keyNodeOrEntry === null) return [];
12630
+ delete(keyNodeEntryRawOrPredicate, ignoreCount = false) {
12631
+ if (keyNodeEntryRawOrPredicate === null) return [];
12127
12632
  const results = [];
12128
12633
  let nodeToDelete;
12129
- if (this._isPredicate(keyNodeOrEntry)) nodeToDelete = this.getNode(keyNodeOrEntry);
12130
- else nodeToDelete = this.isRealNode(keyNodeOrEntry) ? keyNodeOrEntry : this.getNode(keyNodeOrEntry);
12634
+ if (this._isPredicate(keyNodeEntryRawOrPredicate)) nodeToDelete = this.getNode(keyNodeEntryRawOrPredicate);
12635
+ else nodeToDelete = this.isRealNode(keyNodeEntryRawOrPredicate) ? keyNodeEntryRawOrPredicate : this.getNode(keyNodeEntryRawOrPredicate);
12131
12636
  if (!nodeToDelete) {
12132
12637
  return results;
12133
12638
  }
@@ -12170,7 +12675,6 @@ var _TreeCounter = class _TreeCounter extends RedBlackTree {
12170
12675
  if (ignoreCount || nodeToDelete.count <= 1) {
12171
12676
  if (successor.right !== null) {
12172
12677
  this._transplant(successor, successor.right);
12173
- this._count -= nodeToDelete.count;
12174
12678
  }
12175
12679
  } else {
12176
12680
  nodeToDelete.count--;
@@ -12273,6 +12777,11 @@ var _TreeCounter = class _TreeCounter extends RedBlackTree {
12273
12777
  const out = this._createInstance();
12274
12778
  this._clone(out);
12275
12779
  out._count = this._count;
12780
+ for (const node of this.dfs((n) => n, "IN")) {
12781
+ if (!node) continue;
12782
+ const outNode = out.getNode(node.key);
12783
+ if (outNode) outNode.count = node.count;
12784
+ }
12276
12785
  return out;
12277
12786
  }
12278
12787
  /**