heap-typed 1.46.7 → 1.47.1

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 (31) hide show
  1. package/dist/data-structures/binary-tree/avl-tree.d.ts +4 -2
  2. package/dist/data-structures/binary-tree/avl-tree.js +10 -0
  3. package/dist/data-structures/binary-tree/binary-tree.d.ts +51 -13
  4. package/dist/data-structures/binary-tree/binary-tree.js +153 -55
  5. package/dist/data-structures/binary-tree/bst.d.ts +10 -9
  6. package/dist/data-structures/binary-tree/bst.js +16 -14
  7. package/dist/data-structures/binary-tree/rb-tree.d.ts +7 -5
  8. package/dist/data-structures/binary-tree/rb-tree.js +32 -23
  9. package/dist/data-structures/binary-tree/tree-multimap.d.ts +5 -3
  10. package/dist/data-structures/binary-tree/tree-multimap.js +11 -2
  11. package/dist/interfaces/binary-tree.d.ts +3 -3
  12. package/dist/types/common.d.ts +5 -4
  13. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +2 -1
  14. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +3 -1
  15. package/dist/types/data-structures/binary-tree/binary-tree.js +0 -6
  16. package/dist/types/data-structures/binary-tree/bst.d.ts +2 -1
  17. package/dist/types/data-structures/binary-tree/rb-tree.d.ts +2 -1
  18. package/dist/types/data-structures/binary-tree/tree-multimap.d.ts +2 -1
  19. package/package.json +2 -2
  20. package/src/data-structures/binary-tree/avl-tree.ts +17 -5
  21. package/src/data-structures/binary-tree/binary-tree.ts +175 -62
  22. package/src/data-structures/binary-tree/bst.ts +23 -19
  23. package/src/data-structures/binary-tree/rb-tree.ts +38 -27
  24. package/src/data-structures/binary-tree/tree-multimap.ts +19 -6
  25. package/src/interfaces/binary-tree.ts +3 -3
  26. package/src/types/common.ts +2 -5
  27. package/src/types/data-structures/binary-tree/avl-tree.ts +5 -1
  28. package/src/types/data-structures/binary-tree/binary-tree.ts +5 -7
  29. package/src/types/data-structures/binary-tree/bst.ts +3 -1
  30. package/src/types/data-structures/binary-tree/rb-tree.ts +3 -1
  31. package/src/types/data-structures/binary-tree/tree-multimap.ts +3 -1
@@ -6,14 +6,15 @@
6
6
  * @license MIT License
7
7
  */
8
8
  import { BST, BSTNode } from './bst';
9
- import type { AVLTreeNodeNested, AVLTreeOptions, BiTreeDeleteResult, BTNKey } from '../../types';
9
+ import type { AVLTreeNested, AVLTreeNodeNested, AVLTreeOptions, BiTreeDeleteResult, BTNKey } from '../../types';
10
10
  import { BTNCallback } from '../../types';
11
11
  import { IBinaryTree } from '../../interfaces';
12
12
  export declare class AVLTreeNode<V = any, N extends AVLTreeNode<V, N> = AVLTreeNodeNested<V>> extends BSTNode<V, N> {
13
13
  height: number;
14
14
  constructor(key: BTNKey, value?: V);
15
15
  }
