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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "data-structure-typed",
3
- "version": "2.2.8",
3
+ "version": "2.3.0",
4
4
  "description": "Standard data structure",
5
5
  "browser": "dist/umd/data-structure-typed.min.js",
6
6
  "umd:main": "dist/umd/data-structure-typed.min.js",
@@ -51,6 +51,7 @@
51
51
  "test": "npm run test:in-band",
52
52
  "test:integration": "npm run update:subs && jest --config jest.integration.config.js && tsc test/integration/compile.test.ts && node test/integration/compile.mjs",
53
53
  "test:perf": "npm run build:ecut && ts-node test/performance/benchmark-runner.ts --isolate --gc --cooldown-ms=80",
54
+ "test:coverage": "jest --runInBand --coverage",
54
55
  "check": "npm run check:src && npm run check:test",
55
56
  "check:src": "tsc --noEmit",
56
57
  "check:test": "tsc -p tsconfig.test.json --noEmit",
@@ -63,7 +64,7 @@
63
64
  "format:test": "prettier --write 'test/**/*.{js,ts}'",
64
65
  "format": "npm run format:src && npm run format:test",
65
66
  "check:exist-latest": "sh scripts/check_exist_remotely.sh",
66
- "ci": "env && git fetch --tags && npm run update:subs && npm run inspect && npm run lint && npm run test && npm run changelog",
67
+ "ci": "env && git fetch --tags && npm run update:subs && npm run inspect && npm run lint && npm run test:coverage && npm run changelog",
67
68
  "update:subs": "npm i avl-tree-typed binary-tree-typed bst-typed heap-typed data-structure-typed --save-dev",
68
69
  "install:all-subs": "npm i avl-tree-typed binary-tree-typed bst-typed deque-typed directed-graph-typed doubly-linked-list-typed graph-typed heap-typed linked-list-typed max-heap-typed max-priority-queue-typed min-heap-typed min-priority-queue-typed priority-queue-typed singly-linked-list-typed stack-typed tree-multimap-typed trie-typed undirected-graph-typed queue-typed --save-dev",
69
70
  "changelog": "auto-changelog",
@@ -102,7 +103,7 @@
102
103
  "benchmark": "^2.1.4",
103
104
  "binary-tree-typed": "^1.54.3",
104
105
  "bst-typed": "^1.54.3",
105
- "data-structure-typed": "^2.2.7",
106
+ "data-structure-typed": "^2.2.8",
106
107
  "dependency-cruiser": "^16.5.0",
107
108
  "doctoc": "^2.2.1",
108
109
  "eslint": "^9.13.0",
@@ -75,7 +75,7 @@ export abstract class LinearBase<
75
75
  * @param options - `{ maxLen?, ... }` bounds/behavior options.
76
76
  * @remarks Time O(1), Space O(1)
77
77
  */
