max-priority-queue-typed 2.5.1 → 2.5.2

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 (73) hide show
  1. package/dist/cjs/index.cjs +104 -55
  2. package/dist/cjs/index.cjs.map +1 -1
  3. package/dist/cjs-legacy/index.cjs +103 -54
  4. package/dist/cjs-legacy/index.cjs.map +1 -1
  5. package/dist/esm/index.mjs +104 -56
  6. package/dist/esm/index.mjs.map +1 -1
  7. package/dist/esm-legacy/index.mjs +103 -55
  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 +36 -0
  12. package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +42 -0
  13. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +77 -2
  14. package/dist/types/data-structures/binary-tree/bst.d.ts +171 -0
  15. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +57 -0
  16. package/dist/types/data-structures/binary-tree/segment-tree.d.ts +18 -0
  17. package/dist/types/data-structures/binary-tree/tree-map.d.ts +409 -0
  18. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +411 -6
  19. package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +339 -6
  20. package/dist/types/data-structures/binary-tree/tree-set.d.ts +391 -0
  21. package/dist/types/data-structures/graph/directed-graph.d.ts +30 -0
  22. package/dist/types/data-structures/graph/undirected-graph.d.ts +27 -0
  23. package/dist/types/data-structures/hash/hash-map.d.ts +33 -0
  24. package/dist/types/data-structures/heap/heap.d.ts +42 -0
  25. package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +51 -0
  26. package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +45 -0
  27. package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +54 -0
  28. package/dist/types/data-structures/matrix/matrix.d.ts +24 -0
  29. package/dist/types/data-structures/queue/deque.d.ts +45 -0
  30. package/dist/types/data-structures/queue/queue.d.ts +36 -0
  31. package/dist/types/data-structures/stack/stack.d.ts +30 -0
  32. package/dist/types/data-structures/trie/trie.d.ts +36 -0
  33. package/dist/types/types/data-structures/binary-tree/bst.d.ts +1 -0
  34. package/dist/types/types/data-structures/binary-tree/tree-map.d.ts +5 -0
  35. package/dist/types/types/data-structures/binary-tree/tree-multi-set.d.ts +4 -0
  36. package/dist/types/types/data-structures/binary-tree/tree-set.d.ts +4 -0
  37. package/dist/umd/max-priority-queue-typed.js +101 -53
  38. package/dist/umd/max-priority-queue-typed.js.map +1 -1
  39. package/dist/umd/max-priority-queue-typed.min.js +1 -1
  40. package/dist/umd/max-priority-queue-typed.min.js.map +1 -1
  41. package/package.json +2 -2
  42. package/src/common/error.ts +19 -1
  43. package/src/common/index.ts +1 -1
  44. package/src/data-structures/base/iterable-element-base.ts +3 -2
  45. package/src/data-structures/binary-tree/avl-tree.ts +47 -0
  46. package/src/data-structures/binary-tree/binary-indexed-tree.ts +46 -4
  47. package/src/data-structures/binary-tree/binary-tree.ts +79 -4
  48. package/src/data-structures/binary-tree/bst.ts +441 -6
  49. package/src/data-structures/binary-tree/red-black-tree.ts +73 -0
  50. package/src/data-structures/binary-tree/segment-tree.ts +18 -0
  51. package/src/data-structures/binary-tree/tree-map.ts +434 -9
  52. package/src/data-structures/binary-tree/tree-multi-map.ts +426 -5
  53. package/src/data-structures/binary-tree/tree-multi-set.ts +350 -6
  54. package/src/data-structures/binary-tree/tree-set.ts +410 -8
  55. package/src/data-structures/graph/abstract-graph.ts +2 -2
  56. package/src/data-structures/graph/directed-graph.ts +30 -0
  57. package/src/data-structures/graph/undirected-graph.ts +27 -0
  58. package/src/data-structures/hash/hash-map.ts +35 -4
  59. package/src/data-structures/heap/heap.ts +46 -4
  60. package/src/data-structures/heap/max-heap.ts +2 -2
  61. package/src/data-structures/linked-list/doubly-linked-list.ts +51 -0
  62. package/src/data-structures/linked-list/singly-linked-list.ts +45 -0
  63. package/src/data-structures/linked-list/skip-linked-list.ts +59 -5
  64. package/src/data-structures/matrix/matrix.ts +33 -9
  65. package/src/data-structures/priority-queue/max-priority-queue.ts +2 -2
  66. package/src/data-structures/queue/deque.ts +45 -0
  67. package/src/data-structures/queue/queue.ts +36 -0
  68. package/src/data-structures/stack/stack.ts +30 -0
  69. package/src/data-structures/trie/trie.ts +38 -2
  70. package/src/types/data-structures/binary-tree/bst.ts +1 -0
  71. package/src/types/data-structures/binary-tree/tree-map.ts +6 -0
  72. package/src/types/data-structures/binary-tree/tree-multi-set.ts +5 -0
  73. package/src/types/data-structures/binary-tree/tree-set.ts +5 -0
