max-priority-queue-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.
- package/dist/cjs/index.cjs +207 -71
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs +206 -70
- package/dist/cjs-legacy/index.cjs.map +1 -1
- package/dist/esm/index.mjs +207 -72
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs +206 -71
- package/dist/esm-legacy/index.mjs.map +1 -1
- package/dist/types/common/error.d.ts +9 -0
- package/dist/types/common/index.d.ts +1 -1
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +86 -2
- package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +98 -0
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +189 -13
- package/dist/types/data-structures/binary-tree/bst.d.ts +270 -3
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +136 -8
- package/dist/types/data-structures/binary-tree/segment-tree.d.ts +42 -0
- package/dist/types/data-structures/binary-tree/tree-map.d.ts +1089 -161
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +1243 -350
- package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +980 -255
- package/dist/types/data-structures/binary-tree/tree-set.d.ts +1174 -284
- package/dist/types/data-structures/graph/directed-graph.d.ts +70 -0
- package/dist/types/data-structures/graph/undirected-graph.d.ts +63 -0
- package/dist/types/data-structures/hash/hash-map.d.ts +84 -6
- package/dist/types/data-structures/heap/heap.d.ts +140 -12
- package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +126 -0
- package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +106 -1
- package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +126 -0
- package/dist/types/data-structures/matrix/matrix.d.ts +56 -0
- package/dist/types/data-structures/queue/deque.d.ts +127 -0
- package/dist/types/data-structures/queue/queue.d.ts +97 -0
- package/dist/types/data-structures/stack/stack.d.ts +72 -2
- package/dist/types/data-structures/trie/trie.d.ts +84 -0
- package/dist/types/interfaces/binary-tree.d.ts +2 -3
- package/dist/types/types/data-structures/binary-tree/bst.d.ts +1 -0
- package/dist/types/types/data-structures/binary-tree/tree-map.d.ts +5 -0
- package/dist/types/types/data-structures/binary-tree/tree-multi-set.d.ts +4 -0
- package/dist/types/types/data-structures/binary-tree/tree-set.d.ts +4 -0
- package/dist/umd/max-priority-queue-typed.js +204 -69
- package/dist/umd/max-priority-queue-typed.js.map +1 -1
- package/dist/umd/max-priority-queue-typed.min.js +1 -1
- package/dist/umd/max-priority-queue-typed.min.js.map +1 -1
- package/package.json +2 -2
- package/src/common/error.ts +19 -1
- package/src/common/index.ts +1 -1
- package/src/data-structures/base/iterable-element-base.ts +3 -2
- package/src/data-structures/binary-tree/avl-tree.ts +99 -5
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +102 -4
- package/src/data-structures/binary-tree/binary-tree.ts +239 -78
- package/src/data-structures/binary-tree/bst.ts +542 -13
- package/src/data-structures/binary-tree/red-black-tree.ts +155 -15
- package/src/data-structures/binary-tree/segment-tree.ts +42 -0
- package/src/data-structures/binary-tree/tree-map.ts +1223 -261
- package/src/data-structures/binary-tree/tree-multi-map.ts +939 -30
- package/src/data-structures/binary-tree/tree-multi-set.ts +746 -10
- package/src/data-structures/binary-tree/tree-set.ts +1018 -99
- package/src/data-structures/graph/abstract-graph.ts +2 -2
- package/src/data-structures/graph/directed-graph.ts +71 -1
- package/src/data-structures/graph/undirected-graph.ts +64 -1
- package/src/data-structures/hash/hash-map.ts +102 -16
- package/src/data-structures/heap/heap.ts +153 -23
- package/src/data-structures/heap/max-heap.ts +2 -2
- package/src/data-structures/linked-list/doubly-linked-list.ts +139 -0
- package/src/data-structures/linked-list/singly-linked-list.ts +106 -1
- package/src/data-structures/linked-list/skip-linked-list.ts +131 -5
- package/src/data-structures/matrix/matrix.ts +65 -9
- package/src/data-structures/priority-queue/max-priority-queue.ts +2 -2
- package/src/data-structures/queue/deque.ts +130 -0
- package/src/data-structures/queue/queue.ts +109 -0
- package/src/data-structures/stack/stack.ts +75 -5
- package/src/data-structures/trie/trie.ts +86 -2
- package/src/interfaces/binary-tree.ts +1 -9
- package/src/types/data-structures/binary-tree/bst.ts +1 -0
- package/src/types/data-structures/binary-tree/tree-map.ts +6 -0
- package/src/types/data-structures/binary-tree/tree-multi-set.ts +5 -0
- 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
|
|
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
|
-
):
|
|
2704
|
+
): boolean {
|
|
2304
2705
|
const toDelete = this.search(keyNodeEntryOrPredicate, onlyOne, node => node, startNode, iterationType);
|
|
2305
2706
|
|
|
2306
|
-
let
|
|
2707
|
+
let deleted = false;
|
|
2307
2708
|
for (const node of toDelete) {
|
|
2308
|
-
|
|
2309
|
-
results = results.concat(deleteInfo);
|
|
2709
|
+
if (this.delete(node)) deleted = true;
|
|
2310
2710
|
}
|
|
2311
2711
|
|
|
2312
|
-
return
|
|
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))
|
|
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
|
-
|
|
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
|
}
|