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.
Files changed (48) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/README.md +13 -13
  3. package/benchmark/report.html +37 -1
  4. package/benchmark/report.json +390 -12
  5. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js +1 -1
  6. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
  7. package/dist/cjs/data-structures/binary-tree/avl-tree.d.ts +1 -1
  8. package/dist/cjs/data-structures/binary-tree/avl-tree.js +2 -2
  9. package/dist/cjs/data-structures/binary-tree/avl-tree.js.map +1 -1
  10. package/dist/cjs/data-structures/binary-tree/binary-tree.d.ts +17 -11
  11. package/dist/cjs/data-structures/binary-tree/binary-tree.js +98 -92
  12. package/dist/cjs/data-structures/binary-tree/binary-tree.js.map +1 -1
  13. package/dist/cjs/data-structures/binary-tree/bst.d.ts +27 -1
  14. package/dist/cjs/data-structures/binary-tree/bst.js +68 -39
  15. package/dist/cjs/data-structures/binary-tree/bst.js.map +1 -1
  16. package/dist/cjs/data-structures/binary-tree/rb-tree.d.ts +2 -48
  17. package/dist/cjs/data-structures/binary-tree/rb-tree.js +8 -63
  18. package/dist/cjs/data-structures/binary-tree/rb-tree.js.map +1 -1
  19. package/dist/cjs/data-structures/binary-tree/tree-multi-map.d.ts +1 -1
  20. package/dist/cjs/data-structures/binary-tree/tree-multi-map.js +2 -2
  21. package/dist/cjs/data-structures/binary-tree/tree-multi-map.js.map +1 -1
  22. package/dist/mjs/data-structures/binary-tree/avl-tree-multi-map.js +1 -1
  23. package/dist/mjs/data-structures/binary-tree/avl-tree.d.ts +1 -1
  24. package/dist/mjs/data-structures/binary-tree/avl-tree.js +2 -2
  25. package/dist/mjs/data-structures/binary-tree/binary-tree.d.ts +17 -11
  26. package/dist/mjs/data-structures/binary-tree/binary-tree.js +98 -92
  27. package/dist/mjs/data-structures/binary-tree/bst.d.ts +27 -1
  28. package/dist/mjs/data-structures/binary-tree/bst.js +67 -39
  29. package/dist/mjs/data-structures/binary-tree/rb-tree.d.ts +2 -48
  30. package/dist/mjs/data-structures/binary-tree/rb-tree.js +8 -62
  31. package/dist/mjs/data-structures/binary-tree/tree-multi-map.d.ts +1 -1
  32. package/dist/mjs/data-structures/binary-tree/tree-multi-map.js +2 -2
  33. package/dist/umd/data-structure-typed.js +178 -198
  34. package/dist/umd/data-structure-typed.min.js +2 -2
  35. package/dist/umd/data-structure-typed.min.js.map +1 -1
  36. package/package.json +6 -6
  37. package/src/data-structures/binary-tree/avl-tree-multi-map.ts +1 -1
  38. package/src/data-structures/binary-tree/avl-tree.ts +2 -2
  39. package/src/data-structures/binary-tree/binary-tree.ts +98 -93
  40. package/src/data-structures/binary-tree/bst.ts +69 -34
  41. package/src/data-structures/binary-tree/rb-tree.ts +8 -74
  42. package/src/data-structures/binary-tree/tree-multi-map.ts +2 -2
  43. package/test/performance/data-structures/binary-tree/avl-tree.test.ts +4 -0
  44. package/test/performance/data-structures/binary-tree/rb-tree.test.ts +4 -0
  45. package/test/unit/data-structures/binary-tree/overall.test.ts +2 -2
  46. package/test/unit/data-structures/binary-tree/rb-tree.test.ts +40 -40
  47. package/test/unit/data-structures/binary-tree/tree-multi-map.test.ts +1 -0
  48. 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