@@ -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 { ERR, Range } from '../../common';
29
+ import { ERR, Range, raise } from '../../common';
30
30
 
31
31
  /**
32
32
  * Represents a Node in a Binary Search Tree.
@@ -345,6 +345,9 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
345
345
  } else {
346
346
  this._comparator = this._createDefaultComparator();
347
347
  }
348
+ if (options.enableOrderStatistic) {
349
+ this._enableOrderStatistic = true;
350
+ }
348
351
  } else {
349
352
  this._comparator = this._createDefaultComparator();
350
353
  }
@@ -354,6 +357,8 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
354
357
 
355
358
  protected override _root?: BSTNode<K, V> = undefined;
356
359
 
360
+ protected _enableOrderStatistic: boolean = false;
361
+
357
362
  /**
358
363
  * Gets the root node of the tree.
359
364
  * @remarks Time O(1)
@@ -491,6 +496,12 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
491
496
 
492
497
 
493
498
 
499
+
500
+
501
+
502
+
503
+
504
+
494
505
 
495
506
 
496
507
 
@@ -587,6 +598,12 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
587
598
 
588
599
 
589
600
 
601
+
602
+
603
+
604
+
605
+
606
+
590
607
 
591
608
 
592
609
 
@@ -679,6 +696,12 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
679
696
 
680
697
 
681
698
 
699
+
700
+
701
+
702
+
703
+
704
+
682
705
 
683
706
 
684
707
 
@@ -783,6 +806,12 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
783
806
 
784
807
 
785
808
 
809
+
810
+
811
+
812
+
813
+
814
+
786
815
 
787
816
 
788
817
 
@@ -906,6 +935,12 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
906
935
 
907
936
 
908
937
 
938
+
939
+
940
+
941
+
942
+
943
+
909
944
 
910
945
 
911
946
 
@@ -1101,6 +1136,9 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1101
1136
 
1102
1137
 
1103
1138
 
1139
+
1140
+
1141
+
1104
1142
 
1105
1143
 
1106
1144
 
@@ -1140,6 +1178,232 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1140
1178
  return this.search(searchRange, false, callback, startNode, iterationType);
1141
1179
  }
1142
1180
 
1181
+ // ─── Order-Statistic Methods ───────────────────────────
1182
+
1183
+ /**
1184
+ * Returns the element at the k-th position in tree order (0-indexed).
1185
+ * @remarks Time O(log n), Space O(1) iterative / O(log n) recursive. Requires `enableOrderStatistic: true`.
1186
+ * Tree order is defined by the comparator — ascending by default, but respects custom comparators (e.g. descending).
1187
+ *
1188
+ * @param k - The 0-based position in tree order (0 = first element).
1189
+ * @returns The key at position k, or `undefined` if out of bounds.
1190
+ * @example
1191
+ * // Order-statistic on BST
1192
+ * const tree = new BST<number>([30, 10, 50, 20, 40], { enableOrderStatistic: true });
1193
+ * console.log(tree.getByRank(0)); // 10;
1194
+ * console.log(tree.getByRank(4)); // 50;
1195
+ * console.log(tree.getRank(30)); // 2;
1196
+ */
1197
+ getByRank(k: number): K | undefined;
1198
+
1199
+ /**
1200
+ * Returns the element at the k-th position in tree order and applies a callback.
1201
+ * @remarks Time O(log n), Space O(1) iterative / O(log n) recursive. Requires `enableOrderStatistic: true`.
1202
+ *
1203
+ * @param k - The 0-based position in tree order (0 = first element).
1204
+ * @param callback - Callback to apply to the found node.
1205
+ * @param iterationType - Iteration strategy ('ITERATIVE' or 'RECURSIVE').
1206
+ * @returns The callback result, or `undefined` if out of bounds.
1207
+ */
1208
+ getByRank<C extends NodeCallback<BSTNode<K, V>>>(
1209
+ k: number,
1210
+ callback: C,
1211
+ iterationType?: IterationType
1212
+ ): ReturnType<C> | undefined;
1213
+
1214
+ getByRank<C extends NodeCallback<BSTNode<K, V>>>(
1215
+ k: number,
1216
+ callback: C = this._DEFAULT_NODE_CALLBACK as C,
1217
+ iterationType: IterationType = this.iterationType
1218
+ ): K | undefined | ReturnType<C> | undefined {
1219
+ if (!this._enableOrderStatistic) {
1220
+ raise(Error, ERR.orderStatisticNotEnabled('getByRank'));
1221
+ }
1222
+ if (k < 0 || k >= this._size) return undefined;
1223
+
1224
+ let actualCallback: C | undefined = undefined;
1225
+ let actualIterationType: IterationType = this.iterationType;
1226
+
1227
+ if (typeof callback === 'string') {
1228
+ actualIterationType = callback;
1229
+ } else if (callback) {
1230
+ actualCallback = callback;
1231
+ if (iterationType) {
1232
+ actualIterationType = iterationType;
1233
+ }
1234
+ }
1235
+
1236
+ const node = actualIterationType === 'RECURSIVE'
1237
+ ? this._getByRankRecursive(this._root, k)
1238
+ : this._getByRankIterative(this._root, k);
1239
+
1240
+ if (!node) return undefined;
1241
+ return actualCallback ? actualCallback(node) : node.key;
1242
+ }
1243
+
1244
+ /**
1245
+ * Returns the 0-based rank of a key (number of elements that precede it in tree order).
1246
+ * @remarks Time O(log n), Space O(1) iterative / O(log n) recursive. Requires `enableOrderStatistic: true`.
1247
+ * Tree order is defined by the comparator. When the key is not found, returns the insertion position.
1248
+ *
1249
+ * @param keyNodeEntryOrPredicate - The key, node, entry `[K, V]`, or predicate to find.
1250
+ * @returns The rank (0-indexed), or -1 if the tree is empty or input is invalid.
1251
+ */
1252
+ getRank(
1253
+ keyNodeEntryOrPredicate:
1254
+ | K
1255
+ | BSTNode<K, V>
1256
+ | [K | null | undefined, V | undefined]
1257
+ | null
1258
+ | undefined
1259
+ | NodePredicate<BSTNode<K, V>>
1260
+ ): number;
1261
+
1262
+ /**
1263
+ * Returns the 0-based rank (number of preceding elements in tree order) with explicit iteration type.
1264
+ * @remarks Time O(log n), Space O(1) iterative / O(log n) recursive. Requires `enableOrderStatistic: true`.
1265
+ *
1266
+ * @param keyNodeEntryOrPredicate - The key, node, entry, or predicate to find.
1267
+ * @param iterationType - Iteration strategy ('ITERATIVE' or 'RECURSIVE').
1268
+ * @returns The rank (0-indexed), or -1 if the tree is empty or input is invalid.
1269
+ */
1270
+ getRank(
1271
+ keyNodeEntryOrPredicate:
1272
+ | K
1273
+ | BSTNode<K, V>
1274
+ | [K | null | undefined, V | undefined]
1275
+ | null
1276
+ | undefined
1277
+ | NodePredicate<BSTNode<K, V>>,
1278
+ iterationType: IterationType
1279
+ ): number;
1280
+
1281
+ getRank(
1282
+ keyNodeEntryOrPredicate:
1283
+ | K
1284
+ | BSTNode<K, V>
1285
+ | [K | null | undefined, V | undefined]
1286
+ | null
1287
+ | undefined
1288
+ | NodePredicate<BSTNode<K, V>>,
1289
+ iterationType: IterationType = this.iterationType
1290
+ ): number {
1291
+ if (!this._enableOrderStatistic) {
1292
+ raise(Error, ERR.orderStatisticNotEnabled('getRank'));
1293
+ }
1294
+ if (!this._root || this._size === 0) return -1;
1295
+
1296
+ let actualIterationType: IterationType = this.iterationType;
1297
+ if (iterationType) actualIterationType = iterationType;
1298
+
1299
+ // Resolve key from input
1300
+ let key: K | undefined;
1301
+ if (typeof keyNodeEntryOrPredicate === 'function') {
1302
+ // Predicate: find first matching node
1303
+ const results = this.search(keyNodeEntryOrPredicate as NodePredicate<BSTNode<K, V>>, true);
1304
+ if (results.length === 0 || results[0] === undefined) return -1;
1305
+ key = results[0];
1306
+ } else if (keyNodeEntryOrPredicate === null || keyNodeEntryOrPredicate === undefined) {
1307
+ return -1;
1308
+ } else if (this.isNode(keyNodeEntryOrPredicate)) {
1309
+ key = keyNodeEntryOrPredicate.key;
1310
+ } else if (Array.isArray(keyNodeEntryOrPredicate)) {
1311
+ key = keyNodeEntryOrPredicate[0] ?? undefined;
1312
+ if (key === undefined || key === null) return -1;
1313
+ } else {
1314
+ key = keyNodeEntryOrPredicate as K;
1315
+ }
1316
+
1317
+ if (key === undefined) return -1;
1318
+
1319
+ return actualIterationType === 'RECURSIVE'
1320
+ ? this._getRankRecursive(this._root, key)
1321
+ : this._getRankIterative(this._root, key);
1322
+ }
1323
+
1324
+ /**
1325
+ * Returns elements by position range in tree order (0-indexed, inclusive on both ends).
1326
+ * @remarks Time O(log n + k), Space O(k), where k = end - start + 1. Requires `enableOrderStatistic: true`.
1327
+ *
1328
+ * @param start - Start position (inclusive, 0-indexed). Clamped to 0 if negative.
1329
+ * @param end - End position (inclusive, 0-indexed). Clamped to size-1 if too large.
1330
+ * @returns Array of keys in tree order within the specified range.
1331
+ */
1332
+ rangeByRank(start: number, end: number): (K | undefined)[];
1333
+
1334
+ /**
1335
+ * Returns elements by position range in tree order with callback and optional iteration type.
1336
+ * @remarks Time O(log n + k), Space O(k), where k = end - start + 1. Requires `enableOrderStatistic: true`.
1337
+ *
1338
+ * @param start - Start rank (inclusive, 0-indexed).
1339
+ * @param end - End rank (inclusive, 0-indexed).
1340
+ * @param callback - Callback to apply to each node in the range.
1341
+ * @param iterationType - Iteration strategy ('ITERATIVE' or 'RECURSIVE').
1342
+ * @returns Array of callback results for nodes in the rank range.
1343
+ */
1344
+ rangeByRank<C extends NodeCallback<BSTNode<K, V>>>(
1345
+ start: number,
1346
+ end: number,
1347
+ callback: C,
1348
+ iterationType?: IterationType
1349
+ ): ReturnType<C>[];
1350
+
1351
+ rangeByRank<C extends NodeCallback<BSTNode<K, V>>>(
1352
+ start: number,
1353
+ end: number,
1354
+ callback: C = this._DEFAULT_NODE_CALLBACK as C,
1355
+ iterationType: IterationType = this.iterationType
1356
+ ): (K | undefined)[] | ReturnType<C>[] {
1357
+ if (!this._enableOrderStatistic) {
1358
+ raise(Error, ERR.orderStatisticNotEnabled('rangeByRank'));
1359
+ }
1360
+ if (this._size === 0) return [];
1361
+
1362
+ // Clamp
1363
+ const lo = Math.max(0, start);
1364
+ const hi = Math.min(this._size - 1, end);
1365
+ if (lo > hi) return [];
1366
+
1367
+ let actualCallback: C | undefined = undefined;
1368
+ let actualIterationType: IterationType = this.iterationType;
1369
+
1370
+ if (typeof callback === 'string') {
1371
+ actualIterationType = callback;
1372
+ } else if (callback) {
1373
+ actualCallback = callback;
1374
+ if (iterationType) {
1375
+ actualIterationType = iterationType;
1376
+ }
1377
+ }
1378
+
1379
+ const results: (K | undefined | ReturnType<C>)[] = [];
1380
+ const count = hi - lo + 1;
1381
+
1382
+ // Find the lo-th node, then in-order traverse count nodes
1383
+ const startNode = actualIterationType === 'RECURSIVE'
1384
+ ? this._getByRankRecursive(this._root, lo)
1385
+ : this._getByRankIterative(this._root, lo);
1386
+
1387
+ if (!startNode) return [];
1388
+
1389
+ // In-order traversal from startNode collecting count elements
1390
+ let collected = 0;
1391
+ const cb = actualCallback ?? this._DEFAULT_NODE_CALLBACK as C;
1392
+
1393
+ // Use higher() to iterate — it's already O(log n) amortized per step
1394
+ let current: BSTNode<K, V> | undefined = startNode;
1395
+ while (current && collected < count) {
1396
+ results.push(cb(current));
1397
+ collected++;
1398
+ if (collected < count) {
1399
+ // Find next in-order node
1400
+ current = this._next(current);
1401
+ }
1402
+ }
1403
+
1404
+ return results as (K | undefined)[] | ReturnType<C>[];
1405
+ }
1406
+
1143
1407
  /**
1144
1408
  * Adds a new node to the BST based on key comparison.
1145
1409
  * @remarks Time O(log N), where H is tree height. O(N) worst-case (unbalanced tree), O(log N) average. Space O(1).
@@ -1225,6 +1489,15 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1225
1489
 
1226
1490
 
1227
1491
 
1492
+
1493
+
1494
+
1495
+
1496
+
1497
+
1498
+
1499
+
1500
+
1228
1501
 
1229
1502
 
1230
1503
 
@@ -1253,6 +1526,7 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1253
1526
  this._setRoot(newNode);
1254
1527
  if (this._isMapMode && this.isRealNode(newNode)) this._store.set(newNode.key, newNode);
1255
1528
  this._size++;
1529
+ this._updateCount(newNode);
1256
1530
  return true;
1257
1531
  }
1258
1532
 
@@ -1269,6 +1543,7 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1269
1543
  current.left = newNode;
1270
1544
  if (this._isMapMode && this.isRealNode(newNode)) this._store.set(newNode.key, newNode);
1271
1545
  this._size++;
1546
+ this._updateCountAlongPath(newNode);
1272
1547
  return true;
1273
1548
  }
1274
1549
  if (current.left !== null) current = current.left;
@@ -1278,6 +1553,7 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1278
1553
  current.right = newNode;
1279
1554
  if (this._isMapMode && this.isRealNode(newNode)) this._store.set(newNode.key, newNode);
1280
1555
  this._size++;
1556
+ this._updateCountAlongPath(newNode);
1281
1557
  return true;
1282
1558
  }
1283
1559
  if (current.right !== null) current = current.right;
@@ -1344,6 +1620,12 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1344
1620
 
1345
1621
 
1346
1622
 
1623
+
1624
+
1625
+
1626
+
1627
+
1628
+
1347
1629
 
1348
1630
 
1349
1631
 
@@ -1483,6 +1765,9 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1483
1765
 
1484
1766
 
1485
1767
 
1768
+
1769
+
1770
+
1486
1771
 
1487
1772
 
1488
1773
 
@@ -1586,6 +1871,9 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1586
1871
 
1587
1872
 
1588
1873
 
1874
+
1875
+
1876
+
1589
1877
 
1590
1878
 
1591
1879
 
@@ -1688,6 +1976,9 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1688
1976
 
1689
1977
 
1690
1978
 
1979
+
1980
+
1981
+
1691
1982
 
1692
1983
 
1693
1984
 
@@ -1834,6 +2125,9 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
1834
2125
 
1835
2126
 
1836
2127
 
2128
+
2129
+
2130
+
1837
2131
 
1838
2132
 
1839
2133
 
@@ -2036,6 +2330,9 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
2036
2330
 
2037
2331
 
2038
2332
 
2333
+
2334
+
2335
+
2039
2336
 
2040
2337
 
2041
2338
 
@@ -2106,6 +2403,9 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
2106
2403
 
2107
2404
 
2108
2405
 
2406
+
2407
+
2408
+
2109
2409
 
2110
2410
 
2111
2411
 
@@ -2225,6 +2525,12 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
2225
2525
 
2226
2526
 
2227
2527
 
2528
+
2529
+
2530
+
2531
+
2532
+
2533
+
2228
2534
 
2229
2535
 
2230
2536
 
@@ -2331,15 +2637,13 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
2331
2637
  if (a instanceof Date && b instanceof Date) {
2332
2638
  const ta = a.getTime();
2333
2639
  const tb = b.getTime();
2334
- if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate('BST'));
2640
+ if (Number.isNaN(ta) || Number.isNaN(tb)) raise(TypeError, ERR.invalidDate('BST'));
2335
2641
  return ta > tb ? 1 : ta < tb ? -1 : 0;
2336
2642
  }
2337
2643
 
2338
2644
  // If keys are objects and no comparator is provided, throw an error
2339
2645
  if (typeof a === 'object' || typeof b === 'object') {
2340
- throw new TypeError(
2341
- ERR.comparatorRequired('BST')
2342
- );
2646
+ raise(TypeError, ERR.comparatorRequired('BST'));
2343
2647
  }
2344
2648
 
2345
2649
  // Default: keys are equal (fallback case)
@@ -2804,7 +3108,8 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
2804
3108
  protected override _snapshotOptions<TK = K, TV = V, TR = R>(): BSTOptions<TK, TV, TR> {
2805
3109
  return {
2806
3110
  ...super._snapshotOptions<TK, TV, TR>(),
2807
- comparator: this._comparator as unknown as BSTOptions<TK, TV, TR>['comparator']
3111
+ comparator: this._comparator as unknown as BSTOptions<TK, TV, TR>['comparator'],
3112
+ enableOrderStatistic: this._enableOrderStatistic
2808
3113
  };
2809
3114
  }
2810
3115
 
@@ -2831,6 +3136,129 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
2831
3136
  *
2832
3137
  * @param v - The node to set as root.
2833
3138
  */
