binary-tree-typed 2.4.4 → 2.5.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 (85) hide show
  1. package/README.md +0 -84
  2. package/dist/cjs/index.cjs +965 -420
  3. package/dist/cjs/index.cjs.map +1 -1
  4. package/dist/cjs-legacy/index.cjs +962 -417
  5. package/dist/cjs-legacy/index.cjs.map +1 -1
  6. package/dist/esm/index.mjs +965 -421
  7. package/dist/esm/index.mjs.map +1 -1
  8. package/dist/esm-legacy/index.mjs +962 -418
  9. package/dist/esm-legacy/index.mjs.map +1 -1
  10. package/dist/types/common/error.d.ts +23 -0
  11. package/dist/types/common/index.d.ts +1 -0
  12. package/dist/types/data-structures/base/iterable-element-base.d.ts +1 -1
  13. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +128 -51
  14. package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +210 -164
  15. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +439 -78
  16. package/dist/types/data-structures/binary-tree/bst.d.ts +311 -28
  17. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +217 -31
  18. package/dist/types/data-structures/binary-tree/segment-tree.d.ts +218 -152
  19. package/dist/types/data-structures/binary-tree/tree-map.d.ts +1281 -5
  20. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +1087 -201
  21. package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +858 -65
  22. package/dist/types/data-structures/binary-tree/tree-set.d.ts +1133 -5
  23. package/dist/types/data-structures/graph/abstract-graph.d.ts +44 -0
  24. package/dist/types/data-structures/graph/directed-graph.d.ts +220 -47
  25. package/dist/types/data-structures/graph/map-graph.d.ts +59 -1
  26. package/dist/types/data-structures/graph/undirected-graph.d.ts +218 -59
  27. package/dist/types/data-structures/hash/hash-map.d.ts +230 -77
  28. package/dist/types/data-structures/heap/heap.d.ts +287 -99
  29. package/dist/types/data-structures/heap/max-heap.d.ts +46 -0
  30. package/dist/types/data-structures/heap/min-heap.d.ts +59 -0
  31. package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +286 -44
  32. package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +278 -65
  33. package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +415 -12
  34. package/dist/types/data-structures/matrix/matrix.d.ts +331 -0
  35. package/dist/types/data-structures/priority-queue/max-priority-queue.d.ts +57 -0
  36. package/dist/types/data-structures/priority-queue/min-priority-queue.d.ts +60 -0
  37. package/dist/types/data-structures/priority-queue/priority-queue.d.ts +60 -0
  38. package/dist/types/data-structures/queue/deque.d.ts +313 -66
  39. package/dist/types/data-structures/queue/queue.d.ts +211 -42
  40. package/dist/types/data-structures/stack/stack.d.ts +174 -32
  41. package/dist/types/data-structures/trie/trie.d.ts +213 -43
  42. package/dist/types/types/data-structures/binary-tree/segment-tree.d.ts +1 -1
  43. package/dist/types/types/data-structures/linked-list/skip-linked-list.d.ts +1 -4
  44. package/dist/types/types/data-structures/queue/deque.d.ts +6 -0
  45. package/dist/umd/binary-tree-typed.js +959 -414
  46. package/dist/umd/binary-tree-typed.js.map +1 -1
  47. package/dist/umd/binary-tree-typed.min.js +3 -3
  48. package/dist/umd/binary-tree-typed.min.js.map +1 -1
  49. package/package.json +2 -2
  50. package/src/common/error.ts +60 -0
  51. package/src/common/index.ts +2 -0
  52. package/src/data-structures/base/iterable-element-base.ts +2 -2
  53. package/src/data-structures/binary-tree/avl-tree.ts +134 -51
  54. package/src/data-structures/binary-tree/binary-indexed-tree.ts +303 -247
  55. package/src/data-structures/binary-tree/binary-tree.ts +542 -121
  56. package/src/data-structures/binary-tree/bst.ts +346 -37
  57. package/src/data-structures/binary-tree/red-black-tree.ts +309 -96
  58. package/src/data-structures/binary-tree/segment-tree.ts +372 -248
  59. package/src/data-structures/binary-tree/tree-map.ts +1292 -13
  60. package/src/data-structures/binary-tree/tree-multi-map.ts +1098 -215
  61. package/src/data-structures/binary-tree/tree-multi-set.ts +863 -69
  62. package/src/data-structures/binary-tree/tree-set.ts +1143 -15
  63. package/src/data-structures/graph/abstract-graph.ts +106 -1
  64. package/src/data-structures/graph/directed-graph.ts +223 -47
  65. package/src/data-structures/graph/map-graph.ts +59 -1
  66. package/src/data-structures/graph/undirected-graph.ts +299 -59
  67. package/src/data-structures/hash/hash-map.ts +243 -79
  68. package/src/data-structures/heap/heap.ts +291 -102
  69. package/src/data-structures/heap/max-heap.ts +48 -3
  70. package/src/data-structures/heap/min-heap.ts +59 -0
  71. package/src/data-structures/linked-list/doubly-linked-list.ts +286 -44
  72. package/src/data-structures/linked-list/singly-linked-list.ts +278 -65
  73. package/src/data-structures/linked-list/skip-linked-list.ts +689 -90
  74. package/src/data-structures/matrix/matrix.ts +425 -22
  75. package/src/data-structures/priority-queue/max-priority-queue.ts +59 -3
  76. package/src/data-structures/priority-queue/min-priority-queue.ts +60 -0
  77. package/src/data-structures/priority-queue/priority-queue.ts +60 -0
  78. package/src/data-structures/queue/deque.ts +343 -68
  79. package/src/data-structures/queue/queue.ts +211 -42
  80. package/src/data-structures/stack/stack.ts +174 -32
  81. package/src/data-structures/trie/trie.ts +215 -44
  82. package/src/types/data-structures/binary-tree/segment-tree.ts +1 -1
  83. package/src/types/data-structures/linked-list/skip-linked-list.ts +2 -1
  84. package/src/types/data-structures/queue/deque.ts +7 -0
  85. package/src/utils/utils.ts +4 -2