16
- export declare class AVLTree<V = any, N extends AVLTreeNode<V, N> = AVLTreeNode<V, AVLTreeNodeNested<V>>> extends BST<V, N> implements IBinaryTree<V, N> {
16
+ export declare class AVLTree<V = any, N extends AVLTreeNode<V, N> = AVLTreeNode<V, AVLTreeNodeNested<V>>, TREE extends AVLTree<V, N, TREE> = AVLTree<V, N, AVLTreeNested<V, N>>> extends BST<V, N, TREE> implements IBinaryTree<V, N, TREE> {
17
+ options: AVLTreeOptions;
17
18
  /**
18
19
  * This is a constructor function for an AVL tree data structure in TypeScript.
19
20
  * @param {AVLTreeOptions} [options] - The `options` parameter is an optional object that can be passed to the
@@ -31,6 +32,7 @@ export declare class AVLTree<V = any, N extends AVLTreeNode<V, N> = AVLTreeNode<
31
32
  * @returns a new AVLTreeNode object with the specified key and value.
32
33
  */
33
34
  createNode(key: BTNKey, value?: V): N;
35
+ createTree(options?: AVLTreeOptions): TREE;
34
36
  /**
35
37
  * Time Complexity: O(log n) - logarithmic time, where "n" is the number of nodes in the tree. The add method of the superclass (BST) has logarithmic time complexity.
36
38
  * Space Complexity: O(1) - constant space, as it doesn't use additional data structures that scale with input size.
@@ -9,6 +9,7 @@ exports.AVLTree = exports.AVLTreeNode = void 0;
9
9
  * @license MIT License
10
10
  */
11
11
  const bst_1 = require("./bst");
12
+ const types_1 = require("../../types");
12
13
  class AVLTreeNode extends bst_1.BSTNode {
13
14
  constructor(key, value) {
14
15
  super(key, value);
@@ -25,6 +26,12 @@ class AVLTree extends bst_1.BST {
25
26
  */
26
27
  constructor(options) {
27
28
  super(options);
29
+ if (options) {
30
+ this.options = Object.assign({ iterationType: types_1.IterationType.ITERATIVE, comparator: (a, b) => a - b }, options);
31
+ }
32
+ else {
33
+ this.options = { iterationType: types_1.IterationType.ITERATIVE, comparator: (a, b) => a - b };
34
+ }
28
35
  }
29
36
  /**
30
37
  * The function creates a new AVL tree node with the specified key and value.
@@ -38,6 +45,9 @@ class AVLTree extends bst_1.BST {
38
45
  createNode(key, value) {
39
46
  return new AVLTreeNode(key, value);
40
47
  }
48
+ createTree(options) {
49
+ return new AVLTree(Object.assign(Object.assign({}, this.options), options));
50
+ }
41
51
  /**
42
52
  * Time Complexity: O(log n) - logarithmic time, where "n" is the number of nodes in the tree. The add method of the superclass (BST) has logarithmic time complexity.
43
53
  * Space Complexity: O(1) - constant space, as it doesn't use additional data structures that scale with input size.
@@ -6,7 +6,7 @@
6
6
  * @license MIT License
7
7
  */
8
8
  import type { BinaryTreeNodeNested, BinaryTreeOptions, BTNCallback, BTNKey } from '../../types';
9
- import { BiTreeDeleteResult, DFSOrderPattern, FamilyPosition, IterationType } from '../../types';
9
+ import { BinaryTreeNested, BinaryTreePrintOptions, BiTreeDeleteResult, DFSOrderPattern, FamilyPosition, IterationType, NodeDisplayLayout } from '../../types';
10
10
  import { IBinaryTree } from '../../interfaces';
11
11
  /**
12
12
  * Represents a node in a binary tree.
@@ -62,8 +62,8 @@ export declare class BinaryTreeNode<V = any, N extends BinaryTreeNode<V, N> = Bi
62
62
  * Represents a binary tree data structure.
63
63
  * @template N - The type of the binary tree's nodes.
64
64
  */
65
- export declare class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode<V, BinaryTreeNodeNested<V>>> implements IBinaryTree<V, N> {
66
- iterationType: IterationType;
65
+ export declare class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode<V, BinaryTreeNodeNested<V>>, TREE extends BinaryTree<V, N, TREE> = BinaryTree<V, N, BinaryTreeNested<V, N>>> implements IBinaryTree<V, N, TREE> {
66
+ options: BinaryTreeOptions;
67
67
  /**
68
68
  * Creates a new instance of BinaryTree.
69
69
  * @param {BinaryTreeOptions} [options] - The options for the binary tree.
@@ -86,6 +86,7 @@ export declare class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = Binary
86
86
  * @returns {N} - The newly created BinaryTreeNode.
87
87
  */
88
88
  createNode(key: BTNKey, value?: V): N;
89
+ createTree(options?: BinaryTreeOptions): TREE;
89
90
  /**
90
91
  * Time Complexity: O(n)
91
92
  * Space Complexity: O(1)
@@ -181,7 +182,7 @@ export declare class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = Binary
181
182
  * values:
182
183
  * @returns the height of the binary tree.
183
184
  */
184
- getHeight(beginRoot?: BTNKey | N | null | undefined, iterationType?: IterationType): number;
185
+ getHeight(beginRoot?: BTNKey | N | null | undefined, iterationType?: IterationType | undefined): number;
185
186
  /**
186
187
  * Time Complexity: O(n)
187
188
  * Space Complexity: O(log n)
@@ -200,7 +201,7 @@ export declare class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = Binary
200
201
  * to calculate the minimum height of a binary tree. It can have two possible values:
201
202
  * @returns The function `getMinHeight` returns the minimum height of a binary tree.
202
203
  */
203
- getMinHeight(beginRoot?: BTNKey | N | null | undefined, iterationType?: IterationType): number;
204
+ getMinHeight(beginRoot?: BTNKey | N | null | undefined, iterationType?: IterationType | undefined): number;
204
205
  /**
205
206
  * Time Complexity: O(n)
206
207
  * Space Complexity: O(log n)
@@ -306,7 +307,7 @@ export declare class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = Binary
306
307
  * @returns The function `getLeftMost` returns the leftmost node (`N`) in the binary tree. If there
307
308
  * is no leftmost node, it returns `null` or `undefined` depending on the input.
308
309
  */
309
- getLeftMost(beginRoot?: BTNKey | N | null | undefined, iterationType?: IterationType): N | null | undefined;
310
+ getLeftMost(beginRoot?: BTNKey | N | null | undefined, iterationType?: IterationType | undefined): N | null | undefined;
310
311
  /**
311
312
  * Time Complexity: O(log n)
312
313
  * Space Complexity: O(1)
@@ -326,7 +327,7 @@ export declare class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = Binary
326
327
  * @returns The function `getRightMost` returns the rightmost node (`N`) in a binary tree. If there
327
328
  * is no rightmost node, it returns `null` or `undefined`, depending on the input.
328
329
  */
329
- getRightMost(beginRoot?: BTNKey | N | null | undefined, iterationType?: IterationType): N | null | undefined;
330
+ getRightMost(beginRoot?: BTNKey | N | null | undefined, iterationType?: IterationType | undefined): N | null | undefined;
330
331
  /**
331
332
  * Time Complexity: O(n)
332
333
  * Space Complexity: O(1)
@@ -343,7 +344,7 @@ export declare class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = Binary
343
344
  * possible values:
344
345
  * @returns a boolean value.
345
346
  */
346
- isSubtreeBST(beginRoot: BTNKey | N | null | undefined, iterationType?: IterationType): boolean;
347
+ isSubtreeBST(beginRoot: BTNKey | N | null | undefined, iterationType?: IterationType | undefined): boolean;
347
348
  /**
348
349
  * Time Complexity: O(n)
349
350
  * Space Complexity: O(1)
@@ -359,7 +360,7 @@ export declare class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = Binary
359
360
  * expected to be
360
361
  * @returns a boolean value.
361
362
  */
362
- isBST(iterationType?: IterationType): boolean;
363
+ isBST(iterationType?: IterationType | undefined): boolean;
363
364
  subTreeTraverse<C extends BTNCallback<N>>(callback?: C, beginRoot?: BTNKey | N | null | undefined, iterationType?: IterationType, includeNull?: false): ReturnType<C>[];
364
365
  subTreeTraverse<C extends BTNCallback<N>>(callback?: C, beginRoot?: BTNKey | N | null | undefined, iterationType?: IterationType, includeNull?: undefined): ReturnType<C>[];
365
366
  subTreeTraverse<C extends BTNCallback<N | null | undefined>>(callback?: C, beginRoot?: BTNKey | N | null | undefined, iterationType?: IterationType, includeNull?: true): ReturnType<C>[];
@@ -429,6 +430,42 @@ export declare class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = Binary
429
430
  * by the return type of the `callback` function.
430
431
  */
431
432
  morris<C extends BTNCallback<N>>(callback?: C, pattern?: DFSOrderPattern, beginRoot?: BTNKey | N | null | undefined): ReturnType<C>[];
433
+ /**
434
+ * The `forEach` function iterates over each entry in a tree and calls a callback function with the
435
+ * entry and the tree as arguments.
436
+ * @param callback - The callback parameter is a function that will be called for each entry in the
437
+ * tree. It takes two parameters: entry and tree.
438
+ */
439
+ forEach(callback: (entry: [BTNKey, V | undefined], tree: this) => void): void;
440
+ /**
441
+ * The `filter` function creates a new tree by iterating over the entries of the current tree and
442
+ * adding the entries that satisfy the given predicate.
443
+ * @param predicate - The `predicate` parameter is a function that takes two arguments: `entry` and
444
+ * `tree`.
445
+ * @returns The `filter` method is returning a new tree object that contains only the entries that
446
+ * satisfy the given predicate function.
447
+ */
448
+ filter(predicate: (entry: [BTNKey, V | undefined], tree: this) => boolean): TREE;
449
+ /**
450
+ * The `map` function creates a new tree by applying a callback function to each entry in the current
451
+ * tree.
452
+ * @param callback - The callback parameter is a function that takes two arguments: entry and tree.
453
+ * @returns The `map` method is returning a new tree object.
454
+ */
455
+ map(callback: (entry: [BTNKey, V | undefined], tree: this) => V): TREE;
456
+ /**
457
+ * The `reduce` function iterates over the entries of a tree and applies a callback function to each
458
+ * entry, accumulating a single value.
459
+ * @param callback - The callback parameter is a function that takes three arguments: accumulator,
460
+ * entry, and tree. It is called for each entry in the tree and is used to accumulate a single value
461
+ * based on the logic defined in the callback function.
462
+ * @param {T} initialValue - The initialValue parameter is the initial value of the accumulator. It
463
+ * is the value that will be passed as the first argument to the callback function when reducing the
464
+ * elements of the tree.
465
+ * @returns The `reduce` method is returning the final value of the accumulator after iterating over
466
+ * all the entries in the tree and applying the callback function to each entry.
467
+ */
468
+ reduce<T>(callback: (accumulator: T, entry: [BTNKey, V | undefined], tree: this) => T, initialValue: T): T;
432
469
  /**
433
470
  * The above function is an iterator for a binary tree that can be used to traverse the tree in
434
471
  * either an iterative or recursive manner.
@@ -438,15 +475,16 @@ export declare class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = Binary
438
475
  * @returns The `*[Symbol.iterator]` method returns a generator object that yields the keys of the
439
476
  * binary tree nodes in a specific order.
440
477
  */
441
- [Symbol.iterator](node?: N | null | undefined): Generator<BTNKey, void, undefined>;
478
+ [Symbol.iterator](node?: N | null | undefined): Generator<[BTNKey, V | undefined], void, undefined>;
442
479
  /**
443
480
  * The `print` function is used to display a binary tree structure in a visually appealing way.
444
- * @param {N | null | undefined} beginRoot - The `root` parameter is of type `BTNKey | N | null |
481
+ * @param {BTNKey | N | null | undefined} [beginRoot=this.root] - The `root` parameter is of type `BTNKey | N | null |
445
482
  * undefined`. It represents the root node of a binary tree. The root node can have one of the
446
483
  * following types:
484
+ * @param {BinaryTreePrintOptions} [options={ isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false}] - Options object that controls printing behavior. You can specify whether to display undefined, null, or sentinel nodes.
447
485
  */
448
- print(beginRoot?: BTNKey | N | null | undefined): void;
449
- protected _displayAux(node: N | null | undefined): [string[], number, number, number];
486
+ print(beginRoot?: BTNKey | N | null | undefined, options?: BinaryTreePrintOptions): void;
487
+ protected _displayAux(node: N | null | undefined, options: BinaryTreePrintOptions): NodeDisplayLayout;
450
488
  protected _defaultOneParamCallback: (node: N) => number;
451
489
  /**
452
490
  * Swap the data of two nodes in the binary tree.
@@ -87,11 +87,12 @@ class BinaryTree {
87
87
  * @param {BinaryTreeOptions} [options] - The options for the binary tree.
88
88
  */
89
89
  constructor(options) {
90
- this.iterationType = types_1.IterationType.ITERATIVE;
91
90
  this._defaultOneParamCallback = (node) => node.key;
92
91
  if (options) {
93
- const { iterationType = types_1.IterationType.ITERATIVE } = options;
94
- this.iterationType = iterationType;
92
+ this.options = Object.assign({ iterationType: types_1.IterationType.ITERATIVE }, options);
93
+ }
94
+ else {
95
+ this.options = { iterationType: types_1.IterationType.ITERATIVE };
95
96
  }
96
97
  this._size = 0;
97
98
  }
@@ -116,6 +117,9 @@ class BinaryTree {
116
117
  createNode(key, value) {
117
118
  return new BinaryTreeNode(key, value);
118
119
  }
120
+ createTree(options) {
121
+ return new BinaryTree(Object.assign(Object.assign({}, this.options), options));
122
+ }
119
123
  /**
120
124
  * Time Complexity: O(n)
121
125
  * Space Complexity: O(1)
@@ -347,7 +351,7 @@ class BinaryTree {
347
351
  * values:
348
352
  * @returns the height of the binary tree.
349
353
  */
350
- getHeight(beginRoot = this.root, iterationType = this.iterationType) {
354
+ getHeight(beginRoot = this.root, iterationType = this.options.iterationType) {
351
355
  beginRoot = this.ensureNotKey(beginRoot);
352
356
  if (!beginRoot)
353
357
  return -1;
@@ -393,7 +397,7 @@ class BinaryTree {
393
397
  * to calculate the minimum height of a binary tree. It can have two possible values:
394
398
  * @returns The function `getMinHeight` returns the minimum height of a binary tree.
395
399
  */
396
- getMinHeight(beginRoot = this.root, iterationType = this.iterationType) {
400
+ getMinHeight(beginRoot = this.root, iterationType = this.options.iterationType) {
397
401
  var _a, _b, _c;
398
402
  beginRoot = this.ensureNotKey(beginRoot);
399
403
  if (!beginRoot)
@@ -485,7 +489,7 @@ class BinaryTree {
485
489
  * traverse the binary tree. It can have two possible values:
486
490
  * @returns an array of nodes of type `N`.
487
491
  */
488
- getNodes(identifier, callback = this._defaultOneParamCallback, onlyOne = false, beginRoot = this.root, iterationType = this.iterationType) {
492
+ getNodes(identifier, callback = this._defaultOneParamCallback, onlyOne = false, beginRoot = this.root, iterationType = this.options.iterationType) {
489
493
  if ((!callback || callback === this._defaultOneParamCallback) && identifier instanceof BinaryTreeNode)
490
494
  callback = (node => node);
491
495
  beginRoot = this.ensureNotKey(beginRoot);
@@ -547,7 +551,7 @@ class BinaryTree {
547
551
  * be performed in a pre-order, in-order, or post-order manner.
548
552
  * @returns a boolean value.
549
553
  */
550
- has(identifier, callback = this._defaultOneParamCallback, beginRoot = this.root, iterationType = this.iterationType) {
554
+ has(identifier, callback = this._defaultOneParamCallback, beginRoot = this.root, iterationType = this.options.iterationType) {
551
555
  if ((!callback || callback === this._defaultOneParamCallback) && identifier instanceof BinaryTreeNode)
552
556
  callback = (node => node);
553
557
  return this.getNodes(identifier, callback, true, beginRoot, iterationType).length > 0;
@@ -577,7 +581,7 @@ class BinaryTree {
577
581
  * nodes are visited during the search.
578
582
  * @returns a value of type `N | null | undefined`.
579
583
  */
580
- getNode(identifier, callback = this._defaultOneParamCallback, beginRoot = this.root, iterationType = this.iterationType) {
584
+ getNode(identifier, callback = this._defaultOneParamCallback, beginRoot = this.root, iterationType = this.options.iterationType) {
581
585
  var _a;
582
586
  if ((!callback || callback === this._defaultOneParamCallback) && identifier instanceof BinaryTreeNode)
583
587
  callback = (node => node);
@@ -670,7 +674,7 @@ class BinaryTree {
670
674
  * @returns The value of the node with the given identifier is being returned. If the node is not
671
675
  * found, `undefined` is returned.
672
676
  */
673
- get(identifier, callback = this._defaultOneParamCallback, beginRoot = this.root, iterationType = this.iterationType) {
677
+ get(identifier, callback = this._defaultOneParamCallback, beginRoot = this.root, iterationType = this.options.iterationType) {
674
678
  var _a, _b;
675
679
  if ((!callback || callback === this._defaultOneParamCallback) && identifier instanceof BinaryTreeNode)
676
680
  callback = (node => node);
@@ -741,7 +745,7 @@ class BinaryTree {
741
745
  * @returns The function `getLeftMost` returns the leftmost node (`N`) in the binary tree. If there
742
746
  * is no leftmost node, it returns `null` or `undefined` depending on the input.
743
747
  */
744
- getLeftMost(beginRoot = this.root, iterationType = this.iterationType) {
748
+ getLeftMost(beginRoot = this.root, iterationType = this.options.iterationType) {
745
749
  beginRoot = this.ensureNotKey(beginRoot);
746
750
  if (!beginRoot)
747
751
  return beginRoot;
@@ -782,7 +786,7 @@ class BinaryTree {
782
786
  * @returns The function `getRightMost` returns the rightmost node (`N`) in a binary tree. If there
783
787
  * is no rightmost node, it returns `null` or `undefined`, depending on the input.
784
788
  */
785
- getRightMost(beginRoot = this.root, iterationType = this.iterationType) {
789
+ getRightMost(beginRoot = this.root, iterationType = this.options.iterationType) {
786
790
  // TODO support get right most by passing key in
787
791
  beginRoot = this.ensureNotKey(beginRoot);
788
792
  if (!beginRoot)
@@ -821,7 +825,7 @@ class BinaryTree {
821
825
  * possible values:
822
826
  * @returns a boolean value.
823
827
  */
824
- isSubtreeBST(beginRoot, iterationType = this.iterationType) {
828
+ isSubtreeBST(beginRoot, iterationType = this.options.iterationType) {
825
829
  // TODO there is a bug
826
830
  beginRoot = this.ensureNotKey(beginRoot);
827
831
  if (!beginRoot)
@@ -868,7 +872,7 @@ class BinaryTree {
868
872
  * expected to be
869
873
  * @returns a boolean value.
870
874
  */
871
- isBST(iterationType = this.iterationType) {
875
+ isBST(iterationType = this.options.iterationType) {
872
876
  if (this.root === null)
873
877
  return true;
874
878
  return this.isSubtreeBST(this.root, iterationType);
@@ -893,13 +897,13 @@ class BinaryTree {
893
897
  * @param iterationType - The `iterationType` parameter determines the type of traversal to be
894
898
  * performed on the subtree. It can have two possible values:
895
899
  * @param [includeNull=false] - The `includeNull` parameter is a boolean value that determines
896
- * whether or not to include null values in the traversal. If `includeNull` is set to `true`, the
900
+ * whether to include null values in the traversal. If `includeNull` is set to `true`, the
897
901
  * traversal will include null values, otherwise it will skip them.
898
902
  * @returns The function `subTreeTraverse` returns an array of values that are the result of invoking
899
903
  * the `callback` function on each node in the subtree. The type of the array elements is determined
900
904
  * by the return type of the `callback` function.
901
905
  */
902
- subTreeTraverse(callback = this._defaultOneParamCallback, beginRoot = this.root, iterationType = this.iterationType, includeNull = false) {
906
+ subTreeTraverse(callback = this._defaultOneParamCallback, beginRoot = this.root, iterationType = this.options.iterationType, includeNull = false) {
903
907
  beginRoot = this.ensureNotKey(beginRoot);
904
908
  const ans = [];
905
909
  if (!beginRoot)
@@ -1126,12 +1130,12 @@ class BinaryTree {
1126
1130
  * @param iterationType - The `iterationType` parameter determines the type of iteration to be
1127
1131
  * performed during the breadth-first search (BFS). It can have two possible values:
1128
1132
  * @param [includeNull=false] - The `includeNull` parameter is a boolean flag that determines whether
1129
- * or not to include null values in the breadth-first search traversal. If `includeNull` is set to
1133
+ * to include null values in the breadth-first search traversal. If `includeNull` is set to
1130
1134
  * `true`, null values will be included in the traversal, otherwise they will be skipped.
1131
1135
  * @returns an array of values that are the result of invoking the callback function on each node in
1132
1136
  * the breadth-first traversal of a binary tree.
1133
1137
  */
1134
- bfs(callback = this._defaultOneParamCallback, beginRoot = this.root, iterationType = this.iterationType, includeNull = false) {
1138
+ bfs(callback = this._defaultOneParamCallback, beginRoot = this.root, iterationType = this.options.iterationType, includeNull = false) {
1135
1139
  beginRoot = this.ensureNotKey(beginRoot);
1136
1140
  if (!beginRoot)
1137
1141
  return [];
@@ -1203,12 +1207,12 @@ class BinaryTree {
1203
1207
  * @param iterationType - The `iterationType` parameter determines the type of iteration to be
1204
1208
  * performed on the tree. It can have two possible values:
1205
1209
  * @param [includeNull=false] - The `includeNull` parameter is a boolean value that determines
1206
- * whether or not to include null values in the resulting levels. If `includeNull` is set to `true`,
1210
+ * whether to include null values in the resulting levels. If `includeNull` is set to `true`,
1207
1211
  * null values will be included in the levels. If `includeNull` is set to `false`, null values will
1208
1212
  * be excluded
1209
1213
  * @returns The function `listLevels` returns a two-dimensional array of type `ReturnType<C>[][]`.
1210
1214
  */
1211
- listLevels(callback = this._defaultOneParamCallback, beginRoot = this.root, iterationType = this.iterationType, includeNull = false) {
1215
+ listLevels(callback = this._defaultOneParamCallback, beginRoot = this.root, iterationType = this.options.iterationType, includeNull = false) {
1212
1216
  beginRoot = this.ensureNotKey(beginRoot);
1213
1217
  const levelsNodes = [];
1214
1218
  if (!beginRoot)
@@ -1407,6 +1411,74 @@ class BinaryTree {
1407
1411
  }
1408
1412
  return ans;
1409
1413
  }
1414
+ /**
1415
+ * The `forEach` function iterates over each entry in a tree and calls a callback function with the
1416
+ * entry and the tree as arguments.
1417
+ * @param callback - The callback parameter is a function that will be called for each entry in the
1418
+ * tree. It takes two parameters: entry and tree.
1419
+ */
1420
+ forEach(callback) {
1421
+ for (const entry of this) {
1422
+ callback(entry, this);
1423
+ }
1424
+ }
1425
+ /**
1426
+ * The `filter` function creates a new tree by iterating over the entries of the current tree and
1427
+ * adding the entries that satisfy the given predicate.
1428
+ * @param predicate - The `predicate` parameter is a function that takes two arguments: `entry` and
1429
+ * `tree`.
1430
+ * @returns The `filter` method is returning a new tree object that contains only the entries that
1431
+ * satisfy the given predicate function.
1432
+ */
1433
+ filter(predicate) {
1434
+ const newTree = this.createTree();
1435
+ for (const [key, value] of this) {
1436
+ if (predicate([key, value], this)) {
1437
+ newTree.add(key, value);
1438
+ }
1439
+ }
1440
+ return newTree;
1441
+ }
1442
+ // TODO Type error, need to return a TREE<NV> that is a value type only for callback function.
1443
+ // map<NV>(callback: (entry: [BTNKey, V | undefined], tree: this) => NV) {
1444
+ // const newTree = this.createTree();
1445
+ // for (const [key, value] of this) {
1446
+ // newTree.add(key, callback([key, value], this));
1447
+ // }
1448
+ // return newTree;
1449
+ // }
1450
+ /**
1451
+ * The `map` function creates a new tree by applying a callback function to each entry in the current
1452
+ * tree.
1453
+ * @param callback - The callback parameter is a function that takes two arguments: entry and tree.
1454
+ * @returns The `map` method is returning a new tree object.
1455
+ */
1456
+ map(callback) {
1457
+ const newTree = this.createTree();
1458
+ for (const [key, value] of this) {
1459
+ newTree.add(key, callback([key, value], this));
1460
+ }
1461
+ return newTree;
1462
+ }
1463
+ /**
1464
+ * The `reduce` function iterates over the entries of a tree and applies a callback function to each
1465
+ * entry, accumulating a single value.
1466
+ * @param callback - The callback parameter is a function that takes three arguments: accumulator,
1467
+ * entry, and tree. It is called for each entry in the tree and is used to accumulate a single value
1468
+ * based on the logic defined in the callback function.
1469
+ * @param {T} initialValue - The initialValue parameter is the initial value of the accumulator. It
1470
+ * is the value that will be passed as the first argument to the callback function when reducing the
1471
+ * elements of the tree.
1472
+ * @returns The `reduce` method is returning the final value of the accumulator after iterating over
1473
+ * all the entries in the tree and applying the callback function to each entry.
1474
+ */
1475
+ reduce(callback, initialValue) {
1476
+ let accumulator = initialValue;
1477
+ for (const [key, value] of this) {
1478
+ accumulator = callback(accumulator, [key, value], this);
1479
+ }
1480
+ return accumulator;
1481
+ }
1410
1482
  /**
1411
1483
  * The above function is an iterator for a binary tree that can be used to traverse the tree in
1412
1484
  * either an iterative or recursive manner.
@@ -1417,78 +1489,104 @@ class BinaryTree {
1417
1489
  * binary tree nodes in a specific order.
1418
1490
  */
1419
1491
  *[Symbol.iterator](node = this.root) {
1420
- if (!node) {
1492
+ if (!node)
1421
1493
  return;
1422
- }
1423
- if (this.iterationType === types_1.IterationType.ITERATIVE) {
1494
+ if (this.options.iterationType === types_1.IterationType.ITERATIVE) {
1424
1495
  const stack = [];
1425
1496
  let current = node;
1426
1497
  while (current || stack.length > 0) {
1427
- while (current) {
1498
+ while (current && !isNaN(current.key)) {
1428
1499
  stack.push(current);
1429
1500
  current = current.left;
1430
1501
  }
1431
1502
  current = stack.pop();
1432
- if (current)
1433
- yield current.key;
1434
- if (current)
1503
+ if (current && !isNaN(current.key)) {
1504
+ yield [current.key, current.value];
1435
1505
  current = current.right;
1506
+ }
1436
1507
  }
1437
1508
  }
1438
1509
  else {
1439
- if (node.left) {
1510
+ if (node.left && !isNaN(node.key)) {
1440
1511
  yield* this[Symbol.iterator](node.left);
1441
1512
  }
1442
- yield node.key;
1443
- if (node.right) {
1513
+ yield [node.key, node.value];
1514
+ if (node.right && !isNaN(node.key)) {
1444
1515
  yield* this[Symbol.iterator](node.right);
1445
1516
  }
1446
1517
  }
1447
1518
  }
1448
1519
  /**
1449
1520
  * The `print` function is used to display a binary tree structure in a visually appealing way.
1450
- * @param {N | null | undefined} beginRoot - The `root` parameter is of type `BTNKey | N | null |
1521
+ * @param {BTNKey | N | null | undefined} [beginRoot=this.root] - The `root` parameter is of type `BTNKey | N | null |
1451
1522
  * undefined`. It represents the root node of a binary tree. The root node can have one of the
1452
1523
  * following types:
1524
+ * @param {BinaryTreePrintOptions} [options={ isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false}] - Options object that controls printing behavior. You can specify whether to display undefined, null, or sentinel nodes.
1453
1525
  */
1454
- print(beginRoot = this.root) {
1526
+ print(beginRoot = this.root, options) {
1527
+ const opts = Object.assign({ isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false }, options);
1455
1528
  beginRoot = this.ensureNotKey(beginRoot);
1456
1529
  if (!beginRoot)
1457
1530
  return;
1531
+ if (opts.isShowUndefined)
1532
+ console.log(`U for undefined
1533
+ `);
1534
+ if (opts.isShowNull)
1535
+ console.log(`N for null
1536
+ `);
1537
+ if (opts.isShowRedBlackNIL)
1538
+ console.log(`S for Sentinel Node
1539
+ `);
1458
1540
  const display = (root) => {
1459
- const [lines, , ,] = this._displayAux(root);
1541
+ const [lines, , ,] = this._displayAux(root, opts);
1460
1542
  for (const line of lines) {
1461
1543
  console.log(line);
1462
1544
  }
1463
1545
  };
1464
1546
  display(beginRoot);
1465
1547
  }
1466
- _displayAux(node) {
1467
- if (!node) {
1468
- return [['─'], 1, 0, 0];
1548
+ _displayAux(node, options) {
1549
+ const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
1550
+ const emptyDisplayLayout = [['─'], 1, 0, 0];
1551
+ // Check if node is null or undefined or key is NaN
1552
+ if (node === null && !isShowNull) {
1553
+ return emptyDisplayLayout;
1554
+ }
1555
+ else if (node === undefined && !isShowUndefined) {
1556
+ return emptyDisplayLayout;
1557
+ }
1558
+ else if (node !== null && node !== undefined && isNaN(node.key) && !isShowRedBlackNIL) {
1559
+ return emptyDisplayLayout;
1469
1560
  }
1470
- const line = node.key.toString();
1471
- const width = line.length;
1472
- if (!node.left && !node.right) {
1473
- return [[line], width, 1, Math.floor(width / 2)];
1561
+ else if (node !== null && node !== undefined) {
1562
+ // Display logic of normal nodes
1563
+ const key = node.key, line = isNaN(key) ? 'S' : key.toString(), width = line.length;
1564
+ return _buildNodeDisplay(line, width, this._displayAux(node.left, options), this._displayAux(node.right, options));
1474
1565
  }
1475
- const [leftLines, leftWidth, leftHeight, leftMiddle] = node.left ? this._displayAux(node.left) : [[''], 0, 0, 0];
1476
- const [rightLines, rightWidth, rightHeight, rightMiddle] = node.right ? this._displayAux(node.right) : [[''], 0, 0, 0];
1477
- const firstLine = ' '.repeat(Math.max(0, leftMiddle + 1))
1478
- + '_'.repeat(Math.max(0, leftWidth - leftMiddle - 1))
1479
- + line
1480
- + '_'.repeat(Math.max(0, rightMiddle))
1481
- + ' '.repeat(Math.max(0, rightWidth - rightMiddle));
1482
- const secondLine = (leftHeight > 0 ? ' '.repeat(leftMiddle) + '/' + ' '.repeat(leftWidth - leftMiddle - 1) : ' '.repeat(leftWidth))
1483
- + ' '.repeat(width)
1484
- + (rightHeight > 0 ? ' '.repeat(rightMiddle) + '\\' + ' '.repeat(rightWidth - rightMiddle - 1) : ' '.repeat(rightWidth));
1485
- const mergedLines = [firstLine, secondLine];
1486
- for (let i = 0; i < Math.max(leftHeight, rightHeight); i++) {
1487
- const leftLine = i < leftHeight ? leftLines[i] : ' '.repeat(leftWidth);
1488
- const rightLine = i < rightHeight ? rightLines[i] : ' '.repeat(rightWidth);
1489
- mergedLines.push(leftLine + ' '.repeat(width) + rightLine);
1566
+ else {
1567
+ // For cases where none of the conditions are met, null, undefined, and NaN nodes are not displayed
1568
+ const line = node === undefined ? 'U' : 'N', width = line.length;
1569
+ return _buildNodeDisplay(line, width, [[''], 1, 0, 0], [[''], 1, 0, 0]);
1570
+ }
1571
+ function _buildNodeDisplay(line, width, left, right) {
1572
+ const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
1573
+ const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
1574
+ const firstLine = ' '.repeat(Math.max(0, leftMiddle + 1))
1575
+ + '_'.repeat(Math.max(0, leftWidth - leftMiddle - 1))
1576
+ + line
1577
+ + '_'.repeat(Math.max(0, rightMiddle))
1578
+ + ' '.repeat(Math.max(0, rightWidth - rightMiddle));
1579
+ const secondLine = (leftHeight > 0 ? ' '.repeat(leftMiddle) + '/' + ' '.repeat(leftWidth - leftMiddle - 1) : ' '.repeat(leftWidth))
1580
+ + ' '.repeat(width)
1581
+ + (rightHeight > 0 ? ' '.repeat(rightMiddle) + '\\' + ' '.repeat(rightWidth - rightMiddle - 1) : ' '.repeat(rightWidth));
1582
+ const mergedLines = [firstLine, secondLine];
1583
+ for (let i = 0; i < Math.max(leftHeight, rightHeight); i++) {
1584
+ const leftLine = i < leftHeight ? leftLines[i] : ' '.repeat(leftWidth);
1585
+ const rightLine = i < rightHeight ? rightLines[i] : ' '.repeat(rightWidth);
1586
+ mergedLines.push(leftLine + ' '.repeat(width) + rightLine);
1587
+ }
1588
+ return [mergedLines, leftWidth + width + rightWidth, Math.max(leftHeight, rightHeight) + 2, leftWidth + Math.floor(width / 2)];
1490
1589
  }
1491
- return [mergedLines, leftWidth + width + rightWidth, Math.max(leftHeight, rightHeight) + 2, leftWidth + Math.floor(width / 2)];
1492
1590
  }
1493
1591
  /**
1494
1592
  * Swap the data of two nodes in the binary tree.