min-heap-typed 1.42.3 → 1.42.5

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 (34) hide show
  1. package/.prettierignore +1 -1
  2. package/README.md +1 -1
  3. package/dist/data-structures/binary-tree/avl-tree.d.ts +2 -2
  4. package/dist/data-structures/binary-tree/avl-tree.js +5 -3
  5. package/dist/data-structures/binary-tree/binary-tree.d.ts +56 -52
  6. package/dist/data-structures/binary-tree/binary-tree.js +115 -53
  7. package/dist/data-structures/binary-tree/bst.d.ts +42 -15
  8. package/dist/data-structures/binary-tree/bst.js +77 -21
  9. package/dist/data-structures/binary-tree/index.d.ts +1 -1
  10. package/dist/data-structures/binary-tree/index.js +1 -1
  11. package/dist/data-structures/binary-tree/rb-tree.d.ts +28 -51
  12. package/dist/data-structures/binary-tree/rb-tree.js +148 -180
  13. package/dist/data-structures/binary-tree/{tree-multiset.d.ts → tree-multimap.d.ts} +20 -20
  14. package/dist/data-structures/binary-tree/{tree-multiset.js → tree-multimap.js} +34 -31
  15. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +1 -1
  16. package/dist/types/data-structures/binary-tree/index.d.ts +1 -1
  17. package/dist/types/data-structures/binary-tree/index.js +1 -1
  18. package/dist/types/data-structures/binary-tree/rb-tree.d.ts +4 -0
  19. package/dist/types/data-structures/binary-tree/rb-tree.js +0 -5
  20. package/dist/types/data-structures/binary-tree/tree-multimap.d.ts +4 -0
  21. package/package.json +2 -2
  22. package/src/data-structures/binary-tree/avl-tree.ts +5 -4
  23. package/src/data-structures/binary-tree/binary-tree.ts +201 -131
  24. package/src/data-structures/binary-tree/bst.ts +100 -34
  25. package/src/data-structures/binary-tree/index.ts +1 -1
  26. package/src/data-structures/binary-tree/rb-tree.ts +227 -236
  27. package/src/data-structures/binary-tree/{tree-multiset.ts → tree-multimap.ts} +38 -37
  28. package/src/types/data-structures/binary-tree/binary-tree.ts +1 -1
  29. package/src/types/data-structures/binary-tree/index.ts +1 -1
  30. package/src/types/data-structures/binary-tree/rb-tree.ts +5 -5
  31. package/src/types/data-structures/binary-tree/tree-multimap.ts +6 -0
  32. package/dist/types/data-structures/binary-tree/tree-multiset.d.ts +0 -4
  33. package/src/types/data-structures/binary-tree/tree-multiset.ts +0 -6
  34. /package/dist/types/data-structures/binary-tree/{tree-multiset.js → tree-multimap.js} +0 -0
@@ -123,12 +123,12 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
123
123
  }
124
124
  }
125
125
 
126
- protected _root: N | null = null;
126
+ protected _root: N | null | undefined = undefined;
127
127
 
128
128
  /**
129
129
  * Get the root node of the binary tree.
130
130
  */