3139
+ /**
3140
+ * (Protected) Recalculates the subtree count for a single node.
3141
+ * @remarks Time O(1). Only active when enableOrderStatistic is true.
3142
+ */
3143
+ protected _updateCount(node: BSTNode<K, V>): void {
3144
+ if (!this._enableOrderStatistic) return;
3145
+ node._count = 1
3146
+ + (this.isRealNode(node.left) ? node.left._count : 0)
3147
+ + (this.isRealNode(node.right) ? node.right._count : 0);
3148
+ }
3149
+
3150
+ /**
3151
+ * (Protected) Updates subtree counts from a node up to the root.
3152
+ * @remarks Time O(log n). Only active when enableOrderStatistic is true.
3153
+ */
3154
+ protected _updateCountAlongPath(node: OptNode<BSTNode<K, V>>): void {
3155
+ if (!this._enableOrderStatistic) return;
3156
+ let current = node;
3157
+ while (current) {
3158
+ this._updateCount(current);
3159
+ current = current.parent as BSTNode<K, V> | undefined;
3160
+ }
3161
+ }
3162
+
3163
+ /**
3164
+ * (Protected) Finds the node at position k in tree order (iterative).
3165
+ * @remarks Time O(log n), Space O(1)
3166
+ */
3167
+ protected _getByRankIterative(node: OptNode<BSTNode<K, V>>, k: number): BSTNode<K, V> | undefined {
3168
+ let current = node;
3169
+ let remaining = k;
3170
+ while (current) {
3171
+ const leftCount = this.isRealNode(current.left) ? current.left._count : 0;
3172
+ if (remaining < leftCount) {
3173
+ current = current.left as BSTNode<K, V> | undefined;
3174
+ } else if (remaining === leftCount) {
3175
+ return current;
3176
+ } else {
3177
+ remaining = remaining - leftCount - 1;
3178
+ current = current.right as BSTNode<K, V> | undefined;
3179
+ }
3180
+ }
3181
+ return undefined;
3182
+ }
3183
+
3184
+ /**
3185
+ * (Protected) Finds the node at position k in tree order (recursive).
3186
+ * @remarks Time O(log n), Space O(log n) call stack
3187
+ */
3188
+ protected _getByRankRecursive(node: OptNode<BSTNode<K, V>>, k: number): BSTNode<K, V> | undefined {
3189
+ if (!node) return undefined;
3190
+ const leftCount = this.isRealNode(node.left) ? node.left._count : 0;
3191
+ if (k < leftCount) return this._getByRankRecursive(node.left as BSTNode<K, V> | undefined, k);
3192
+ if (k === leftCount) return node;
3193
+ return this._getByRankRecursive(node.right as BSTNode<K, V> | undefined, k - leftCount - 1);
3194
+ }
3195
+
3196
+ /**
3197
+ * (Protected) Computes the rank of a key iteratively.
3198
+ * @remarks Time O(log n), Space O(1)
3199
+ */
3200
+ protected _getRankIterative(node: OptNode<BSTNode<K, V>>, key: K): number {
3201
+ let rank = 0;
3202
+ let current = node;
3203
+ while (this.isRealNode(current)) {
3204
+ const cmp = this._compare(current.key, key);
3205
+ if (cmp > 0) {
3206
+ // key < current.key, go left
3207
+ current = current.left as BSTNode<K, V> | undefined;
3208
+ } else if (cmp < 0) {
3209
+ // key > current.key
3210
+ rank += (this.isRealNode(current.left) ? current.left._count : 0) + 1;
3211
+ current = current.right as BSTNode<K, V> | undefined;
3212
+ } else {
3213
+ // Found
3214
+ rank += this.isRealNode(current.left) ? current.left._count : 0;
3215
+ return rank;
3216
+ }
3217
+ }
3218
+ // Key not found, rank = insertion position
3219
+ return rank;
3220
+ }
3221
+
3222
+ /**
3223
+ * (Protected) Computes the rank of a key recursively.
3224
+ * @remarks Time O(log n), Space O(log n) call stack
3225
+ */
3226
+ protected _getRankRecursive(node: OptNode<BSTNode<K, V>>, key: K): number {
3227
+ if (!node) return 0;
3228
+ const cmp = this._compare(node.key, key);
3229
+ if (cmp > 0) {
3230
+ return this._getRankRecursive(node.left as BSTNode<K, V> | undefined, key);
3231
+ } else if (cmp < 0) {
3232
+ return (this.isRealNode(node.left) ? node.left._count : 0) + 1
3233
+ + this._getRankRecursive(node.right as BSTNode<K, V> | undefined, key);
3234
+ } else {
3235
+ return this.isRealNode(node.left) ? node.left._count : 0;
3236
+ }
3237
+ }
3238
+
3239
+ /**
3240
+ * (Protected) Finds the in-order successor of a node.
3241
+ * @remarks Time O(log n), Space O(1)
3242
+ */
3243
+ protected _next(node: BSTNode<K, V>): BSTNode<K, V> | undefined {
3244
+ if (this.isRealNode(node.right)) {
3245
+ // Leftmost in right subtree
3246
+ let current = node.right as BSTNode<K, V>;
3247
+ while (this.isRealNode(current.left)) {
3248
+ current = current.left as BSTNode<K, V>;
3249
+ }
3250
+ return current;
3251
+ }
3252
+ // Go up until we come from a left child
3253
+ let current: BSTNode<K, V> | undefined = node;
3254
+ let parent = current.parent as BSTNode<K, V> | undefined;
3255
+ while (parent && current === parent.right) {
3256
+ current = parent;
3257
+ parent = parent.parent as BSTNode<K, V> | undefined;
3258
+ }
3259
+ return parent;
3260
+ }
3261
+
2834
3262
  protected override _setRoot(v: OptNode<BSTNode<K, V>>) {
2835
3263
  if (v) v.parent = undefined;
2836
3264
  this._root = v;
@@ -2887,25 +3315,32 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
2887
3315
  };
