binary-tree-typed 2.5.1 → 2.5.3

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 (75) hide show
  1. package/dist/cjs/index.cjs +340 -107
  2. package/dist/cjs/index.cjs.map +1 -1
  3. package/dist/cjs-legacy/index.cjs +339 -106
  4. package/dist/cjs-legacy/index.cjs.map +1 -1
  5. package/dist/esm/index.mjs +340 -108
  6. package/dist/esm/index.mjs.map +1 -1
  7. package/dist/esm-legacy/index.mjs +339 -107
  8. package/dist/esm-legacy/index.mjs.map +1 -1
  9. package/dist/types/common/error.d.ts +9 -0
  10. package/dist/types/common/index.d.ts +1 -1
  11. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +86 -2
  12. package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +98 -0
  13. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +189 -13
  14. package/dist/types/data-structures/binary-tree/bst.d.ts +270 -3
  15. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +136 -8
  16. package/dist/types/data-structures/binary-tree/segment-tree.d.ts +42 -0
  17. package/dist/types/data-structures/binary-tree/tree-map.d.ts +1089 -161
  18. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +1243 -350
  19. package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +980 -255
  20. package/dist/types/data-structures/binary-tree/tree-set.d.ts +1174 -284
  21. package/dist/types/data-structures/graph/directed-graph.d.ts +70 -0
  22. package/dist/types/data-structures/graph/undirected-graph.d.ts +63 -0
  23. package/dist/types/data-structures/hash/hash-map.d.ts +84 -6
  24. package/dist/types/data-structures/heap/heap.d.ts +140 -12
  25. package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +126 -0
  26. package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +106 -1
  27. package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +126 -0
  28. package/dist/types/data-structures/matrix/matrix.d.ts +56 -0
  29. package/dist/types/data-structures/queue/deque.d.ts +127 -0
  30. package/dist/types/data-structures/queue/queue.d.ts +97 -0
  31. package/dist/types/data-structures/stack/stack.d.ts +72 -2
  32. package/dist/types/data-structures/trie/trie.d.ts +84 -0
  33. package/dist/types/interfaces/binary-tree.d.ts +2 -3
  34. package/dist/types/types/data-structures/binary-tree/bst.d.ts +1 -0
  35. package/dist/types/types/data-structures/binary-tree/tree-map.d.ts +5 -0
  36. package/dist/types/types/data-structures/binary-tree/tree-multi-set.d.ts +4 -0
  37. package/dist/types/types/data-structures/binary-tree/tree-set.d.ts +4 -0
  38. package/dist/umd/binary-tree-typed.js +337 -105
  39. package/dist/umd/binary-tree-typed.js.map +1 -1
  40. package/dist/umd/binary-tree-typed.min.js +5 -5
  41. package/dist/umd/binary-tree-typed.min.js.map +1 -1
  42. package/package.json +2 -2
  43. package/src/common/error.ts +19 -1
  44. package/src/common/index.ts +1 -1
  45. package/src/data-structures/base/iterable-element-base.ts +3 -2
  46. package/src/data-structures/binary-tree/avl-tree.ts +99 -5
  47. package/src/data-structures/binary-tree/binary-indexed-tree.ts +102 -4
  48. package/src/data-structures/binary-tree/binary-tree.ts +239 -78
  49. package/src/data-structures/binary-tree/bst.ts +542 -13
  50. package/src/data-structures/binary-tree/red-black-tree.ts +155 -15
  51. package/src/data-structures/binary-tree/segment-tree.ts +42 -0
  52. package/src/data-structures/binary-tree/tree-map.ts +1223 -261
  53. package/src/data-structures/binary-tree/tree-multi-map.ts +939 -30
  54. package/src/data-structures/binary-tree/tree-multi-set.ts +746 -10
  55. package/src/data-structures/binary-tree/tree-set.ts +1018 -99
  56. package/src/data-structures/graph/abstract-graph.ts +2 -2
  57. package/src/data-structures/graph/directed-graph.ts +71 -1
  58. package/src/data-structures/graph/undirected-graph.ts +64 -1
  59. package/src/data-structures/hash/hash-map.ts +102 -16
  60. package/src/data-structures/heap/heap.ts +153 -23
  61. package/src/data-structures/heap/max-heap.ts +2 -2
  62. package/src/data-structures/linked-list/doubly-linked-list.ts +139 -0
  63. package/src/data-structures/linked-list/singly-linked-list.ts +106 -1
  64. package/src/data-structures/linked-list/skip-linked-list.ts +131 -5
  65. package/src/data-structures/matrix/matrix.ts +65 -9
  66. package/src/data-structures/priority-queue/max-priority-queue.ts +2 -2
  67. package/src/data-structures/queue/deque.ts +130 -0
  68. package/src/data-structures/queue/queue.ts +109 -0
  69. package/src/data-structures/stack/stack.ts +75 -5
  70. package/src/data-structures/trie/trie.ts +86 -2
  71. package/src/interfaces/binary-tree.ts +1 -9
  72. package/src/types/data-structures/binary-tree/bst.ts +1 -0
  73. package/src/types/data-structures/binary-tree/tree-map.ts +6 -0
  74. package/src/types/data-structures/binary-tree/tree-multi-set.ts +5 -0
  75. package/src/types/data-structures/binary-tree/tree-set.ts +5 -0
