heap-typed 1.50.7 → 1.50.9
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/data-structures/binary-tree/avl-tree-multi-map.d.ts +14 -3
- package/dist/data-structures/binary-tree/avl-tree-multi-map.js +17 -6
- package/dist/data-structures/binary-tree/binary-tree.d.ts +1 -1
- package/dist/data-structures/binary-tree/binary-tree.js +33 -34
- package/dist/data-structures/binary-tree/bst.d.ts +22 -3
- package/dist/data-structures/binary-tree/bst.js +78 -39
- package/dist/data-structures/binary-tree/rb-tree.d.ts +5 -5
- package/dist/data-structures/binary-tree/rb-tree.js +47 -50
- package/dist/data-structures/binary-tree/tree-multi-map.d.ts +40 -23
- package/dist/data-structures/binary-tree/tree-multi-map.js +44 -28
- package/dist/data-structures/heap/heap.d.ts +1 -1
- package/dist/data-structures/heap/heap.js +5 -5
- package/dist/types/common.d.ts +6 -29
- package/dist/types/common.js +0 -40
- package/dist/types/data-structures/binary-tree/rb-tree.d.ts +1 -4
- package/dist/types/data-structures/binary-tree/rb-tree.js +0 -6
- package/package.json +2 -2
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +20 -7
- package/src/data-structures/binary-tree/binary-tree.ts +54 -45
- package/src/data-structures/binary-tree/bst.ts +86 -42
- package/src/data-structures/binary-tree/rb-tree.ts +49 -49
- package/src/data-structures/binary-tree/tree-multi-map.ts +48 -29
- package/src/data-structures/heap/heap.ts +5 -5
- package/src/types/common.ts +6 -30
- package/src/types/data-structures/binary-tree/rb-tree.ts +1 -1
|
@@ -126,7 +126,7 @@ export class BST<
|
|
|
126
126
|
return this._root;
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
-
protected _variant =
|
|
129
|
+
protected _variant: BSTVariant = 'STANDARD';
|
|
130
130
|
|
|
131
131
|
/**
|
|
132
132
|
* The function returns the value of the _variant property.
|
|
@@ -207,12 +207,12 @@ export class BST<
|
|
|
207
207
|
* @param {K | NODE | undefined} keyOrNodeOrEntry - The `key` parameter can be of type `K`, `NODE`, or
|
|
208
208
|
* `undefined`.
|
|
209
209
|
* @param iterationType - The `iterationType` parameter is an optional parameter that specifies the
|
|
210
|
-
* type of iteration to be performed. It has a default value of `
|
|
210
|
+
* type of iteration to be performed. It has a default value of `'ITERATIVE'`.
|
|
211
211
|
* @returns either a node object (NODE) or undefined.
|
|
212
212
|
*/
|
|
213
213
|
override ensureNode(
|
|
214
214
|
keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>,
|
|
215
|
-
iterationType =
|
|
215
|
+
iterationType: IterationType = 'ITERATIVE'
|
|
216
216
|
): NODE | undefined {
|
|
217
217
|
let res: NODE | undefined;
|
|
218
218
|
if (this.isRealNode(keyOrNodeOrEntry)) {
|
|
@@ -263,7 +263,7 @@ export class BST<
|
|
|
263
263
|
|
|
264
264
|
let current = this.root;
|
|
265
265
|
while (current !== undefined) {
|
|
266
|
-
if (this._compare(current.key, newNode.key) ===
|
|
266
|
+
if (this._compare(current.key, newNode.key) === 'EQ') {
|
|
267
267
|
// if (current !== newNode) {
|
|
268
268
|
// The key value is the same but the reference is different, update the value of the existing node
|
|
269
269
|
this._replaceNode(current, newNode);
|
|
@@ -275,7 +275,7 @@ export class BST<
|
|
|
275
275
|
|
|
276
276
|
// return;
|
|
277
277
|
// }
|
|
278
|
-
} else if (this._compare(current.key, newNode.key) ===
|
|
278
|
+
} else if (this._compare(current.key, newNode.key) === 'GT') {
|
|
279
279
|
if (current.left === undefined) {
|
|
280
280
|
current.left = newNode;
|
|
281
281
|
this._size++;
|
|
@@ -324,7 +324,7 @@ export class BST<
|
|
|
324
324
|
keysOrNodesOrEntries: Iterable<KeyOrNodeOrEntry<K, V, NODE>>,
|
|
325
325
|
values?: Iterable<V | undefined>,
|
|
326
326
|
isBalanceAdd = true,
|
|
327
|
-
iterationType = this.iterationType
|
|
327
|
+
iterationType: IterationType = this.iterationType
|
|
328
328
|
): boolean[] {
|
|
329
329
|
const inserted: boolean[] = [];
|
|
330
330
|
|
|
@@ -397,7 +397,7 @@ export class BST<
|
|
|
397
397
|
}
|
|
398
398
|
};
|
|
399
399
|
|
|
400
|
-
if (iterationType ===
|
|
400
|
+
if (iterationType === 'RECURSIVE') {
|
|
401
401
|
_dfs(sorted);
|
|
402
402
|
} else {
|
|
403
403
|
_iterate();
|
|
@@ -425,15 +425,16 @@ export class BST<
|
|
|
425
425
|
* @returns The function `getNodeByKey` returns a node (`NODE`) if a node with the specified key is
|
|
426
426
|
* found in the binary tree. If no node is found, it returns `undefined`.
|
|
427
427
|
*/
|
|
428
|
-
override getNodeByKey(key: K, iterationType =
|
|
428
|
+
override getNodeByKey(key: K, iterationType: IterationType = 'ITERATIVE'): NODE | undefined {
|
|
429
|
+
// return this.getNodes(key, this._defaultOneParamCallback, true, this.root, iterationType)[0];
|
|
429
430
|
if (!this.isRealNode(this.root)) return undefined;
|
|
430
|
-
if (iterationType ===
|
|
431
|
+
if (iterationType === 'RECURSIVE') {
|
|
431
432
|
const _dfs = (cur: NODE): NODE | undefined => {
|
|
432
433
|
if (cur.key === key) return cur;
|
|
433
434
|
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return;
|
|
434
435
|
|
|
435
|
-
if (this._compare(cur.key, key) ===
|
|
436
|
-
if (this._compare(cur.key, key) ===
|
|
436
|
+
if (this._compare(cur.key, key) === 'GT' && this.isRealNode(cur.left)) return _dfs(cur.left);
|
|
437
|
+
if (this._compare(cur.key, key) === 'LT' && this.isRealNode(cur.right)) return _dfs(cur.right);
|
|
437
438
|
};
|
|
438
439
|
|
|
439
440
|
return _dfs(this.root);
|
|
@@ -442,9 +443,9 @@ export class BST<
|
|
|
442
443
|
while (queue.size > 0) {
|
|
443
444
|
const cur = queue.shift();
|
|
444
445
|
if (this.isRealNode(cur)) {
|
|
445
|
-
if (this._compare(cur.key, key) ===
|
|
446
|
-
if (this._compare(cur.key, key) ===
|
|
447
|
-
if (this._compare(cur.key, key) ===
|
|
446
|
+
if (this._compare(cur.key, key) === 'EQ') return cur;
|
|
447
|
+
if (this._compare(cur.key, key) === 'GT') this.isRealNode(cur.left) && queue.push(cur.left);
|
|
448
|
+
if (this._compare(cur.key, key) === 'LT') this.isRealNode(cur.right) && queue.push(cur.right);
|
|
448
449
|
}
|
|
449
450
|
}
|
|
450
451
|
}
|
|
@@ -483,13 +484,13 @@ export class BST<
|
|
|
483
484
|
callback: C = this._defaultOneParamCallback as C,
|
|
484
485
|
onlyOne = false,
|
|
485
486
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
486
|
-
iterationType = this.iterationType
|
|
487
|
+
iterationType: IterationType = this.iterationType
|
|
487
488
|
): NODE[] {
|
|
488
489
|
beginRoot = this.ensureNode(beginRoot);
|
|
489
490
|
if (!beginRoot) return [];
|
|
490
491
|
const ans: NODE[] = [];
|
|
491
492
|
|
|
492
|
-
if (iterationType ===
|
|
493
|
+
if (iterationType === 'RECURSIVE') {
|
|
493
494
|
const _traverse = (cur: NODE) => {
|
|
494
495
|
const callbackResult = callback(cur);
|
|
495
496
|
if (callbackResult === identifier) {
|
|
@@ -500,8 +501,8 @@ export class BST<
|
|
|
500
501
|
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return;
|
|
501
502
|
// TODO potential bug
|
|
502
503
|
if (callback === this._defaultOneParamCallback) {
|
|
503
|
-
if (this._compare(cur.key, identifier as K) ===
|
|
504
|
-
if (this._compare(cur.key, identifier as K) ===
|
|
504
|
+
if (this.isRealNode(cur.left) && this._compare(cur.key, identifier as K) === 'GT') _traverse(cur.left);
|
|
505
|
+
if (this.isRealNode(cur.right) && this._compare(cur.key, identifier as K) === 'LT') _traverse(cur.right);
|
|
505
506
|
} else {
|
|
506
507
|
this.isRealNode(cur.left) && _traverse(cur.left);
|
|
507
508
|
this.isRealNode(cur.right) && _traverse(cur.right);
|
|
@@ -510,9 +511,9 @@ export class BST<
|
|
|
510
511
|
|
|
511
512
|
_traverse(beginRoot);
|
|
512
513
|
} else {
|
|
513
|
-
const
|
|
514
|
-
while (
|
|
515
|
-
const cur =
|
|
514
|
+
const stack = [beginRoot];
|
|
515
|
+
while (stack.length > 0) {
|
|
516
|
+
const cur = stack.pop();
|
|
516
517
|
if (this.isRealNode(cur)) {
|
|
517
518
|
const callbackResult = callback(cur);
|
|
518
519
|
if (callbackResult === identifier) {
|
|
@@ -521,11 +522,19 @@ export class BST<
|
|
|
521
522
|
}
|
|
522
523
|
// TODO potential bug
|
|
523
524
|
if (callback === this._defaultOneParamCallback) {
|
|
524
|
-
if (this._compare(cur.key, identifier as K) ===
|
|
525
|
-
if (this._compare(cur.key, identifier as K) ===
|
|
525
|
+
if (this.isRealNode(cur.right) && this._compare(cur.key, identifier as K) === 'LT') stack.push(cur.right);
|
|
526
|
+
if (this.isRealNode(cur.left) && this._compare(cur.key, identifier as K) === 'GT') stack.push(cur.left);
|
|
527
|
+
|
|
528
|
+
// if (this.isRealNode(cur.right) && this._lt(cur.key, identifier as K)) stack.push(cur.right);
|
|
529
|
+
// if (this.isRealNode(cur.left) && this._gt(cur.key, identifier as K)) stack.push(cur.left);
|
|
530
|
+
|
|
531
|
+
// // @ts-ignore
|
|
532
|
+
// if (this.isRealNode(cur.right) && cur.key > identifier) stack.push(cur.right);
|
|
533
|
+
// // @ts-ignore
|
|
534
|
+
// if (this.isRealNode(cur.left) && cur.key < identifier) stack.push(cur.left);
|
|
526
535
|
} else {
|
|
527
|
-
this.isRealNode(cur.
|
|
528
|
-
this.isRealNode(cur.
|
|
536
|
+
this.isRealNode(cur.right) && stack.push(cur.right);
|
|
537
|
+
this.isRealNode(cur.left) && stack.push(cur.left);
|
|
529
538
|
}
|
|
530
539
|
}
|
|
531
540
|
}
|
|
@@ -560,9 +569,9 @@ export class BST<
|
|
|
560
569
|
*/
|
|
561
570
|
override dfs<C extends BTNCallback<NODE>>(
|
|
562
571
|
callback: C = this._defaultOneParamCallback as C,
|
|
563
|
-
pattern: DFSOrderPattern = '
|
|
572
|
+
pattern: DFSOrderPattern = 'IN',
|
|
564
573
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
565
|
-
iterationType: IterationType =
|
|
574
|
+
iterationType: IterationType = 'ITERATIVE'
|
|
566
575
|
): ReturnType<C>[] {
|
|
567
576
|
return super.dfs(callback, pattern, beginRoot, iterationType, false);
|
|
568
577
|
}
|
|
@@ -592,7 +601,7 @@ export class BST<
|
|
|
592
601
|
override bfs<C extends BTNCallback<NODE>>(
|
|
593
602
|
callback: C = this._defaultOneParamCallback as C,
|
|
594
603
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
595
|
-
iterationType = this.iterationType
|
|
604
|
+
iterationType: IterationType = this.iterationType
|
|
596
605
|
): ReturnType<C>[] {
|
|
597
606
|
return super.bfs(callback, beginRoot, iterationType, false);
|
|
598
607
|
}
|
|
@@ -623,7 +632,7 @@ export class BST<
|
|
|
623
632
|
override listLevels<C extends BTNCallback<NODE>>(
|
|
624
633
|
callback: C = this._defaultOneParamCallback as C,
|
|
625
634
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
626
|
-
iterationType = this.iterationType
|
|
635
|
+
iterationType: IterationType = this.iterationType
|
|
627
636
|
): ReturnType<C>[][] {
|
|
628
637
|
return super.listLevels(callback, beginRoot, iterationType, false);
|
|
629
638
|
}
|
|
@@ -650,7 +659,7 @@ export class BST<
|
|
|
650
659
|
let current = this.ensureNode(beginRoot);
|
|
651
660
|
if (!current) return undefined;
|
|
652
661
|
|
|
653
|
-
if (this._variant ===
|
|
662
|
+
if (this._variant === 'STANDARD') {
|
|
654
663
|
// For BSTVariant.MIN, find the rightmost node
|
|
655
664
|
while (current.right !== undefined) {
|
|
656
665
|
current = current.right;
|
|
@@ -692,9 +701,9 @@ export class BST<
|
|
|
692
701
|
*/
|
|
693
702
|
lesserOrGreaterTraverse<C extends BTNCallback<NODE>>(
|
|
694
703
|
callback: C = this._defaultOneParamCallback as C,
|
|
695
|
-
lesserOrGreater: CP =
|
|
704
|
+
lesserOrGreater: CP = 'LT',
|
|
696
705
|
targetNode: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
697
|
-
iterationType = this.iterationType
|
|
706
|
+
iterationType: IterationType = this.iterationType
|
|
698
707
|
): ReturnType<C>[] {
|
|
699
708
|
targetNode = this.ensureNode(targetNode);
|
|
700
709
|
const ans: ReturnType<BTNCallback<NODE>>[] = [];
|
|
@@ -703,7 +712,7 @@ export class BST<
|
|
|
703
712
|
|
|
704
713
|
const targetKey = targetNode.key;
|
|
705
714
|
|
|
706
|
-
if (iterationType ===
|
|
715
|
+
if (iterationType === 'RECURSIVE') {
|
|
707
716
|
const _traverse = (cur: NODE) => {
|
|
708
717
|
const compared = this._compare(cur.key, targetKey);
|
|
709
718
|
if (compared === lesserOrGreater) ans.push(callback(cur));
|
|
@@ -746,13 +755,13 @@ export class BST<
|
|
|
746
755
|
* values:
|
|
747
756
|
* @returns The function `perfectlyBalance` returns a boolean value.
|
|
748
757
|
*/
|
|
749
|
-
perfectlyBalance(iterationType = this.iterationType): boolean {
|
|
750
|
-
const sorted = this.dfs(node => node, '
|
|
758
|
+
perfectlyBalance(iterationType: IterationType = this.iterationType): boolean {
|
|
759
|
+
const sorted = this.dfs(node => node, 'IN'),
|
|
751
760
|
n = sorted.length;
|
|
752
761
|
this.clear();
|
|
753
762
|
|
|
754
763
|
if (sorted.length < 1) return false;
|
|
755
|
-
if (iterationType ===
|
|
764
|
+
if (iterationType === 'RECURSIVE') {
|
|
756
765
|
const buildBalanceBST = (l: number, r: number) => {
|
|
757
766
|
if (l > r) return;
|
|
758
767
|
const m = l + Math.floor((r - l) / 2);
|
|
@@ -807,12 +816,12 @@ export class BST<
|
|
|
807
816
|
* to check if the AVL tree is balanced. It can have two possible values:
|
|
808
817
|
* @returns a boolean value.
|
|
809
818
|
*/
|
|
810
|
-
isAVLBalanced(iterationType = this.iterationType): boolean {
|
|
819
|
+
isAVLBalanced(iterationType: IterationType = this.iterationType): boolean {
|
|
811
820
|
if (!this.root) return true;
|
|
812
821
|
|
|
813
822
|
let balanced = true;
|
|
814
823
|
|
|
815
|
-
if (iterationType ===
|
|
824
|
+
if (iterationType === 'RECURSIVE') {
|
|
816
825
|
const _height = (cur: NODE | undefined): number => {
|
|
817
826
|
if (!cur) return 0;
|
|
818
827
|
const leftHeight = _height(cur.left),
|
|
@@ -868,14 +877,49 @@ export class BST<
|
|
|
868
877
|
* is greater than, less than, or equal to the second value.
|
|
869
878
|
* @param {K} a - The parameter "a" is of type K.
|
|
870
879
|
* @param {K} b - The parameter "b" in the above code represents a K.
|
|
871
|
-
* @returns a value of type CP (ComparisonResult). The possible return values are
|
|
872
|
-
* than),
|
|
880
|
+
* @returns a value of type CP (ComparisonResult). The possible return values are 'GT' (greater
|
|
881
|
+
* than), 'LT' (less than), or 'EQ' (equal).
|
|
873
882
|
*/
|
|
874
883
|
protected _compare(a: K, b: K): CP {
|
|
875
884
|
const extractedA = this.extractor(a);
|
|
876
885
|
const extractedB = this.extractor(b);
|
|
877
|
-
const compared = this.variant ===
|
|
886
|
+
const compared = this.variant === 'STANDARD' ? extractedA - extractedB : extractedB - extractedA;
|
|
878
887
|
|
|
879
|
-
return compared > 0 ?
|
|
888
|
+
return compared > 0 ? 'GT' : compared < 0 ? 'LT' : 'EQ';
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
/**
|
|
892
|
+
* The function `_lt` compares two values `a` and `b` using an extractor function and returns true if
|
|
893
|
+
* `a` is less than `b` based on the specified variant.
|
|
894
|
+
* @param {K} a - The parameter "a" is of type "K", which means it can be any type. It represents the
|
|
895
|
+
* first value to be compared in the function.
|
|
896
|
+
* @param {K} b - The parameter `b` is of type `K`, which means it can be any type. It is used as one
|
|
897
|
+
* of the arguments for the comparison in the `_lt` function.
|
|
898
|
+
* @returns a boolean value.
|
|
899
|
+
*/
|
|
900
|
+
protected _lt(a: K, b: K): boolean {
|
|
901
|
+
const extractedA = this.extractor(a);
|
|
902
|
+
const extractedB = this.extractor(b);
|
|
903
|
+
// return this.variant === BSTVariant.STANDARD ? extractedA < extractedB : extractedA > extractedB;
|
|
904
|
+
return this.variant === 'STANDARD' ? extractedA < extractedB : extractedA > extractedB;
|
|
905
|
+
// return extractedA < extractedB;
|
|
906
|
+
// return a < b;
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
/**
|
|
910
|
+
* The function compares two values using a custom extractor function and returns true if the first
|
|
911
|
+
* value is greater than the second value.
|
|
912
|
+
* @param {K} a - The parameter "a" is of type K, which means it can be any type.
|
|
913
|
+
* @param {K} b - The parameter "b" is of type K, which means it can be any type. It is used as one
|
|
914
|
+
* of the arguments for the comparison in the function.
|
|
915
|
+
* @returns a boolean value.
|
|
916
|
+
*/
|
|
917
|
+
protected _gt(a: K, b: K): boolean {
|
|
918
|
+
const extractedA = this.extractor(a);
|
|
919
|
+
const extractedB = this.extractor(b);
|
|
920
|
+
// return this.variant === BSTVariant.STANDARD ? extractedA > extractedB : extractedA < extractedB;
|
|
921
|
+
return this.variant === 'STANDARD' ? extractedA > extractedB : extractedA < extractedB;
|
|
922
|
+
// return extractedA > extractedB;
|
|
923
|
+
// return a > b;
|
|
880
924
|
}
|
|
881
925
|
}
|
|
@@ -2,6 +2,7 @@ import type {
|
|
|
2
2
|
BinaryTreeDeleteResult,
|
|
3
3
|
BSTNKeyOrNode,
|
|
4
4
|
BTNCallback,
|
|
5
|
+
IterationType,
|
|
5
6
|
KeyOrNodeOrEntry,
|
|
6
7
|
RBTreeOptions,
|
|
7
8
|
RedBlackTreeNested,
|
|
@@ -25,9 +26,9 @@ export class RedBlackTreeNode<
|
|
|
25
26
|
* associated with the key in the Red-Black Tree Node. It is not required and can be omitted when
|
|
26
27
|
* creating a new instance of the Red-Black Tree Node.
|
|
27
28
|
* @param {RBTNColor} color - The `color` parameter is used to specify the color of the Red-Black
|
|
28
|
-
* Tree Node. It is an optional parameter with a default value of `
|
|
29
|
+
* Tree Node. It is an optional parameter with a default value of `'BLACK'`.
|
|
29
30
|
*/
|
|
30
|
-
constructor(key: K, value?: V, color: RBTNColor =
|
|
31
|
+
constructor(key: K, value?: V, color: RBTNColor = 'BLACK') {
|
|
31
32
|
super(key, value);
|
|
32
33
|
this._color = color;
|
|
33
34
|
}
|
|
@@ -106,12 +107,12 @@ export class RedBlackTree<
|
|
|
106
107
|
* @param {V} [value] - The `value` parameter is an optional parameter that represents the value
|
|
107
108
|
* associated with the key in the node. It is not required and can be omitted if not needed.
|
|
108
109
|
* @param {RBTNColor} color - The "color" parameter is used to specify the color of the node in a
|
|
109
|
-
* Red-Black Tree. It is an optional parameter with a default value of "
|
|
110
|
-
* can be either "
|
|
110
|
+
* Red-Black Tree. It is an optional parameter with a default value of "'BLACK'". The color
|
|
111
|
+
* can be either "'RED'" or "'BLACK'".
|
|
111
112
|
* @returns The method is returning a new instance of a RedBlackTreeNode with the specified key,
|
|
112
113
|
* value, and color.
|
|
113
114
|
*/
|
|
114
|
-
override createNode(key: K, value?: V, color: RBTNColor =
|
|
115
|
+
override createNode(key: K, value?: V, color: RBTNColor = 'BLACK'): NODE {
|
|
115
116
|
return new RedBlackTreeNode<K, V, NODE>(key, value, color) as NODE;
|
|
116
117
|
}
|
|
117
118
|
|
|
@@ -156,10 +157,10 @@ export class RedBlackTree<
|
|
|
156
157
|
if (key === undefined || key === null) {
|
|
157
158
|
return;
|
|
158
159
|
} else {
|
|
159
|
-
node = this.createNode(key, value,
|
|
160
|
+
node = this.createNode(key, value, 'RED');
|
|
160
161
|
}
|
|
161
162
|
} else if (!this.isNode(keyOrNodeOrEntry)) {
|
|
162
|
-
node = this.createNode(keyOrNodeOrEntry, value,
|
|
163
|
+
node = this.createNode(keyOrNodeOrEntry, value, 'RED');
|
|
163
164
|
} else {
|
|
164
165
|
return;
|
|
165
166
|
}
|
|
@@ -232,10 +233,9 @@ export class RedBlackTree<
|
|
|
232
233
|
identifier: ReturnType<C> | undefined,
|
|
233
234
|
callback: C = this._defaultOneParamCallback as C,
|
|
234
235
|
beginRoot: BSTNKeyOrNode<K, NODE> = this.root,
|
|
235
|
-
iterationType = this.iterationType
|
|
236
|
+
iterationType: IterationType = this.iterationType
|
|
236
237
|
): NODE | null | undefined {
|
|
237
|
-
|
|
238
|
-
return super.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? undefined;
|
|
238
|
+
return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? undefined;
|
|
239
239
|
}
|
|
240
240
|
|
|
241
241
|
/**
|
|
@@ -279,16 +279,16 @@ export class RedBlackTree<
|
|
|
279
279
|
|
|
280
280
|
const insertStatus = this._insert(newNode);
|
|
281
281
|
|
|
282
|
-
if (insertStatus ===
|
|
282
|
+
if (insertStatus === 'CREATED') {
|
|
283
283
|
// Ensure the root is black
|
|
284
284
|
if (this.isRealNode(this._root)) {
|
|
285
|
-
this._root.color =
|
|
285
|
+
this._root.color = 'BLACK';
|
|
286
286
|
} else {
|
|
287
287
|
return false;
|
|
288
288
|
}
|
|
289
289
|
this._size++;
|
|
290
290
|
return true;
|
|
291
|
-
} else return insertStatus ===
|
|
291
|
+
} else return insertStatus === 'UPDATED';
|
|
292
292
|
}
|
|
293
293
|
|
|
294
294
|
/**
|
|
@@ -363,7 +363,7 @@ export class RedBlackTree<
|
|
|
363
363
|
this._size--;
|
|
364
364
|
|
|
365
365
|
// If the original color was black, fix the tree
|
|
366
|
-
if (originalColor ===
|
|
366
|
+
if (originalColor === 'BLACK') {
|
|
367
367
|
this._deleteFixup(replacementNode);
|
|
368
368
|
}
|
|
369
369
|
|
|
@@ -435,7 +435,7 @@ export class RedBlackTree<
|
|
|
435
435
|
current = current.right ?? this.SENTINEL;
|
|
436
436
|
} else {
|
|
437
437
|
this._replaceNode(current, node);
|
|
438
|
-
return
|
|
438
|
+
return 'UPDATED';
|
|
439
439
|
}
|
|
440
440
|
}
|
|
441
441
|
|
|
@@ -451,10 +451,10 @@ export class RedBlackTree<
|
|
|
451
451
|
|
|
452
452
|
node.left = this.SENTINEL;
|
|
453
453
|
node.right = this.SENTINEL;
|
|
454
|
-
node.color =
|
|
454
|
+
node.color = 'RED';
|
|
455
455
|
|
|
456
456
|
this._insertFixup(node);
|
|
457
|
-
return
|
|
457
|
+
return 'CREATED';
|
|
458
458
|
}
|
|
459
459
|
|
|
460
460
|
/**
|
|
@@ -500,16 +500,16 @@ export class RedBlackTree<
|
|
|
500
500
|
*/
|
|
501
501
|
protected _insertFixup(z: NODE | undefined): void {
|
|
502
502
|
// Continue fixing the tree as long as the parent of z is red
|
|
503
|
-
while (z?.parent?.color ===
|
|
503
|
+
while (z?.parent?.color === 'RED') {
|
|
504
504
|
// Check if the parent of z is the left child of its parent
|
|
505
505
|
if (z.parent === z.parent.parent?.left) {
|
|
506
506
|
// Case 1: The uncle (y) of z is red
|
|
507
507
|
const y = z.parent.parent.right;
|
|
508
|
-
if (y?.color ===
|
|
508
|
+
if (y?.color === 'RED') {
|
|
509
509
|
// Set colors to restore properties of Red-Black Tree
|
|
510
|
-
z.parent.color =
|
|
511
|
-
y.color =
|
|
512
|
-
z.parent.parent.color =
|
|
510
|
+
z.parent.color = 'BLACK';
|
|
511
|
+
y.color = 'BLACK';
|
|
512
|
+
z.parent.parent.color = 'RED';
|
|
513
513
|
// Move up the tree to continue fixing
|
|
514
514
|
z = z.parent.parent;
|
|
515
515
|
} else {
|
|
@@ -523,8 +523,8 @@ export class RedBlackTree<
|
|
|
523
523
|
// Case 3: The uncle (y) of z is black, and z is a left child
|
|
524
524
|
// Adjust colors and perform a right rotation
|
|
525
525
|
if (z && this.isRealNode(z.parent) && this.isRealNode(z.parent.parent)) {
|
|
526
|
-
z.parent.color =
|
|
527
|
-
z.parent.parent.color =
|
|
526
|
+
z.parent.color = 'BLACK';
|
|
527
|
+
z.parent.parent.color = 'RED';
|
|
528
528
|
this._rightRotate(z.parent.parent);
|
|
529
529
|
}
|
|
530
530
|
}
|
|
@@ -532,10 +532,10 @@ export class RedBlackTree<
|
|
|
532
532
|
// Symmetric case for the right child (left and right exchanged)
|
|
533
533
|
// Follow the same logic as above with left and right exchanged
|
|
534
534
|
const y: NODE | undefined = z?.parent?.parent?.left;
|
|
535
|
-
if (y?.color ===
|
|
536
|
-
z.parent.color =
|
|
537
|
-
y.color =
|
|
538
|
-
z.parent.parent!.color =
|
|
535
|
+
if (y?.color === 'RED') {
|
|
536
|
+
z.parent.color = 'BLACK';
|
|
537
|
+
y.color = 'BLACK';
|
|
538
|
+
z.parent.parent!.color = 'RED';
|
|
539
539
|
z = z.parent.parent;
|
|
540
540
|
} else {
|
|
541
541
|
if (z === z.parent.left) {
|
|
@@ -544,8 +544,8 @@ export class RedBlackTree<
|
|
|
544
544
|
}
|
|
545
545
|
|
|
546
546
|
if (z && this.isRealNode(z.parent) && this.isRealNode(z.parent.parent)) {
|
|
547
|
-
z.parent.color =
|
|
548
|
-
z.parent.parent.color =
|
|
547
|
+
z.parent.color = 'BLACK';
|
|
548
|
+
z.parent.parent.color = 'RED';
|
|
549
549
|
this._leftRotate(z.parent.parent);
|
|
550
550
|
}
|
|
551
551
|
}
|
|
@@ -553,7 +553,7 @@ export class RedBlackTree<
|
|
|
553
553
|
}
|
|
554
554
|
|
|
555
555
|
// Ensure that the root is black after fixing
|
|
556
|
-
if (this.isRealNode(this._root)) this._root.color =
|
|
556
|
+
if (this.isRealNode(this._root)) this._root.color = 'BLACK';
|
|
557
557
|
}
|
|
558
558
|
|
|
559
559
|
/**
|
|
@@ -573,14 +573,14 @@ export class RedBlackTree<
|
|
|
573
573
|
*/
|
|
574
574
|
protected _deleteFixup(node: NODE | undefined): void {
|
|
575
575
|
// Early exit condition
|
|
576
|
-
if (!node || node === this.root || node.color ===
|
|
576
|
+
if (!node || node === this.root || node.color === 'BLACK') {
|
|
577
577
|
if (node) {
|
|
578
|
-
node.color =
|
|
578
|
+
node.color = 'BLACK'; // Ensure the final node is black
|
|
579
579
|
}
|
|
580
580
|
return;
|
|
581
581
|
}
|
|
582
582
|
|
|
583
|
-
while (node && node !== this.root && node.color ===
|
|
583
|
+
while (node && node !== this.root && node.color === 'BLACK') {
|
|
584
584
|
const parent: NODE | undefined = node.parent;
|
|
585
585
|
|
|
586
586
|
if (!parent) {
|
|
@@ -591,22 +591,22 @@ export class RedBlackTree<
|
|
|
591
591
|
let sibling = parent.right;
|
|
592
592
|
|
|
593
593
|
// Cases 1 and 2: Sibling is red or both children of sibling are black
|
|
594
|
-
if (sibling?.color ===
|
|
595
|
-
sibling.color =
|
|
596
|
-
parent.color =
|
|
594
|
+
if (sibling?.color === 'RED') {
|
|
595
|
+
sibling.color = 'BLACK';
|
|
596
|
+
parent.color = 'RED';
|
|
597
597
|
this._leftRotate(parent);
|
|
598
598
|
sibling = parent.right;
|
|
599
599
|
}
|
|
600
600
|
|
|
601
601
|
// Case 3: Sibling's left child is black
|
|
602
|
-
if ((sibling?.left?.color ??
|
|
603
|
-
if (sibling) sibling.color =
|
|
602
|
+
if ((sibling?.left?.color ?? 'BLACK') === 'BLACK') {
|
|
603
|
+
if (sibling) sibling.color = 'RED';
|
|
604
604
|
node = parent;
|
|
605
605
|
} else {
|
|
606
606
|
// Case 4: Adjust colors and perform a right rotation
|
|
607
|
-
if (sibling?.left) sibling.left.color =
|
|
607
|
+
if (sibling?.left) sibling.left.color = 'BLACK';
|
|
608
608
|
if (sibling) sibling.color = parent.color;
|
|
609
|
-
parent.color =
|
|
609
|
+
parent.color = 'BLACK';
|
|
610
610
|
this._rightRotate(parent);
|
|
611
611
|
node = this.root;
|
|
612
612
|
}
|
|
@@ -615,22 +615,22 @@ export class RedBlackTree<
|
|
|
615
615
|
let sibling = parent.left;
|
|
616
616
|
|
|
617
617
|
// Cases 1 and 2: Sibling is red or both children of sibling are black
|
|
618
|
-
if (sibling?.color ===
|
|
619
|
-
sibling.color =
|
|
620
|
-
if (parent) parent.color =
|
|
618
|
+
if (sibling?.color === 'RED') {
|
|
619
|
+
sibling.color = 'BLACK';
|
|
620
|
+
if (parent) parent.color = 'RED';
|
|
621
621
|
this._rightRotate(parent);
|
|
622
622
|
if (parent) sibling = parent.left;
|
|
623
623
|
}
|
|
624
624
|
|
|
625
625
|
// Case 3: Sibling's left child is black
|
|
626
|
-
if ((sibling?.right?.color ??
|
|
627
|
-
if (sibling) sibling.color =
|
|
626
|
+
if ((sibling?.right?.color ?? 'BLACK') === 'BLACK') {
|
|
627
|
+
if (sibling) sibling.color = 'RED';
|
|
628
628
|
node = parent;
|
|
629
629
|
} else {
|
|
630
630
|
// Case 4: Adjust colors and perform a left rotation
|
|
631
|
-
if (sibling?.right) sibling.right.color =
|
|
631
|
+
if (sibling?.right) sibling.right.color = 'BLACK';
|
|
632
632
|
if (sibling) sibling.color = parent.color;
|
|
633
|
-
if (parent) parent.color =
|
|
633
|
+
if (parent) parent.color = 'BLACK';
|
|
634
634
|
this._leftRotate(parent);
|
|
635
635
|
node = this.root;
|
|
636
636
|
}
|
|
@@ -639,7 +639,7 @@ export class RedBlackTree<
|
|
|
639
639
|
|
|
640
640
|
// Ensure that the final node (possibly the root) is black
|
|
641
641
|
if (node) {
|
|
642
|
-
node.color =
|
|
642
|
+
node.color = 'BLACK';
|
|
643
643
|
}
|
|
644
644
|
}
|
|
645
645
|
|