data-structure-typed 1.51.0 → 1.51.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1 -1
- package/README.md +13 -13
- package/benchmark/report.html +37 -1
- package/benchmark/report.json +390 -12
- package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js +1 -1
- package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/avl-tree.d.ts +1 -1
- package/dist/cjs/data-structures/binary-tree/avl-tree.js +2 -2
- package/dist/cjs/data-structures/binary-tree/avl-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/binary-tree.d.ts +17 -11
- package/dist/cjs/data-structures/binary-tree/binary-tree.js +98 -92
- package/dist/cjs/data-structures/binary-tree/binary-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/bst.d.ts +27 -1
- package/dist/cjs/data-structures/binary-tree/bst.js +68 -39
- package/dist/cjs/data-structures/binary-tree/bst.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/rb-tree.d.ts +2 -48
- package/dist/cjs/data-structures/binary-tree/rb-tree.js +8 -63
- package/dist/cjs/data-structures/binary-tree/rb-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/tree-multi-map.d.ts +1 -1
- package/dist/cjs/data-structures/binary-tree/tree-multi-map.js +2 -2
- package/dist/cjs/data-structures/binary-tree/tree-multi-map.js.map +1 -1
- package/dist/mjs/data-structures/binary-tree/avl-tree-multi-map.js +1 -1
- package/dist/mjs/data-structures/binary-tree/avl-tree.d.ts +1 -1
- package/dist/mjs/data-structures/binary-tree/avl-tree.js +2 -2
- package/dist/mjs/data-structures/binary-tree/binary-tree.d.ts +17 -11
- package/dist/mjs/data-structures/binary-tree/binary-tree.js +98 -92
- package/dist/mjs/data-structures/binary-tree/bst.d.ts +27 -1
- package/dist/mjs/data-structures/binary-tree/bst.js +67 -39
- package/dist/mjs/data-structures/binary-tree/rb-tree.d.ts +2 -48
- package/dist/mjs/data-structures/binary-tree/rb-tree.js +8 -62
- package/dist/mjs/data-structures/binary-tree/tree-multi-map.d.ts +1 -1
- package/dist/mjs/data-structures/binary-tree/tree-multi-map.js +2 -2
- package/dist/umd/data-structure-typed.js +178 -198
- package/dist/umd/data-structure-typed.min.js +2 -2
- package/dist/umd/data-structure-typed.min.js.map +1 -1
- package/package.json +6 -6
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +1 -1
- package/src/data-structures/binary-tree/avl-tree.ts +2 -2
- package/src/data-structures/binary-tree/binary-tree.ts +98 -93
- package/src/data-structures/binary-tree/bst.ts +69 -34
- package/src/data-structures/binary-tree/rb-tree.ts +8 -74
- package/src/data-structures/binary-tree/tree-multi-map.ts +2 -2
- package/test/performance/data-structures/binary-tree/avl-tree.test.ts +4 -0
- package/test/performance/data-structures/binary-tree/rb-tree.test.ts +4 -0
- package/test/unit/data-structures/binary-tree/overall.test.ts +2 -2
- package/test/unit/data-structures/binary-tree/rb-tree.test.ts +40 -40
- package/test/unit/data-structures/binary-tree/tree-multi-map.test.ts +1 -0
- package/test/utils/big-o.ts +12 -0
|
@@ -13,7 +13,7 @@ import type {
|
|
|
13
13
|
BTNodePureExemplar,
|
|
14
14
|
KeyOrNodeOrEntry
|
|
15
15
|
} from '../../types';
|
|
16
|
-
import { BSTVariant, CP, DFSOrderPattern, IterationType } from '../../types';
|
|
16
|
+
import { BSTNKeyOrNode, BSTVariant, CP, DFSOrderPattern, IterationType } from '../../types';
|
|
17
17
|
import { BinaryTree, BinaryTreeNode } from './binary-tree';
|
|
18
18
|
import { IBinaryTree } from '../../interfaces';
|
|
19
19
|
import { Queue } from '../queue';
|
|
@@ -214,15 +214,15 @@ export class BST<
|
|
|
214
214
|
keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>,
|
|
215
215
|
iterationType: IterationType = 'ITERATIVE'
|
|
216
216
|
): NODE | undefined {
|
|
217
|
-
let res: NODE | undefined;
|
|
218
217
|
if (this.isRealNode(keyOrNodeOrEntry)) {
|
|
219
|
-
|
|
218
|
+
return keyOrNodeOrEntry;
|
|
220
219
|
} else if (this.isEntry(keyOrNodeOrEntry)) {
|
|
221
|
-
if (keyOrNodeOrEntry[0]
|
|
220
|
+
if (keyOrNodeOrEntry[0] === null || keyOrNodeOrEntry[0] === undefined) return;
|
|
221
|
+
return this.getNodeByKey(keyOrNodeOrEntry[0], iterationType);
|
|
222
222
|
} else {
|
|
223
|
-
if (keyOrNodeOrEntry
|
|
223
|
+
if (keyOrNodeOrEntry === null || keyOrNodeOrEntry === undefined) return;
|
|
224
|
+
return this.getNodeByKey(keyOrNodeOrEntry, iterationType);
|
|
224
225
|
}
|
|
225
|
-
return res;
|
|
226
226
|
}
|
|
227
227
|
|
|
228
228
|
/**
|
|
@@ -426,26 +426,26 @@ export class BST<
|
|
|
426
426
|
* found in the binary tree. If no node is found, it returns `undefined`.
|
|
427
427
|
*/
|
|
428
428
|
override getNodeByKey(key: K, iterationType: IterationType = 'ITERATIVE'): NODE | undefined {
|
|
429
|
-
// return this.getNodes(key, this.
|
|
430
|
-
if (!this.isRealNode(this.root)) return
|
|
429
|
+
// return this.getNodes(key, this._DEFAULT_CALLBACK, true, this.root, iterationType)[0];
|
|
430
|
+
if (!this.isRealNode(this.root)) return;
|
|
431
431
|
if (iterationType === 'RECURSIVE') {
|
|
432
|
-
const
|
|
432
|
+
const dfs = (cur: NODE): NODE | undefined => {
|
|
433
433
|
if (cur.key === key) return cur;
|
|
434
434
|
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return;
|
|
435
435
|
|
|
436
|
-
if (this._compare(cur.key, key) === 'GT'
|
|
437
|
-
if (this._compare(cur.key, key) === 'LT'
|
|
436
|
+
if (this.isRealNode(cur.left) && this._compare(cur.key, key) === 'GT') return dfs(cur.left);
|
|
437
|
+
if (this.isRealNode(cur.right) && this._compare(cur.key, key) === 'LT') return dfs(cur.right);
|
|
438
438
|
};
|
|
439
439
|
|
|
440
|
-
return
|
|
440
|
+
return dfs(this.root);
|
|
441
441
|
} else {
|
|
442
|
-
const
|
|
443
|
-
while (
|
|
444
|
-
const cur =
|
|
442
|
+
const stack = [this.root];
|
|
443
|
+
while (stack.length > 0) {
|
|
444
|
+
const cur = stack.pop();
|
|
445
445
|
if (this.isRealNode(cur)) {
|
|
446
446
|
if (this._compare(cur.key, key) === 'EQ') return cur;
|
|
447
|
-
if (this._compare(cur.key, key) === 'GT')
|
|
448
|
-
if (this._compare(cur.key, key) === 'LT')
|
|
447
|
+
if (this.isRealNode(cur.left) && this._compare(cur.key, key) === 'GT') stack.push(cur.left);
|
|
448
|
+
if (this.isRealNode(cur.right) && this._compare(cur.key, key) === 'LT') stack.push(cur.right);
|
|
449
449
|
}
|
|
450
450
|
}
|
|
451
451
|
}
|
|
@@ -481,7 +481,7 @@ export class BST<
|
|
|
481
481
|
*/
|
|
482
482
|
override getNodes<C extends BTNCallback<NODE>>(
|
|
483
483
|
identifier: ReturnType<C> | undefined,
|
|
484
|
-
callback: C = this.
|
|
484
|
+
callback: C = this._DEFAULT_CALLBACK as C,
|
|
485
485
|
onlyOne = false,
|
|
486
486
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
487
487
|
iterationType: IterationType = this.iterationType
|
|
@@ -491,7 +491,7 @@ export class BST<
|
|
|
491
491
|
const ans: NODE[] = [];
|
|
492
492
|
|
|
493
493
|
if (iterationType === 'RECURSIVE') {
|
|
494
|
-
const
|
|
494
|
+
const dfs = (cur: NODE) => {
|
|
495
495
|
const callbackResult = callback(cur);
|
|
496
496
|
if (callbackResult === identifier) {
|
|
497
497
|
ans.push(cur);
|
|
@@ -500,16 +500,16 @@ export class BST<
|
|
|
500
500
|
|
|
501
501
|
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return;
|
|
502
502
|
// TODO potential bug
|
|
503
|
-
if (callback === this.
|
|
504
|
-
if (this.isRealNode(cur.left) && this._compare(cur.key, identifier as K) === 'GT')
|
|
505
|
-
if (this.isRealNode(cur.right) && this._compare(cur.key, identifier as K) === 'LT')
|
|
503
|
+
if (callback === this._DEFAULT_CALLBACK) {
|
|
504
|
+
if (this.isRealNode(cur.left) && this._compare(cur.key, identifier as K) === 'GT') dfs(cur.left);
|
|
505
|
+
if (this.isRealNode(cur.right) && this._compare(cur.key, identifier as K) === 'LT') dfs(cur.right);
|
|
506
506
|
} else {
|
|
507
|
-
this.isRealNode(cur.left) &&
|
|
508
|
-
this.isRealNode(cur.right) &&
|
|
507
|
+
this.isRealNode(cur.left) && dfs(cur.left);
|
|
508
|
+
this.isRealNode(cur.right) && dfs(cur.right);
|
|
509
509
|
}
|
|
510
510
|
};
|
|
511
511
|
|
|
512
|
-
|
|
512
|
+
dfs(beginRoot);
|
|
513
513
|
} else {
|
|
514
514
|
const stack = [beginRoot];
|
|
515
515
|
while (stack.length > 0) {
|
|
@@ -521,7 +521,7 @@ export class BST<
|
|
|
521
521
|
if (onlyOne) return ans;
|
|
522
522
|
}
|
|
523
523
|
// TODO potential bug
|
|
524
|
-
if (callback === this.
|
|
524
|
+
if (callback === this._DEFAULT_CALLBACK) {
|
|
525
525
|
if (this.isRealNode(cur.right) && this._compare(cur.key, identifier as K) === 'LT') stack.push(cur.right);
|
|
526
526
|
if (this.isRealNode(cur.left) && this._compare(cur.key, identifier as K) === 'GT') stack.push(cur.left);
|
|
527
527
|
|
|
@@ -543,6 +543,41 @@ export class BST<
|
|
|
543
543
|
return ans;
|
|
544
544
|
}
|
|
545
545
|
|
|
546
|
+
/**
|
|
547
|
+
* Time Complexity: O(log n)
|
|
548
|
+
* Space Complexity: O(1)
|
|
549
|
+
*/
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* Time Complexity: O(log n)
|
|
553
|
+
* Space Complexity: O(1)
|
|
554
|
+
*
|
|
555
|
+
* The `getNode` function retrieves a node from a Red-Black Tree based on the provided identifier and
|
|
556
|
+
* callback function.
|
|
557
|
+
* @param {ReturnType<C> | undefined} identifier - The `identifier` parameter is the value or key
|
|
558
|
+
* that you want to search for in the binary search tree. It can be of any type that is compatible
|
|
559
|
+
* with the type of nodes in the tree.
|
|
560
|
+
* @param {C} callback - The `callback` parameter is a function that will be called for each node in
|
|
561
|
+
* the tree. It is used to determine whether a node matches the given identifier. The `callback`
|
|
562
|
+
* function should take a node as its parameter and return a value that can be compared to the
|
|
563
|
+
* `identifier` parameter.
|
|
564
|
+
* @param beginRoot - The `beginRoot` parameter is the starting point for the search in the binary
|
|
565
|
+
* search tree. It can be either a key or a node. If it is a key, it will be converted to a node
|
|
566
|
+
* using the `ensureNode` method. If it is not provided, the `root`
|
|
567
|
+
* @param iterationType - The `iterationType` parameter is used to specify the type of iteration to
|
|
568
|
+
* be performed when searching for nodes in the binary search tree. It is an optional parameter and
|
|
569
|
+
* its default value is taken from the `iterationType` property of the class.
|
|
570
|
+
* @returns The method is returning a value of type `NODE | null | undefined`.
|
|
571
|
+
*/
|
|
572
|
+
override getNode<C extends BTNCallback<NODE>>(
|
|
573
|
+
identifier: ReturnType<C> | undefined,
|
|
574
|
+
callback: C = this._DEFAULT_CALLBACK as C,
|
|
575
|
+
beginRoot: BSTNKeyOrNode<K, NODE> = this.root,
|
|
576
|
+
iterationType: IterationType = this.iterationType
|
|
577
|
+
): NODE | undefined {
|
|
578
|
+
return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? undefined;
|
|
579
|
+
}
|
|
580
|
+
|
|
546
581
|
/**
|
|
547
582
|
* Time complexity: O(n)
|
|
548
583
|
* Space complexity: O(n)
|
|
@@ -568,7 +603,7 @@ export class BST<
|
|
|
568
603
|
* @returns The method is returning an array of the return type of the callback function.
|
|
569
604
|
*/
|
|
570
605
|
override dfs<C extends BTNCallback<NODE>>(
|
|
571
|
-
callback: C = this.
|
|
606
|
+
callback: C = this._DEFAULT_CALLBACK as C,
|
|
572
607
|
pattern: DFSOrderPattern = 'IN',
|
|
573
608
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
574
609
|
iterationType: IterationType = 'ITERATIVE'
|
|
@@ -599,7 +634,7 @@ export class BST<
|
|
|
599
634
|
* @returns The method is returning an array of the return type of the callback function.
|
|
600
635
|
*/
|
|
601
636
|
override bfs<C extends BTNCallback<NODE>>(
|
|
602
|
-
callback: C = this.
|
|
637
|
+
callback: C = this._DEFAULT_CALLBACK as C,
|
|
603
638
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
604
639
|
iterationType: IterationType = this.iterationType
|
|
605
640
|
): ReturnType<C>[] {
|
|
@@ -630,7 +665,7 @@ export class BST<
|
|
|
630
665
|
* function.
|
|
631
666
|
*/
|
|
632
667
|
override listLevels<C extends BTNCallback<NODE>>(
|
|
633
|
-
callback: C = this.
|
|
668
|
+
callback: C = this._DEFAULT_CALLBACK as C,
|
|
634
669
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
635
670
|
iterationType: IterationType = this.iterationType
|
|
636
671
|
): ReturnType<C>[][] {
|
|
@@ -700,7 +735,7 @@ export class BST<
|
|
|
700
735
|
* `ReturnType<C>`, which is the return type of the callback function passed as an argument.
|
|
701
736
|
*/
|
|
702
737
|
lesserOrGreaterTraverse<C extends BTNCallback<NODE>>(
|
|
703
|
-
callback: C = this.
|
|
738
|
+
callback: C = this._DEFAULT_CALLBACK as C,
|
|
704
739
|
lesserOrGreater: CP = 'LT',
|
|
705
740
|
targetNode: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
706
741
|
iterationType: IterationType = this.iterationType
|
|
@@ -713,15 +748,15 @@ export class BST<
|
|
|
713
748
|
const targetKey = targetNode.key;
|
|
714
749
|
|
|
715
750
|
if (iterationType === 'RECURSIVE') {
|
|
716
|
-
const
|
|
751
|
+
const dfs = (cur: NODE) => {
|
|
717
752
|
const compared = this._compare(cur.key, targetKey);
|
|
718
753
|
if (compared === lesserOrGreater) ans.push(callback(cur));
|
|
719
754
|
|
|
720
|
-
if (this.isRealNode(cur.left))
|
|
721
|
-
if (this.isRealNode(cur.right))
|
|
755
|
+
if (this.isRealNode(cur.left)) dfs(cur.left);
|
|
756
|
+
if (this.isRealNode(cur.right)) dfs(cur.right);
|
|
722
757
|
};
|
|
723
758
|
|
|
724
|
-
|
|
759
|
+
dfs(this.root);
|
|
725
760
|
return ans;
|
|
726
761
|
} else {
|
|
727
762
|
const queue = new Queue<NODE>([this.root]);
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
BinaryTreeDeleteResult,
|
|
3
|
-
BSTNKeyOrNode,
|
|
4
3
|
BTNCallback,
|
|
5
|
-
IterationType,
|
|
6
4
|
KeyOrNodeOrEntry,
|
|
7
5
|
RBTreeOptions,
|
|
8
6
|
RedBlackTreeNested,
|
|
@@ -73,23 +71,13 @@ export class RedBlackTree<
|
|
|
73
71
|
constructor(keysOrNodesOrEntries: Iterable<KeyOrNodeOrEntry<K, V, NODE>> = [], options?: RBTreeOptions<K>) {
|
|
74
72
|
super([], options);
|
|
75
73
|
|
|
76
|
-
this._root = this.
|
|
74
|
+
this._root = this.NIL;
|
|
77
75
|
|
|
78
76
|
if (keysOrNodesOrEntries) {
|
|
79
77
|
this.addMany(keysOrNodesOrEntries);
|
|
80
78
|
}
|
|
81
79
|
}
|
|
82
80
|
|
|
83
|
-
protected _SENTINEL: NODE = new RedBlackTreeNode<K, V>(NaN as K) as unknown as NODE;
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* The function returns the value of the _SENTINEL property.
|
|
87
|
-
* @returns The method is returning the value of the `_SENTINEL` property.
|
|
88
|
-
*/
|
|
89
|
-
get SENTINEL(): NODE {
|
|
90
|
-
return this._SENTINEL;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
81
|
protected override _root: NODE | undefined;
|
|
94
82
|
|
|
95
83
|
/**
|
|
@@ -184,60 +172,6 @@ export class RedBlackTree<
|
|
|
184
172
|
return keyOrNodeOrEntry instanceof RedBlackTreeNode;
|
|
185
173
|
}
|
|
186
174
|
|
|
187
|
-
/**
|
|
188
|
-
* Time Complexity: O(1)
|
|
189
|
-
* Space Complexity: O(1)
|
|
190
|
-
*/
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Time Complexity: O(1)
|
|
194
|
-
* Space Complexity: O(1)
|
|
195
|
-
*
|
|
196
|
-
* The function checks if a given node is a real node in a Red-Black Tree.
|
|
197
|
-
* @param {NODE | undefined} node - The `node` parameter is of type `NODE | undefined`, which means
|
|
198
|
-
* it can either be of type `NODE` or `undefined`.
|
|
199
|
-
* @returns a boolean value.
|
|
200
|
-
*/
|
|
201
|
-
override isRealNode(node: NODE | undefined): node is NODE {
|
|
202
|
-
if (node === this.SENTINEL || node === undefined) return false;
|
|
203
|
-
return node instanceof RedBlackTreeNode;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* Time Complexity: O(log n)
|
|
208
|
-
* Space Complexity: O(1)
|
|
209
|
-
*/
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* Time Complexity: O(log n)
|
|
213
|
-
* Space Complexity: O(1)
|
|
214
|
-
*
|
|
215
|
-
* The `getNode` function retrieves a node from a Red-Black Tree based on the provided identifier and
|
|
216
|
-
* callback function.
|
|
217
|
-
* @param {ReturnType<C> | undefined} identifier - The `identifier` parameter is the value or key
|
|
218
|
-
* that you want to search for in the binary search tree. It can be of any type that is compatible
|
|
219
|
-
* with the type of nodes in the tree.
|
|
220
|
-
* @param {C} callback - The `callback` parameter is a function that will be called for each node in
|
|
221
|
-
* the tree. It is used to determine whether a node matches the given identifier. The `callback`
|
|
222
|
-
* function should take a node as its parameter and return a value that can be compared to the
|
|
223
|
-
* `identifier` parameter.
|
|
224
|
-
* @param beginRoot - The `beginRoot` parameter is the starting point for the search in the binary
|
|
225
|
-
* search tree. It can be either a key or a node. If it is a key, it will be converted to a node
|
|
226
|
-
* using the `ensureNode` method. If it is not provided, the `root`
|
|
227
|
-
* @param iterationType - The `iterationType` parameter is used to specify the type of iteration to
|
|
228
|
-
* be performed when searching for nodes in the binary search tree. It is an optional parameter and
|
|
229
|
-
* its default value is taken from the `iterationType` property of the class.
|
|
230
|
-
* @returns The method is returning a value of type `NODE | null | undefined`.
|
|
231
|
-
*/
|
|
232
|
-
override getNode<C extends BTNCallback<NODE>>(
|
|
233
|
-
identifier: ReturnType<C> | undefined,
|
|
234
|
-
callback: C = this._defaultOneParamCallback as C,
|
|
235
|
-
beginRoot: BSTNKeyOrNode<K, NODE> = this.root,
|
|
236
|
-
iterationType: IterationType = this.iterationType
|
|
237
|
-
): NODE | null | undefined {
|
|
238
|
-
return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? undefined;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
175
|
/**
|
|
242
176
|
* Time Complexity: O(1)
|
|
243
177
|
* Space Complexity: O(1)
|
|
@@ -252,7 +186,7 @@ export class RedBlackTree<
|
|
|
252
186
|
*/
|
|
253
187
|
override clear() {
|
|
254
188
|
super.clear();
|
|
255
|
-
this._root = this.
|
|
189
|
+
this._root = this.NIL;
|
|
256
190
|
}
|
|
257
191
|
|
|
258
192
|
/**
|
|
@@ -308,13 +242,13 @@ export class RedBlackTree<
|
|
|
308
242
|
* deleted is not found.
|
|
309
243
|
* @param {C} callback - The `callback` parameter is a function that is used to retrieve a node from
|
|
310
244
|
* the binary tree based on its identifier. It is an optional parameter and if not provided, the
|
|
311
|
-
* `
|
|
245
|
+
* `_DEFAULT_CALLBACK` function is used as the default callback. The callback function should
|
|
312
246
|
* return the identifier of the node to
|
|
313
247
|
* @returns an array of BinaryTreeDeleteResult<NODE> objects.
|
|
314
248
|
*/
|
|
315
249
|
override delete<C extends BTNCallback<NODE>>(
|
|
316
250
|
identifier: ReturnType<C> | null | undefined,
|
|
317
|
-
callback: C = this.
|
|
251
|
+
callback: C = this._DEFAULT_CALLBACK as C
|
|
318
252
|
): BinaryTreeDeleteResult<NODE>[] {
|
|
319
253
|
if (identifier === null) return [];
|
|
320
254
|
const results: BinaryTreeDeleteResult<NODE>[] = [];
|
|
@@ -430,9 +364,9 @@ export class RedBlackTree<
|
|
|
430
364
|
while (this.isRealNode(current)) {
|
|
431
365
|
parent = current;
|
|
432
366
|
if (node.key < current.key) {
|
|
433
|
-
current = current.left ?? this.
|
|
367
|
+
current = current.left ?? this.NIL;
|
|
434
368
|
} else if (node.key > current.key) {
|
|
435
|
-
current = current.right ?? this.
|
|
369
|
+
current = current.right ?? this.NIL;
|
|
436
370
|
} else {
|
|
437
371
|
this._replaceNode(current, node);
|
|
438
372
|
return 'UPDATED';
|
|
@@ -449,8 +383,8 @@ export class RedBlackTree<
|
|
|
449
383
|
parent.right = node;
|
|
450
384
|
}
|
|
451
385
|
|
|
452
|
-
node.left = this.
|
|
453
|
-
node.right = this.
|
|
386
|
+
node.left = this.NIL;
|
|
387
|
+
node.right = this.NIL;
|
|
454
388
|
node.color = 'RED';
|
|
455
389
|
|
|
456
390
|
this._insertFixup(node);
|
|
@@ -242,7 +242,7 @@ export class TreeMultiMap<
|
|
|
242
242
|
* function. It can also be null or undefined if no node needs to be deleted.
|
|
243
243
|
* @param {C} callback - The `callback` parameter is a function that takes a node of type `NODE` as
|
|
244
244
|
* input and returns a value of type `ReturnType<C>`. It is used to determine if a node matches the
|
|
245
|
-
* identifier for deletion. If no callback is provided, the `
|
|
245
|
+
* identifier for deletion. If no callback is provided, the `_DEFAULT_CALLBACK` function is
|
|
246
246
|
* used
|
|
247
247
|
* @param [ignoreCount=false] - A boolean value indicating whether to ignore the count of the target
|
|
248
248
|
* node when performing deletion. If set to true, the count of the target node will not be considered
|
|
@@ -252,7 +252,7 @@ export class TreeMultiMap<
|
|
|
252
252
|
*/
|
|
253
253
|
override delete<C extends BTNCallback<NODE>>(
|
|
254
254
|
identifier: ReturnType<C> | null | undefined,
|
|
255
|
-
callback: C = this.
|
|
255
|
+
callback: C = this._DEFAULT_CALLBACK as C,
|
|
256
256
|
ignoreCount = false
|
|
257
257
|
): BinaryTreeDeleteResult<NODE>[] {
|
|
258
258
|
if (identifier === null) return [];
|
|
@@ -12,6 +12,10 @@ suite
|
|
|
12
12
|
avlTree.clear();
|
|
13
13
|
for (let i = 0; i < randomArray.length; i++) avlTree.add(i);
|
|
14
14
|
})
|
|
15
|
+
.add(`${HUNDRED_THOUSAND.toLocaleString()} add randomly`, () => {
|
|
16
|
+
avlTree.clear();
|
|
17
|
+
for (let i = 0; i < randomArray.length; i++) avlTree.add(randomArray[i]);
|
|
18
|
+
})
|
|
15
19
|
.add(`${HUNDRED_THOUSAND.toLocaleString()} get`, () => {
|
|
16
20
|
for (let i = 0; i < randomArray.length; i++) avlTree.get(randomArray[i]);
|
|
17
21
|
})
|
|
@@ -15,6 +15,10 @@ suite
|
|
|
15
15
|
rbTree.clear();
|
|
16
16
|
for (let i = 0; i < randomArray.length; i++) rbTree.add(i);
|
|
17
17
|
})
|
|
18
|
+
.add(`${HUNDRED_THOUSAND.toLocaleString()} add randomly`, () => {
|
|
19
|
+
rbTree.clear();
|
|
20
|
+
for (let i = 0; i < randomArray.length; i++) rbTree.add(randomArray[i]);
|
|
21
|
+
})
|
|
18
22
|
.add(`${HUNDRED_THOUSAND.toLocaleString()} get`, () => {
|
|
19
23
|
for (let i = 0; i < randomArray.length; i++) rbTree.get(randomArray[i]);
|
|
20
24
|
})
|
|
@@ -20,8 +20,8 @@ describe('Overall BinaryTree Test', () => {
|
|
|
20
20
|
leftMost?.key === 1; // true
|
|
21
21
|
expect(leftMost?.key).toBe(1);
|
|
22
22
|
bst.delete(6);
|
|
23
|
-
bst.getNode(6); //
|
|
24
|
-
expect(bst.getNode(6)).
|
|
23
|
+
bst.getNode(6); // undefined
|
|
24
|
+
expect(bst.getNode(6)).toBe(undefined);
|
|
25
25
|
bst.isAVLBalanced(); // true or false
|
|
26
26
|
expect(bst.isAVLBalanced()).toBe(true);
|
|
27
27
|
const bfsIDs: number[] = [];
|
|
@@ -74,7 +74,7 @@ describe('RedBlackTree 1', () => {
|
|
|
74
74
|
|
|
75
75
|
it('should handle an empty rbTree', () => {
|
|
76
76
|
const minNode = rbTree.getLeftMost(rbTree.root);
|
|
77
|
-
expect(minNode).toBe(rbTree.
|
|
77
|
+
expect(minNode).toBe(rbTree.NIL);
|
|
78
78
|
});
|
|
79
79
|
});
|
|
80
80
|
|
|
@@ -92,7 +92,7 @@ describe('RedBlackTree 1', () => {
|
|
|
92
92
|
|
|
93
93
|
it('should handle an empty rbTree', () => {
|
|
94
94
|
const maxNode = rbTree.getRightMost(rbTree.root);
|
|
95
|
-
expect(maxNode).toBe(rbTree.
|
|
95
|
+
expect(maxNode).toBe(rbTree.NIL);
|
|
96
96
|
});
|
|
97
97
|
});
|
|
98
98
|
|
|
@@ -116,7 +116,7 @@ describe('RedBlackTree 1', () => {
|
|
|
116
116
|
|
|
117
117
|
const node = rbTree.getNode(10);
|
|
118
118
|
const successorNode = rbTree.getSuccessor(node!);
|
|
119
|
-
// TODO not sure if it should be undefined or rbTree.
|
|
119
|
+
// TODO not sure if it should be undefined or rbTree.NIL
|
|
120
120
|
expect(successorNode).toBe(undefined);
|
|
121
121
|
});
|
|
122
122
|
});
|
|
@@ -141,7 +141,7 @@ describe('RedBlackTree 1', () => {
|
|
|
141
141
|
|
|
142
142
|
const node = rbTree.getNode(20);
|
|
143
143
|
const predecessorNode = rbTree.getPredecessor(node!);
|
|
144
|
-
// TODO not sure if it should be rbTree.
|
|
144
|
+
// TODO not sure if it should be rbTree.NIL or something else.
|
|
145
145
|
expect(predecessorNode).toBe(rbTree.getNode(20));
|
|
146
146
|
});
|
|
147
147
|
});
|
|
@@ -279,28 +279,28 @@ describe('RedBlackTree 2', () => {
|
|
|
279
279
|
expect(node5F?.parent).toBe(node10F);
|
|
280
280
|
expect(node15F?.key).toBe(15);
|
|
281
281
|
expect(node15F?.color).toBe('RED');
|
|
282
|
-
expect(node15F?.left).toBe(rbTree.
|
|
283
|
-
expect(node15F?.right).toBe(rbTree.
|
|
282
|
+
expect(node15F?.left).toBe(rbTree.NIL);
|
|
283
|
+
expect(node15F?.right).toBe(rbTree.NIL);
|
|
284
284
|
expect(node15F?.parent).toBe(node20F);
|
|
285
285
|
expect(node21F?.key).toBe(21);
|
|
286
286
|
expect(node21F?.color).toBe('RED');
|
|
287
|
-
expect(node21F?.left).toBe(rbTree.
|
|
288
|
-
expect(node21F?.right).toBe(rbTree.
|
|
287
|
+
expect(node21F?.left).toBe(rbTree.NIL);
|
|
288
|
+
expect(node21F?.right).toBe(rbTree.NIL);
|
|
289
289
|
expect(node21F?.parent).toBe(node20F);
|
|
290
290
|
expect(node6F?.key).toBe(6);
|
|
291
291
|
expect(node6F?.color).toBe('RED');
|
|
292
|
-
expect(node6F?.left).toBe(rbTree.
|
|
293
|
-
expect(node6F?.right).toBe(rbTree.
|
|
292
|
+
expect(node6F?.left).toBe(rbTree.NIL);
|
|
293
|
+
expect(node6F?.right).toBe(rbTree.NIL);
|
|
294
294
|
expect(node6F?.parent).toBe(node5F);
|
|
295
295
|
expect(node2F?.key).toBe(2);
|
|
296
296
|
expect(node2F?.color).toBe('RED');
|
|
297
|
-
expect(node2F?.left).toBe(rbTree.
|
|
298
|
-
expect(node2F?.right).toBe(rbTree.
|
|
297
|
+
expect(node2F?.left).toBe(rbTree.NIL);
|
|
298
|
+
expect(node2F?.right).toBe(rbTree.NIL);
|
|
299
299
|
expect(node2F?.parent).toBe(node5F);
|
|
300
300
|
expect(node15F?.key).toBe(15);
|
|
301
301
|
expect(node15F?.color).toBe('RED');
|
|
302
|
-
expect(node15F?.left).toBe(rbTree.
|
|
303
|
-
expect(node15F?.right).toBe(rbTree.
|
|
302
|
+
expect(node15F?.left).toBe(rbTree.NIL);
|
|
303
|
+
expect(node15F?.right).toBe(rbTree.NIL);
|
|
304
304
|
expect(node15F?.parent).toBe(node20F);
|
|
305
305
|
rbTree.delete(5);
|
|
306
306
|
node10F = rbTree.getNode(10);
|
|
@@ -323,28 +323,28 @@ describe('RedBlackTree 2', () => {
|
|
|
323
323
|
expect(node5F).toBe(undefined);
|
|
324
324
|
expect(node15F?.key).toBe(15);
|
|
325
325
|
expect(node15F?.color).toBe('RED');
|
|
326
|
-
expect(node15F?.left).toBe(rbTree.
|
|
327
|
-
expect(node15F?.right).toBe(rbTree.
|
|
326
|
+
expect(node15F?.left).toBe(rbTree.NIL);
|
|
327
|
+
expect(node15F?.right).toBe(rbTree.NIL);
|
|
328
328
|
expect(node15F?.parent).toBe(node20F);
|
|
329
329
|
expect(node21F?.key).toBe(21);
|
|
330
330
|
expect(node21F?.color).toBe('RED');
|
|
331
|
-
expect(node21F?.left).toBe(rbTree.
|
|
332
|
-
expect(node21F?.right).toBe(rbTree.
|
|
331
|
+
expect(node21F?.left).toBe(rbTree.NIL);
|
|
332
|
+
expect(node21F?.right).toBe(rbTree.NIL);
|
|
333
333
|
expect(node21F?.parent).toBe(node20F);
|
|
334
334
|
expect(node6F?.key).toBe(6);
|
|
335
335
|
expect(node6F?.color).toBe('BLACK');
|
|
336
336
|
expect(node6F?.left).toBe(node2F);
|
|
337
|
-
expect(node6F?.right).toBe(rbTree.
|
|
337
|
+
expect(node6F?.right).toBe(rbTree.NIL);
|
|
338
338
|
expect(node6F?.parent).toBe(node10F);
|
|
339
339
|
expect(node2F?.key).toBe(2);
|
|
340
340
|
expect(node2F?.color).toBe('RED');
|
|
341
|
-
expect(node2F?.left).toBe(rbTree.
|
|
342
|
-
expect(node2F?.right).toBe(rbTree.
|
|
341
|
+
expect(node2F?.left).toBe(rbTree.NIL);
|
|
342
|
+
expect(node2F?.right).toBe(rbTree.NIL);
|
|
343
343
|
expect(node2F?.parent).toBe(node6F);
|
|
344
344
|
expect(node15F?.key).toBe(15);
|
|
345
345
|
expect(node15F?.color).toBe('RED');
|
|
346
|
-
expect(node15F?.left).toBe(rbTree.
|
|
347
|
-
expect(node15F?.right).toBe(rbTree.
|
|
346
|
+
expect(node15F?.left).toBe(rbTree.NIL);
|
|
347
|
+
expect(node15F?.right).toBe(rbTree.NIL);
|
|
348
348
|
expect(node15F?.parent).toBe(node20F);
|
|
349
349
|
rbTree.delete(20);
|
|
350
350
|
node10F = rbTree.getNode(10);
|
|
@@ -363,28 +363,28 @@ describe('RedBlackTree 2', () => {
|
|
|
363
363
|
expect(node5F).toBe(undefined);
|
|
364
364
|
expect(node15F?.key).toBe(15);
|
|
365
365
|
expect(node15F?.color).toBe('RED');
|
|
366
|
-
expect(node15F?.left).toBe(rbTree.
|
|
367
|
-
expect(node15F?.right).toBe(rbTree.
|
|
366
|
+
expect(node15F?.left).toBe(rbTree.NIL);
|
|
367
|
+
expect(node15F?.right).toBe(rbTree.NIL);
|
|
368
368
|
expect(node15F?.parent).toBe(node21F);
|
|
369
369
|
expect(node21F?.key).toBe(21);
|
|
370
370
|
expect(node21F?.color).toBe('BLACK');
|
|
371
371
|
expect(node21F?.left).toBe(node15F);
|
|
372
|
-
expect(node21F?.right).toBe(rbTree.
|
|
372
|
+
expect(node21F?.right).toBe(rbTree.NIL);
|
|
373
373
|
expect(node21F?.parent).toBe(node10F);
|
|
374
374
|
expect(node6F?.key).toBe(6);
|
|
375
375
|
expect(node6F?.color).toBe('BLACK');
|
|
376
376
|
expect(node6F?.left).toBe(node2F);
|
|
377
|
-
expect(node6F?.right).toBe(rbTree.
|
|
377
|
+
expect(node6F?.right).toBe(rbTree.NIL);
|
|
378
378
|
expect(node6F?.parent).toBe(node10F);
|
|
379
379
|
expect(node2F?.key).toBe(2);
|
|
380
380
|
expect(node2F?.color).toBe('RED');
|
|
381
|
-
expect(node2F?.left).toBe(rbTree.
|
|
382
|
-
expect(node2F?.right).toBe(rbTree.
|
|
381
|
+
expect(node2F?.left).toBe(rbTree.NIL);
|
|
382
|
+
expect(node2F?.right).toBe(rbTree.NIL);
|
|
383
383
|
expect(node2F?.parent).toBe(node6F);
|
|
384
384
|
expect(node15F?.key).toBe(15);
|
|
385
385
|
expect(node15F?.color).toBe('RED');
|
|
386
|
-
expect(node15F?.left).toBe(rbTree.
|
|
387
|
-
expect(node15F?.right).toBe(rbTree.
|
|
386
|
+
expect(node15F?.left).toBe(rbTree.NIL);
|
|
387
|
+
expect(node15F?.right).toBe(rbTree.NIL);
|
|
388
388
|
expect(node15F?.parent).toBe(node21F);
|
|
389
389
|
});
|
|
390
390
|
|
|
@@ -394,8 +394,8 @@ describe('RedBlackTree 2', () => {
|
|
|
394
394
|
rbTree.add(5);
|
|
395
395
|
rbTree.add(15);
|
|
396
396
|
const node15F = rbTree.getNode(15);
|
|
397
|
-
expect(node15F?.left).toBe(rbTree.
|
|
398
|
-
expect(node15F?.right).toBe(rbTree.
|
|
397
|
+
expect(node15F?.left).toBe(rbTree.NIL);
|
|
398
|
+
expect(node15F?.right).toBe(rbTree.NIL);
|
|
399
399
|
expect(node15F?.parent).toBe(rbTree.getNode(5));
|
|
400
400
|
|
|
401
401
|
rbTree.add(25);
|
|
@@ -410,8 +410,8 @@ describe('RedBlackTree 2', () => {
|
|
|
410
410
|
rbTree.add(155);
|
|
411
411
|
rbTree.add(225);
|
|
412
412
|
const node225F = rbTree.getNode(225);
|
|
413
|
-
expect(node225F?.left).toBe(rbTree.
|
|
414
|
-
expect(node225F?.right).toBe(rbTree.
|
|
413
|
+
expect(node225F?.left).toBe(rbTree.NIL);
|
|
414
|
+
expect(node225F?.right).toBe(rbTree.NIL);
|
|
415
415
|
expect(node225F?.parent?.key).toBe(155);
|
|
416
416
|
rbTree.add(7);
|
|
417
417
|
isDebug && rbTree.print();
|
|
@@ -438,14 +438,14 @@ describe('RedBlackTree 2', () => {
|
|
|
438
438
|
const node50 = rbTree.getNode(50);
|
|
439
439
|
expect(node50?.key).toBe(50);
|
|
440
440
|
expect(node50?.left?.key).toBe(33);
|
|
441
|
-
expect(node50?.right).toBe(rbTree.
|
|
441
|
+
expect(node50?.right).toBe(rbTree.NIL);
|
|
442
442
|
const node15Fo = rbTree.getNode(15);
|
|
443
443
|
|
|
444
444
|
expect(node15Fo?.key).toBe(15);
|
|
445
|
-
expect(node15Fo?.left).toBe(rbTree.
|
|
445
|
+
expect(node15Fo?.left).toBe(rbTree.NIL);
|
|
446
446
|
const node225S = rbTree.getNode(225);
|
|
447
|
-
expect(node225S?.left).toBe(rbTree.
|
|
448
|
-
expect(node225S?.right).toBe(rbTree.
|
|
447
|
+
expect(node225S?.left).toBe(rbTree.NIL);
|
|
448
|
+
expect(node225S?.right).toBe(rbTree.NIL);
|
|
449
449
|
expect(node225S?.parent?.key).toBe(155);
|
|
450
450
|
// TODO
|
|
451
451
|
// expect(rbTree.getNode(0)).toBe(undefined);
|
|
@@ -512,7 +512,7 @@ describe('RedBlackTree 2', () => {
|
|
|
512
512
|
rbTree.delete(getRandomInt(-100, 1000));
|
|
513
513
|
}
|
|
514
514
|
|
|
515
|
-
// TODO there is a bug when dfs the rbTree with
|
|
515
|
+
// TODO there is a bug when dfs the rbTree with NIL node
|
|
516
516
|
// expect(rbTree.isBST()).toBe(true);
|
|
517
517
|
});
|
|
518
518
|
const { HUNDRED_THOUSAND } = magnitude;
|
|
@@ -45,6 +45,7 @@ describe('TreeMultiMap operations test1', () => {
|
|
|
45
45
|
expect(tmm.getMinHeight()).toBe(-1);
|
|
46
46
|
|
|
47
47
|
tmm.addMany([1, 6, 7, 2, 3, 4, 9, 11, 8, 5, 10, 12, 16, 14, 13, 15]);
|
|
48
|
+
// tmm.print()
|
|
48
49
|
expect(tmm.getHeight()).toBe(5);
|
|
49
50
|
expect(tmm.getMinHeight()).toBe(2);
|
|
50
51
|
});
|
package/test/utils/big-o.ts
CHANGED
|
@@ -205,3 +205,15 @@ export function logBigOMetrics(target: any, propertyKey: string, descriptor: Pro
|
|
|
205
205
|
|
|
206
206
|
return descriptor;
|
|
207
207
|
}
|
|
208
|
+
|
|
209
|
+
export const logPerf = function (fn: (...args: any[]) => any, args: any[], thisArg?: any) {
|
|
210
|
+
const start = performance.now();
|
|
211
|
+
if (thisArg) {
|
|
212
|
+
if (args && args.length > 0) fn.apply(thisArg, args);
|
|
213
|
+
else fn.apply(thisArg);
|
|
214
|
+
} else {
|
|
215
|
+
if (args && args.length > 0) fn(...args);
|
|
216
|
+
else fn();
|
|
217
|
+
}
|
|
218
|
+
console.log(`function running cost : ${(performance.now() - start).toFixed(2)} ms`);
|
|
219
|
+
};
|