@@ -7,7 +7,6 @@
7
7
  */
8
8
 
9
9
  import type {
10
- BinaryTreeDeleteResult,
11
10
  BSTNOptKeyOrNode,
12
11
  BSTOptions,
13
12
  BTNRep,
@@ -26,7 +25,7 @@ import { BinaryTree } from './binary-tree';
26
25
  import { IBinaryTree } from '../../interfaces';
27
26
  import { Queue } from '../queue';
28
27
  import { isComparable } from '../../utils';
29
- import { ERR, Range } from '../../common';
28
+ import { ERR, Range, raise } from '../../common';
30
29
 
31
30
  /**
32
31
  * Represents a Node in a Binary Search Tree.
@@ -345,6 +344,9 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
345
344
  } else {
346
345
  this._comparator = this._createDefaultComparator();
347
346
  }
347
+ if (options.enableOrderStatistic) {
348
+ this._enableOrderStatistic = true;
349
+ }
348
350
  } else {
349
351
  this._comparator = this._createDefaultComparator();
350
352
  }
@@ -354,6 +356,8 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
354
356
 
355
357
  protected override _root?: BSTNode<K, V> = undefined;
356
358
 
359
+ protected _enableOrderStatistic: boolean = false;
360
+
357
361
  /**
358
362
  * Gets the root node of the tree.
359
363
  * @remarks Time O(1)
@@ -483,6 +487,20 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
483
487
 
484
488
 
485
489
 
490
+
491
+
492
+
493
+
494
+
495
+
496
+
497
+
498
+
499
+
500
+
501
+
502
+
503
+
486
504
 
487
505
 
488
506
 
@@ -579,6 +597,20 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
579
597
 
580
598
 
581
599
 
600
+
601
+
602
+
603
+
604
+
605
+
606
+
607
+
608
+
609
+
610
+
611
+
612
+
613
+
582
614
 
583
615
 
584
616
 
@@ -671,6 +703,20 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
671
703
 
672
704
 
673
705
 
706
+
707
+
708
+
709
+
710
+
711
+
712
+
713
+
714
+
715
+
716
+
717
+
718
+
719
+
674
720
 
675
721
 
676
722
 
@@ -690,7 +736,7 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
690
736
  * // Level-order grouping
691
737
  * const bst = new BST<number>([5, 3, 7, 1, 4]);
692
738
  * const levels = bst.listLevels(node => node.key);
693
- * console.log(levels.length); // > 0;
739
+ * console.log(levels); // toBeInstanceOf;
694
740
  * console.log(levels[0].length); // 1; // root level has 1 node
695
741
  * const allKeys = levels.flat().sort((a, b) => a - b);
696
742
  * console.log(allKeys); // [1, 3, 4, 5, 7];
@@ -775,6 +821,20 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
775
821
 
776
822
 
777
823
 
824
+
825
+
826
+
827
+
828
+
829
+
830
+
831
+
832
+
833
+
834
+
835
+
836
+
837
+
778
838
 
779
839
 
780
840
 
@@ -898,6 +958,20 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
898
958
 
899
959
 
900
960
 
961
+
962
+
963
+
964
+
965
+
966
+
967
+
968
+
969
+
970
+
971
+
972
+
973
+
974
+
901
975
 
902
976
 
903
977
 
@@ -1097,6 +1171,13 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1097
1171
 
1098
1172
 
1099
1173
 
1174
+
1175
+
1176
+
1177
+
1178
+
1179
+
1180
+
1100
1181
 
1101
1182
 
1102
1183
 
@@ -1140,6 +1221,232 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1140
1221
  return this.search(searchRange, false, callback, startNode, iterationType);
1141
1222
  }
1142
1223
 
1224
+ // ─── Order-Statistic Methods ───────────────────────────
1225
+
1226
+ /**
1227
+ * Returns the element at the k-th position in tree order (0-indexed).
1228
+ * @remarks Time O(log n), Space O(1) iterative / O(log n) recursive. Requires `enableOrderStatistic: true`.
1229
+ * Tree order is defined by the comparator — ascending by default, but respects custom comparators (e.g. descending).
1230
+ *
1231
+ * @param k - The 0-based position in tree order (0 = first element).
1232
+ * @returns The key at position k, or `undefined` if out of bounds.
1233
+ * @example
1234
+ * // Order-statistic on BST
1235
+ * const tree = new BST<number>([30, 10, 50, 20, 40], { enableOrderStatistic: true });
1236
+ * console.log(tree.getByRank(0)); // 10;
1237
+ * console.log(tree.getByRank(4)); // 50;
1238
+ * console.log(tree.getRank(30)); // 2;
1239
+ */
1240
+ getByRank(k: number): K | undefined;
1241
+
1242
+ /**
1243
+ * Returns the element at the k-th position in tree order and applies a callback.
1244
+ * @remarks Time O(log n), Space O(1) iterative / O(log n) recursive. Requires `enableOrderStatistic: true`.
1245
+ *
1246
+ * @param k - The 0-based position in tree order (0 = first element).
1247
+ * @param callback - Callback to apply to the found node.
1248
+ * @param iterationType - Iteration strategy ('ITERATIVE' or 'RECURSIVE').
1249
+ * @returns The callback result, or `undefined` if out of bounds.
1250
+ */
1251
+ getByRank<C extends NodeCallback<BSTNode<K, V>>>(
1252
+ k: number,
1253
+ callback: C,
1254
+ iterationType?: IterationType
1255
+ ): ReturnType<C> | undefined;
1256
+
1257
+ getByRank<C extends NodeCallback<BSTNode<K, V>>>(
1258
+ k: number,
1259
+ callback: C = this._DEFAULT_NODE_CALLBACK as C,
1260
+ iterationType: IterationType = this.iterationType
1261
+ ): K | undefined | ReturnType<C> | undefined {
1262
+ if (!this._enableOrderStatistic) {
1263
+ raise(Error, ERR.orderStatisticNotEnabled('getByRank'));
1264
+ }
1265
+ if (k < 0 || k >= this._size) return undefined;
1266
+
1267
+ let actualCallback: C | undefined = undefined;
1268
+ let actualIterationType: IterationType = this.iterationType;
1269
+
1270
+ if (typeof callback === 'string') {
1271
+ actualIterationType = callback;
1272
+ } else if (callback) {
1273
+ actualCallback = callback;
1274
+ if (iterationType) {
1275
+ actualIterationType = iterationType;
1276
+ }
1277
+ }
1278
+
1279
+ const node = actualIterationType === 'RECURSIVE'
1280
+ ? this._getByRankRecursive(this._root, k)
1281
+ : this._getByRankIterative(this._root, k);
1282
+
1283
+ if (!node) return undefined;
1284
+ return actualCallback ? actualCallback(node) : node.key;
1285
+ }
1286
+
1287
+ /**
1288
+ * Returns the 0-based rank of a key (number of elements that precede it in tree order).
1289
+ * @remarks Time O(log n), Space O(1) iterative / O(log n) recursive. Requires `enableOrderStatistic: true`.
1290
+ * Tree order is defined by the comparator. When the key is not found, returns the insertion position.
1291
+ *
1292
+ * @param keyNodeEntryOrPredicate - The key, node, entry `[K, V]`, or predicate to find.
1293
+ * @returns The rank (0-indexed), or -1 if the tree is empty or input is invalid.
1294
+ */
1295
+ getRank(
1296
+ keyNodeEntryOrPredicate:
1297
+ | K
1298
+ | BSTNode<K, V>
1299
+ | [K | null | undefined, V | undefined]
1300
+ | null
1301
+ | undefined
1302
+ | NodePredicate<BSTNode<K, V>>
1303
+ ): number;
1304
+
1305
+ /**
1306
+ * Returns the 0-based rank (number of preceding elements in tree order) with explicit iteration type.
1307
+ * @remarks Time O(log n), Space O(1) iterative / O(log n) recursive. Requires `enableOrderStatistic: true`.
1308
+ *
1309
+ * @param keyNodeEntryOrPredicate - The key, node, entry, or predicate to find.
1310
+ * @param iterationType - Iteration strategy ('ITERATIVE' or 'RECURSIVE').
1311
+ * @returns The rank (0-indexed), or -1 if the tree is empty or input is invalid.
1312
+ */
1313
+ getRank(
1314
+ keyNodeEntryOrPredicate:
1315
+ | K
1316
+ | BSTNode<K, V>
1317
+ | [K | null | undefined, V | undefined]
1318
+ | null
1319
+ | undefined
1320
+ | NodePredicate<BSTNode<K, V>>,
1321
+ iterationType: IterationType
1322
+ ): number;
1323
+
1324
+ getRank(
1325
+ keyNodeEntryOrPredicate:
1326
+ | K
1327
+ | BSTNode<K, V>
1328
+ | [K | null | undefined, V | undefined]
1329
+ | null
1330
+ | undefined
1331
+ | NodePredicate<BSTNode<K, V>>,
1332
+ iterationType: IterationType = this.iterationType
1333
+ ): number {
1334
+ if (!this._enableOrderStatistic) {
1335
+ raise(Error, ERR.orderStatisticNotEnabled('getRank'));
1336
+ }
1337
+ if (!this._root || this._size === 0) return -1;
1338
+
1339
+ let actualIterationType: IterationType = this.iterationType;
1340
+ if (iterationType) actualIterationType = iterationType;
1341
+
1342
+ // Resolve key from input
1343
+ let key: K | undefined;
1344
+ if (typeof keyNodeEntryOrPredicate === 'function') {
1345
+ // Predicate: find first matching node
1346
+ const results = this.search(keyNodeEntryOrPredicate as NodePredicate<BSTNode<K, V>>, true);
1347
+ if (results.length === 0 || results[0] === undefined) return -1;
1348
+ key = results[0];
1349
+ } else if (keyNodeEntryOrPredicate === null || keyNodeEntryOrPredicate === undefined) {
1350
+ return -1;
1351
+ } else if (this.isNode(keyNodeEntryOrPredicate)) {
1352
+ key = keyNodeEntryOrPredicate.key;
1353
+ } else if (Array.isArray(keyNodeEntryOrPredicate)) {
1354
+ key = keyNodeEntryOrPredicate[0] ?? undefined;
1355
+ if (key === undefined || key === null) return -1;
1356
+ } else {
1357
+ key = keyNodeEntryOrPredicate as K;
1358
+ }
1359
+
1360
+ if (key === undefined) return -1;
1361
+
1362
+ return actualIterationType === 'RECURSIVE'
1363
+ ? this._getRankRecursive(this._root, key)
1364
+ : this._getRankIterative(this._root, key);
1365
+ }
1366
+
1367
+ /**
1368
+ * Returns elements by position range in tree order (0-indexed, inclusive on both ends).
1369
+ * @remarks Time O(log n + k), Space O(k), where k = end - start + 1. Requires `enableOrderStatistic: true`.
1370
+ *
1371
+ * @param start - Start position (inclusive, 0-indexed). Clamped to 0 if negative.
1372
+ * @param end - End position (inclusive, 0-indexed). Clamped to size-1 if too large.
1373
+ * @returns Array of keys in tree order within the specified range.
1374
+ */
1375
+ rangeByRank(start: number, end: number): (K | undefined)[];
1376
+
1377
+ /**
1378
+ * Returns elements by position range in tree order with callback and optional iteration type.
1379
+ * @remarks Time O(log n + k), Space O(k), where k = end - start + 1. Requires `enableOrderStatistic: true`.
1380
+ *
1381
+ * @param start - Start rank (inclusive, 0-indexed).
1382
+ * @param end - End rank (inclusive, 0-indexed).
1383
+ * @param callback - Callback to apply to each node in the range.
1384
+ * @param iterationType - Iteration strategy ('ITERATIVE' or 'RECURSIVE').
1385
+ * @returns Array of callback results for nodes in the rank range.
1386
+ */
1387
+ rangeByRank<C extends NodeCallback<BSTNode<K, V>>>(
1388
+ start: number,
1389
+ end: number,
1390
+ callback: C,
1391
+ iterationType?: IterationType
1392
+ ): ReturnType<C>[];
1393
+
1394
+ rangeByRank<C extends NodeCallback<BSTNode<K, V>>>(
1395
+ start: number,
1396
+ end: number,
1397
+ callback: C = this._DEFAULT_NODE_CALLBACK as C,
1398
+ iterationType: IterationType = this.iterationType
1399
+ ): (K | undefined)[] | ReturnType<C>[] {
1400
+ if (!this._enableOrderStatistic) {
1401
+ raise(Error, ERR.orderStatisticNotEnabled('rangeByRank'));
1402
+ }
1403
+ if (this._size === 0) return [];
1404
+
1405
+ // Clamp
1406
+ const lo = Math.max(0, start);
1407
+ const hi = Math.min(this._size - 1, end);
1408
+ if (lo > hi) return [];
1409
+
1410
+ let actualCallback: C | undefined = undefined;
1411
+ let actualIterationType: IterationType = this.iterationType;
1412
+
1413
+ if (typeof callback === 'string') {
1414
+ actualIterationType = callback;
1415
+ } else if (callback) {
1416
+ actualCallback = callback;
1417
+ if (iterationType) {
1418
+ actualIterationType = iterationType;
1419
+ }
1420
+ }
1421
+
1422
+ const results: (K | undefined | ReturnType<C>)[] = [];
1423
+ const count = hi - lo + 1;
1424
+
1425
+ // Find the lo-th node, then in-order traverse count nodes
1426
+ const startNode = actualIterationType === 'RECURSIVE'
1427
+ ? this._getByRankRecursive(this._root, lo)
1428
+ : this._getByRankIterative(this._root, lo);
1429
+
1430
+ if (!startNode) return [];
1431
+
1432
+ // In-order traversal from startNode collecting count elements
1433
+ let collected = 0;
1434
+ const cb = actualCallback ?? this._DEFAULT_NODE_CALLBACK as C;
1435
+
1436
+ // Use higher() to iterate — it's already O(log n) amortized per step
1437
+ let current: BSTNode<K, V> | undefined = startNode;
1438
+ while (current && collected < count) {
1439
+ results.push(cb(current));
1440
+ collected++;
1441
+ if (collected < count) {
1442
+ // Find next in-order node
1443
+ current = this._next(current);
1444
+ }
1445
+ }
1446
+
1447
+ return results as (K | undefined)[] | ReturnType<C>[];
1448
+ }
1449
+
1143
1450
  /**
1144
1451
  * Adds a new node to the BST based on key comparison.
1145
1452
  * @remarks Time O(log N), where H is tree height. O(N) worst-case (unbalanced tree), O(log N) average. Space O(1).
@@ -1214,6 +1521,27 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1214
1521
 
1215
1522
 
1216
1523
 
1524
+
1525
+
1526
+
1527
+
1528
+
1529
+
1530
+
1531
+
1532
+
1533
+
1534
+
1535
+
1536
+
1537
+
1538
+
1539
+
1540
+
1541
+
1542
+
1543
+
1544
+
1217
1545
 
1218
1546
 
1219
1547
 
@@ -1253,6 +1581,7 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1253
1581
  this._setRoot(newNode);
1254
1582
  if (this._isMapMode && this.isRealNode(newNode)) this._store.set(newNode.key, newNode);
1255
1583
  this._size++;
1584
+ this._updateCount(newNode);
1256
1585
  return true;
1257
1586
  }
1258
1587
 
@@ -1269,6 +1598,7 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1269
1598
  current.left = newNode;
1270
1599
  if (this._isMapMode && this.isRealNode(newNode)) this._store.set(newNode.key, newNode);
1271
1600
  this._size++;
1601
+ this._updateCountAlongPath(newNode);
1272
1602
  return true;
1273
1603
  }
1274
1604
  if (current.left !== null) current = current.left;
@@ -1278,6 +1608,7 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1278
1608
  current.right = newNode;
1279
1609
  if (this._isMapMode && this.isRealNode(newNode)) this._store.set(newNode.key, newNode);
1280
1610
  this._size++;
1611
+ this._updateCountAlongPath(newNode);
1281
1612
  return true;
1282
1613
  }
1283
1614
  if (current.right !== null) current = current.right;
@@ -1336,6 +1667,20 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1336
1667
 
1337
1668
 
1338
1669
 
1670
+
1671
+
1672
+
1673
+
1674
+
1675
+
1676
+
1677
+
1678
+
1679
+
1680
+
1681
+
1682
+
1683
+
1339
1684
 
1340
1685
 
1341
1686
 
@@ -1479,6 +1824,13 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1479
1824
 
1480
1825
 
1481
1826
 
1827
+
1828
+
1829
+
1830
+
1831
+
1832
+
1833
+
1482
1834
 
1483
1835
 
1484
1836
 
@@ -1582,6 +1934,13 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1582
1934
 
1583
1935
 
1584
1936
 
1937
+
1938
+
1939
+
1940
+
1941
+
1942
+
1943
+
1585
1944
 
1586
1945
 
1587
1946
 
@@ -1684,6 +2043,13 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1684
2043
 
1685
2044
 
1686
2045
 
2046
+
2047
+
2048
+
2049
+
2050
+
2051
+
2052
+
1687
2053
 
1688
2054
 
1689
2055
 
@@ -1830,6 +2196,13 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1830
2196
 
1831
2197
 
1832
2198
 
2199
+
2200
+
2201
+
2202
+
2203
+
2204
+
2205
+
1833
2206
 
1834
2207
 
1835
2208
 
@@ -2032,6 +2405,13 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
2032
2405
 
2033
2406
 
2034
2407
 
2408
+
2409
+
2410
+
2411
+
2412
+
2413
+
2414
+
2035
2415
 
2036
2416
 
2037
2417
 
@@ -2102,6 +2482,13 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
2102
2482
 
2103
2483
 
2104
2484
 
2485
+
2486
+
2487
+
2488
+
2489
+
2490
+
2491
+
2105
2492
 
2106
2493
 
2107
2494
 
@@ -2217,6 +2604,20 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
2217
2604
 
2218
2605
 
2219
2606
 
2607
+
2608
+
2609
+
2610
+
2611
+
2612
+
2613
+
2614
+
2615
+
2616
+
2617
+
2618
+
2619
+
2620
+
2220
2621
 
2221
2622
 
2222
2623
 
@@ -2300,16 +2701,15 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
2300
2701
  onlyOne = false,
2301
2702
  startNode: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
2302
2703
  iterationType: IterationType = this.iterationType
2303
- ): BinaryTreeDeleteResult<BSTNode<K, V>>[] {
2704
+ ): boolean {
2304
2705
  const toDelete = this.search(keyNodeEntryOrPredicate, onlyOne, node => node, startNode, iterationType);
2305
2706
 
2306
- let results: BinaryTreeDeleteResult<BSTNode<K, V>>[] = [];
2707
+ let deleted = false;
2307
2708
  for (const node of toDelete) {
2308
- const deleteInfo = this.delete(node);
2309
- results = results.concat(deleteInfo);
2709
+ if (this.delete(node)) deleted = true;
2310
2710
  }
2311
2711
 
2312
- return results;
2712
+ return deleted;
2313
2713
  }
2314
2714
 
2315
2715
  /**
@@ -2331,15 +2731,13 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
2331
2731
  if (a instanceof Date && b instanceof Date) {
2332
2732
  const ta = a.getTime();
2333
2733
  const tb = b.getTime();
2334
- if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate('BST'));
2734
+ if (Number.isNaN(ta) || Number.isNaN(tb)) raise(TypeError, ERR.invalidDate('BST'));
2335
2735
  return ta > tb ? 1 : ta < tb ? -1 : 0;
2336
2736
  }
2337
2737
 
2338
2738
  // If keys are objects and no comparator is provided, throw an error
2339
2739
  if (typeof a === 'object' || typeof b === 'object') {
2340
- throw new TypeError(
2341
- ERR.comparatorRequired('BST')
2342
- );
2740
+ raise(TypeError, ERR.comparatorRequired('BST'));
2343
2741
  }
2344
2742
 
2345
2743
  // Default: keys are equal (fallback case)
@@ -2804,7 +3202,8 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
2804
3202
  protected override _snapshotOptions<TK = K, TV = V, TR = R>(): BSTOptions<TK, TV, TR> {
2805
3203
  return {
2806
3204
  ...super._snapshotOptions<TK, TV, TR>(),
2807
- comparator: this._comparator as unknown as BSTOptions<TK, TV, TR>['comparator']
3205
+ comparator: this._comparator as unknown as BSTOptions<TK, TV, TR>['comparator'],
3206
+ enableOrderStatistic: this._enableOrderStatistic
2808
3207
  };
2809
3208
  }
2810
3209
 
@@ -2831,6 +3230,129 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
2831
3230
  *
2832
3231
  * @param v - The node to set as root.
2833
3232
  */
3233
+ /**
3234
+ * (Protected) Recalculates the subtree count for a single node.
3235
+ * @remarks Time O(1). Only active when enableOrderStatistic is true.
3236
+ */
3237
+ protected _updateCount(node: BSTNode<K, V>): void {
3238
+ if (!this._enableOrderStatistic) return;
3239
+ node._count = 1
3240
+ + (this.isRealNode(node.left) ? node.left._count : 0)
3241
+ + (this.isRealNode(node.right) ? node.right._count : 0);
3242
+ }
3243
+
3244
+ /**
3245
+ * (Protected) Updates subtree counts from a node up to the root.
3246
+ * @remarks Time O(log n). Only active when enableOrderStatistic is true.
3247
+ */
3248
+ protected _updateCountAlongPath(node: OptNode<BSTNode<K, V>>): void {
3249
+ if (!this._enableOrderStatistic) return;
3250
+ let current = node;
3251
+ while (current) {
3252
+ this._updateCount(current);
3253
+ current = current.parent as BSTNode<K, V> | undefined;
3254
+ }
3255
+ }
3256
+
3257
+ /**
3258
+ * (Protected) Finds the node at position k in tree order (iterative).
3259
+ * @remarks Time O(log n), Space O(1)
3260
+ */
3261
+ protected _getByRankIterative(node: OptNode<BSTNode<K, V>>, k: number): BSTNode<K, V> | undefined {
3262
+ let current = node;
3263
+ let remaining = k;
3264
+ while (current) {
3265
+ const leftCount = this.isRealNode(current.left) ? current.left._count : 0;
3266
+ if (remaining < leftCount) {
3267
+ current = current.left as BSTNode<K, V> | undefined;
3268
+ } else if (remaining === leftCount) {
3269
+ return current;
3270
+ } else {
3271
+ remaining = remaining - leftCount - 1;
3272
+ current = current.right as BSTNode<K, V> | undefined;
3273
+ }
3274
+ }
3275
+ return undefined;
3276
+ }
3277
+
3278
+ /**
3279
+ * (Protected) Finds the node at position k in tree order (recursive).
3280
+ * @remarks Time O(log n), Space O(log n) call stack
3281
+ */
3282
+ protected _getByRankRecursive(node: OptNode<BSTNode<K, V>>, k: number): BSTNode<K, V> | undefined {
3283
+ if (!node) return undefined;
3284
+ const leftCount = this.isRealNode(node.left) ? node.left._count : 0;
3285
+ if (k < leftCount) return this._getByRankRecursive(node.left as BSTNode<K, V> | undefined, k);
3286
+ if (k === leftCount) return node;
3287
+ return this._getByRankRecursive(node.right as BSTNode<K, V> | undefined, k - leftCount - 1);
3288
+ }
3289
+
3290
+ /**
3291
+ * (Protected) Computes the rank of a key iteratively.
3292
+ * @remarks Time O(log n), Space O(1)
3293
+ */
3294
+ protected _getRankIterative(node: OptNode<BSTNode<K, V>>, key: K): number {
3295
+ let rank = 0;
3296
+ let current = node;
3297
+ while (this.isRealNode(current)) {
3298
+ const cmp = this._compare(current.key, key);
3299
+ if (cmp > 0) {
3300
+ // key < current.key, go left
3301
+ current = current.left as BSTNode<K, V> | undefined;
3302
+ } else if (cmp < 0) {
3303
+ // key > current.key
3304
+ rank += (this.isRealNode(current.left) ? current.left._count : 0) + 1;
3305
+ current = current.right as BSTNode<K, V> | undefined;
3306
+ } else {
3307
+ // Found
3308
+ rank += this.isRealNode(current.left) ? current.left._count : 0;
3309
+ return rank;
3310
+ }
3311
+ }
3312
+ // Key not found, rank = insertion position
3313
+ return rank;
3314
+ }
3315
+
3316
+ /**
3317
+ * (Protected) Computes the rank of a key recursively.
3318
+ * @remarks Time O(log n), Space O(log n) call stack
3319
+ */
3320
+ protected _getRankRecursive(node: OptNode<BSTNode<K, V>>, key: K): number {
3321
+ if (!node) return 0;
3322
+ const cmp = this._compare(node.key, key);
3323
+ if (cmp > 0) {
3324
+ return this._getRankRecursive(node.left as BSTNode<K, V> | undefined, key);
3325
+ } else if (cmp < 0) {
3326
+ return (this.isRealNode(node.left) ? node.left._count : 0) + 1
3327
+ + this._getRankRecursive(node.right as BSTNode<K, V> | undefined, key);
3328
+ } else {
3329
+ return this.isRealNode(node.left) ? node.left._count : 0;
3330
+ }
3331
+ }
3332
+
3333
+ /**
3334
+ * (Protected) Finds the in-order successor of a node.
3335
+ * @remarks Time O(log n), Space O(1)
3336
+ */
3337
+ protected _next(node: BSTNode<K, V>): BSTNode<K, V> | undefined {
3338
+ if (this.isRealNode(node.right)) {
3339
+ // Leftmost in right subtree
3340
+ let current = node.right as BSTNode<K, V>;
3341
+ while (this.isRealNode(current.left)) {
3342
+ current = current.left as BSTNode<K, V>;
3343
+ }
3344
+ return current;
3345
+ }
3346
+ // Go up until we come from a left child
3347
+ let current: BSTNode<K, V> | undefined = node;
3348
+ let parent = current.parent as BSTNode<K, V> | undefined;
3349
+ while (parent && current === parent.right) {
3350
+ current = parent;
3351
+ parent = parent.parent as BSTNode<K, V> | undefined;
3352
+ }
3353
+ return parent;
3354
+ }
3355
+
2834
3356
  protected override _setRoot(v: OptNode<BSTNode<K, V>>) {
2835
3357
  if (v) v.parent = undefined;
2836
3358
  this._root = v;
@@ -2887,25 +3409,32 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
2887
3409
  };
2888
3410
 
2889
3411
  // 2. Perform deletion
3412
+ let countUpdateStart: BSTNode<K, V> | undefined;
2890
3413
  if (node.left === undefined) {
2891
3414
  // Case 1: No left child
3415
+ countUpdateStart = node.parent as BSTNode<K, V> | undefined;
2892
3416
  transplant(node, node.right as BSTNode<K, V> | undefined);
2893
3417
  } else if (node.right === undefined) {
2894
3418
  // Case 2: No right child
3419
+ countUpdateStart = node.parent as BSTNode<K, V> | undefined;
2895
3420
  transplant(node, node.left as BSTNode<K, V> | undefined);
2896
3421
  } else {
2897
3422
  // Case 3: Two children
2898
3423
  const succ = minNode(node.right as BSTNode<K, V> | undefined)!; // Find successor
2899
3424
  if (succ.parent !== node) {
3425
+ countUpdateStart = succ.parent as BSTNode<K, V> | undefined;
2900
3426
  transplant(succ, succ.right as BSTNode<K, V> | undefined);
2901
3427
  succ.right = node.right as BSTNode<K, V> | undefined;
2902
3428
  if (succ.right) (succ.right as BSTNode<K, V>).parent = succ;
3429
+ } else {
3430
+ countUpdateStart = succ;
2903
3431
  }
2904
3432
  transplant(node, succ);
2905
3433
  succ.left = node.left as BSTNode<K, V> | undefined;
2906
3434
  if (succ.left) (succ.left as BSTNode<K, V>).parent = succ;
2907
3435
  }
2908
3436
 
3437
+ this._updateCountAlongPath(countUpdateStart);
2909
3438
  this._size = Math.max(0, this._size - 1);
2910
3439
  return true;
2911
3440
  }