78
- protected constructor(options?: LinearBaseOptions<E, R>) {
78
+ constructor(options?: LinearBaseOptions<E, R>) {
79
79
  super(options);
80
80
  if (options) {
81
81
  const { maxLen } = options;
@@ -156,14 +156,6 @@ export abstract class LinearBase<
156
156
  return -1;
157
157
  }
158
158
 
159
- /**
160
- * Concatenate multiple containers of the same species.
161
- * @param items - Other lists to append.
162
- * @returns New container with combined elements (`this` type).
163
- * @remarks Time O(sum(length)), Space O(sum(length))
164
- */
165
- concat(...items: this[]): this;
166
-
167
159
  /**
168
160
  * Concatenate elements and/or containers.
169
161
  * @param items - Elements or other containers.
@@ -412,7 +404,7 @@ export abstract class LinearLinkedBase<
412
404
  R = any,
413
405
  NODE extends LinkedListNode<E> = LinkedListNode<E>
414
406
  > extends LinearBase<E, R, NODE> {
415
- protected constructor(options?: LinearBaseOptions<E, R>) {
407
+ constructor(options?: LinearBaseOptions<E, R>) {
416
408
  super(options);
417
409
  if (options) {
418
410
  const { maxLen } = options;
@@ -478,8 +470,6 @@ export abstract class LinearLinkedBase<
478
470
  * @returns New list with combined elements (`this` type).
479
471
  * @remarks Time O(sum(length)), Space O(sum(length))
480
472
  */
481
- override concat(...items: LinearBase<E, R>[]): this;
482
-
483
473
  override concat(...items: (E | LinearBase<E, R>)[]): this {
484
474
  const newList = this.clone();
485
475
 
@@ -10,7 +10,7 @@ import type {
10
10
  BinaryTreeDeleteResult,
11
11
  BinaryTreeOptions,
12
12
  BinaryTreePrintOptions,
13
- BTNEntry,
13
+ BTNEntry, BTNRep,
14
14
  DFSOrderPattern,
15
15
  DFSStackItem,
16
16
  EntryCallback,
@@ -717,7 +717,6 @@ export class BinaryTree<K = any, V = any, R = any>
717
717
  * @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).
718
718
  *
719
719
  * @param keysNodesEntriesOrRaws - An iterable of items to set.
720
- * @param [values] - An optional parallel iterable of values.
721
720
  * @returns An array of booleans indicating the success of each individual `set` operation.
722
721
  */
723
722
  addMany(
@@ -796,16 +795,16 @@ export class BinaryTree<K = any, V = any, R = any>
796
795
  * Deletes a node from the tree.
797
796
  * @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).
798
797
  *
799
- * @param keyNodeOrEntry - The node to delete.
798
+ * @param keyNodeEntryRawOrPredicate - The node to delete.
800
799
  * @returns An array containing deletion results (for compatibility with self-balancing trees).
801
800
  */
802
801
  delete(
803
- keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
802
+ keyNodeEntryRawOrPredicate: BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V> | null>
804
803
  ): BinaryTreeDeleteResult<BinaryTreeNode<K, V>>[] {
805
804
  const deletedResult: BinaryTreeDeleteResult<BinaryTreeNode<K, V>>[] = [];
806
805
  if (!this._root) return deletedResult;
807
806
 
808
- const curr = this.getNode(keyNodeOrEntry);
807
+ const curr = this.getNode(keyNodeEntryRawOrPredicate);
809
808
  if (!curr) return deletedResult;
810
809
 
811
810
  const parent: BinaryTreeNode<K, V> | undefined = curr?.parent;
@@ -1140,7 +1139,7 @@ export class BinaryTree<K = any, V = any, R = any>
1140
1139
  }
1141
1140
  return true;
1142
1141
  };
1143
- const isStandardBST = checkBST(false);
1142
+ const isStandardBST = checkBST();
1144
1143
  const isInverseBST = checkBST(true);
1145
1144
  return isStandardBST || isInverseBST;
1146
1145
  }
@@ -204,7 +204,8 @@ export class BSTNode<K = any, V = any> {
204
204
  * // Create a simple BST with numeric keys
205
205
  * const bst = new BST<number>([11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]);
206
206
  *
207
- * bst.print();
207
+ * // Keep the example output in source comments but avoid noisy test logs.
208
+ * await withMutedConsole(() => bst.print());
208
209
  * // _______8__________
209
210
  * // / \
210
211
  * // ___4___ ____12_____
@@ -556,9 +557,55 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
556
557
  startNode: BSTNOptKeyOrNode<K, BSTNode<K, V>> = this._root,
557
558
  iterationType: IterationType = this.iterationType
558
559
  ): OptNode<BSTNode<K, V>> {
559
- return this.getNodes(keyNodeEntryOrPredicate, true, startNode, iterationType)[0] ?? undefined;
560
+ // Fast-path: key lookup should not allocate arrays or build predicate closures.
561
+ // (This is a hot path for get/has in Node Mode.)
562
+ if (keyNodeEntryOrPredicate === null || keyNodeEntryOrPredicate === undefined) return undefined;
563
+
564
+ // If a predicate is provided, defer to the full search logic.
565
+ if (this._isPredicate(keyNodeEntryOrPredicate)) {
566
+ return this.getNodes(keyNodeEntryOrPredicate, true, startNode, iterationType)[0] ?? undefined;
567
+ }
568
+
569
+ // NOTE: Range<K> is not part of this overload, but callers may still pass it at runtime.
570
+ // Let search handle it.
571
+ if (keyNodeEntryOrPredicate instanceof Range) {
572
+ return (
573
+ this.getNodes(
574
+ keyNodeEntryOrPredicate,
575
+ true,
576
+ startNode as K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
577
+ iterationType
578
+ )[0] ?? undefined
579
+ );
580
+ }
581
+
582
+ let targetKey: K | undefined;
583
+ if (this.isNode(keyNodeEntryOrPredicate)) {
584
+ targetKey = keyNodeEntryOrPredicate.key;
585
+ } else if (this.isEntry(keyNodeEntryOrPredicate)) {
586
+ const k = keyNodeEntryOrPredicate[0];
587
+ if (k === null || k === undefined) return undefined;
588
+ targetKey = k;
589
+ } else {
590
+ targetKey = keyNodeEntryOrPredicate;
591
+ }
592
+
593
+ const start = this.ensureNode(startNode);
594
+ if (!start) return undefined;
595
+
596
+ const NIL = this._NIL as unknown as BSTNode<K, V> | null | undefined;
597
+ let cur: BSTNode<K, V> | null | undefined = start;
598
+ const cmpFn = this._comparator;
599
+ while (cur && cur !== NIL) {
600
+ const c = cmpFn(targetKey, cur.key);
601
+ if (c === 0) return cur;
602
+ cur = c < 0 ? cur._left : cur._right;
603
+ }
604
+
605
+ return undefined;
560
606
  }
561
607
 
608
+
562
609
  override search(
563
610
  keyNodeEntryOrPredicate:
564
611
  | K
@@ -619,9 +666,37 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
619
666
  startNode = this.ensureNode(startNode);
620
667
  if (!startNode) return [];
621
668
 
622
- let predicate: NodePredicate<BSTNode<K, V>>;
669
+ // Fast-path: key lookup (unique keys) using a tight BST walk (no allocations).
670
+ // This is the hot path for get/has/search by key.
623
671
  const isRange = this.isRange(keyNodeEntryOrPredicate);
672
+ const isPred = !isRange && this._isPredicate(keyNodeEntryOrPredicate);
673
+
674
+ if (!isRange && !isPred) {
675
+ let targetKey: K | undefined;
676
+ if (this.isNode(keyNodeEntryOrPredicate)) {
677
+ targetKey = keyNodeEntryOrPredicate.key;
678
+ } else if (this.isEntry(keyNodeEntryOrPredicate)) {
679
+ const k = keyNodeEntryOrPredicate[0];
680
+ if (k !== null && k !== undefined) targetKey = k;
681
+ } else {
682
+ targetKey = keyNodeEntryOrPredicate;
683
+ }
684
+ if (targetKey === undefined) return [];
685
+
686
+ const NIL = this._NIL as unknown as BSTNode<K, V> | null | undefined;
687
+ const cmpFn = this._comparator;
688
+ let cur: BSTNode<K, V> | null | undefined = startNode;
689
+
690
+ // Loop intentionally avoids getters and extra type checks.
691
+ while (cur && cur !== NIL) {
692
+ const c = cmpFn(targetKey, cur.key);
693
+ if (c === 0) return [callback(cur)];
694
+ cur = c < 0 ? cur._left : cur._right;
695
+ }
696
+ return [];
697
+ }
624
698
 
699
+ let predicate: NodePredicate<BSTNode<K, V>>;
625
700
  if (isRange) {
626
701
  predicate = node => {
627
702
  if (!node) return false;
@@ -2018,7 +2093,7 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
2018
2093
  if (succ.left) (succ.left as BSTNode<K, V>).parent = succ;
2019
2094
  }
2020
2095
 
2021
- this._size = Math.max(0, ((this as any)._size ?? 0) - 1);
2096
+ this._size = Math.max(0, this._size - 1);
2022
2097
  return true;
2023
2098
  }
2024
2099
  }