2888
3316
 
2889
3317
  // 2. Perform deletion
3318
+ let countUpdateStart: BSTNode<K, V> | undefined;
2890
3319
  if (node.left === undefined) {
2891
3320
  // Case 1: No left child
3321
+ countUpdateStart = node.parent as BSTNode<K, V> | undefined;
2892
3322
  transplant(node, node.right as BSTNode<K, V> | undefined);
2893
3323
  } else if (node.right === undefined) {
2894
3324
  // Case 2: No right child
3325
+ countUpdateStart = node.parent as BSTNode<K, V> | undefined;
2895
3326
  transplant(node, node.left as BSTNode<K, V> | undefined);
2896
3327
  } else {
2897
3328
  // Case 3: Two children
2898
3329
  const succ = minNode(node.right as BSTNode<K, V> | undefined)!; // Find successor
2899
3330
  if (succ.parent !== node) {
3331
+ countUpdateStart = succ.parent as BSTNode<K, V> | undefined;
2900
3332
  transplant(succ, succ.right as BSTNode<K, V> | undefined);
2901
3333
  succ.right = node.right as BSTNode<K, V> | undefined;
2902
3334
  if (succ.right) (succ.right as BSTNode<K, V>).parent = succ;
3335
+ } else {
3336
+ countUpdateStart = succ;
2903
3337
  }
2904
3338
  transplant(node, succ);
2905
3339
  succ.left = node.left as BSTNode<K, V> | undefined;
2906
3340
  if (succ.left) (succ.left as BSTNode<K, V>).parent = succ;
2907
3341
  }
2908
3342
 
3343
+ this._updateCountAlongPath(countUpdateStart);
2909
3344
  this._size = Math.max(0, this._size - 1);
2910
3345
  return true;
2911
3346
  }