@@ -26,7 +26,7 @@ import { BinaryTree } from './binary-tree';
26
26
  import { IBinaryTree } from '../../interfaces';
27
27
  import { Queue } from '../queue';
28
28
  import { isComparable } from '../../utils';
29
- import { Range } from '../../common';
29
+ import { ERR, Range } from '../../common';
30
30
 
31
31
  /**
32
32
  * Represents a Node in a Binary Search Tree.
@@ -105,6 +105,7 @@ export class BSTNode<K = any, V = any> {
105
105
  *
106
106
  * @returns The height.
107
107
  */
108
+ /* istanbul ignore next -- covered by AVLTree/RedBlackTree tests (subclass uses height) */
108
109
  get height(): number {
109
110
  return this._height;
110
111
  }
@@ -115,6 +116,7 @@ export class BSTNode<K = any, V = any> {
115
116
  *
116
117
  * @param value - The new height.
117
118
  */
119
+ /* istanbul ignore next -- covered by AVLTree/RedBlackTree tests (subclass uses height) */
118
120
  set height(value: number) {
119
121
  this._height = value;
120
122
  }
@@ -127,6 +129,7 @@ export class BSTNode<K = any, V = any> {
127
129
  *
128
130
  * @returns The node's color.
129
131
  */
132
+ /* istanbul ignore next -- covered by RedBlackTree tests (subclass uses color) */
130
133
  get color(): RBTNColor {
131
134
  return this._color;
132
135
  }
@@ -137,6 +140,7 @@ export class BSTNode<K = any, V = any> {
137
140
  *
138
141
  * @param value - The new color.
139
142
  */
143
+ /* istanbul ignore next -- covered by RedBlackTree tests (subclass uses color) */
140
144
  set color(value: RBTNColor) {
141
145
  this._color = value;
142
146
  }
@@ -149,6 +153,7 @@ export class BSTNode<K = any, V = any> {
149
153
  *
150
154
  * @returns The subtree node count.
151
155
  */
156
+ /* istanbul ignore next -- internal field used by subclasses */
152
157
  get count(): number {
153
158
  return this._count;
154
159
  }
@@ -159,6 +164,7 @@ export class BSTNode<K = any, V = any> {
159
164
  *
160
165
  * @param value - The new count.
161
166
  */
167
+ /* istanbul ignore next -- internal field used by subclasses */
162
168
  set count(value: number) {
163
169
  this._count = value;
164
170
  }
@@ -200,34 +206,6 @@ export class BSTNode<K = any, V = any> {
200
206
  * 7. No Auto-Balancing: Standard BSTs don't automatically balance themselves.
201
207
  *
202
208
  * @example
203
- * // basic BST creation and add operation
204
- * // Create a simple BST with numeric keys
205
- * const bst = new BST<number>([11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]);
206
- *
207
- * // Keep the example output in source comments but avoid noisy test logs.
208
- * await withMutedConsole(() => bst.print());
209
- * // _______8__________
210
- * // / \
211
- * // ___4___ ____12_____
212
- * // / \ / \
213
- * // _2_ _6_ _10__ _14__
214
- * // / \ / \ / \ / \
215
- * // 1 3 5 7 9 11 13 15__
216
- * // \
217
- * // 16
218
- *
219
- * // Verify size
220
- * console.log(bst.size); // 16;
221
- *
222
- * // Add new elements
223
- * bst.set(17);
224
- * bst.set(0);
225
- * console.log(bst.size); // 18;
226
- *
227
- * // Verify keys are searchable
228
- * console.log(bst.has(11)); // true;
229
- * console.log(bst.has(100)); // false;
230
- * @example
231
209
  * // BST delete and search after deletion
232
210
  * const bst = new BST<number>([11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]);
233
211
  *
@@ -454,6 +432,36 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
454
432
  return isComparable(key);
455
433
  }
456
434
 
435
+ /**
436
+ * Depth-first search traversal
437
+
438
+
439
+
440
+
441
+
442
+
443
+
444
+
445
+
446
+
447
+
448
+
449
+
450
+
451
+
452
+
453
+
454
+
455
+
456
+
457
+
458
+
459
+ * @example
460
+ * // Depth-first traversal
461
+ * const bst = new BST<number>([5, 3, 7, 1, 4]);
462
+ * const inOrder = bst.dfs(node => node.key, 'IN');
463
+ * console.log(inOrder); // [1, 3, 4, 5, 7];
464
+ */
457
465
  override dfs(): (K | undefined)[];
458
466
 
459
467
  override dfs<C extends NodeCallback<BSTNode<K, V>>>(
@@ -486,6 +494,28 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
486
494
  return super.dfs(callback, pattern, onlyOne, startNode, iterationType);
487
495
  }
488
496
 
497
+ /**
498
+ * BinaryTree level-order traversal
499
+
500
+
501
+
502
+
503
+
504
+
505
+
506
+
507
+
508
+
509
+
510
+
511
+
512
+
513
+ * @example
514
+ * // Breadth-first traversal
515
+ * const bst = new BST<number>([5, 3, 7]);
516
+ * const result = bst.bfs(node => node.key);
517
+ * console.log(result.length); // 3;
518
+ */
489
519
  override bfs(): (K | undefined)[];
490
520
  override bfs<C extends NodeCallback<BSTNode<K, V>>>(
491
521
  callback: C,
@@ -511,6 +541,34 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
511
541
  return super.bfs(callback, startNode, iterationType, false);
512
542
  }
513
543
 
544
+ /**
545
+ * Level-order grouping
546
+
547
+
548
+
549
+
550
+
551
+
552
+
553
+
554
+
555
+
556
+
557
+
558
+
559
+
560
+
561
+
562
+
563
+ * @example
564
+ * // Level-order grouping
565
+ * const bst = new BST<number>([5, 3, 7, 1, 4]);
566
+ * const levels = bst.listLevels(node => node.key);
567
+ * console.log(levels.length); // > 0;
568
+ * console.log(levels[0].length); // 1; // root level has 1 node
569
+ * const allKeys = levels.flat().sort((a, b) => a - b);
570
+ * console.log(allKeys); // [1, 3, 4, 5, 7];
571
+ */
514
572
  override listLevels(): (K | undefined)[][];
515
573
 
516
574
  override listLevels<C extends NodeCallback<BSTNode<K, V>>>(
@@ -545,6 +603,31 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
545
603
  * @param [startNode=this._root] - The node to start the search from.
546
604
  * @param [iterationType=this.iterationType] - The traversal method.
547
605
  * @returns The first matching node, or undefined if not found.
606
+
607
+
608
+
609
+
610
+
611
+
612
+
613
+
614
+
615
+
616
+
617
+
618
+
619
+
620
+
621
+
622
+
623
+
624
+
625
+ * @example
626
+ * // Get node object by key
627
+ * const bst = new BST<number, string>([[5, 'root'], [3, 'left'], [7, 'right']]);
628
+ * const node = bst.getNode(3);
629
+ * console.log(node?.key); // 3;
630
+ * console.log(node?.value); // 'left';
548
631
  */
549
632
  override getNode(
550
633
  keyNodeEntryOrPredicate:
@@ -606,6 +689,26 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
606
689
  }
607
690
 
608
691
 
692
+ /**
693
+ * Search nodes by predicate
694
+
695
+
696
+
697
+
698
+
699
+
700
+
701
+
702
+
703
+
704
+
705
+
706
+ * @example
707
+ * // Search nodes by predicate
708
+ * const bst = new BST<number, string>([[1, 'a'], [2, 'b'], [3, 'c'], [4, 'd']]);
709
+ * const found = bst.search(node => node.key > 2, true);
710
+ * console.log(found.length); // >= 1;
711
+ */
609
712
  override search(
610
713
  keyNodeEntryOrPredicate:
611
714
  | K
@@ -699,6 +802,7 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
699
802
  let predicate: NodePredicate<BSTNode<K, V>>;
700
803
  if (isRange) {
701
804
  predicate = node => {
805
+ /* istanbul ignore next -- node is always defined in iteration callbacks */
702
806
  if (!node) return false;
703
807
  return (keyNodeEntryOrPredicate).isInRange(node.key, this._comparator);
704
808
  };
@@ -708,7 +812,7 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
708
812
 
709
813
  // Optimization: Pruning logic
710
814
  const shouldVisitLeft = (cur: BSTNode<K, V> | null | undefined) => {
711
- if (!cur) return false;
815
+ /* istanbul ignore next -- defensive: cur is always defined when called from iteration */ if (!cur) return false;
712
816
  if (!this.isRealNode(cur.left)) return false;
713
817
  if (isRange) {
714
818
  // Range search: Only go left if the current key is >= the lower bound
@@ -726,7 +830,7 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
726
830
  };
727
831
 
728
832
  const shouldVisitRight = (cur: BSTNode<K, V> | null | undefined) => {
729
- if (!cur) return false;
833
+ /* istanbul ignore next -- defensive */ if (!cur) return false;
730
834
  if (!this.isRealNode(cur.right)) return false;
731
835
  if (isRange) {
732
836
  // Range search: Only go right if current key <= upper bound
@@ -757,6 +861,24 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
757
861
  );
758
862
  }
759
863
 
864
+ /**
865
+ * Find all keys in a range
866
+
867
+
868
+
869
+
870
+
871
+
872
+
873
+
874
+
875
+
876
+
877
+ * @example
878
+ * // Find all keys in a range
879
+ * const bst = new BST<number>([10, 20, 30, 40, 50]);
880
+ * console.log(bst.rangeSearch([15, 35])); // [20, 30];
881
+ */
760
882
  rangeSearch(range: Range<K> | [K, K]): (K | undefined)[];
761
883
 
762
884
  rangeSearch<C extends NodeCallback<BSTNode<K, V>>>(
@@ -794,6 +916,37 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
794
916
  * @param keyNodeOrEntry - The key, node, or entry to set.
795
917
  * @param [value] - The value, if providing just a key.
796
918
  * @returns True if the addition was successful, false otherwise.
919
+
920
+
921
+
922
+
923
+
924
+
925
+
926
+
927
+
928
+
929
+
930
+
931
+
932
+
933
+
934
+
935
+
936
+
937
+
938
+
939
+
940
+
941
+
942
+
943
+
944
+ * @example
945
+ * // Set a key-value pair
946
+ * const bst = new BST<number, string>();
947
+ * bst.set(1, 'one');
948
+ * bst.set(2, 'two');
949
+ * console.log(bst.get(1)); // 'one';
797
950
  */
798
951
  override set(
799
952
  keyNodeOrEntry: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
@@ -836,6 +989,7 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
836
989
  if (current.right !== null) current = current.right;
837
990
  }
838
991
  }
992
+ /* istanbul ignore next -- defensive: traversal always finds undefined slot before exhausting tree */
839
993
  return false;
840
994
  }
841
995
 
@@ -850,6 +1004,23 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
850
1004
  * @param [isBalanceAdd=true] - If true, builds a balanced tree from the items.
851
1005
  * @param [iterationType=this.iterationType] - The traversal method for balanced set (recursive or iterative).
852
1006
  * @returns An array of booleans indicating the success of each individual `set` operation.
1007
+
1008
+
1009
+
1010
+
1011
+
1012
+
1013
+
1014
+
1015
+
1016
+
1017
+
1018
+ * @example
1019
+ * // Set multiple key-value pairs
1020
+ * const bst = new BST<number, string>();
1021
+ * bst.setMany([[1, 'a'], [2, 'b'], [3, 'c']]);
1022
+ * console.log(bst.size); // 3;
1023
+ * console.log(bst.get(2)); // 'b';
853
1024
  */
854
1025
  override setMany(
855
1026
  keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V, BSTNode<K, V>>>,
@@ -920,6 +1091,7 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
920
1091
  const stack: Array<[number, number]> = [[0, n - 1]];
921
1092
  while (stack.length > 0) {
922
1093
  const popped = stack.pop();
1094
+ /* istanbul ignore next -- stack.pop() on non-empty stack always returns a value */
923
1095
  if (!popped) continue;
924
1096
  const [l, r] = popped;
925
1097
  if (l > r) continue;
@@ -947,6 +1119,23 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
947
1119
  * Equivalent to Java TreeMap.ceiling.
948
1120
  * Time Complexity: O(log n) average, O(h) worst case.
949
1121
  * Space Complexity: O(h) for recursion, O(1) for iteration.
1122
+
1123
+
1124
+
1125
+
1126
+
1127
+
1128
+
1129
+
1130
+
1131
+
1132
+
1133
+ * @example
1134
+ * // Find the least key ≥ target
1135
+ * const bst = new BST<number>([10, 20, 30, 40, 50]);
1136
+ * console.log(bst.ceiling(25)); // 30;
1137
+ * console.log(bst.ceiling(30)); // 30;
1138
+ * console.log(bst.ceiling(55)); // undefined;
950
1139
  */
951
1140
  ceiling(
952
1141
  keyNodeEntryOrPredicate:
@@ -1012,6 +1201,22 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1012
1201
  * Equivalent to Java TreeMap.higher.
1013
1202
  * Time Complexity: O(log n) average, O(h) worst case.
1014
1203
  * Space Complexity: O(h) for recursion, O(1) for iteration.
1204
+
1205
+
1206
+
1207
+
1208
+
1209
+
1210
+
1211
+
1212
+
1213
+
1214
+
1215
+ * @example
1216
+ * // Find the least key strictly > target
1217
+ * const bst = new BST<number>([10, 20, 30, 40]);
1218
+ * console.log(bst.higher(20)); // 30;
1219
+ * console.log(bst.higher(40)); // undefined;
1015
1220
  */
1016
1221
  higher(
1017
1222
  keyNodeEntryOrPredicate:
@@ -1077,6 +1282,23 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1077
1282
  * Equivalent to Java TreeMap.floor.
1078
1283
  * Time Complexity: O(log n) average, O(h) worst case.
1079
1284
  * Space Complexity: O(h) for recursion, O(1) for iteration.
1285
+
1286
+
1287
+
1288
+
1289
+
1290
+
1291
+
1292
+
1293
+
1294
+
1295
+
1296
+ * @example
1297
+ * // Find the greatest key ≤ target
1298
+ * const bst = new BST<number>([10, 20, 30, 40, 50]);
1299
+ * console.log(bst.floor(25)); // 20;
1300
+ * console.log(bst.floor(10)); // 10;
1301
+ * console.log(bst.floor(5)); // undefined;
1080
1302
  */
1081
1303
  floor(
1082
1304
  keyNodeEntryOrPredicate:
@@ -1117,7 +1339,7 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1117
1339
  iterationType?: IterationType
1118
1340
  ): K | undefined | ReturnType<C> {
1119
1341
  if (keyNodeEntryOrPredicate === null || keyNodeEntryOrPredicate === undefined) {
1120
- if (typeof callback === 'string' || !callback) {
1342
+ /* istanbul ignore next */ if (typeof callback === 'string' || !callback) {
1121
1343
  return undefined;
1122
1344
  }
1123
1345
  return undefined;
@@ -1151,7 +1373,7 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1151
1373
  } else if (this.isEntry(keyNodeEntryOrPredicate)) {
1152
1374
  const key = keyNodeEntryOrPredicate[0];
1153
1375
  if (key === null || key === undefined) {
1154
- if (typeof callback === 'string' || !callback) {
1376
+ /* istanbul ignore next */ if (typeof callback === 'string' || !callback) {
1155
1377
  return undefined;
1156
1378
  }
1157
1379
  return undefined;
@@ -1164,6 +1386,7 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1164
1386
  if (targetKey !== undefined) {
1165
1387
  const node = this._floorByKey(targetKey, actualIterationType);
1166
1388
 
1389
+ /* istanbul ignore next */
1167
1390
  if (!actualCallback) {
1168
1391
  return node?.key;
1169
1392
  }
@@ -1171,9 +1394,11 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1171
1394
  return node ? actualCallback(node) : undefined;
1172
1395
  }
1173
1396
 
1397
+ /* istanbul ignore next -- targetKey is always defined if we reach here (null/undefined caught above) */
1174
1398
  if (typeof callback === 'string' || !callback) {
1175
1399
  return undefined;
1176
1400
  }
1401
+ /* istanbul ignore next */
1177
1402
  return undefined;
1178
1403
  }
1179
1404
 
@@ -1182,6 +1407,22 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1182
1407
  * Equivalent to Java TreeMap.lower.
1183
1408
  * Time Complexity: O(log n) average, O(h) worst case.
1184
1409
  * Space Complexity: O(h) for recursion, O(1) for iteration.
1410
+
1411
+
1412
+
1413
+
1414
+
1415
+
1416
+
1417
+
1418
+
1419
+
1420
+
1421
+ * @example
1422
+ * // Find the greatest key strictly < target
1423
+ * const bst = new BST<number>([10, 20, 30, 40]);
1424
+ * console.log(bst.lower(30)); // 20;
1425
+ * console.log(bst.lower(10)); // undefined;
1185
1426
  */
1186
1427
  lower(
1187
1428
  keyNodeEntryOrPredicate:
@@ -1222,9 +1463,10 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1222
1463
  iterationType?: IterationType
1223
1464
  ): K | undefined | ReturnType<C> {
1224
1465
  if (keyNodeEntryOrPredicate === null || keyNodeEntryOrPredicate === undefined) {
1225
- if (typeof callback === 'string' || !callback) {
1466
+ /* istanbul ignore next */ if (typeof callback === 'string' || !callback) {
1226
1467
  return undefined;
1227
1468
  }
1469
+ /* istanbul ignore next */
1228
1470
  return undefined;
1229
1471
  }
1230
1472
 
@@ -1256,9 +1498,10 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1256
1498
  } else if (this.isEntry(keyNodeEntryOrPredicate)) {
1257
1499
  const key = keyNodeEntryOrPredicate[0];
1258
1500
  if (key === null || key === undefined) {
1259
- if (typeof callback === 'string' || !callback) {
1501
+ /* istanbul ignore next */ if (typeof callback === 'string' || !callback) {
1260
1502
  return undefined;
1261
1503
  }
1504
+ /* istanbul ignore next */
1262
1505
  return undefined;
1263
1506
  }
1264
1507
  targetKey = key;
@@ -1276,9 +1519,11 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1276
1519
  return node ? actualCallback(node) : undefined;
1277
1520
  }
1278
1521
 
1522
+ /* istanbul ignore next -- targetKey is always defined if we reach here (null/undefined caught above) */
1279
1523
  if (typeof callback === 'string' || !callback) {
1280
1524
  return undefined;
1281
1525
  }
1526
+ /* istanbul ignore next */
1282
1527
  return undefined;
1283
1528
  }
1284
1529
 
@@ -1345,6 +1590,23 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1345
1590
  *
1346
1591
  * @param [iterationType=this.iterationType] - The traversal method for the initial node export.
1347
1592
  * @returns True if successful, false if the tree was empty.
1593
+
1594
+
1595
+
1596
+
1597
+
1598
+
1599
+
1600
+
1601
+
1602
+ * @example
1603
+ * // Rebalance the tree
1604
+ * const bst = new BST<number>();
1605
+ * // Insert in sorted order (worst case for BST)
1606
+ * for (let i = 1; i <= 7; i++) bst.add(i);
1607
+ * console.log(bst.isAVLBalanced()); // false;
1608
+ * bst.perfectlyBalance();
1609
+ * console.log(bst.isAVLBalanced()); // true;
1348
1610
  */
1349
1611
  perfectlyBalance(iterationType: IterationType = this.iterationType): boolean {
1350
1612
  const nodes = this.dfs(node => node, 'IN', false, this._root, iterationType);
@@ -1377,6 +1639,19 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1377
1639
  *
1378
1640
  * @param [iterationType=this.iterationType] - The traversal method.
1379
1641
  * @returns True if the tree is AVL balanced, false otherwise.
1642
+
1643
+
1644
+
1645
+
1646
+
1647
+
1648
+
1649
+
1650
+
1651
+ * @example
1652
+ * // Check if tree is height-balanced
1653
+ * const bst = new BST<number>([3, 1, 5, 2, 4]);
1654
+ * console.log(bst.isAVLBalanced()); // true;
1380
1655
  */
1381
1656
  isAVLBalanced(iterationType: IterationType = this.iterationType): boolean {
1382
1657
  if (!this._root) return true;
@@ -1434,6 +1709,30 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1434
1709
  * @param [options] - Options for the new BST.
1435
1710
  * @param [thisArg] - `this` context for the callback.
1436
1711
  * @returns A new, mapped BST.
1712
+
1713
+
1714
+
1715
+
1716
+
1717
+
1718
+
1719
+
1720
+
1721
+
1722
+
1723
+
1724
+
1725
+
1726
+
1727
+
1728
+
1729
+
1730
+
1731
+ * @example
1732
+ * // Transform to new tree
1733
+ * const bst = new BST<number, number>([[1, 10], [2, 20], [3, 30]]);
1734
+ * const doubled = bst.map((value, key) => [key, (value ?? 0) * 2] as [number, number]);
1735
+ * console.log([...doubled.values()]); // [20, 40, 60];
1437
1736
  */
1438
1737
  override map<MK = K, MV = V, MR = any>(
1439
1738
  callback: EntryCallback<K, V | undefined, [MK, MV]>,
@@ -1523,10 +1822,19 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1523
1822
  return 0;
1524
1823
  }
1525
1824
 
1825
+ /* istanbul ignore next -- Date objects satisfy isComparable(), so this branch is unreachable via default comparator */
1826
+ // Date keys: compare by getTime()
1827
+ if (a instanceof Date && b instanceof Date) {
1828
+ const ta = a.getTime();
1829
+ const tb = b.getTime();
1830
+ if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate('BST'));
1831
+ return ta > tb ? 1 : ta < tb ? -1 : 0;
1832
+ }
1833
+
1526
1834
  // If keys are objects and no comparator is provided, throw an error
1527
1835
  if (typeof a === 'object' || typeof b === 'object') {
1528
- throw TypeError(
1529
- `When comparing object type keys, a custom comparator must be provided in the constructor's options!`
1836
+ throw new TypeError(
1837
+ ERR.comparatorRequired('BST')
1530
1838
  );
1531
1839
  }
1532
1840
 
@@ -1823,6 +2131,7 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1823
2131
  return this._boundByKey(targetKey, isLower, iterationType);
1824
2132
  }
1825
2133
 
2134
+ /* istanbul ignore next -- defensive: targetKey is always defined if predicate path was skipped */
1826
2135
  return undefined;
1827
2136
  }
1828
2137