data-structure-typed 2.4.4 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -1
- package/README.md +34 -1
- package/dist/cjs/index.cjs +10639 -2151
- package/dist/cjs-legacy/index.cjs +10694 -2195
- package/dist/esm/index.mjs +10639 -2150
- package/dist/esm-legacy/index.mjs +10694 -2194
- package/dist/types/common/error.d.ts +23 -0
- package/dist/types/common/index.d.ts +1 -0
- package/dist/types/data-structures/base/iterable-element-base.d.ts +1 -1
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +128 -51
- package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +210 -164
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +439 -78
- package/dist/types/data-structures/binary-tree/bst.d.ts +311 -28
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +217 -31
- package/dist/types/data-structures/binary-tree/segment-tree.d.ts +218 -152
- package/dist/types/data-structures/binary-tree/tree-map.d.ts +1281 -5
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +1087 -201
- package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +858 -65
- package/dist/types/data-structures/binary-tree/tree-set.d.ts +1133 -5
- package/dist/types/data-structures/graph/abstract-graph.d.ts +44 -0
- package/dist/types/data-structures/graph/directed-graph.d.ts +220 -47
- package/dist/types/data-structures/graph/map-graph.d.ts +59 -1
- package/dist/types/data-structures/graph/undirected-graph.d.ts +218 -59
- package/dist/types/data-structures/hash/hash-map.d.ts +230 -77
- package/dist/types/data-structures/heap/heap.d.ts +287 -99
- package/dist/types/data-structures/heap/max-heap.d.ts +46 -0
- package/dist/types/data-structures/heap/min-heap.d.ts +59 -0
- package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +286 -44
- package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +278 -65
- package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +415 -12
- package/dist/types/data-structures/matrix/matrix.d.ts +331 -0
- package/dist/types/data-structures/priority-queue/max-priority-queue.d.ts +57 -0
- package/dist/types/data-structures/priority-queue/min-priority-queue.d.ts +60 -0
- package/dist/types/data-structures/priority-queue/priority-queue.d.ts +60 -0
- package/dist/types/data-structures/queue/deque.d.ts +313 -66
- package/dist/types/data-structures/queue/queue.d.ts +211 -42
- package/dist/types/data-structures/stack/stack.d.ts +174 -32
- package/dist/types/data-structures/trie/trie.d.ts +213 -43
- package/dist/types/types/data-structures/binary-tree/segment-tree.d.ts +1 -1
- package/dist/types/types/data-structures/linked-list/skip-linked-list.d.ts +1 -4
- package/dist/types/types/data-structures/queue/deque.d.ts +6 -0
- package/dist/umd/data-structure-typed.js +10725 -2221
- package/dist/umd/data-structure-typed.min.js +4 -2
- package/package.json +5 -4
- package/src/common/error.ts +60 -0
- package/src/common/index.ts +2 -0
- package/src/data-structures/base/iterable-element-base.ts +2 -2
- package/src/data-structures/binary-tree/avl-tree.ts +146 -51
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +317 -247
- package/src/data-structures/binary-tree/binary-tree.ts +567 -121
- package/src/data-structures/binary-tree/bst.ts +370 -37
- package/src/data-structures/binary-tree/red-black-tree.ts +328 -96
- package/src/data-structures/binary-tree/segment-tree.ts +378 -248
- package/src/data-structures/binary-tree/tree-map.ts +1411 -13
- package/src/data-structures/binary-tree/tree-multi-map.ts +1218 -215
- package/src/data-structures/binary-tree/tree-multi-set.ts +959 -69
- package/src/data-structures/binary-tree/tree-set.ts +1257 -15
- package/src/data-structures/graph/abstract-graph.ts +106 -1
- package/src/data-structures/graph/directed-graph.ts +233 -47
- package/src/data-structures/graph/map-graph.ts +59 -1
- package/src/data-structures/graph/undirected-graph.ts +308 -59
- package/src/data-structures/hash/hash-map.ts +254 -79
- package/src/data-structures/heap/heap.ts +305 -102
- package/src/data-structures/heap/max-heap.ts +48 -3
- package/src/data-structures/heap/min-heap.ts +59 -0
- package/src/data-structures/linked-list/doubly-linked-list.ts +303 -44
- package/src/data-structures/linked-list/singly-linked-list.ts +293 -65
- package/src/data-structures/linked-list/skip-linked-list.ts +707 -90
- package/src/data-structures/matrix/matrix.ts +433 -22
- package/src/data-structures/priority-queue/max-priority-queue.ts +59 -3
- package/src/data-structures/priority-queue/min-priority-queue.ts +60 -0
- package/src/data-structures/priority-queue/priority-queue.ts +60 -0
- package/src/data-structures/queue/deque.ts +358 -68
- package/src/data-structures/queue/queue.ts +223 -42
- package/src/data-structures/stack/stack.ts +184 -32
- package/src/data-structures/trie/trie.ts +227 -44
- package/src/types/data-structures/binary-tree/segment-tree.ts +1 -1
- package/src/types/data-structures/linked-list/skip-linked-list.ts +2 -1
- package/src/types/data-structures/queue/deque.ts +7 -0
- package/src/utils/utils.ts +4 -2
|
@@ -26,7 +26,7 @@ import { BinaryTree } from './binary-tree';
|
|
|
26
26
|
import { IBinaryTree } from '../../interfaces';
|
|
27
27
|
import { Queue } from '../queue';
|
|
28
28
|
import { isComparable } from '../../utils';
|
|
29
|
-
import { Range } from '../../common';
|
|
29
|
+
import { ERR, Range } from '../../common';
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
32
|
* Represents a Node in a Binary Search Tree.
|
|
@@ -105,6 +105,7 @@ export class BSTNode<K = any, V = any> {
|
|
|
105
105
|
*
|
|
106
106
|
* @returns The height.
|
|
107
107
|
*/
|
|
108
|
+
/* istanbul ignore next -- covered by AVLTree/RedBlackTree tests (subclass uses height) */
|
|
108
109
|
get height(): number {
|
|
109
110
|
return this._height;
|
|
110
111
|
}
|
|
@@ -115,6 +116,7 @@ export class BSTNode<K = any, V = any> {
|
|
|
115
116
|
*
|
|
116
117
|
* @param value - The new height.
|
|
117
118
|
*/
|
|
119
|
+
/* istanbul ignore next -- covered by AVLTree/RedBlackTree tests (subclass uses height) */
|
|
118
120
|
set height(value: number) {
|
|
119
121
|
this._height = value;
|
|
120
122
|
}
|
|
@@ -127,6 +129,7 @@ export class BSTNode<K = any, V = any> {
|
|
|
127
129
|
*
|
|
128
130
|
* @returns The node's color.
|
|
129
131
|
*/
|
|
132
|
+
/* istanbul ignore next -- covered by RedBlackTree tests (subclass uses color) */
|
|
130
133
|
get color(): RBTNColor {
|
|
131
134
|
return this._color;
|
|
132
135
|
}
|
|
@@ -137,6 +140,7 @@ export class BSTNode<K = any, V = any> {
|
|
|
137
140
|
*
|
|
138
141
|
* @param value - The new color.
|
|
139
142
|
*/
|
|
143
|
+
/* istanbul ignore next -- covered by RedBlackTree tests (subclass uses color) */
|
|
140
144
|
set color(value: RBTNColor) {
|
|
141
145
|
this._color = value;
|
|
142
146
|
}
|
|
@@ -149,6 +153,7 @@ export class BSTNode<K = any, V = any> {
|
|
|
149
153
|
*
|
|
150
154
|
* @returns The subtree node count.
|
|
151
155
|
*/
|
|
156
|
+
/* istanbul ignore next -- internal field used by subclasses */
|
|
152
157
|
get count(): number {
|
|
153
158
|
return this._count;
|
|
154
159
|
}
|
|
@@ -159,6 +164,7 @@ export class BSTNode<K = any, V = any> {
|
|
|
159
164
|
*
|
|
160
165
|
* @param value - The new count.
|
|
161
166
|
*/
|
|
167
|
+
/* istanbul ignore next -- internal field used by subclasses */
|
|
162
168
|
set count(value: number) {
|
|
163
169
|
this._count = value;
|
|
164
170
|
}
|
|
@@ -200,34 +206,6 @@ export class BSTNode<K = any, V = any> {
|
|
|
200
206
|
* 7. No Auto-Balancing: Standard BSTs don't automatically balance themselves.
|
|
201
207
|
*
|
|
202
208
|
* @example
|
|
203
|
-
* // basic BST creation and add operation
|
|
204
|
-
* // Create a simple BST with numeric keys
|
|
205
|
-
* const bst = new BST<number>([11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]);
|
|
206
|
-
*
|
|
207
|
-
* // Keep the example output in source comments but avoid noisy test logs.
|
|
208
|
-
* await withMutedConsole(() => bst.print());
|
|
209
|
-
* // _______8__________
|
|
210
|
-
* // / \
|
|
211
|
-
* // ___4___ ____12_____
|
|
212
|
-
* // / \ / \
|
|
213
|
-
* // _2_ _6_ _10__ _14__
|
|
214
|
-
* // / \ / \ / \ / \
|
|
215
|
-
* // 1 3 5 7 9 11 13 15__
|
|
216
|
-
* // \
|
|
217
|
-
* // 16
|
|
218
|
-
*
|
|
219
|
-
* // Verify size
|
|
220
|
-
* console.log(bst.size); // 16;
|
|
221
|
-
*
|
|
222
|
-
* // Add new elements
|
|
223
|
-
* bst.set(17);
|
|
224
|
-
* bst.set(0);
|
|
225
|
-
* console.log(bst.size); // 18;
|
|
226
|
-
*
|
|
227
|
-
* // Verify keys are searchable
|
|
228
|
-
* console.log(bst.has(11)); // true;
|
|
229
|
-
* console.log(bst.has(100)); // false;
|
|
230
|
-
* @example
|
|
231
209
|
* // BST delete and search after deletion
|
|
232
210
|
* const bst = new BST<number>([11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]);
|
|
233
211
|
*
|
|
@@ -454,6 +432,38 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
454
432
|
return isComparable(key);
|
|
455
433
|
}
|
|
456
434
|
|
|
435
|
+
/**
|
|
436
|
+
* Depth-first search traversal
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
* @example
|
|
462
|
+
* // Depth-first traversal
|
|
463
|
+
* const bst = new BST<number>([5, 3, 7, 1, 4]);
|
|
464
|
+
* const inOrder = bst.dfs(node => node.key, 'IN');
|
|
465
|
+
* console.log(inOrder); // [1, 3, 4, 5, 7];
|
|
466
|
+
*/
|
|
457
467
|
override dfs(): (K | undefined)[];
|
|
458
468
|
|
|
459
469
|
override dfs<C extends NodeCallback<BSTNode<K, V>>>(
|
|
@@ -486,6 +496,30 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
486
496
|
return super.dfs(callback, pattern, onlyOne, startNode, iterationType);
|
|
487
497
|
}
|
|
488
498
|
|
|
499
|
+
/**
|
|
500
|
+
* BinaryTree level-order traversal
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
* @example
|
|
518
|
+
* // Breadth-first traversal
|
|
519
|
+
* const bst = new BST<number>([5, 3, 7]);
|
|
520
|
+
* const result = bst.bfs(node => node.key);
|
|
521
|
+
* console.log(result.length); // 3;
|
|
522
|
+
*/
|
|
489
523
|
override bfs(): (K | undefined)[];
|
|
490
524
|
override bfs<C extends NodeCallback<BSTNode<K, V>>>(
|
|
491
525
|
callback: C,
|
|
@@ -511,6 +545,36 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
511
545
|
return super.bfs(callback, startNode, iterationType, false);
|
|
512
546
|
}
|
|
513
547
|
|
|
548
|
+
/**
|
|
549
|
+
* Level-order grouping
|
|
550
|
+
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
|
|
563
|
+
|
|
564
|
+
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
|
|
568
|
+
|
|
569
|
+
* @example
|
|
570
|
+
* // Level-order grouping
|
|
571
|
+
* const bst = new BST<number>([5, 3, 7, 1, 4]);
|
|
572
|
+
* const levels = bst.listLevels(node => node.key);
|
|
573
|
+
* console.log(levels.length); // > 0;
|
|
574
|
+
* console.log(levels[0].length); // 1; // root level has 1 node
|
|
575
|
+
* const allKeys = levels.flat().sort((a, b) => a - b);
|
|
576
|
+
* console.log(allKeys); // [1, 3, 4, 5, 7];
|
|
577
|
+
*/
|
|
514
578
|
override listLevels(): (K | undefined)[][];
|
|
515
579
|
|
|
516
580
|
override listLevels<C extends NodeCallback<BSTNode<K, V>>>(
|
|
@@ -545,6 +609,33 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
545
609
|
* @param [startNode=this._root] - The node to start the search from.
|
|
546
610
|
* @param [iterationType=this.iterationType] - The traversal method.
|
|
547
611
|
* @returns The first matching node, or undefined if not found.
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
|
|
623
|
+
|
|
624
|
+
|
|
625
|
+
|
|
626
|
+
|
|
627
|
+
|
|
628
|
+
|
|
629
|
+
|
|
630
|
+
|
|
631
|
+
|
|
632
|
+
|
|
633
|
+
* @example
|
|
634
|
+
* // Get node object by key
|
|
635
|
+
* const bst = new BST<number, string>([[5, 'root'], [3, 'left'], [7, 'right']]);
|
|
636
|
+
* const node = bst.getNode(3);
|
|
637
|
+
* console.log(node?.key); // 3;
|
|
638
|
+
* console.log(node?.value); // 'left';
|
|
548
639
|
*/
|
|
549
640
|
override getNode(
|
|
550
641
|
keyNodeEntryOrPredicate:
|
|
@@ -606,6 +697,28 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
606
697
|
}
|
|
607
698
|
|
|
608
699
|
|
|
700
|
+
/**
|
|
701
|
+
* Search nodes by predicate
|
|
702
|
+
|
|
703
|
+
|
|
704
|
+
|
|
705
|
+
|
|
706
|
+
|
|
707
|
+
|
|
708
|
+
|
|
709
|
+
|
|
710
|
+
|
|
711
|
+
|
|
712
|
+
|
|
713
|
+
|
|
714
|
+
|
|
715
|
+
|
|
716
|
+
* @example
|
|
717
|
+
* // Search nodes by predicate
|
|
718
|
+
* const bst = new BST<number, string>([[1, 'a'], [2, 'b'], [3, 'c'], [4, 'd']]);
|
|
719
|
+
* const found = bst.search(node => node.key > 2, true);
|
|
720
|
+
* console.log(found.length); // >= 1;
|
|
721
|
+
*/
|
|
609
722
|
override search(
|
|
610
723
|
keyNodeEntryOrPredicate:
|
|
611
724
|
| K
|
|
@@ -699,6 +812,7 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
699
812
|
let predicate: NodePredicate<BSTNode<K, V>>;
|
|
700
813
|
if (isRange) {
|
|
701
814
|
predicate = node => {
|
|
815
|
+
/* istanbul ignore next -- node is always defined in iteration callbacks */
|
|
702
816
|
if (!node) return false;
|
|
703
817
|
return (keyNodeEntryOrPredicate).isInRange(node.key, this._comparator);
|
|
704
818
|
};
|
|
@@ -708,7 +822,7 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
708
822
|
|
|
709
823
|
// Optimization: Pruning logic
|
|
710
824
|
const shouldVisitLeft = (cur: BSTNode<K, V> | null | undefined) => {
|
|
711
|
-
if (!cur) return false;
|
|
825
|
+
/* istanbul ignore next -- defensive: cur is always defined when called from iteration */ if (!cur) return false;
|
|
712
826
|
if (!this.isRealNode(cur.left)) return false;
|
|
713
827
|
if (isRange) {
|
|
714
828
|
// Range search: Only go left if the current key is >= the lower bound
|
|
@@ -726,7 +840,7 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
726
840
|
};
|
|
727
841
|
|
|
728
842
|
const shouldVisitRight = (cur: BSTNode<K, V> | null | undefined) => {
|
|
729
|
-
if (!cur) return false;
|
|
843
|
+
/* istanbul ignore next -- defensive */ if (!cur) return false;
|
|
730
844
|
if (!this.isRealNode(cur.right)) return false;
|
|
731
845
|
if (isRange) {
|
|
732
846
|
// Range search: Only go right if current key <= upper bound
|
|
@@ -757,6 +871,25 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
757
871
|
);
|
|
758
872
|
}
|
|
759
873
|
|
|
874
|
+
/**
|
|
875
|
+
* Find all keys in a range
|
|
876
|
+
|
|
877
|
+
|
|
878
|
+
|
|
879
|
+
|
|
880
|
+
|
|
881
|
+
|
|
882
|
+
|
|
883
|
+
|
|
884
|
+
|
|
885
|
+
|
|
886
|
+
|
|
887
|
+
|
|
888
|
+
* @example
|
|
889
|
+
* // Find all keys in a range
|
|
890
|
+
* const bst = new BST<number>([10, 20, 30, 40, 50]);
|
|
891
|
+
* console.log(bst.rangeSearch([15, 35])); // [20, 30];
|
|
892
|
+
*/
|
|
760
893
|
rangeSearch(range: Range<K> | [K, K]): (K | undefined)[];
|
|
761
894
|
|
|
762
895
|
rangeSearch<C extends NodeCallback<BSTNode<K, V>>>(
|
|
@@ -794,6 +927,40 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
794
927
|
* @param keyNodeOrEntry - The key, node, or entry to set.
|
|
795
928
|
* @param [value] - The value, if providing just a key.
|
|
796
929
|
* @returns True if the addition was successful, false otherwise.
|
|
930
|
+
|
|
931
|
+
|
|
932
|
+
|
|
933
|
+
|
|
934
|
+
|
|
935
|
+
|
|
936
|
+
|
|
937
|
+
|
|
938
|
+
|
|
939
|
+
|
|
940
|
+
|
|
941
|
+
|
|
942
|
+
|
|
943
|
+
|
|
944
|
+
|
|
945
|
+
|
|
946
|
+
|
|
947
|
+
|
|
948
|
+
|
|
949
|
+
|
|
950
|
+
|
|
951
|
+
|
|
952
|
+
|
|
953
|
+
|
|
954
|
+
|
|
955
|
+
|
|
956
|
+
|
|
957
|
+
|
|
958
|
+
* @example
|
|
959
|
+
* // Set a key-value pair
|
|
960
|
+
* const bst = new BST<number, string>();
|
|
961
|
+
* bst.set(1, 'one');
|
|
962
|
+
* bst.set(2, 'two');
|
|
963
|
+
* console.log(bst.get(1)); // 'one';
|
|
797
964
|
*/
|
|
798
965
|
override set(
|
|
799
966
|
keyNodeOrEntry: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
|
|
@@ -836,6 +1003,7 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
836
1003
|
if (current.right !== null) current = current.right;
|
|
837
1004
|
}
|
|
838
1005
|
}
|
|
1006
|
+
/* istanbul ignore next -- defensive: traversal always finds undefined slot before exhausting tree */
|
|
839
1007
|
return false;
|
|
840
1008
|
}
|
|
841
1009
|
|
|
@@ -850,6 +1018,25 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
850
1018
|
* @param [isBalanceAdd=true] - If true, builds a balanced tree from the items.
|
|
851
1019
|
* @param [iterationType=this.iterationType] - The traversal method for balanced set (recursive or iterative).
|
|
852
1020
|
* @returns An array of booleans indicating the success of each individual `set` operation.
|
|
1021
|
+
|
|
1022
|
+
|
|
1023
|
+
|
|
1024
|
+
|
|
1025
|
+
|
|
1026
|
+
|
|
1027
|
+
|
|
1028
|
+
|
|
1029
|
+
|
|
1030
|
+
|
|
1031
|
+
|
|
1032
|
+
|
|
1033
|
+
|
|
1034
|
+
* @example
|
|
1035
|
+
* // Set multiple key-value pairs
|
|
1036
|
+
* const bst = new BST<number, string>();
|
|
1037
|
+
* bst.setMany([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
1038
|
+
* console.log(bst.size); // 3;
|
|
1039
|
+
* console.log(bst.get(2)); // 'b';
|
|
853
1040
|
*/
|
|
854
1041
|
override setMany(
|
|
855
1042
|
keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V, BSTNode<K, V>>>,
|
|
@@ -920,6 +1107,7 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
920
1107
|
const stack: Array<[number, number]> = [[0, n - 1]];
|
|
921
1108
|
while (stack.length > 0) {
|
|
922
1109
|
const popped = stack.pop();
|
|
1110
|
+
/* istanbul ignore next -- stack.pop() on non-empty stack always returns a value */
|
|
923
1111
|
if (!popped) continue;
|
|
924
1112
|
const [l, r] = popped;
|
|
925
1113
|
if (l > r) continue;
|
|
@@ -947,6 +1135,24 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
947
1135
|
* Equivalent to Java TreeMap.ceiling.
|
|
948
1136
|
* Time Complexity: O(log n) average, O(h) worst case.
|
|
949
1137
|
* Space Complexity: O(h) for recursion, O(1) for iteration.
|
|
1138
|
+
|
|
1139
|
+
|
|
1140
|
+
|
|
1141
|
+
|
|
1142
|
+
|
|
1143
|
+
|
|
1144
|
+
|
|
1145
|
+
|
|
1146
|
+
|
|
1147
|
+
|
|
1148
|
+
|
|
1149
|
+
|
|
1150
|
+
* @example
|
|
1151
|
+
* // Find the least key ≥ target
|
|
1152
|
+
* const bst = new BST<number>([10, 20, 30, 40, 50]);
|
|
1153
|
+
* console.log(bst.ceiling(25)); // 30;
|
|
1154
|
+
* console.log(bst.ceiling(30)); // 30;
|
|
1155
|
+
* console.log(bst.ceiling(55)); // undefined;
|
|
950
1156
|
*/
|
|
951
1157
|
ceiling(
|
|
952
1158
|
keyNodeEntryOrPredicate:
|
|
@@ -1012,6 +1218,23 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
1012
1218
|
* Equivalent to Java TreeMap.higher.
|
|
1013
1219
|
* Time Complexity: O(log n) average, O(h) worst case.
|
|
1014
1220
|
* Space Complexity: O(h) for recursion, O(1) for iteration.
|
|
1221
|
+
|
|
1222
|
+
|
|
1223
|
+
|
|
1224
|
+
|
|
1225
|
+
|
|
1226
|
+
|
|
1227
|
+
|
|
1228
|
+
|
|
1229
|
+
|
|
1230
|
+
|
|
1231
|
+
|
|
1232
|
+
|
|
1233
|
+
* @example
|
|
1234
|
+
* // Find the least key strictly > target
|
|
1235
|
+
* const bst = new BST<number>([10, 20, 30, 40]);
|
|
1236
|
+
* console.log(bst.higher(20)); // 30;
|
|
1237
|
+
* console.log(bst.higher(40)); // undefined;
|
|
1015
1238
|
*/
|
|
1016
1239
|
higher(
|
|
1017
1240
|
keyNodeEntryOrPredicate:
|
|
@@ -1077,6 +1300,24 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
1077
1300
|
* Equivalent to Java TreeMap.floor.
|
|
1078
1301
|
* Time Complexity: O(log n) average, O(h) worst case.
|
|
1079
1302
|
* Space Complexity: O(h) for recursion, O(1) for iteration.
|
|
1303
|
+
|
|
1304
|
+
|
|
1305
|
+
|
|
1306
|
+
|
|
1307
|
+
|
|
1308
|
+
|
|
1309
|
+
|
|
1310
|
+
|
|
1311
|
+
|
|
1312
|
+
|
|
1313
|
+
|
|
1314
|
+
|
|
1315
|
+
* @example
|
|
1316
|
+
* // Find the greatest key ≤ target
|
|
1317
|
+
* const bst = new BST<number>([10, 20, 30, 40, 50]);
|
|
1318
|
+
* console.log(bst.floor(25)); // 20;
|
|
1319
|
+
* console.log(bst.floor(10)); // 10;
|
|
1320
|
+
* console.log(bst.floor(5)); // undefined;
|
|
1080
1321
|
*/
|
|
1081
1322
|
floor(
|
|
1082
1323
|
keyNodeEntryOrPredicate:
|
|
@@ -1117,7 +1358,7 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
1117
1358
|
iterationType?: IterationType
|
|
1118
1359
|
): K | undefined | ReturnType<C> {
|
|
1119
1360
|
if (keyNodeEntryOrPredicate === null || keyNodeEntryOrPredicate === undefined) {
|
|
1120
|
-
if (typeof callback === 'string' || !callback) {
|
|
1361
|
+
/* istanbul ignore next */ if (typeof callback === 'string' || !callback) {
|
|
1121
1362
|
return undefined;
|
|
1122
1363
|
}
|
|
1123
1364
|
return undefined;
|
|
@@ -1151,7 +1392,7 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
1151
1392
|
} else if (this.isEntry(keyNodeEntryOrPredicate)) {
|
|
1152
1393
|
const key = keyNodeEntryOrPredicate[0];
|
|
1153
1394
|
if (key === null || key === undefined) {
|
|
1154
|
-
if (typeof callback === 'string' || !callback) {
|
|
1395
|
+
/* istanbul ignore next */ if (typeof callback === 'string' || !callback) {
|
|
1155
1396
|
return undefined;
|
|
1156
1397
|
}
|
|
1157
1398
|
return undefined;
|
|
@@ -1164,6 +1405,7 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
1164
1405
|
if (targetKey !== undefined) {
|
|
1165
1406
|
const node = this._floorByKey(targetKey, actualIterationType);
|
|
1166
1407
|
|
|
1408
|
+
/* istanbul ignore next */
|
|
1167
1409
|
if (!actualCallback) {
|
|
1168
1410
|
return node?.key;
|
|
1169
1411
|
}
|
|
@@ -1171,9 +1413,11 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
1171
1413
|
return node ? actualCallback(node) : undefined;
|
|
1172
1414
|
}
|
|
1173
1415
|
|
|
1416
|
+
/* istanbul ignore next -- targetKey is always defined if we reach here (null/undefined caught above) */
|
|
1174
1417
|
if (typeof callback === 'string' || !callback) {
|
|
1175
1418
|
return undefined;
|
|
1176
1419
|
}
|
|
1420
|
+
/* istanbul ignore next */
|
|
1177
1421
|
return undefined;
|
|
1178
1422
|
}
|
|
1179
1423
|
|
|
@@ -1182,6 +1426,23 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
1182
1426
|
* Equivalent to Java TreeMap.lower.
|
|
1183
1427
|
* Time Complexity: O(log n) average, O(h) worst case.
|
|
1184
1428
|
* Space Complexity: O(h) for recursion, O(1) for iteration.
|
|
1429
|
+
|
|
1430
|
+
|
|
1431
|
+
|
|
1432
|
+
|
|
1433
|
+
|
|
1434
|
+
|
|
1435
|
+
|
|
1436
|
+
|
|
1437
|
+
|
|
1438
|
+
|
|
1439
|
+
|
|
1440
|
+
|
|
1441
|
+
* @example
|
|
1442
|
+
* // Find the greatest key strictly < target
|
|
1443
|
+
* const bst = new BST<number>([10, 20, 30, 40]);
|
|
1444
|
+
* console.log(bst.lower(30)); // 20;
|
|
1445
|
+
* console.log(bst.lower(10)); // undefined;
|
|
1185
1446
|
*/
|
|
1186
1447
|
lower(
|
|
1187
1448
|
keyNodeEntryOrPredicate:
|
|
@@ -1222,9 +1483,10 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
1222
1483
|
iterationType?: IterationType
|
|
1223
1484
|
): K | undefined | ReturnType<C> {
|
|
1224
1485
|
if (keyNodeEntryOrPredicate === null || keyNodeEntryOrPredicate === undefined) {
|
|
1225
|
-
if (typeof callback === 'string' || !callback) {
|
|
1486
|
+
/* istanbul ignore next */ if (typeof callback === 'string' || !callback) {
|
|
1226
1487
|
return undefined;
|
|
1227
1488
|
}
|
|
1489
|
+
/* istanbul ignore next */
|
|
1228
1490
|
return undefined;
|
|
1229
1491
|
}
|
|
1230
1492
|
|
|
@@ -1256,9 +1518,10 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
1256
1518
|
} else if (this.isEntry(keyNodeEntryOrPredicate)) {
|
|
1257
1519
|
const key = keyNodeEntryOrPredicate[0];
|
|
1258
1520
|
if (key === null || key === undefined) {
|
|
1259
|
-
if (typeof callback === 'string' || !callback) {
|
|
1521
|
+
/* istanbul ignore next */ if (typeof callback === 'string' || !callback) {
|
|
1260
1522
|
return undefined;
|
|
1261
1523
|
}
|
|
1524
|
+
/* istanbul ignore next */
|
|
1262
1525
|
return undefined;
|
|
1263
1526
|
}
|
|
1264
1527
|
targetKey = key;
|
|
@@ -1276,9 +1539,11 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
1276
1539
|
return node ? actualCallback(node) : undefined;
|
|
1277
1540
|
}
|
|
1278
1541
|
|
|
1542
|
+
/* istanbul ignore next -- targetKey is always defined if we reach here (null/undefined caught above) */
|
|
1279
1543
|
if (typeof callback === 'string' || !callback) {
|
|
1280
1544
|
return undefined;
|
|
1281
1545
|
}
|
|
1546
|
+
/* istanbul ignore next */
|
|
1282
1547
|
return undefined;
|
|
1283
1548
|
}
|
|
1284
1549
|
|
|
@@ -1345,6 +1610,24 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
1345
1610
|
*
|
|
1346
1611
|
* @param [iterationType=this.iterationType] - The traversal method for the initial node export.
|
|
1347
1612
|
* @returns True if successful, false if the tree was empty.
|
|
1613
|
+
|
|
1614
|
+
|
|
1615
|
+
|
|
1616
|
+
|
|
1617
|
+
|
|
1618
|
+
|
|
1619
|
+
|
|
1620
|
+
|
|
1621
|
+
|
|
1622
|
+
|
|
1623
|
+
* @example
|
|
1624
|
+
* // Rebalance the tree
|
|
1625
|
+
* const bst = new BST<number>();
|
|
1626
|
+
* // Insert in sorted order (worst case for BST)
|
|
1627
|
+
* for (let i = 1; i <= 7; i++) bst.add(i);
|
|
1628
|
+
* console.log(bst.isAVLBalanced()); // false;
|
|
1629
|
+
* bst.perfectlyBalance();
|
|
1630
|
+
* console.log(bst.isAVLBalanced()); // true;
|
|
1348
1631
|
*/
|
|
1349
1632
|
perfectlyBalance(iterationType: IterationType = this.iterationType): boolean {
|
|
1350
1633
|
const nodes = this.dfs(node => node, 'IN', false, this._root, iterationType);
|
|
@@ -1377,6 +1660,20 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
1377
1660
|
*
|
|
1378
1661
|
* @param [iterationType=this.iterationType] - The traversal method.
|
|
1379
1662
|
* @returns True if the tree is AVL balanced, false otherwise.
|
|
1663
|
+
|
|
1664
|
+
|
|
1665
|
+
|
|
1666
|
+
|
|
1667
|
+
|
|
1668
|
+
|
|
1669
|
+
|
|
1670
|
+
|
|
1671
|
+
|
|
1672
|
+
|
|
1673
|
+
* @example
|
|
1674
|
+
* // Check if tree is height-balanced
|
|
1675
|
+
* const bst = new BST<number>([3, 1, 5, 2, 4]);
|
|
1676
|
+
* console.log(bst.isAVLBalanced()); // true;
|
|
1380
1677
|
*/
|
|
1381
1678
|
isAVLBalanced(iterationType: IterationType = this.iterationType): boolean {
|
|
1382
1679
|
if (!this._root) return true;
|
|
@@ -1434,6 +1731,32 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
1434
1731
|
* @param [options] - Options for the new BST.
|
|
1435
1732
|
* @param [thisArg] - `this` context for the callback.
|
|
1436
1733
|
* @returns A new, mapped BST.
|
|
1734
|
+
|
|
1735
|
+
|
|
1736
|
+
|
|
1737
|
+
|
|
1738
|
+
|
|
1739
|
+
|
|
1740
|
+
|
|
1741
|
+
|
|
1742
|
+
|
|
1743
|
+
|
|
1744
|
+
|
|
1745
|
+
|
|
1746
|
+
|
|
1747
|
+
|
|
1748
|
+
|
|
1749
|
+
|
|
1750
|
+
|
|
1751
|
+
|
|
1752
|
+
|
|
1753
|
+
|
|
1754
|
+
|
|
1755
|
+
* @example
|
|
1756
|
+
* // Transform to new tree
|
|
1757
|
+
* const bst = new BST<number, number>([[1, 10], [2, 20], [3, 30]]);
|
|
1758
|
+
* const doubled = bst.map((value, key) => [key, (value ?? 0) * 2] as [number, number]);
|
|
1759
|
+
* console.log([...doubled.values()]); // [20, 40, 60];
|
|
1437
1760
|
*/
|
|
1438
1761
|
override map<MK = K, MV = V, MR = any>(
|
|
1439
1762
|
callback: EntryCallback<K, V | undefined, [MK, MV]>,
|
|
@@ -1523,10 +1846,19 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
1523
1846
|
return 0;
|
|
1524
1847
|
}
|
|
1525
1848
|
|
|
1849
|
+
/* istanbul ignore next -- Date objects satisfy isComparable(), so this branch is unreachable via default comparator */
|
|
1850
|
+
// Date keys: compare by getTime()
|
|
1851
|
+
if (a instanceof Date && b instanceof Date) {
|
|
1852
|
+
const ta = a.getTime();
|
|
1853
|
+
const tb = b.getTime();
|
|
1854
|
+
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate('BST'));
|
|
1855
|
+
return ta > tb ? 1 : ta < tb ? -1 : 0;
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1526
1858
|
// If keys are objects and no comparator is provided, throw an error
|
|
1527
1859
|
if (typeof a === 'object' || typeof b === 'object') {
|
|
1528
|
-
throw TypeError(
|
|
1529
|
-
|
|
1860
|
+
throw new TypeError(
|
|
1861
|
+
ERR.comparatorRequired('BST')
|
|
1530
1862
|
);
|
|
1531
1863
|
}
|
|
1532
1864
|
|
|
@@ -1823,6 +2155,7 @@ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implemen
|
|
|
1823
2155
|
return this._boundByKey(targetKey, isLower, iterationType);
|
|
1824
2156
|
}
|
|
1825
2157
|
|
|
2158
|
+
/* istanbul ignore next -- defensive: targetKey is always defined if predicate path was skipped */
|
|
1826
2159
|
return undefined;
|
|
1827
2160
|
}
|
|
1828
2161
|
|