- res = keyOrNodeOrEntry;
218
+ return keyOrNodeOrEntry;
220
219
  } else if (this.isEntry(keyOrNodeOrEntry)) {
221
- if (keyOrNodeOrEntry[0]) res = this.getNodeByKey(keyOrNodeOrEntry[0], iterationType);
220
+ if (keyOrNodeOrEntry[0] === null || keyOrNodeOrEntry[0] === undefined) return;
221
+ return this.getNodeByKey(keyOrNodeOrEntry[0], iterationType);
222
222
  } else {
223
- if (keyOrNodeOrEntry) res = this.getNodeByKey(keyOrNodeOrEntry, iterationType);
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._defaultOneParamCallback, true, this.root, iterationType)[0];
430
- if (!this.isRealNode(this.root)) return undefined;
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 _dfs = (cur: NODE): NODE | undefined => {
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' && this.isRealNode(cur.left)) return _dfs(cur.left);
437
- if (this._compare(cur.key, key) === 'LT' && this.isRealNode(cur.right)) return _dfs(cur.right);
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 _dfs(this.root);
440
+ return dfs(this.root);
441
441
  } else {
442
- const queue = new Queue<NODE>([this.root]);
443
- while (queue.size > 0) {
444
- const cur = queue.shift();
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') this.isRealNode(cur.left) && queue.push(cur.left);
448
- if (this._compare(cur.key, key) === 'LT') this.isRealNode(cur.right) && queue.push(cur.right);
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._defaultOneParamCallback as C,
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 _traverse = (cur: NODE) => {
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._defaultOneParamCallback) {
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);
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) && _traverse(cur.left);
508
- this.isRealNode(cur.right) && _traverse(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
- _traverse(beginRoot);
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._defaultOneParamCallback) {
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._defaultOneParamCallback as C,
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._defaultOneParamCallback as C,
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._defaultOneParamCallback as C,
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._defaultOneParamCallback as C,
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 _traverse = (cur: NODE) => {
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)) _traverse(cur.left);
721
- if (this.isRealNode(cur.right)) _traverse(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
- _traverse(this.root);
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.SENTINEL;
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.SENTINEL;
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
- * `_defaultOneParamCallback` function is used as the default callback. The callback function should
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._defaultOneParamCallback as C
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.SENTINEL;
367
+ current = current.left ?? this.NIL;
434
368
  } else if (node.key > current.key) {
435
- current = current.right ?? this.SENTINEL;
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.SENTINEL;
453
- node.right = this.SENTINEL;
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 `_defaultOneParamCallback` function is
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._defaultOneParamCallback as C,
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); // null
24
- expect(bst.getNode(6)).toBeNull();
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.SENTINEL);
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.SENTINEL);
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.SENTINEL
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.SENTINEL or something else.
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.SENTINEL);
283
- expect(node15F?.right).toBe(rbTree.SENTINEL);
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.SENTINEL);
288
- expect(node21F?.right).toBe(rbTree.SENTINEL);
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.SENTINEL);
293
- expect(node6F?.right).toBe(rbTree.SENTINEL);
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.SENTINEL);
298
- expect(node2F?.right).toBe(rbTree.SENTINEL);
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.SENTINEL);
303
- expect(node15F?.right).toBe(rbTree.SENTINEL);
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.SENTINEL);
327
- expect(node15F?.right).toBe(rbTree.SENTINEL);
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.SENTINEL);
332
- expect(node21F?.right).toBe(rbTree.SENTINEL);
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.SENTINEL);
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.SENTINEL);
342
- expect(node2F?.right).toBe(rbTree.SENTINEL);
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.SENTINEL);
347
- expect(node15F?.right).toBe(rbTree.SENTINEL);
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.SENTINEL);
367
- expect(node15F?.right).toBe(rbTree.SENTINEL);
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.SENTINEL);
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.SENTINEL);
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.SENTINEL);
382
- expect(node2F?.right).toBe(rbTree.SENTINEL);
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.SENTINEL);
387
- expect(node15F?.right).toBe(rbTree.SENTINEL);
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.SENTINEL);
398
- expect(node15F?.right).toBe(rbTree.SENTINEL);
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.SENTINEL);
414
- expect(node225F?.right).toBe(rbTree.SENTINEL);
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.SENTINEL);
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.SENTINEL);
445
+ expect(node15Fo?.left).toBe(rbTree.NIL);
446
446
  const node225S = rbTree.getNode(225);
447
- expect(node225S?.left).toBe(rbTree.SENTINEL);
448
- expect(node225S?.right).toBe(rbTree.SENTINEL);
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 SENTINEL node
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
  });
@@ -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
+ };