131
- get root(): N | null {
131
+ get root(): N | null | undefined {
132
132
  return this._root;
133
133
  }
134
134
 
@@ -155,7 +155,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
155
155
  * Clear the binary tree, removing all nodes.
156
156
  */
157
157
  clear() {
158
- this._setRoot(null);
158
+ this._setRoot(undefined);
159
159
  this._size = 0;
160
160
  }
161
161
 
@@ -173,7 +173,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
173
173
  * @param {V} value - The value for the new node (optional).
174
174
  * @returns {N | null | undefined} - The inserted node, or null if nothing was inserted, or undefined if the operation failed.
175
175
  */
176
- add(keyOrNode: BTNKey | N | null, value?: V): N | null | undefined {
176
+ add(keyOrNode: BTNKey | N | null | undefined, value?: V): N | null | undefined {
177
177
  const _bfs = (root: N, newNode: N | null): N | undefined | null => {
178
178
  const queue = new Queue<N | null>([root]);
179
179
  while (queue.size > 0) {
@@ -236,7 +236,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
236
236
  * the value of the nodes will be `undefined`.
237
237
  * @returns The function `addMany` returns an array of `N`, `null`, or `undefined` values.
238
238
  */
239
- addMany(keysOrNodes: (BTNKey | null)[] | (N | null)[], values?: V[]): (N | null | undefined)[] {
239
+ addMany(keysOrNodes: (BTNKey | null | undefined)[] | (N | null | undefined)[], values?: V[]): (N | null | undefined)[] {
240
240
  // TODO not sure addMany not be run multi times
241
241
  return keysOrNodes.map((keyOrNode, i) => {
242
242
  if (keyOrNode instanceof BinaryTreeNode) {
@@ -261,14 +261,14 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
261
261
  * array. Each value in the `data` array will be assigned to the
262
262
  * @returns The method is returning a boolean value.
263
263
  */
264
- refill(keysOrNodes: (BTNKey | null)[] | (N | null)[], data?: Array<V>): boolean {
264
+ refill(keysOrNodes: (BTNKey | null | undefined)[] | (N | null | undefined)[], data?: Array<V>): boolean {
265
265
  this.clear();
266
266
  return keysOrNodes.length === this.addMany(keysOrNodes, data).length;
267
267
  }
268
268
 
269
269
  delete<C extends BTNCallback<N, BTNKey>>(identifier: BTNKey, callback?: C): BinaryTreeDeletedResult<N>[];
270
270
 
271
- delete<C extends BTNCallback<N, N>>(identifier: N | null, callback?: C): BinaryTreeDeletedResult<N>[];
271
+ delete<C extends BTNCallback<N, N>>(identifier: N | null | undefined, callback?: C): BinaryTreeDeletedResult<N>[];
272
272
 
273
273
  delete<C extends BTNCallback<N>>(identifier: ReturnType<C>, callback: C): BinaryTreeDeletedResult<N>[];
274
274
 
@@ -287,7 +287,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
287
287
  * `this.defaultOneParamCallback`, which
288
288
  */
289
289
  delete<C extends BTNCallback<N>>(
290
- identifier: ReturnType<C> | null,
290
+ identifier: ReturnType<C> | null | undefined,
291
291
  callback: C = this.defaultOneParamCallback as C
292
292
  ): BinaryTreeDeletedResult<N>[] {
293
293
  const bstDeletedResult: BinaryTreeDeletedResult<N>[] = [];
@@ -297,8 +297,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
297
297
  const curr = this.getNode(identifier, callback);
298
298
  if (!curr) return bstDeletedResult;
299
299
 
300
- const parent: N | null = curr?.parent ? curr.parent : null;
301
- let needBalanced: N | null = null,
300
+ const parent: N | null | undefined = curr?.parent ? curr.parent : null;
301
+ let needBalanced: N | null | undefined = null,
302
302
  orgCurrent = curr;
303
303
 
304
304
  if (!curr.left) {
@@ -336,16 +336,16 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
336
336
  /**
337
337
  * The function `getDepth` calculates the depth of a given node in a binary tree relative to a
338
338
  * specified root node.
339
- * @param {BTNKey | N | null} distNode - The `distNode` parameter represents the node
339
+ * @param {BTNKey | N | null | undefined} distNode - The `distNode` parameter represents the node
340
340
  * whose depth we want to find in the binary tree. It can be either a node object (`N`), a key value
341
341
  * of the node (`BTNKey`), or `null`.
342
- * @param {BTNKey | N | null} beginRoot - The `beginRoot` parameter represents the
342
+ * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
343
343
  * starting node from which we want to calculate the depth. It can be either a node object or the key
344
344
  * of a node in the binary tree. If no value is provided for `beginRoot`, it defaults to the root
345
345
  * node of the binary tree.
346
346
  * @returns the depth of the `distNode` relative to the `beginRoot`.
347
347
  */
348
- getDepth(distNode: BTNKey | N | null, beginRoot: BTNKey | N | null = this.root): number {
348
+ getDepth(distNode: BTNKey | N | null | undefined, beginRoot: BTNKey | N | null | undefined = this.root): number {
349
349
  if (typeof distNode === 'number') distNode = this.getNode(distNode);
350
350
  if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);
351
351
  let depth = 0;
@@ -362,7 +362,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
362
362
  /**
363
363
  * The `getHeight` function calculates the maximum height of a binary tree using either recursive or
364
364
  * iterative approach.
365
- * @param {BTNKey | N | null} beginRoot - The `beginRoot` parameter represents the
365
+ * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
366
366
  * starting node from which the height of the binary tree is calculated. It can be either a node
367
367
  * object (`N`), a key value of a node in the tree (`BTNKey`), or `null` if no starting
368
368
  * node is specified. If `
@@ -371,7 +371,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
371
371
  * possible values:
372
372
  * @returns the height of the binary tree.
373
373
  */
374
- getHeight(beginRoot: BTNKey | N | null = this.root, iterationType = this.iterationType): number {
374
+ getHeight(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.iterationType): number {
375
375
  if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);
376
376
  if (!beginRoot) return -1;
377
377
 
@@ -413,14 +413,14 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
413
413
  /**
414
414
  * The `getMinHeight` function calculates the minimum height of a binary tree using either a
415
415
  * recursive or iterative approach.
416
- * @param {N | null} beginRoot - The `beginRoot` parameter is the starting node from which we want to
416
+ * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node from which we want to
417
417
  * calculate the minimum height of the tree. It is optional and defaults to the root of the tree if
418
418
  * not provided.
419
419
  * @param iterationType - The `iterationType` parameter is used to determine the method of iteration
420
420
  * to calculate the minimum height of a binary tree. It can have two possible values:
421
421
  * @returns The function `getMinHeight` returns the minimum height of a binary tree.
422
422
  */
423
- getMinHeight(beginRoot: N | null = this.root, iterationType = this.iterationType): number {
423
+ getMinHeight(beginRoot: N | null | undefined = this.root, iterationType = this.iterationType): number {
424
424
  if (!beginRoot) return -1;
425
425
 
426
426
  if (iterationType === IterationType.RECURSIVE) {
@@ -436,7 +436,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
436
436
  } else {
437
437
  const stack: N[] = [];
438
438
  let node: N | null | undefined = beginRoot,
439
- last: N | null = null;
439
+ last: N | null | undefined = null;
440
440
  const depths: Map<N, number> = new Map();
441
441
 
442
442
  while (stack.length > 0 || node) {
@@ -465,11 +465,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
465
465
  /**
466
466
  * The function checks if a binary tree is perfectly balanced by comparing the minimum height and the
467
467
  * height of the tree.
468
- * @param {N | null} beginRoot - The parameter `beginRoot` is of type `N | null`, which means it can
468
+ * @param {N | null | undefined} beginRoot - The parameter `beginRoot` is of type `N | null | undefined`, which means it can
469
469
  * either be of type `N` (representing a node in a tree) or `null` (representing an empty tree).
470
470
  * @returns The method is returning a boolean value.
471
471
  */
472
- isPerfectlyBalanced(beginRoot: N | null = this.root): boolean {
472
+ isPerfectlyBalanced(beginRoot: N | null | undefined = this.root): boolean {
473
473
  return this.getMinHeight(beginRoot) + 1 >= this.getHeight(beginRoot);
474
474
  }
475
475
 
@@ -477,15 +477,15 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
477
477
  identifier: BTNKey,
478
478
  callback?: C,
479
479
  onlyOne?: boolean,
480
- beginRoot?: N | null,
480
+ beginRoot?: N | null | undefined,
481
481
  iterationType?: IterationType
482
482
  ): N[];
483
483
 
484
484
  getNodes<C extends BTNCallback<N, N>>(
485
- identifier: N | null,
485
+ identifier: N | null | undefined,
486
486
  callback?: C,
487
487
  onlyOne?: boolean,
488
- beginRoot?: N | null,
488
+ beginRoot?: N | null | undefined,
489
489
  iterationType?: IterationType
490
490
  ): N[];
491
491
 
@@ -493,7 +493,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
493
493
  identifier: ReturnType<C>,
494
494
  callback: C,
495
495
  onlyOne?: boolean,
496
- beginRoot?: N | null,
496
+ beginRoot?: N | null | undefined,
497
497
  iterationType?: IterationType
498
498
  ): N[];
499
499
 
@@ -511,7 +511,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
511
511
  * first node that matches the identifier. If set to true, the function will return an array with
512
512
  * only one element (or an empty array if no matching node is found). If set to false (default), the
513
513
  * function will continue searching for all
514
- * @param {N | null} beginRoot - The `beginRoot` parameter is the starting node from which the
514
+ * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node from which the
515
515
  * traversal of the binary tree will begin. It is optional and defaults to the root of the binary
516
516
  * tree.
517
517
  * @param iterationType - The `iterationType` parameter determines the type of iteration used to
@@ -519,10 +519,10 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
519
519
  * @returns The function `getNodes` returns an array of nodes (`N[]`).
520
520
  */
521
521
  getNodes<C extends BTNCallback<N>>(
522
- identifier: ReturnType<C> | null,
522
+ identifier: ReturnType<C> | null | undefined,
523
523
  callback: C = this.defaultOneParamCallback as C,
524
524
  onlyOne = false,
525
- beginRoot: N | null = this.root,
525
+ beginRoot: N | null | undefined = this.root,
526
526
  iterationType = this.iterationType
527
527
  ): N[] {
528
528
  if (!beginRoot) return [];
@@ -562,21 +562,21 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
562
562
  has<C extends BTNCallback<N, BTNKey>>(
563
563
  identifier: BTNKey,
564
564
  callback?: C,
565
- beginRoot?: N | null,
565
+ beginRoot?: N | null | undefined,
566
566
  iterationType?: IterationType
567
567
  ): boolean;
568
568
 
569
569
  has<C extends BTNCallback<N, N>>(
570
- identifier: N | null,
570
+ identifier: N | null | undefined,
571
571
  callback?: C,
572
- beginRoot?: N | null,
572
+ beginRoot?: N | null | undefined,
573
573
  iterationType?: IterationType
574
574
  ): boolean;
575
575
 
576
576
  has<C extends BTNCallback<N>>(
577
- identifier: ReturnType<C> | null,
577
+ identifier: ReturnType<C> | null | undefined,
578
578
  callback: C,
579
- beginRoot?: N | null,
579
+ beginRoot?: N | null | undefined,
580
580
  iterationType?: IterationType
581
581
  ): boolean;
582
582
 
@@ -598,7 +598,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
598
598
  * @returns a boolean value.
599
599
  */
600
600
  has<C extends BTNCallback<N>>(
601
- identifier: ReturnType<C> | null,
601
+ identifier: ReturnType<C> | null | undefined,
602
602
  callback: C = this.defaultOneParamCallback as C,
603
603
  beginRoot = this.root,
604
604
  iterationType = this.iterationType
@@ -611,23 +611,23 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
611
611
  getNode<C extends BTNCallback<N, BTNKey>>(
612
612
  identifier: BTNKey,
613
613
  callback?: C,
614
- beginRoot?: N | null,
614
+ beginRoot?: N | null | undefined,
615
615
  iterationType?: IterationType
616
- ): N | null;
616
+ ): N | null | undefined;
617
617
 
618
618
  getNode<C extends BTNCallback<N, N>>(
619
- identifier: N | null,
619
+ identifier: N | null | undefined,
620
620
  callback?: C,
621
- beginRoot?: N | null,
621
+ beginRoot?: N | null | undefined,
622
622
  iterationType?: IterationType
623
- ): N | null;
623
+ ): N | null | undefined;
624
624
 
625
625
  getNode<C extends BTNCallback<N>>(
626
626
  identifier: ReturnType<C>,
627
627
  callback: C,
628
- beginRoot?: N | null,
628
+ beginRoot?: N | null | undefined,
629
629
  iterationType?: IterationType
630
- ): N | null;
630
+ ): N | null | undefined;
631
631
 
632
632
  /**
633
633
  * The function `get` returns the first node in a binary tree that matches the given property or key.
@@ -645,11 +645,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
645
645
  * @returns either the found node (of type N) or null if no node is found.
646
646
  */
647
647
  getNode<C extends BTNCallback<N>>(
648
- identifier: ReturnType<C> | null,
648
+ identifier: ReturnType<C> | null | undefined,
649
649
  callback: C = this.defaultOneParamCallback as C,
650
650
  beginRoot = this.root,
651
651
  iterationType = this.iterationType
652
- ): N | null {
652
+ ): N | null | undefined {
653
653
  if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;
654
654
 
655
655
  return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? null;
@@ -658,21 +658,21 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
658
658
  get<C extends BTNCallback<N, BTNKey>>(
659
659
  identifier: BTNKey,
660
660
  callback?: C,
661
- beginRoot?: N | null,
661
+ beginRoot?: N | null | undefined,
662
662
  iterationType?: IterationType
663
663
  ): V | undefined;
664
664
 
665
665
  get<C extends BTNCallback<N, N>>(
666
- identifier: N | null,
666
+ identifier: N | null | undefined,
667
667
  callback?: C,
668
- beginRoot?: N | null,
668
+ beginRoot?: N | null | undefined,
669
669
  iterationType?: IterationType
670
670
  ): V | undefined;
671
671
 
672
672
  get<C extends BTNCallback<N>>(
673
673
  identifier: ReturnType<C>,
674
674
  callback: C,
675
- beginRoot?: N | null,
675
+ beginRoot?: N | null | undefined,
676
676
  iterationType?: IterationType
677
677
  ): V | undefined;
678
678
 
@@ -692,7 +692,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
692
692
  * @returns either the found value (of type V) or undefined if no node value is found.
693
693
  */
694
694
  get<C extends BTNCallback<N>>(
695
- identifier: ReturnType<C> | null,
695
+ identifier: ReturnType<C> | null | undefined,
696
696
  callback: C = this.defaultOneParamCallback as C,
697
697
  beginRoot = this.root,
698
698
  iterationType = this.iterationType
@@ -728,7 +728,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
728
728
  /**
729
729
  * The function `getLeftMost` returns the leftmost node in a binary tree, either using recursive or
730
730
  * iterative traversal.
731
- * @param {BTNKey | N | null} beginRoot - The `beginRoot` parameter is the starting point
731
+ * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
732
732
  * for finding the leftmost node in a binary tree. It can be either a node object (`N`), a key value
733
733
  * of a node (`BTNKey`), or `null` if the tree is empty.
734
734
  * @param iterationType - The `iterationType` parameter is used to determine the type of iteration to
@@ -736,7 +736,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
736
736
  * @returns The function `getLeftMost` returns the leftmost node (`N`) in a binary tree. If there is
737
737
  * no leftmost node, it returns `null`.
738
738
  */
739
- getLeftMost(beginRoot: BTNKey | N | null = this.root, iterationType = this.iterationType): N | null {
739
+ getLeftMost(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.iterationType): N | null | undefined {
740
740
  if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);
741
741
 
742
742
  if (!beginRoot) return beginRoot;
@@ -762,15 +762,15 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
762
762
  /**
763
763
  * The function `getRightMost` returns the rightmost node in a binary tree, either recursively or
764
764
  * iteratively.
765
- * @param {N | null} beginRoot - The `beginRoot` parameter is the starting node from which we want to
766
- * find the rightmost node. It is of type `N | null`, which means it can either be a node of type `N`
765
+ * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node from which we want to
766
+ * find the rightmost node. It is of type `N | null | undefined`, which means it can either be a node of type `N`
767
767
  * or `null`. If it is `null`, it means there is no starting node
768
768
  * @param iterationType - The `iterationType` parameter is used to determine the type of iteration to
769
769
  * be performed when finding the rightmost node in a binary tree. It can have two possible values:
770
770
  * @returns The function `getRightMost` returns the rightmost node (`N`) in a binary tree. If the
771
771
  * `beginRoot` parameter is `null`, it returns `null`.
772
772
  */
773
- getRightMost(beginRoot: N | null = this.root, iterationType = this.iterationType): N | null {
773
+ getRightMost(beginRoot: N | null | undefined = this.root, iterationType = this.iterationType): N | null | undefined {
774
774
  // TODO support get right most by passing key in
775
775
  if (!beginRoot) return beginRoot;
776
776
 
@@ -801,7 +801,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
801
801
  * possible values:
802
802
  * @returns The function `isSubtreeBST` returns a boolean value.
803
803
  */
804
- isSubtreeBST(beginRoot: N | null, iterationType = this.iterationType): boolean {
804
+ isSubtreeBST(beginRoot: N | null | undefined, iterationType = this.iterationType): boolean {
805
805
  // TODO there is a bug
806
806
  if (!beginRoot) return true;
807
807
 
@@ -846,21 +846,21 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
846
846
 
847
847
  subTreeTraverse<C extends BTNCallback<N>>(
848
848
  callback?: C,
849
- beginRoot?: BTNKey | N | null,
849
+ beginRoot?: BTNKey | N | null | undefined,
850
850
  iterationType?: IterationType,
851
851
  includeNull?: false
852
852
  ): ReturnType<C>[];
853
853
 
854
854
  subTreeTraverse<C extends BTNCallback<N>>(
855
855
  callback?: C,
856
- beginRoot?: BTNKey | N | null,
856
+ beginRoot?: BTNKey | N | null | undefined,
857
857
  iterationType?: IterationType,
858
858
  includeNull?: undefined
859
859
  ): ReturnType<C>[];
860
860
 
861
- subTreeTraverse<C extends BTNCallback<N | null>>(
861
+ subTreeTraverse<C extends BTNCallback<N | null | undefined>>(
862
862
  callback?: C,
863
- beginRoot?: BTNKey | N | null,
863
+ beginRoot?: BTNKey | N | null | undefined,
864
864
  iterationType?: IterationType,
865
865
  includeNull?: true
866
866
  ): ReturnType<C>[];
@@ -872,7 +872,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
872
872
  * subtree traversal. It takes a single argument, which is the current node being traversed, and
873
873
  * returns a value. The return values from each callback invocation will be collected and returned as
874
874
  * an array.
875
- * @param {BTNKey | N | null} beginRoot - The `beginRoot` parameter is the starting point
875
+ * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
876
876
  * for traversing the subtree. It can be either a node object, a key value of a node, or `null` to
877
877
  * start from the root of the tree.
878
878
  * @param iterationType - The `iterationType` parameter determines the type of traversal to be
@@ -880,56 +880,68 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
880
880
  * @param includeNull - The choice to output null values during binary tree traversal should be provided.
881
881
  * @returns The function `subTreeTraverse` returns an array of `ReturnType<BTNCallback<N>>`.
882
882
  */
883
- subTreeTraverse<C extends BTNCallback<N | null>>(
883
+ subTreeTraverse<C extends BTNCallback<N | null | undefined>>(
884
884
  callback: C = this.defaultOneParamCallback as C,
885
- beginRoot: BTNKey | N | null = this.root,
885
+ beginRoot: BTNKey | N | null | undefined = this.root,
886
886
  iterationType = this.iterationType,
887
887
  includeNull = false
888
888
  ): ReturnType<C>[] {
889
889
  if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);
890
890
 
891
- const ans: (ReturnType<BTNCallback<N>> | null)[] = [];
891
+ const ans: (ReturnType<BTNCallback<N>> | null | undefined)[] = [];
892
892
  if (!beginRoot) return ans;
893
893
 
894
894
  if (iterationType === IterationType.RECURSIVE) {
895
- const _traverse = (cur: N | null) => {
895
+ const _traverse = (cur: N | null | undefined) => {
896
896
  if (cur !== undefined) {
897
897
  ans.push(callback(cur));
898
898
  if (includeNull) {
899
- cur !== null && cur.left !== undefined && _traverse(cur.left);
900
- cur !== null && cur.right !== undefined && _traverse(cur.right);
899
+ cur && this.isNodeOrNull(cur.left) && _traverse(cur.left);
900
+ cur && this.isNodeOrNull(cur.right) && _traverse(cur.right);
901
901
  } else {
902
- cur !== null && cur.left && _traverse(cur.left);
903
- cur !== null && cur.right && _traverse(cur.right);
902
+ cur && cur.left && _traverse(cur.left);
903
+ cur && cur.right && _traverse(cur.right);
904
904
  }
905
905
  }
906
906
  };
907
907
 
908
908
  _traverse(beginRoot);
909
909
  } else {
910
- const stack: (N | null)[] = [beginRoot];
910
+ const stack: (N | null | undefined)[] = [beginRoot];
911
911
 
912
912
  while (stack.length > 0) {
913
913
  const cur = stack.pop();
914
914
  if (cur !== undefined) {
915
915
  ans.push(callback(cur));
916
916
  if (includeNull) {
917
- cur !== null && cur.right !== undefined && stack.push(cur.right);
918
- cur !== null && cur.left !== undefined && stack.push(cur.left);
917
+ cur && this.isNodeOrNull(cur.right) && stack.push(cur.right);
918
+ cur && this.isNodeOrNull(cur.left) && stack.push(cur.left);
919
919
  } else {
920
- cur !== null && cur.right && stack.push(cur.right);
921
- cur !== null && cur.left && stack.push(cur.left);
920
+ cur && cur.right && stack.push(cur.right);
921
+ cur && cur.left && stack.push(cur.left);
922
922
  }
923
923
  }
924
924
  }
925
925
  }
926
926
  return ans;
927
927
  }
928
+
929
+ isNode(node: any): node is N {
930
+ return node instanceof BinaryTreeNode && node.key.toString() !== 'NaN';
931
+ }
932
+
933
+ isNIL(node: any) {
934
+ return node instanceof BinaryTreeNode && node.key.toString() === 'NaN';
935
+ }
936
+
937
+ isNodeOrNull(node: any): node is (N | null){
938
+ return this.isNode(node) || node === null;
939
+ }
928
940
 
929
941
  dfs<C extends BTNCallback<N>>(
930
942
  callback?: C,
931
943
  pattern?: DFSOrderPattern,
932
- beginRoot?: N | null,
944
+ beginRoot?: N | null | undefined,
933
945
  iterationType?: IterationType,
934
946
  includeNull?: false
935
947
  ): ReturnType<C>[];
@@ -937,15 +949,15 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
937
949
  dfs<C extends BTNCallback<N>>(
938
950
  callback?: C,
939
951
  pattern?: DFSOrderPattern,
940
- beginRoot?: N | null,
952
+ beginRoot?: N | null | undefined,
941
953
  iterationType?: IterationType,
942
954
  includeNull?: undefined
943
955
  ): ReturnType<C>[];
944
956
 
945
- dfs<C extends BTNCallback<N | null>>(
957
+ dfs<C extends BTNCallback<N | null | undefined>>(
946
958
  callback?: C,
947
959
  pattern?: DFSOrderPattern,
948
- beginRoot?: N | null,
960
+ beginRoot?: N | null | undefined,
949
961
  iterationType?: IterationType,
950
962
  includeNull?: true
951
963
  ): ReturnType<C>[];
@@ -958,7 +970,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
958
970
  * is `this.defaultOneParamCallback`, which is a callback function defined elsewhere in the code.
959
971
  * @param {DFSOrderPattern} [pattern=in] - The `pattern` parameter determines the order in which the
960
972
  * nodes are visited during the depth-first search. There are three possible values for `pattern`:
961
- * @param {N | null} beginRoot - The `beginRoot` parameter is the starting node for the depth-first
973
+ * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node for the depth-first
962
974
  * search. It determines where the search will begin in the tree or graph structure. If `beginRoot`
963
975
  * is `null`, an empty array will be returned.
964
976
  * @param {IterationType} iterationType - The `iterationType` parameter determines the type of
@@ -966,49 +978,49 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
966
978
  * @param includeNull - The choice to output null values during binary tree traversal should be provided.
967
979
  * @returns The function `dfs` returns an array of `ReturnType<BTNCallback<N>>` values.
968
980
  */
969
- dfs<C extends BTNCallback<N | null>>(
981
+ dfs<C extends BTNCallback<N | null | undefined>>(
970
982
  callback: C = this.defaultOneParamCallback as C,
971
983
  pattern: DFSOrderPattern = 'in',
972
- beginRoot: N | null = this.root,
984
+ beginRoot: N | null | undefined = this.root,
973
985
  iterationType: IterationType = IterationType.ITERATIVE,
974
986
  includeNull = false
975
987
  ): ReturnType<C>[] {
976
988
  if (!beginRoot) return [];
977
989
  const ans: ReturnType<C>[] = [];
978
990
  if (iterationType === IterationType.RECURSIVE) {
979
- const _traverse = (node: N | null) => {
991
+ const _traverse = (node: N | null | undefined) => {
980
992
  switch (pattern) {
981
993
  case 'in':
982
994
  if (includeNull) {
983
- if (node !== null && node.left !== undefined) _traverse(node.left);
984
- ans.push(callback(node));
985
- if (node !== null && node.right !== undefined) _traverse(node.right);
995
+ if (node && this.isNodeOrNull(node.left)) _traverse(node.left);
996
+ this.isNodeOrNull(node) && ans.push(callback(node));
997
+ if (node && this.isNodeOrNull(node.right)) _traverse(node.right);
986
998
  } else {
987
- if (node !== null && node.left) _traverse(node.left);
988
- ans.push(callback(node));
989
- if (node !== null && node.right) _traverse(node.right);
999
+ if (node && node.left) _traverse(node.left);
1000
+ this.isNode(node) && ans.push(callback(node));
1001
+ if (node && node.right) _traverse(node.right);
990
1002
  }
991
1003
  break;
992
1004
  case 'pre':
993
1005
  if (includeNull) {
994
- ans.push(callback(node));
995
- if (node !== null && node.left !== undefined) _traverse(node.left);
996
- if (node !== null && node.right !== undefined) _traverse(node.right);
1006
+ this.isNodeOrNull(node) && ans.push(callback(node));
1007
+ if (node && this.isNodeOrNull(node.left)) _traverse(node.left);
1008
+ if (node && this.isNodeOrNull(node.right)) _traverse(node.right);
997
1009
  } else {
998
- ans.push(callback(node));
999
- if (node !== null && node.left) _traverse(node.left);
1000
- if (node !== null && node.right) _traverse(node.right);
1010
+ this.isNode(node) && ans.push(callback(node));
1011
+ if (node && node.left) _traverse(node.left);
1012
+ if (node && node.right) _traverse(node.right);
1001
1013
  }
1002
1014
  break;
1003
1015
  case 'post':
1004
1016
  if (includeNull) {
1005
- if (node !== null && node.left !== undefined) _traverse(node.left);
1006
- if (node !== null && node.right !== undefined) _traverse(node.right);
1007
- ans.push(callback(node));
1017
+ if (node && this.isNodeOrNull(node.left)) _traverse(node.left);
1018
+ if (node && this.isNodeOrNull(node.right)) _traverse(node.right);
1019
+ this.isNodeOrNull(node) && ans.push(callback(node));
1008
1020
  } else {
1009
- if (node !== null && node.left) _traverse(node.left);
1010
- if (node !== null && node.right) _traverse(node.right);
1011
- ans.push(callback(node));
1021
+ if (node && node.left) _traverse(node.left);
1022
+ if (node && node.right) _traverse(node.right);
1023
+ this.isNode(node) && ans.push(callback(node));
1012
1024
  }
1013
1025
 
1014
1026
  break;
@@ -1022,7 +1034,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1022
1034
 
1023
1035
  while (stack.length > 0) {
1024
1036
  const cur = stack.pop();
1025
- if (cur === undefined) continue;
1037
+ if (cur === undefined || this.isNIL(cur.node)) continue;
1026
1038
  if (includeNull) {
1027
1039
  if (cur.node === undefined) continue;
1028
1040
  } else {
@@ -1062,21 +1074,21 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1062
1074
 
1063
1075
  bfs<C extends BTNCallback<N>>(
1064
1076
  callback?: C,
1065
- beginRoot?: N | null,
1077
+ beginRoot?: N | null | undefined,
1066
1078
  iterationType?: IterationType,
1067
1079
  includeNull?: false
1068
1080
  ): ReturnType<C>[];
1069
1081
 
1070
1082
  bfs<C extends BTNCallback<N>>(
1071
1083
  callback?: C,
1072
- beginRoot?: N | null,
1084
+ beginRoot?: N | null | undefined,
1073
1085
  iterationType?: IterationType,
1074
1086
  includeNull?: undefined
1075
1087
  ): ReturnType<C>[];
1076
1088
 
1077
- bfs<C extends BTNCallback<N | null>>(
1089
+ bfs<C extends BTNCallback<N | null | undefined>>(
1078
1090
  callback?: C,
1079
- beginRoot?: N | null,
1091
+ beginRoot?: N | null | undefined,
1080
1092
  iterationType?: IterationType,
1081
1093
  includeNull?: true
1082
1094
  ): ReturnType<C>[];
@@ -1087,7 +1099,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1087
1099
  * @param callback - The `callback` parameter is a function that will be called for each node in the
1088
1100
  * breadth-first search. It takes a node of type `N` as its argument and returns a value of type
1089
1101
  * `ReturnType<BTNCallback<N>>`. The default value for this parameter is `this.defaultOneParamCallback
1090
- * @param {N | null} beginRoot - The `beginRoot` parameter is the starting node for the breadth-first
1102
+ * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node for the breadth-first
1091
1103
  * search. It determines from which node the search will begin. If `beginRoot` is `null`, the search
1092
1104
  * will not be performed and an empty array will be returned.
1093
1105
  * @param iterationType - The `iterationType` parameter determines the type of iteration to be used
@@ -1095,9 +1107,9 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1095
1107
  * @param includeNull - The choice to output null values during binary tree traversal should be provided.
1096
1108
  * @returns The function `bfs` returns an array of `ReturnType<BTNCallback<N>>[]`.
1097
1109
  */
1098
- bfs<C extends BTNCallback<N | null>>(
1110
+ bfs<C extends BTNCallback<N | null | undefined>>(
1099
1111
  callback: C = this.defaultOneParamCallback as C,
1100
- beginRoot: N | null = this.root,
1112
+ beginRoot: N | null | undefined = this.root,
1101
1113
  iterationType = this.iterationType,
1102
1114
  includeNull = false
1103
1115
  ): ReturnType<C>[] {
@@ -1106,7 +1118,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1106
1118
  const ans: ReturnType<BTNCallback<N>>[] = [];
1107
1119
 
1108
1120
  if (iterationType === IterationType.RECURSIVE) {
1109
- const queue: Queue<N | null> = new Queue<N | null>([beginRoot]);
1121
+ const queue: Queue<N | null | undefined> = new Queue<N | null | undefined>([beginRoot]);
1110
1122
 
1111
1123
  const traverse = (level: number) => {
1112
1124
  if (queue.size === 0) return;
@@ -1115,8 +1127,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1115
1127
  ans.push(callback(current));
1116
1128
 
1117
1129
  if (includeNull) {
1118
- if (current && current.left !== undefined) queue.push(current.left);
1119
- if (current && current.right !== undefined) queue.push(current.right);
1130
+ if (current && this.isNodeOrNull(current.left)) queue.push(current.left);
1131
+ if (current && this.isNodeOrNull(current.right)) queue.push(current.right);
1120
1132
  } else {
1121
1133
  if (current.left) queue.push(current.left);
1122
1134
  if (current.right) queue.push(current.right);
@@ -1127,7 +1139,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1127
1139
 
1128
1140
  traverse(0);
1129
1141
  } else {
1130
- const queue = new Queue<N | null>([beginRoot]);
1142
+ const queue = new Queue<N | null | undefined>([beginRoot]);
1131
1143
  while (queue.size > 0) {
1132
1144
  const levelSize = queue.size;
1133
1145
 
@@ -1136,8 +1148,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1136
1148
  ans.push(callback(current));
1137
1149
 
1138
1150
  if (includeNull) {
1139
- if (current !== null && current.left !== undefined) queue.push(current.left);
1140
- if (current !== null && current.right !== undefined) queue.push(current.right);
1151
+ if (current && this.isNodeOrNull(current.left)) queue.push(current.left);
1152
+ if (current && this.isNodeOrNull(current.right)) queue.push(current.right);
1141
1153
  } else {
1142
1154
  if (current.left) queue.push(current.left);
1143
1155
  if (current.right) queue.push(current.right);
@@ -1150,21 +1162,21 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1150
1162
 
1151
1163
  listLevels<C extends BTNCallback<N>>(
1152
1164
  callback?: C,
1153
- beginRoot?: N | null,
1165
+ beginRoot?: N | null | undefined,
1154
1166
  iterationType?: IterationType,
1155
1167
  includeNull?: false
1156
1168
  ): ReturnType<C>[][];
1157
1169
 
1158
1170
  listLevels<C extends BTNCallback<N>>(
1159
1171
  callback?: C,
1160
- beginRoot?: N | null,
1172
+ beginRoot?: N | null | undefined,
1161
1173
  iterationType?: IterationType,
1162
1174
  includeNull?: undefined
1163
1175
  ): ReturnType<C>[][];
1164
1176
 
1165
- listLevels<C extends BTNCallback<N | null>>(
1177
+ listLevels<C extends BTNCallback<N | null | undefined>>(
1166
1178
  callback?: C,
1167
- beginRoot?: N | null,
1179
+ beginRoot?: N | null | undefined,
1168
1180
  iterationType?: IterationType,
1169
1181
  includeNull?: true
1170
1182
  ): ReturnType<C>[][];
@@ -1175,7 +1187,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1175
1187
  * @param {C} callback - The `callback` parameter is a function that will be called on each node in
1176
1188
  * the tree. It takes a node as input and returns a value. The return type of the callback function
1177
1189
  * is determined by the generic type `C`.
1178
- * @param {N | null} beginRoot - The `beginRoot` parameter represents the starting node of the binary tree
1190
+ * @param {N | null | undefined} beginRoot - The `beginRoot` parameter represents the starting node of the binary tree
1179
1191
  * traversal. It can be any node in the binary tree. If no node is provided, the traversal will start
1180
1192
  * from the root node of the binary tree.
1181
1193
  * @param iterationType - The `iterationType` parameter determines whether the tree traversal is done
@@ -1185,9 +1197,9 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1185
1197
  * level in a binary tree. Each inner array contains the return type of the provided callback
1186
1198
  * function `C` applied to the nodes at that level.
1187
1199
  */
1188
- listLevels<C extends BTNCallback<N | null>>(
1200
+ listLevels<C extends BTNCallback<N | null | undefined>>(
1189
1201
  callback: C = this.defaultOneParamCallback as C,
1190
- beginRoot: N | null = this.root,
1202
+ beginRoot: N | null | undefined = this.root,
1191
1203
  iterationType = this.iterationType,
1192
1204
  includeNull = false
1193
1205
  ): ReturnType<C>[][] {
@@ -1195,12 +1207,12 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1195
1207
  const levelsNodes: ReturnType<C>[][] = [];
1196
1208
 
1197
1209
  if (iterationType === IterationType.RECURSIVE) {
1198
- const _recursive = (node: N | null, level: number) => {
1210
+ const _recursive = (node: N | null | undefined, level: number) => {
1199
1211
  if (!levelsNodes[level]) levelsNodes[level] = [];
1200
1212
  levelsNodes[level].push(callback(node));
1201
1213
  if (includeNull) {
1202
- if (node && node.left !== undefined) _recursive(node.left, level + 1);
1203
- if (node && node.right !== undefined) _recursive(node.right, level + 1);
1214
+ if (node && this.isNodeOrNull(node.left)) _recursive(node.left, level + 1);
1215
+ if (node && this.isNodeOrNull(node.right)) _recursive(node.right, level + 1);
1204
1216
  } else {
1205
1217
  if (node && node.left) _recursive(node.left, level + 1);
1206
1218
  if (node && node.right) _recursive(node.right, level + 1);
@@ -1209,7 +1221,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1209
1221
 
1210
1222
  _recursive(beginRoot, 0);
1211
1223
  } else {
1212
- const stack: [N | null, number][] = [[beginRoot, 0]];
1224
+ const stack: [N | null | undefined, number][] = [[beginRoot, 0]];
1213
1225
 
1214
1226
  while (stack.length > 0) {
1215
1227
  const head = stack.pop()!;
@@ -1219,8 +1231,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1219
1231
  levelsNodes[level].push(callback(node));
1220
1232
 
1221
1233
  if (includeNull) {
1222
- if (node && node.right !== undefined) stack.push([node.right, level + 1]);
1223
- if (node && node.left !== undefined) stack.push([node.left, level + 1]);
1234
+ if (node && this.isNodeOrNull(node.right)) stack.push([node.right, level + 1]);
1235
+ if (node && this.isNodeOrNull(node.left)) stack.push([node.left, level + 1]);
1224
1236
  } else {
1225
1237
  if (node && node.right) stack.push([node.right, level + 1]);
1226
1238
  if (node && node.left) stack.push([node.left, level + 1]);
@@ -1279,7 +1291,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1279
1291
  * @param {DFSOrderPattern} [pattern=in] - The `pattern` parameter in the `morris` function
1280
1292
  * determines the order in which the nodes of a binary tree are traversed. It can have one of the
1281
1293
  * following values:
1282
- * @param {N | null} beginRoot - The `beginRoot` parameter is the starting node for the Morris
1294
+ * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node for the Morris
1283
1295
  * traversal. It specifies the root node of the tree from which the traversal should begin. If
1284
1296
  * `beginRoot` is `null`, an empty array will be returned.
1285
1297
  * @returns The `morris` function returns an array of `ReturnType<BTNCallback<N>>` values.
@@ -1287,7 +1299,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1287
1299
  morris<C extends BTNCallback<N>>(
1288
1300
  callback: C = this.defaultOneParamCallback as C,
1289
1301
  pattern: DFSOrderPattern = 'in',
1290
- beginRoot: N | null = this.root
1302
+ beginRoot: N | null | undefined = this.root
1291
1303
  ): ReturnType<C>[] {
1292
1304
  if (beginRoot === null) return [];
1293
1305
  const ans: ReturnType<BTNCallback<N>>[] = [];
@@ -1304,7 +1316,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1304
1316
  }
1305
1317
  return pre;
1306
1318
  };
1307
- const _printEdge = (node: N | null) => {
1319
+ const _printEdge = (node: N | null | undefined) => {
1308
1320
  const tail: N | null | undefined = _reverseEdge(node);
1309
1321
  let cur: N | null | undefined = tail;
1310
1322
  while (cur) {
@@ -1438,7 +1450,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1438
1450
 
1439
1451
  /**
1440
1452
  * The function `_addTo` adds a new node to a binary tree if there is an available position.
1441
- * @param {N | null} newNode - The `newNode` parameter represents the node that you want to add to
1453
+ * @param {N | null | undefined} newNode - The `newNode` parameter represents the node that you want to add to
1442
1454
  * the binary tree. It can be either a node object or `null`.
1443
1455
  * @param {N} parent - The `parent` parameter represents the parent node to which the new node will
1444
1456
  * be added as a child.
@@ -1447,7 +1459,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1447
1459
  * the binary tree. If neither the left nor right child is available, the function returns undefined.
1448
1460
  * If the parent node is null, the function also returns undefined.
1449
1461
  */
1450
- protected _addTo(newNode: N | null, parent: N): N | null | undefined {
1462
+ protected _addTo(newNode: N | null | undefined, parent: N): N | null | undefined {
1451
1463
  if (parent) {
1452
1464
  // When all leaf nodes are null, it will no longer be possible to add new entity nodes to this binary tree.
1453
1465
  // In this scenario, null nodes serve as "sentinel nodes," "virtual nodes," or "placeholder nodes."
@@ -1474,15 +1486,73 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1474
1486
  /**
1475
1487
  * The function sets the root property of an object to a given value, and if the value is not null,
1476
1488
  * it also sets the parent property of the value to undefined.
1477
- * @param {N | null} v - The parameter `v` is of type `N | null`, which means it can either be of
1489
+ * @param {N | null | undefined} v - The parameter `v` is of type `N | null | undefined`, which means it can either be of
1478
1490
  * type `N` or `null`.
1479
1491
  */
1480
- protected _setRoot(v: N | null) {
1492
+ protected _setRoot(v: N | null | undefined) {
1481
1493
  if (v) {
1482
1494
  v.parent = undefined;
1483
1495
  }
1484
1496
  this._root = v;
1485
1497
  }
1486
1498
 
1499
+ print(beginRoot: N | null | undefined = this.root) {
1500
+ const display = (root: N | null | undefined): void => {
1501
+ const [lines, , ,] = _displayAux(root);
1502
+ for (const line of lines) {
1503
+ console.log(line);
1504
+ }
1505
+ };
1506
+
1507
+ const _displayAux = (node: N | null | undefined): [string[], number, number, number] => {
1508
+ if (node === undefined || node === null) {
1509
+ return [[], 0, 0, 0];
1510
+ }
1511
+
1512
+ if (node && node.right === undefined && node.left === undefined) {
1513
+ const line = `${node.key}`;
1514
+ const width = line.length;
1515
+ const height = 1;
1516
+ const middle = Math.floor(width / 2);
1517
+ return [[line], width, height, middle];
1518
+ }
1519
+
1520
+ if (node && node.right === undefined) {
1521
+ const [lines, n, p, x] = _displayAux(node.left);
1522
+ const s = `${node.key}`;
1523
+ const u = s.length;
1524
+ const first_line = ' '.repeat(x + 1) + '_'.repeat(n - x - 1) + s;
1525
+ const second_line = ' '.repeat(x) + '/' + ' '.repeat(n - x - 1 + u);
1526
+ const shifted_lines = lines.map(line => line + ' '.repeat(u));
1527
+ return [[first_line, second_line, ...shifted_lines], n + u, p + 2, n + Math.floor(u / 2)];
1528
+ }
1529
+
1530
+ if (node && node.left === undefined) {
1531
+ const [lines, n, p, u] = _displayAux(node.right);
1532
+ const s = `${node.key}`;
1533
+ const x = s.length;
1534
+ const first_line = s + '_'.repeat(x) + ' '.repeat(n - x);
1535
+ const second_line = ' '.repeat(u + x) + '\\' + ' '.repeat(n - x - 1);
1536
+ const shifted_lines = lines.map(line => ' '.repeat(u) + line);
1537
+ return [[first_line, second_line, ...shifted_lines], n + x, p + 2, Math.floor(u / 2)];
1538
+ }
1539
+
1540
+ const [left, n, p, x] = _displayAux(node.left);
1541
+ const [right, m, q, y] = _displayAux(node.right);
1542
+ const s = `${node.key}`;
1543
+ const u = s.length;
1544
+ const first_line = ' '.repeat(x + 1) + '_'.repeat(n - x - 1) + s + '_'.repeat(y) + ' '.repeat(m - y);
1545
+ const second_line = ' '.repeat(x) + '/' + ' '.repeat(n - x - 1 + u + y) + '\\' + ' '.repeat(m - y - 1);
1546
+ if (p < q) {
1547
+ left.push(...new Array(q - p).fill(' '.repeat(n)));
1548
+ } else if (q < p) {
1549
+ right.push(...new Array(p - q).fill(' '.repeat(m)));
1550
+ }
1551
+ const zipped_lines = left.map((a, i) => a + ' '.repeat(u) + right[i]);
1552
+ return [[first_line, second_line, ...zipped_lines], n + m + u, Math.max(p, q) + 2, n + Math.floor(u / 2)];
1553
+ };
1554
+
1555
+ display(beginRoot);
1556
+ }
1487
1557
  // --- end additional methods ---
1488
1558
  }