bst-typed 1.48.1 → 1.48.3

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 (76) hide show
  1. package/dist/data-structures/base/index.d.ts +1 -0
  2. package/dist/data-structures/base/index.js +17 -0
  3. package/dist/data-structures/base/iterable-base.d.ts +232 -0
  4. package/dist/data-structures/base/iterable-base.js +312 -0
  5. package/dist/data-structures/binary-tree/avl-tree.d.ts +16 -16
  6. package/dist/data-structures/binary-tree/avl-tree.js +7 -7
  7. package/dist/data-structures/binary-tree/binary-tree.d.ts +121 -152
  8. package/dist/data-structures/binary-tree/binary-tree.js +140 -182
  9. package/dist/data-structures/binary-tree/bst.d.ts +28 -47
  10. package/dist/data-structures/binary-tree/bst.js +54 -57
  11. package/dist/data-structures/binary-tree/rb-tree.d.ts +15 -15
  12. package/dist/data-structures/binary-tree/rb-tree.js +7 -7
  13. package/dist/data-structures/binary-tree/tree-multimap.d.ts +22 -22
  14. package/dist/data-structures/binary-tree/tree-multimap.js +11 -11
  15. package/dist/data-structures/graph/abstract-graph.d.ts +44 -6
  16. package/dist/data-structures/graph/abstract-graph.js +50 -27
  17. package/dist/data-structures/hash/hash-map.d.ts +59 -100
  18. package/dist/data-structures/hash/hash-map.js +69 -173
  19. package/dist/data-structures/heap/heap.d.ts +50 -7
  20. package/dist/data-structures/heap/heap.js +60 -30
  21. package/dist/data-structures/index.d.ts +1 -0
  22. package/dist/data-structures/index.js +1 -0
  23. package/dist/data-structures/linked-list/doubly-linked-list.d.ts +38 -51
  24. package/dist/data-structures/linked-list/doubly-linked-list.js +46 -73
  25. package/dist/data-structures/linked-list/singly-linked-list.d.ts +32 -51
  26. package/dist/data-structures/linked-list/singly-linked-list.js +40 -73
  27. package/dist/data-structures/queue/deque.d.ts +29 -51
  28. package/dist/data-structures/queue/deque.js +36 -71
  29. package/dist/data-structures/queue/queue.d.ts +49 -48
  30. package/dist/data-structures/queue/queue.js +69 -82
  31. package/dist/data-structures/stack/stack.d.ts +43 -10
  32. package/dist/data-structures/stack/stack.js +50 -31
  33. package/dist/data-structures/trie/trie.d.ts +41 -6
  34. package/dist/data-structures/trie/trie.js +53 -32
  35. package/dist/interfaces/binary-tree.d.ts +6 -6
  36. package/dist/types/common.d.ts +11 -8
  37. package/dist/types/common.js +6 -1
  38. package/dist/types/data-structures/base/base.d.ts +5 -0
  39. package/dist/types/data-structures/base/base.js +2 -0
  40. package/dist/types/data-structures/base/index.d.ts +1 -0
  41. package/dist/types/data-structures/base/index.js +17 -0
  42. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +3 -3
  43. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +4 -4
  44. package/dist/types/data-structures/binary-tree/bst.d.ts +6 -6
  45. package/dist/types/data-structures/binary-tree/rb-tree.d.ts +3 -3
  46. package/dist/types/data-structures/binary-tree/tree-multimap.d.ts +3 -3
  47. package/dist/types/data-structures/index.d.ts +1 -0
  48. package/dist/types/data-structures/index.js +1 -0
  49. package/package.json +2 -2
  50. package/src/data-structures/base/index.ts +1 -0
  51. package/src/data-structures/base/iterable-base.ts +329 -0
  52. package/src/data-structures/binary-tree/avl-tree.ts +20 -21
  53. package/src/data-structures/binary-tree/binary-tree.ts +222 -267
  54. package/src/data-structures/binary-tree/bst.ts +86 -82
  55. package/src/data-structures/binary-tree/rb-tree.ts +25 -26
  56. package/src/data-structures/binary-tree/tree-multimap.ts +30 -35
  57. package/src/data-structures/graph/abstract-graph.ts +55 -28
  58. package/src/data-structures/hash/hash-map.ts +76 -185
  59. package/src/data-structures/heap/heap.ts +63 -36
  60. package/src/data-structures/index.ts +1 -0
  61. package/src/data-structures/linked-list/doubly-linked-list.ts +50 -79
  62. package/src/data-structures/linked-list/singly-linked-list.ts +45 -80
  63. package/src/data-structures/queue/deque.ts +40 -82
  64. package/src/data-structures/queue/queue.ts +72 -87
  65. package/src/data-structures/stack/stack.ts +53 -34
  66. package/src/data-structures/trie/trie.ts +58 -35
  67. package/src/interfaces/binary-tree.ts +5 -6
  68. package/src/types/common.ts +11 -8
  69. package/src/types/data-structures/base/base.ts +6 -0
  70. package/src/types/data-structures/base/index.ts +1 -0
  71. package/src/types/data-structures/binary-tree/avl-tree.ts +3 -3
  72. package/src/types/data-structures/binary-tree/binary-tree.ts +6 -5
  73. package/src/types/data-structures/binary-tree/bst.ts +6 -6
  74. package/src/types/data-structures/binary-tree/rb-tree.ts +3 -3
  75. package/src/types/data-structures/binary-tree/tree-multimap.ts +3 -3
  76. package/src/types/data-structures/index.ts +1 -0
@@ -10,10 +10,9 @@ import type {
10
10
  BinaryTreeNodeNested,
11
11
  BinaryTreeOptions,
12
12
  BTNCallback,
13
- BTNKey,
14
13
  BTNodeEntry,
15
14
  BTNodeExemplar,
16
- BTNodeKeyOrNode
15
+ BTNodeKeyOrNode,
17
16
  } from '../../types';
18
17
  import {
19
18
  BinaryTreeNested,
@@ -22,25 +21,27 @@ import {
22
21
  DFSOrderPattern,
23
22
  FamilyPosition,
24
23
  IterationType,
25
- NodeDisplayLayout
24
+ NodeDisplayLayout,
25
+ PairCallback
26
26
  } from '../../types';
27
27
  import { IBinaryTree } from '../../interfaces';
28
28
  import { trampoline } from '../../utils';
29
29
  import { Queue } from '../queue';
30
+ import { IterablePairBase } from "../base";
30
31
 
31
32
  /**
32
33
  * Represents a node in a binary tree.
33
34
  * @template V - The type of data stored in the node.
34
35
  * @template N - The type of the family relationship in the binary tree.
35
36
  */
36
- export class BinaryTreeNode<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode<V, BinaryTreeNodeNested<V>>> {
37
- key: BTNKey;
37
+ export class BinaryTreeNode<K = any, V = any, N extends BinaryTreeNode<K, V, N> = BinaryTreeNode<K, V, BinaryTreeNodeNested<K, V>>> {
38
+ key: K;
38
39
 
39
40
  value?: V;
40
41
 
41
42
  parent?: N;
42
43
 
43
- constructor(key: BTNKey, value?: V) {
44
+ constructor(key: K, value?: V) {
44
45
  this.key = key;
45
46
  this.value = value;
46
47
  }
@@ -103,9 +104,9 @@ export class BinaryTreeNode<V = any, N extends BinaryTreeNode<V, N> = BinaryTree
103
104
  * 9. Complete Trees: All levels are fully filled except possibly the last, filled from left to right.
104
105
  */
105
106
 
106
- export 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>>>
107
+ export class BinaryTree<K = any, V = any, N extends BinaryTreeNode<K, V, N> = BinaryTreeNode<K, V, BinaryTreeNodeNested<K, V>>, TREE extends BinaryTree<K, V, N, TREE> = BinaryTree<K, V, N, BinaryTreeNested<K, V, N>>> extends IterablePairBase<K, V | undefined>
107
108
 
108
- implements IBinaryTree<V, N, TREE> {
109
+ implements IBinaryTree<K, V, N, TREE> {
109
110
  iterationType = IterationType.ITERATIVE
110
111
 
111
112
  /**
@@ -117,13 +118,16 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
117
118
  * `Partial<BinaryTreeOptions>`, which means that not all properties of `BinaryTreeOptions` are
118
119
  * required.
119
120
  */
120
- constructor(elements?: Iterable<BTNodeExemplar<V, N>>, options?: Partial<BinaryTreeOptions>) {
121
-
121
+ constructor(elements?: Iterable<BTNodeExemplar<K, V, N>>, options?: Partial<BinaryTreeOptions<K>>) {
122
+ super();
122
123
  if (options) {
123
- const { iterationType } = options;
124
+ const { iterationType, extractor } = options;
124
125
  if (iterationType) {
125
126
  this.iterationType = iterationType;
126
127
  }
128
+ if (extractor) {
129
+ this._extractor = extractor;
130
+ }
127
131
  }
128
132
 
129
133
  this._size = 0;
@@ -131,6 +135,12 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
131
135
  if (elements) this.addMany(elements);
132
136
  }
133
137
 
138
+ protected _extractor = (key: K) => Number(key)
139
+
140
+ get extractor() {
141
+ return this._extractor;
142
+ }
143
+
134
144
  protected _root?: N | null;
135
145
 
136
146
  get root(): N | null | undefined {
@@ -145,12 +155,12 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
145
155
 
146
156
  /**
147
157
  * Creates a new instance of BinaryTreeNode with the given key and value.
148
- * @param {BTNKey} key - The key for the new node.
158
+ * @param {K} key - The key for the new node.
149
159
  * @param {V} value - The value for the new node.
150
160
  * @returns {N} - The newly created BinaryTreeNode.
151
161
  */
152
- createNode(key: BTNKey, value?: V): N {
153
- return new BinaryTreeNode<V, N>(key, value) as N;
162
+ createNode(key: K, value?: V): N {
163
+ return new BinaryTreeNode<K, V, N>(key, value) as N;
154
164
  }
155
165
 
156
166
  /**
@@ -160,27 +170,27 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
160
170
  * you can provide only a subset of the properties defined in the `BinaryTreeOptions` interface.
161
171
  * @returns a new instance of a binary tree.
162
172
  */
163
- createTree(options?: Partial<BinaryTreeOptions>): TREE {
164
- return new BinaryTree<V, N, TREE>([], { iterationType: this.iterationType, ...options }) as TREE;
173
+ createTree(options?: Partial<BinaryTreeOptions<K>>): TREE {
174
+ return new BinaryTree<K, V, N, TREE>([], { iterationType: this.iterationType, ...options }) as TREE;
165
175
  }
166
176
 
167
177
  /**
168
178
  * The function "isNode" checks if an exemplar is an instance of the BinaryTreeNode class.
169
- * @param exemplar - The `exemplar` parameter is a variable of type `BTNodeExemplar<V, N>`.
179
+ * @param exemplar - The `exemplar` parameter is a variable of type `BTNodeExemplar<K, V,N>`.
170
180
  * @returns a boolean value indicating whether the exemplar is an instance of the class N.
171
181
  */
172
- isNode(exemplar: BTNodeExemplar<V, N>): exemplar is N {
182
+ isNode(exemplar: BTNodeExemplar<K, V, N>): exemplar is N {
173
183
  return exemplar instanceof BinaryTreeNode;
174
184
  }
175
185
 
176
186
  /**
177
187
  * The function `exemplarToNode` converts an exemplar of a binary tree node into an actual node
178
188
  * object.
179
- * @param exemplar - BTNodeExemplar<V, N> - A generic type representing the exemplar parameter of the
189
+ * @param exemplar - BTNodeExemplar<K, V,N> - A generic type representing the exemplar parameter of the
180
190
  * function. It can be any type.
181
191
  * @returns a value of type `N` (which represents a node), or `null`, or `undefined`.
182
192
  */
183
- exemplarToNode(exemplar: BTNodeExemplar<V, N>): N | null | undefined {
193
+ exemplarToNode(exemplar: BTNodeExemplar<K, V, N>): N | null | undefined {
184
194
  if (exemplar === undefined) return;
185
195
 
186
196
  let node: N | null | undefined;
@@ -197,7 +207,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
197
207
  }
198
208
  } else if (this.isNode(exemplar)) {
199
209
  node = exemplar;
200
- } else if (this.isNodeKey(exemplar)) {
210
+ } else if (this.isNotNodeInstance(exemplar)) {
201
211
  node = this.createNode(exemplar);
202
212
  } else {
203
213
  return;
@@ -207,11 +217,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
207
217
 
208
218
  /**
209
219
  * The function checks if a given value is an entry in a binary tree node.
210
- * @param kne - BTNodeExemplar<V, N> - A generic type representing a node in a binary tree. It has
220
+ * @param kne - BTNodeExemplar<K, V,N> - A generic type representing a node in a binary tree. It has
211
221
  * two type parameters V and N, representing the value and node type respectively.
212
222
  * @returns a boolean value.
213
223
  */
214
- isEntry(kne: BTNodeExemplar<V, N>): kne is BTNodeEntry<V> {
224
+ isEntry(kne: BTNodeExemplar<K, V, N>): kne is BTNodeEntry<K, V> {
215
225
  return Array.isArray(kne) && kne.length === 2;
216
226
  }
217
227
 
@@ -228,7 +238,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
228
238
  * @param keyOrNodeOrEntry - The parameter `keyOrNodeOrEntry` can be one of the following:
229
239
  * @returns The function `add` returns the inserted node (`N`), `null`, or `undefined`.
230
240
  */
231
- add(keyOrNodeOrEntry: BTNodeExemplar<V, N>): N | null | undefined {
241
+ add(keyOrNodeOrEntry: BTNodeExemplar<K, V, N>): N | null | undefined {
232
242
 
233
243
  let inserted: N | null | undefined;
234
244
  const newNode = this.exemplarToNode(keyOrNodeOrEntry);
@@ -277,11 +287,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
277
287
  * The function `addMany` takes in an iterable of `BTNodeExemplar` objects, adds each object to the
278
288
  * current instance, and returns an array of the inserted nodes.
279
289
  * @param nodes - The `nodes` parameter is an iterable (such as an array or a set) of
280
- * `BTNodeExemplar<V, N>` objects.
290
+ * `BTNodeExemplar<K, V,N>` objects.
281
291
  * @returns The function `addMany` returns an array of values, where each value is either of type
282
292
  * `N`, `null`, or `undefined`.
283
293
  */
284
- addMany(nodes: Iterable<BTNodeExemplar<V, N>>): (N | null | undefined)[] {
294
+ addMany(nodes: Iterable<BTNodeExemplar<K, V, N>>): (N | null | undefined)[] {
285
295
  // TODO not sure addMany not be run multi times
286
296
  const inserted: (N | null | undefined)[] = [];
287
297
  for (const kne of nodes) {
@@ -303,7 +313,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
303
313
  * @param nodesOrKeysOrEntries - The parameter `nodesOrKeysOrEntries` is an iterable object that can
304
314
  * contain either `BTNodeExemplar` objects, keys, or entries.
305
315
  */
306
- refill(nodesOrKeysOrEntries: Iterable<BTNodeExemplar<V, N>>): void {
316
+ refill(nodesOrKeysOrEntries: Iterable<BTNodeExemplar<K, V, N>>): void {
307
317
  this.clear();
308
318
  this.addMany(nodesOrKeysOrEntries);
309
319
  }
@@ -313,7 +323,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
313
323
  * Space Complexity: O(1)
314
324
  */
315
325
 
316
- delete<C extends BTNCallback<N, BTNKey>>(identifier: BTNKey, callback?: C): BiTreeDeleteResult<N>[];
326
+ delete<C extends BTNCallback<N, K>>(identifier: K, callback?: C): BiTreeDeleteResult<N>[];
317
327
 
318
328
  delete<C extends BTNCallback<N, N>>(identifier: N | null | undefined, callback?: C): BiTreeDeleteResult<N>[];
319
329
 
@@ -394,15 +404,15 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
394
404
  * Space Complexity: O(1)
395
405
  *
396
406
  * The function calculates the depth of a given node in a binary tree.
397
- * @param {BTNKey | N | null | undefined} distNode - The `distNode` parameter represents the node in
398
- * the binary tree whose depth we want to find. It can be of type `BTNKey`, `N`, `null`, or
407
+ * @param {K | N | null | undefined} distNode - The `distNode` parameter represents the node in
408
+ * the binary tree whose depth we want to find. It can be of type `K`, `N`, `null`, or
399
409
  * `undefined`.
400
- * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node
401
- * from which we want to calculate the depth. It can be either a `BTNKey` (binary tree node key) or
410
+ * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node
411
+ * from which we want to calculate the depth. It can be either a `K` (binary tree node key) or
402
412
  * `N` (binary tree node) or `null` or `undefined`. If no value is provided for `beginRoot
403
413
  * @returns the depth of the `distNode` relative to the `beginRoot`.
404
414
  */
405
- getDepth(distNode: BTNodeKeyOrNode<N>, beginRoot: BTNodeKeyOrNode<N> = this.root): number {
415
+ getDepth(distNode: BTNodeKeyOrNode<K, N>, beginRoot: BTNodeKeyOrNode<K, N> = this.root): number {
406
416
  distNode = this.ensureNode(distNode);
407
417
  beginRoot = this.ensureNode(beginRoot);
408
418
  let depth = 0;
@@ -427,15 +437,15 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
427
437
  *
428
438
  * The function `getHeight` calculates the maximum height of a binary tree using either recursive or
429
439
  * iterative traversal.
430
- * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
440
+ * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
431
441
  * starting node of the binary tree from which we want to calculate the height. It can be of type
432
- * `BTNKey`, `N`, `null`, or `undefined`. If not provided, it defaults to `this.root`.
442
+ * `K`, `N`, `null`, or `undefined`. If not provided, it defaults to `this.root`.
433
443
  * @param iterationType - The `iterationType` parameter is used to determine whether to calculate the
434
444
  * height of the tree using a recursive approach or an iterative approach. It can have two possible
435
445
  * values:
436
446
  * @returns the height of the binary tree.
437
447
  */
438
- getHeight(beginRoot: BTNodeKeyOrNode<N> = this.root, iterationType = this.iterationType): number {
448
+ getHeight(beginRoot: BTNodeKeyOrNode<K, N> = this.root, iterationType = this.iterationType): number {
439
449
  beginRoot = this.ensureNode(beginRoot);
440
450
  if (!beginRoot) return -1;
441
451
 
@@ -477,14 +487,14 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
477
487
  *
478
488
  * The `getMinHeight` function calculates the minimum height of a binary tree using either a
479
489
  * recursive or iterative approach.
480
- * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
490
+ * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
481
491
  * starting node of the binary tree from which we want to calculate the minimum height. It can be of
482
- * type `BTNKey`, `N`, `null`, or `undefined`. If no value is provided, it defaults to `this.root`.
492
+ * type `K`, `N`, `null`, or `undefined`. If no value is provided, it defaults to `this.root`.
483
493
  * @param iterationType - The `iterationType` parameter is used to determine the method of iteration
484
494
  * to calculate the minimum height of a binary tree. It can have two possible values:
485
495
  * @returns The function `getMinHeight` returns the minimum height of a binary tree.
486
496
  */
487
- getMinHeight(beginRoot: BTNodeKeyOrNode<N> = this.root, iterationType = this.iterationType): number {
497
+ getMinHeight(beginRoot: BTNodeKeyOrNode<K, N> = this.root, iterationType = this.iterationType): number {
488
498
  beginRoot = this.ensureNode(beginRoot);
489
499
  if (!beginRoot) return -1;
490
500
 
@@ -539,12 +549,12 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
539
549
  *
540
550
  * The function checks if a binary tree is perfectly balanced by comparing the minimum height and the
541
551
  * height of the tree.
542
- * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
543
- * for calculating the height and minimum height of a binary tree. It can be either a `BTNKey` (a key
552
+ * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
553
+ * for calculating the height and minimum height of a binary tree. It can be either a `K` (a key
544
554
  * value of a binary tree node), `N` (a node of a binary tree), `null`, or `undefined`. If
545
555
  * @returns a boolean value.
546
556
  */
547
- isPerfectlyBalanced(beginRoot: BTNodeKeyOrNode<N> = this.root): boolean {
557
+ isPerfectlyBalanced(beginRoot: BTNodeKeyOrNode<K, N> = this.root): boolean {
548
558
  return this.getMinHeight(beginRoot) + 1 >= this.getHeight(beginRoot);
549
559
  }
550
560
 
@@ -553,11 +563,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
553
563
  * Space Complexity: O(log n)
554
564
  */
555
565
 
556
- getNodes<C extends BTNCallback<N, BTNKey>>(
557
- identifier: BTNKey,
566
+ getNodes<C extends BTNCallback<N, K>>(
567
+ identifier: K,
558
568
  callback?: C,
559
569
  onlyOne?: boolean,
560
- beginRoot?: BTNodeKeyOrNode<N>,
570
+ beginRoot?: BTNodeKeyOrNode<K, N>,
561
571
  iterationType?: IterationType
562
572
  ): N[];
563
573
 
@@ -565,7 +575,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
565
575
  identifier: N | null | undefined,
566
576
  callback?: C,
567
577
  onlyOne?: boolean,
568
- beginRoot?: BTNodeKeyOrNode<N>,
578
+ beginRoot?: BTNodeKeyOrNode<K, N>,
569
579
  iterationType?: IterationType
570
580
  ): N[];
571
581
 
@@ -573,7 +583,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
573
583
  identifier: ReturnType<C>,
574
584
  callback: C,
575
585
  onlyOne?: boolean,
576
- beginRoot?: BTNodeKeyOrNode<N>,
586
+ beginRoot?: BTNodeKeyOrNode<K, N>,
577
587
  iterationType?: IterationType
578
588
  ): N[];
579
589
 
@@ -595,7 +605,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
595
605
  * matches the identifier. If set to true, the function will stop iterating once it finds a matching
596
606
  * node and return that node. If set to false (default), the function will continue iterating and
597
607
  * return all nodes that match the identifier.
598
- * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
608
+ * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
599
609
  * starting node for the traversal. It can be either a key, a node object, or `null`/`undefined`. If
600
610
  * it is `null` or `undefined`, an empty array will be returned.
601
611
  * @param iterationType - The `iterationType` parameter determines the type of iteration used to
@@ -606,7 +616,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
606
616
  identifier: ReturnType<C> | null | undefined,
607
617
  callback: C = this._defaultOneParamCallback as C,
608
618
  onlyOne = false,
609
- beginRoot: BTNodeKeyOrNode<N> = this.root,
619
+ beginRoot: BTNodeKeyOrNode<K, N> = this.root,
610
620
  iterationType = this.iterationType
611
621
  ): N[] {
612
622
  if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
@@ -651,24 +661,24 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
651
661
  * Space Complexity: O(log n).
652
662
  */
653
663
 
654
- has<C extends BTNCallback<N, BTNKey>>(
655
- identifier: BTNKey,
664
+ has<C extends BTNCallback<N, K>>(
665
+ identifier: K,
656
666
  callback?: C,
657
- beginRoot?: BTNodeKeyOrNode<N>,
667
+ beginRoot?: BTNodeKeyOrNode<K, N>,
658
668
  iterationType?: IterationType
659
669
  ): boolean;
660
670
 
661
671
  has<C extends BTNCallback<N, N>>(
662
672
  identifier: N | null | undefined,
663
673
  callback?: C,
664
- beginRoot?: BTNodeKeyOrNode<N>,
674
+ beginRoot?: BTNodeKeyOrNode<K, N>,
665
675
  iterationType?: IterationType
666
676
  ): boolean;
667
677
 
668
678
  has<C extends BTNCallback<N>>(
669
679
  identifier: ReturnType<C> | null | undefined,
670
680
  callback: C,
671
- beginRoot?: BTNodeKeyOrNode<N>,
681
+ beginRoot?: BTNodeKeyOrNode<K, N>,
672
682
  iterationType?: IterationType
673
683
  ): boolean;
674
684
 
@@ -684,8 +694,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
684
694
  * the binary tree. It is used to filter the nodes based on certain conditions. The `callback`
685
695
  * function should return a boolean value indicating whether the node should be included in the
686
696
  * result or not.
687
- * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
688
- * for the search in the binary tree. It can be specified as a `BTNKey` (a unique identifier for a
697
+ * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
698
+ * for the search in the binary tree. It can be specified as a `K` (a unique identifier for a
689
699
  * node in the binary tree), a node object (`N`), or `null`/`undefined` to start the search from
690
700
  * @param iterationType - The `iterationType` parameter is a variable that determines the type of
691
701
  * iteration to be performed on the binary tree. It is used to specify whether the iteration should
@@ -695,7 +705,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
695
705
  has<C extends BTNCallback<N>>(
696
706
  identifier: ReturnType<C> | null | undefined,
697
707
  callback: C = this._defaultOneParamCallback as C,
698
- beginRoot: BTNodeKeyOrNode<N> = this.root,
708
+ beginRoot: BTNodeKeyOrNode<K, N> = this.root,
699
709
  iterationType = this.iterationType
700
710
  ): boolean {
701
711
  if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
@@ -709,24 +719,24 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
709
719
  * Space Complexity: O(log n).
710
720
  */
711
721
 
712
- getNode<C extends BTNCallback<N, BTNKey>>(
713
- identifier: BTNKey,
722
+ getNode<C extends BTNCallback<N, K>>(
723
+ identifier: K,
714
724
  callback?: C,
715
- beginRoot?: BTNodeKeyOrNode<N>,
725
+ beginRoot?: BTNodeKeyOrNode<K, N>,
716
726
  iterationType?: IterationType
717
727
  ): N | null | undefined;
718
728
 
719
729
  getNode<C extends BTNCallback<N, N>>(
720
730
  identifier: N | null | undefined,
721
731
  callback?: C,
722
- beginRoot?: BTNodeKeyOrNode<N>,
732
+ beginRoot?: BTNodeKeyOrNode<K, N>,
723
733
  iterationType?: IterationType
724
734
  ): N | null | undefined;
725
735
 
726
736
  getNode<C extends BTNCallback<N>>(
727
737
  identifier: ReturnType<C>,
728
738
  callback: C,
729
- beginRoot?: BTNodeKeyOrNode<N>,
739
+ beginRoot?: BTNodeKeyOrNode<K, N>,
730
740
  iterationType?: IterationType
731
741
  ): N | null | undefined;
732
742
 
@@ -743,7 +753,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
743
753
  * @param {C} callback - The `callback` parameter is a function that will be called for each node in
744
754
  * the binary tree. It is used to determine if a node matches the given identifier. The `callback`
745
755
  * function should take a single parameter of type `N` (the type of the nodes in the binary tree) and
746
- * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
756
+ * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
747
757
  * for searching the binary tree. It can be either a key value, a node object, or `null`/`undefined`.
748
758
  * If `null` or `undefined` is passed, the search will start from the root of the binary tree.
749
759
  * @param iterationType - The `iterationType` parameter is used to specify the type of iteration to
@@ -754,7 +764,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
754
764
  getNode<C extends BTNCallback<N>>(
755
765
  identifier: ReturnType<C> | null | undefined,
756
766
  callback: C = this._defaultOneParamCallback as C,
757
- beginRoot: BTNodeKeyOrNode<N> = this.root,
767
+ beginRoot: BTNodeKeyOrNode<K, N> = this.root,
758
768
  iterationType = this.iterationType
759
769
  ): N | null | undefined {
760
770
  if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
@@ -774,7 +784,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
774
784
  *
775
785
  * The function `getNodeByKey` searches for a node in a binary tree by its key, using either
776
786
  * recursive or iterative iteration.
777
- * @param {BTNKey} key - The `key` parameter is the key value that we are searching for in the tree.
787
+ * @param {K} key - The `key` parameter is the key value that we are searching for in the tree.
778
788
  * It is used to find the node with the matching key value.
779
789
  * @param iterationType - The `iterationType` parameter is used to determine whether the search for
780
790
  * the node with the given key should be performed iteratively or recursively. It has two possible
@@ -782,7 +792,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
782
792
  * @returns The function `getNodeByKey` returns a node (`N`) if a node with the specified key is
783
793
  * found in the binary tree. If no node is found, it returns `undefined`.
784
794
  */
785
- getNodeByKey(key: BTNKey, iterationType = IterationType.ITERATIVE): N | undefined {
795
+ getNodeByKey(key: K, iterationType = IterationType.ITERATIVE): N | undefined {
786
796
  if (!this.root) return undefined;
787
797
  if (iterationType === IterationType.RECURSIVE) {
788
798
  const _dfs = (cur: N): N | undefined => {
@@ -815,7 +825,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
815
825
  /**
816
826
  * The function `ensureNode` returns the node corresponding to the given key if it is a valid node
817
827
  * key, otherwise it returns the key itself.
818
- * @param {BTNKey | N | null | undefined} key - The `key` parameter can be of type `BTNKey`, `N`,
828
+ * @param {K | N | null | undefined} key - The `key` parameter can be of type `K`, `N`,
819
829
  * `null`, or `undefined`. It represents a key used to identify a node in a binary tree.
820
830
  * @param iterationType - The `iterationType` parameter is an optional parameter that specifies the
821
831
  * type of iteration to be used when searching for a node by key. It has a default value of
@@ -823,28 +833,28 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
823
833
  * @returns either the node corresponding to the given key if it is a valid node key, or the key
824
834
  * itself if it is not a valid node key.
825
835
  */
826
- ensureNode(key: BTNodeKeyOrNode<N>, iterationType = IterationType.ITERATIVE): N | null | undefined {
827
- return this.isNodeKey(key) ? this.getNodeByKey(key, iterationType) : key;
836
+ ensureNode(key: BTNodeKeyOrNode<K, N>, iterationType = IterationType.ITERATIVE): N | null | undefined {
837
+ return this.isNotNodeInstance(key) ? this.getNodeByKey(key, iterationType) : key;
828
838
  }
829
839
 
830
- get<C extends BTNCallback<N, BTNKey>>(
831
- identifier: BTNKey,
840
+ get<C extends BTNCallback<N, K>>(
841
+ identifier: K,
832
842
  callback?: C,
833
- beginRoot?: BTNodeKeyOrNode<N>,
843
+ beginRoot?: BTNodeKeyOrNode<K, N>,
834
844
  iterationType?: IterationType
835
845
  ): V | undefined;
836
846
 
837
847
  get<C extends BTNCallback<N, N>>(
838
848
  identifier: N | null | undefined,
839
849
  callback?: C,
840
- beginRoot?: BTNodeKeyOrNode<N>,
850
+ beginRoot?: BTNodeKeyOrNode<K, N>,
841
851
  iterationType?: IterationType
842
852
  ): V | undefined;
843
853
 
844
854
  get<C extends BTNCallback<N>>(
845
855
  identifier: ReturnType<C>,
846
856
  callback: C,
847
- beginRoot?: BTNodeKeyOrNode<N>,
857
+ beginRoot?: BTNodeKeyOrNode<K, N>,
848
858
  iterationType?: IterationType
849
859
  ): V | undefined;
850
860
 
@@ -861,8 +871,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
861
871
  * the binary tree. It is used to determine whether a node matches the given identifier. The callback
862
872
  * function should return a value that can be compared to the identifier to determine if it is a
863
873
  * match.
864
- * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
865
- * for the search in the binary tree. It can be specified as a `BTNKey` (a unique identifier for a
874
+ * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
875
+ * for the search in the binary tree. It can be specified as a `K` (a unique identifier for a
866
876
  * node), a node object of type `N`, or `null`/`undefined` to start the search from the root of
867
877
  * @param iterationType - The `iterationType` parameter is used to specify the type of iteration to
868
878
  * be performed when searching for a node in the binary tree. It is an optional parameter with a
@@ -873,7 +883,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
873
883
  get<C extends BTNCallback<N>>(
874
884
  identifier: ReturnType<C> | null | undefined,
875
885
  callback: C = this._defaultOneParamCallback as C,
876
- beginRoot: BTNodeKeyOrNode<N> = this.root,
886
+ beginRoot: BTNodeKeyOrNode<K, N> = this.root,
877
887
  iterationType = this.iterationType
878
888
  ): V | undefined {
879
889
  if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
@@ -909,15 +919,15 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
909
919
  *
910
920
  * The function `getPathToRoot` returns an array of nodes from a given node to the root of a tree
911
921
  * structure, with the option to reverse the order of the nodes.
912
- * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
913
- * starting node from which you want to find the path to the root. It can be of type `BTNKey`, `N`,
922
+ * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
923
+ * starting node from which you want to find the path to the root. It can be of type `K`, `N`,
914
924
  * `null`, or `undefined`.
915
925
  * @param [isReverse=true] - The `isReverse` parameter is a boolean flag that determines whether the
916
926
  * resulting path should be reversed or not. If `isReverse` is set to `true`, the path will be
917
927
  * reversed before returning it. If `isReverse` is set to `false`, the path will be returned as is
918
928
  * @returns The function `getPathToRoot` returns an array of nodes (`N[]`).
919
929
  */
920
- getPathToRoot(beginRoot: BTNodeKeyOrNode<N>, isReverse = true): N[] {
930
+ getPathToRoot(beginRoot: BTNodeKeyOrNode<K, N>, isReverse = true): N[] {
921
931
  // TODO to support get path through passing key
922
932
  const result: N[] = [];
923
933
  beginRoot = this.ensureNode(beginRoot);
@@ -945,8 +955,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
945
955
  *
946
956
  * The function `getLeftMost` returns the leftmost node in a binary tree, either recursively or
947
957
  * iteratively.
948
- * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
949
- * for finding the leftmost node in a binary tree. It can be either a `BTNKey` (a key value), `N` (a
958
+ * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
959
+ * for finding the leftmost node in a binary tree. It can be either a `K` (a key value), `N` (a
950
960
  * node), `null`, or `undefined`. If not provided, it defaults to `this.root`,
951
961
  * @param iterationType - The `iterationType` parameter is used to determine the type of iteration to
952
962
  * be performed when finding the leftmost node in a binary tree. It can have two possible values:
@@ -954,7 +964,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
954
964
  * is no leftmost node, it returns `null` or `undefined` depending on the input.
955
965
  */
956
966
  getLeftMost(
957
- beginRoot: BTNodeKeyOrNode<N> = this.root,
967
+ beginRoot: BTNodeKeyOrNode<K, N> = this.root,
958
968
  iterationType = this.iterationType
959
969
  ): N | null | undefined {
960
970
  beginRoot = this.ensureNode(beginRoot);
@@ -990,8 +1000,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
990
1000
  *
991
1001
  * The function `getRightMost` returns the rightmost node in a binary tree, either recursively or
992
1002
  * iteratively.
993
- * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
994
- * starting node from which we want to find the rightmost node. It can be of type `BTNKey`, `N`,
1003
+ * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
1004
+ * starting node from which we want to find the rightmost node. It can be of type `K`, `N`,
995
1005
  * `null`, or `undefined`. If not provided, it defaults to `this.root`, which is a property of the
996
1006
  * current object.
997
1007
  * @param iterationType - The `iterationType` parameter is an optional parameter that specifies the
@@ -1000,7 +1010,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1000
1010
  * is no rightmost node, it returns `null` or `undefined`, depending on the input.
1001
1011
  */
1002
1012
  getRightMost(
1003
- beginRoot: BTNodeKeyOrNode<N> = this.root,
1013
+ beginRoot: BTNodeKeyOrNode<K, N> = this.root,
1004
1014
  iterationType = this.iterationType
1005
1015
  ): N | null | undefined {
1006
1016
  // TODO support get right most by passing key in
@@ -1035,23 +1045,24 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1035
1045
  * Space Complexity: O(1)
1036
1046
  *
1037
1047
  * The function `isSubtreeBST` checks if a given binary tree is a valid binary search tree.
1038
- * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the root
1048
+ * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the root
1039
1049
  * node of the binary search tree (BST) that you want to check if it is a subtree of another BST.
1040
1050
  * @param iterationType - The `iterationType` parameter is an optional parameter that specifies the
1041
1051
  * type of iteration to use when checking if a subtree is a binary search tree (BST). It can have two
1042
1052
  * possible values:
1043
1053
  * @returns a boolean value.
1044
1054
  */
1045
- isSubtreeBST(beginRoot: BTNodeKeyOrNode<N>, iterationType = this.iterationType): boolean {
1055
+ isSubtreeBST(beginRoot: BTNodeKeyOrNode<K, N>, iterationType = this.iterationType): boolean {
1046
1056
  // TODO there is a bug
1047
1057
  beginRoot = this.ensureNode(beginRoot);
1048
1058
  if (!beginRoot) return true;
1049
1059
 
1050
1060
  if (iterationType === IterationType.RECURSIVE) {
1051
- const dfs = (cur: N | null | undefined, min: BTNKey, max: BTNKey): boolean => {
1061
+ const dfs = (cur: N | null | undefined, min: number, max: number): boolean => {
1052
1062
  if (!cur) return true;
1053
- if (cur.key <= min || cur.key >= max) return false;
1054
- return dfs(cur.left, min, cur.key) && dfs(cur.right, cur.key, max);
1063
+ const numKey = this.extractor(cur.key);
1064
+ if (numKey <= min || numKey >= max) return false;
1065
+ return dfs(cur.left, min, numKey) && dfs(cur.right, numKey, max);
1055
1066
  };
1056
1067
 
1057
1068
  return dfs(beginRoot, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);
@@ -1065,8 +1076,9 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1065
1076
  curr = curr.left;
1066
1077
  }
1067
1078
  curr = stack.pop()!;
1068
- if (!curr || prev >= curr.key) return false;
1069
- prev = curr.key;
1079
+ const numKey = this.extractor(curr.key);
1080
+ if (!curr || prev >= numKey) return false;
1081
+ prev = numKey;
1070
1082
  curr = curr.right;
1071
1083
  }
1072
1084
  return true;
@@ -1101,21 +1113,21 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1101
1113
 
1102
1114
  subTreeTraverse<C extends BTNCallback<N>>(
1103
1115
  callback?: C,
1104
- beginRoot?: BTNodeKeyOrNode<N>,
1116
+ beginRoot?: BTNodeKeyOrNode<K, N>,
1105
1117
  iterationType?: IterationType,
1106
1118
  includeNull?: false
1107
1119
  ): ReturnType<C>[];
1108
1120
 
1109
1121
  subTreeTraverse<C extends BTNCallback<N>>(
1110
1122
  callback?: C,
1111
- beginRoot?: BTNodeKeyOrNode<N>,
1123
+ beginRoot?: BTNodeKeyOrNode<K, N>,
1112
1124
  iterationType?: IterationType,
1113
1125
  includeNull?: undefined
1114
1126
  ): ReturnType<C>[];
1115
1127
 
1116
1128
  subTreeTraverse<C extends BTNCallback<N | null | undefined>>(
1117
1129
  callback?: C,
1118
- beginRoot?: BTNodeKeyOrNode<N>,
1130
+ beginRoot?: BTNodeKeyOrNode<K, N>,
1119
1131
  iterationType?: IterationType,
1120
1132
  includeNull?: true
1121
1133
  ): ReturnType<C>[];
@@ -1129,8 +1141,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1129
1141
  * @param {C} callback - The `callback` parameter is a function that will be called for each node in
1130
1142
  * the subtree traversal. It takes a single parameter, which is the current node being traversed, and
1131
1143
  * returns a value of any type.
1132
- * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
1133
- * starting node or key from which the subtree traversal should begin. It can be of type `BTNKey`,
1144
+ * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
1145
+ * starting node or key from which the subtree traversal should begin. It can be of type `K`,
1134
1146
  * `N`, `null`, or `undefined`. If not provided, the `root` property of the current object is used as
1135
1147
  * the default value.
1136
1148
  * @param iterationType - The `iterationType` parameter determines the type of traversal to be
@@ -1144,7 +1156,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1144
1156
  */
1145
1157
  subTreeTraverse<C extends BTNCallback<N | null | undefined>>(
1146
1158
  callback: C = this._defaultOneParamCallback as C,
1147
- beginRoot: BTNodeKeyOrNode<N> = this.root,
1159
+ beginRoot: BTNodeKeyOrNode<K, N> = this.root,
1148
1160
  iterationType = this.iterationType,
1149
1161
  includeNull = false
1150
1162
  ): ReturnType<C>[] {
@@ -1222,19 +1234,19 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1222
1234
  }
1223
1235
 
1224
1236
  /**
1225
- * The function "isNodeKey" checks if a potential key is a number.
1237
+ * The function "isNotNodeInstance" checks if a potential key is a number.
1226
1238
  * @param {any} potentialKey - The potentialKey parameter is of type any, which means it can be any
1227
1239
  * data type.
1228
1240
  * @returns a boolean value indicating whether the potentialKey is of type number or not.
1229
1241
  */
1230
- isNodeKey(potentialKey: any): potentialKey is number {
1231
- return typeof potentialKey === 'number';
1242
+ isNotNodeInstance(potentialKey: BTNodeKeyOrNode<K, N>): potentialKey is K {
1243
+ return !(potentialKey instanceof BinaryTreeNode)
1232
1244
  }
1233
1245
 
1234
1246
  dfs<C extends BTNCallback<N>>(
1235
1247
  callback?: C,
1236
1248
  pattern?: DFSOrderPattern,
1237
- beginRoot?: BTNodeKeyOrNode<N>,
1249
+ beginRoot?: BTNodeKeyOrNode<K, N>,
1238
1250
  iterationType?: IterationType,
1239
1251
  includeNull?: false
1240
1252
  ): ReturnType<C>[];
@@ -1242,7 +1254,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1242
1254
  dfs<C extends BTNCallback<N>>(
1243
1255
  callback?: C,
1244
1256
  pattern?: DFSOrderPattern,
1245
- beginRoot?: BTNodeKeyOrNode<N>,
1257
+ beginRoot?: BTNodeKeyOrNode<K, N>,
1246
1258
  iterationType?: IterationType,
1247
1259
  includeNull?: undefined
1248
1260
  ): ReturnType<C>[];
@@ -1250,7 +1262,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1250
1262
  dfs<C extends BTNCallback<N | null | undefined>>(
1251
1263
  callback?: C,
1252
1264
  pattern?: DFSOrderPattern,
1253
- beginRoot?: BTNodeKeyOrNode<N>,
1265
+ beginRoot?: BTNodeKeyOrNode<K, N>,
1254
1266
  iterationType?: IterationType,
1255
1267
  includeNull?: true
1256
1268
  ): ReturnType<C>[];
@@ -1267,7 +1279,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1267
1279
  * `null`, or `undefined`, and returns a value of any type. The default value for this parameter is
1268
1280
  * @param {DFSOrderPattern} [pattern=in] - The `pattern` parameter determines the order in which the
1269
1281
  * nodes are traversed during the depth-first search. It can have one of the following values:
1270
- * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node
1282
+ * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node
1271
1283
  * for the depth-first search traversal. It can be specified as a key, a node object, or
1272
1284
  * `null`/`undefined`. If not provided, the `beginRoot` will default to the root node of the tree.
1273
1285
  * @param {IterationType} iterationType - The `iterationType` parameter determines the type of
@@ -1281,7 +1293,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1281
1293
  dfs<C extends BTNCallback<N | null | undefined>>(
1282
1294
  callback: C = this._defaultOneParamCallback as C,
1283
1295
  pattern: DFSOrderPattern = 'in',
1284
- beginRoot: BTNodeKeyOrNode<N> = this.root,
1296
+ beginRoot: BTNodeKeyOrNode<K, N> = this.root,
1285
1297
  iterationType: IterationType = IterationType.ITERATIVE,
1286
1298
  includeNull = false
1287
1299
  ): ReturnType<C>[] {
@@ -1380,21 +1392,21 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1380
1392
 
1381
1393
  bfs<C extends BTNCallback<N>>(
1382
1394
  callback?: C,
1383
- beginRoot?: BTNodeKeyOrNode<N>,
1395
+ beginRoot?: BTNodeKeyOrNode<K, N>,
1384
1396
  iterationType?: IterationType,
1385
1397
  includeNull?: false
1386
1398
  ): ReturnType<C>[];
1387
1399
 
1388
1400
  bfs<C extends BTNCallback<N>>(
1389
1401
  callback?: C,
1390
- beginRoot?: BTNodeKeyOrNode<N>,
1402
+ beginRoot?: BTNodeKeyOrNode<K, N>,
1391
1403
  iterationType?: IterationType,
1392
1404
  includeNull?: undefined
1393
1405
  ): ReturnType<C>[];
1394
1406
 
1395
1407
  bfs<C extends BTNCallback<N | null | undefined>>(
1396
1408
  callback?: C,
1397
- beginRoot?: BTNodeKeyOrNode<N>,
1409
+ beginRoot?: BTNodeKeyOrNode<K, N>,
1398
1410
  iterationType?: IterationType,
1399
1411
  includeNull?: true
1400
1412
  ): ReturnType<C>[];
@@ -1408,7 +1420,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1408
1420
  * @param {C} callback - The `callback` parameter is a function that will be called for each node in
1409
1421
  * the breadth-first search traversal. It takes a single parameter, which is the current node being
1410
1422
  * visited, and returns a value of any type.
1411
- * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
1423
+ * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
1412
1424
  * starting node for the breadth-first search traversal. It can be specified as a key, a node object,
1413
1425
  * or `null`/`undefined` to indicate the root of the tree. If not provided, the `root` property of
1414
1426
  * the class is used as
@@ -1422,7 +1434,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1422
1434
  */
1423
1435
  bfs<C extends BTNCallback<N | null | undefined>>(
1424
1436
  callback: C = this._defaultOneParamCallback as C,
1425
- beginRoot: BTNodeKeyOrNode<N> = this.root,
1437
+ beginRoot: BTNodeKeyOrNode<K, N> = this.root,
1426
1438
  iterationType = this.iterationType,
1427
1439
  includeNull = false
1428
1440
  ): ReturnType<C>[] {
@@ -1481,21 +1493,21 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1481
1493
 
1482
1494
  listLevels<C extends BTNCallback<N>>(
1483
1495
  callback?: C,
1484
- beginRoot?: BTNodeKeyOrNode<N>,
1496
+ beginRoot?: BTNodeKeyOrNode<K, N>,
1485
1497
  iterationType?: IterationType,
1486
1498
  includeNull?: false
1487
1499
  ): ReturnType<C>[][];
1488
1500
 
1489
1501
  listLevels<C extends BTNCallback<N>>(
1490
1502
  callback?: C,
1491
- beginRoot?: BTNodeKeyOrNode<N>,
1503
+ beginRoot?: BTNodeKeyOrNode<K, N>,
1492
1504
  iterationType?: IterationType,
1493
1505
  includeNull?: undefined
1494
1506
  ): ReturnType<C>[][];
1495
1507
 
1496
1508
  listLevels<C extends BTNCallback<N | null | undefined>>(
1497
1509
  callback?: C,
1498
- beginRoot?: BTNodeKeyOrNode<N>,
1510
+ beginRoot?: BTNodeKeyOrNode<K, N>,
1499
1511
  iterationType?: IterationType,
1500
1512
  includeNull?: true
1501
1513
  ): ReturnType<C>[][];
@@ -1510,9 +1522,9 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1510
1522
  * @param {C} callback - The `callback` parameter is a function that will be called for each node in
1511
1523
  * the tree. It takes a single parameter, which can be of type `N`, `null`, or `undefined`, and
1512
1524
  * returns a value of any type.
1513
- * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
1525
+ * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
1514
1526
  * starting node for traversing the tree. It can be either a node object (`N`), a key value
1515
- * (`BTNKey`), `null`, or `undefined`. If not provided, it defaults to the root node of the tree.
1527
+ * (`K`), `null`, or `undefined`. If not provided, it defaults to the root node of the tree.
1516
1528
  * @param iterationType - The `iterationType` parameter determines the type of iteration to be
1517
1529
  * performed on the tree. It can have two possible values:
1518
1530
  * @param [includeNull=false] - The `includeNull` parameter is a boolean value that determines
@@ -1523,7 +1535,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1523
1535
  */
1524
1536
  listLevels<C extends BTNCallback<N | null | undefined>>(
1525
1537
  callback: C = this._defaultOneParamCallback as C,
1526
- beginRoot: BTNodeKeyOrNode<N> = this.root,
1538
+ beginRoot: BTNodeKeyOrNode<K, N> = this.root,
1527
1539
  iterationType = this.iterationType,
1528
1540
  includeNull = false
1529
1541
  ): ReturnType<C>[][] {
@@ -1577,11 +1589,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1577
1589
 
1578
1590
  /**
1579
1591
  * The function `getPredecessor` returns the predecessor node of a given node in a binary tree.
1580
- * @param {BTNKey | N | null | undefined} node - The `node` parameter can be of type `BTNKey`, `N`,
1592
+ * @param {K | N | null | undefined} node - The `node` parameter can be of type `K`, `N`,
1581
1593
  * `null`, or `undefined`.
1582
1594
  * @returns The function `getPredecessor` returns a value of type `N | undefined`.
1583
1595
  */
1584
- getPredecessor(node: BTNodeKeyOrNode<N>): N | undefined {
1596
+ getPredecessor(node: BTNodeKeyOrNode<K, N>): N | undefined {
1585
1597
  node = this.ensureNode(node);
1586
1598
  if (!this.isRealNode(node)) return undefined;
1587
1599
 
@@ -1600,11 +1612,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1600
1612
 
1601
1613
  /**
1602
1614
  * The function `getSuccessor` returns the next node in a binary tree given a current node.
1603
- * @param {BTNKey | N | null} [x] - The parameter `x` can be of type `BTNKey`, `N`, or `null`.
1615
+ * @param {K | N | null} [x] - The parameter `x` can be of type `K`, `N`, or `null`.
1604
1616
  * @returns the successor of the given node or key. The successor is the node that comes immediately
1605
1617
  * after the given node in the inorder traversal of the binary tree.
1606
1618
  */
1607
- getSuccessor(x?: BTNKey | N | null): N | null | undefined {
1619
+ getSuccessor(x?: K | N | null): N | null | undefined {
1608
1620
  x = this.ensureNode(x);
1609
1621
  if (!x) return undefined;
1610
1622
 
@@ -1631,7 +1643,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1631
1643
  * @param {DFSOrderPattern} [pattern=in] - The `pattern` parameter in the `morris` function
1632
1644
  * determines the order in which the nodes of a binary tree are traversed. It can have one of the
1633
1645
  * following values:
1634
- * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node
1646
+ * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node
1635
1647
  * for the traversal. It can be specified as a key, a node object, or `null`/`undefined` to indicate
1636
1648
  * the root of the tree. If no value is provided, the default value is the root of the tree.
1637
1649
  * @returns The function `morris` returns an array of values that are the result of invoking the
@@ -1641,7 +1653,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1641
1653
  morris<C extends BTNCallback<N>>(
1642
1654
  callback: C = this._defaultOneParamCallback as C,
1643
1655
  pattern: DFSOrderPattern = 'in',
1644
- beginRoot: BTNodeKeyOrNode<N> = this.root
1656
+ beginRoot: BTNodeKeyOrNode<K, N> = this.root
1645
1657
  ): ReturnType<C>[] {
1646
1658
  beginRoot = this.ensureNode(beginRoot);
1647
1659
  if (beginRoot === null) return [];
@@ -1724,47 +1736,6 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1724
1736
  return ans;
1725
1737
  }
1726
1738
 
1727
- /**
1728
- * Time complexity: O(n)
1729
- * Space complexity: O(n)
1730
- */
1731
-
1732
- /**
1733
- * Time complexity: O(n)
1734
- * Space complexity: O(n)
1735
- *
1736
- * The function "keys" returns an array of keys from a given object.
1737
- * @returns an array of BTNKey objects.
1738
- */
1739
- keys(): BTNKey[] {
1740
- const keys: BTNKey[] = [];
1741
- for (const entry of this) {
1742
- keys.push(entry[0]);
1743
- }
1744
- return keys;
1745
- }
1746
-
1747
- /**
1748
- * Time complexity: O(n)
1749
- * Space complexity: O(n)
1750
- */
1751
-
1752
- /**
1753
- * Time complexity: O(n)
1754
- * Space complexity: O(n)
1755
- *
1756
- * The function "values" returns an array of values from a map-like object.
1757
- * @returns The `values()` method is returning an array of values (`V`) from the entries in the
1758
- * object.
1759
- */
1760
- values(): (V | undefined)[] {
1761
- const values: (V | undefined)[] = [];
1762
- for (const entry of this) {
1763
- values.push(entry[1]);
1764
- }
1765
- return values;
1766
- }
1767
-
1768
1739
  /**
1769
1740
  * Time complexity: O(n)
1770
1741
  * Space complexity: O(n)
@@ -1785,34 +1756,30 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1785
1756
  }
1786
1757
 
1787
1758
  /**
1788
- * Time complexity: O(n)
1789
- * Space complexity: O(1)
1790
- */
1791
-
1792
- /**
1793
- * The `forEach` function iterates over each entry in a tree and calls a callback function with the
1794
- * entry and the tree as arguments.
1795
- * @param callback - The callback parameter is a function that will be called for each entry in the
1796
- * tree. It takes two parameters: entry and tree.
1759
+ * Time Complexity: O(n)
1760
+ * Space Complexity: O(n)
1797
1761
  */
1798
- forEach(callback: (entry: [BTNKey, V | undefined], tree: this) => void): void {
1799
- for (const entry of this) {
1800
- callback(entry, this);
1801
- }
1802
- }
1803
1762
 
1804
1763
  /**
1805
- * The `filter` function creates a new tree by iterating over the entries of the current tree and
1806
- * adding the entries that satisfy the given predicate.
1807
- * @param predicate - The `predicate` parameter is a function that takes two arguments: `entry` and
1808
- * `tree`.
1809
- * @returns The `filter` method is returning a new tree object that contains only the entries that
1810
- * satisfy the given predicate function.
1811
- */
1812
- filter(predicate: (entry: [BTNKey, V | undefined], tree: this) => boolean) {
1764
+ * Time Complexity: O(n)
1765
+ * Space Complexity: O(n)
1766
+ *
1767
+ * The `filter` function creates a new tree by iterating over the elements of the current tree and
1768
+ * adding only the elements that satisfy the given predicate function.
1769
+ * @param predicate - The `predicate` parameter is a function that takes three arguments: `value`,
1770
+ * `key`, and `index`. It should return a boolean value indicating whether the pair should be
1771
+ * included in the filtered tree or not.
1772
+ * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
1773
+ * to be used as the `this` value when executing the `predicate` function. If `thisArg` is provided,
1774
+ * it will be passed as the first argument to the `predicate` function. If `thisArg` is
1775
+ * @returns The `filter` method is returning a new tree object that contains the key-value pairs that
1776
+ * pass the given predicate function.
1777
+ */
1778
+ filter(predicate: PairCallback<K, V | undefined, boolean>, thisArg?: any) {
1813
1779
  const newTree = this.createTree();
1780
+ let index = 0;
1814
1781
  for (const [key, value] of this) {
1815
- if (predicate([key, value], this)) {
1782
+ if (predicate.call(thisArg, value, key, index++, this)) {
1816
1783
  newTree.add([key, value]);
1817
1784
  }
1818
1785
  }
@@ -1820,58 +1787,74 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1820
1787
  }
1821
1788
 
1822
1789
  /**
1823
- * The `map` function creates a new tree by applying a callback function to each entry in the current
1824
- * tree.
1825
- * @param callback - The callback parameter is a function that takes two arguments: entry and tree.
1790
+ * Time Complexity: O(n)
1791
+ * Space Complexity: O(n)
1792
+ */
1793
+
1794
+ /**
1795
+ * Time Complexity: O(n)
1796
+ * Space Complexity: O(n)
1797
+ *
1798
+ * The `map` function creates a new tree by applying a callback function to each key-value pair in
1799
+ * the original tree.
1800
+ * @param callback - The callback parameter is a function that will be called for each key-value pair
1801
+ * in the tree. It takes four arguments: the value of the current pair, the key of the current pair,
1802
+ * the index of the current pair, and a reference to the tree itself. The callback function should
1803
+ * return a new
1804
+ * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
1805
+ * specify the value of `this` within the callback function. If you pass a value for `thisArg`, it
1806
+ * will be used as the `this` value when the callback function is called. If you don't pass a value
1826
1807
  * @returns The `map` method is returning a new tree object.
1827
1808
  */
1828
- map(callback: (entry: [BTNKey, V | undefined], tree: this) => V) {
1809
+ map(callback: PairCallback<K, V | undefined, V>, thisArg?: any) {
1829
1810
  const newTree = this.createTree();
1811
+ let index = 0;
1830
1812
  for (const [key, value] of this) {
1831
- newTree.add([key, callback([key, value], this)]);
1813
+ newTree.add([key, callback.call(thisArg, value, key, index++, this)]);
1832
1814
  }
1833
1815
  return newTree;
1834
1816
  }
1835
1817
 
1836
- // TODO Type error, need to return a TREE<NV> that is a value type only for callback function.
1837
- // map<NV>(callback: (entry: [BTNKey, V | undefined], tree: this) => NV) {
1838
- // const newTree = this.createTree();
1839
- // for (const [key, value] of this) {
1840
- // newTree.add(key, callback([key, value], this));
1841
- // }
1842
- // return newTree;
1843
- // }
1844
-
1845
- /**
1846
- * The `reduce` function iterates over the entries of a tree and applies a callback function to each
1847
- * entry, accumulating a single value.
1848
- * @param callback - The callback parameter is a function that takes three arguments: accumulator,
1849
- * entry, and tree. It is called for each entry in the tree and is used to accumulate a single value
1850
- * based on the logic defined in the callback function.
1851
- * @param {T} initialValue - The initialValue parameter is the initial value of the accumulator. It
1852
- * is the value that will be passed as the first argument to the callback function when reducing the
1853
- * elements of the tree.
1854
- * @returns The `reduce` method is returning the final value of the accumulator after iterating over
1855
- * all the entries in the tree and applying the callback function to each entry.
1856
- */
1857
- reduce<T>(callback: (accumulator: T, entry: [BTNKey, V | undefined], tree: this) => T, initialValue: T): T {
1858
- let accumulator = initialValue;
1859
- for (const [key, value] of this) {
1860
- accumulator = callback(accumulator, [key, value], this);
1861
- }
1862
- return accumulator;
1863
- }
1818
+ // // TODO Type error, need to return a TREE<NV> that is a value type only for callback function.
1819
+ // // map<NV>(callback: (entry: [K, V | undefined], tree: this) => NV) {
1820
+ // // const newTree = this.createTree();
1821
+ // // for (const [key, value] of this) {
1822
+ // // newTree.add(key, callback([key, value], this));
1823
+ // // }
1824
+ // // return newTree;
1825
+ // // }
1826
+ //
1864
1827
 
1865
1828
  /**
1866
- * The above function is an iterator for a binary tree that can be used to traverse the tree in
1867
- * either an iterative or recursive manner.
1868
- * @param node - The `node` parameter represents the current node in the binary tree from which the
1869
- * iteration starts. It is an optional parameter with a default value of `this.root`, which means
1870
- * that if no node is provided, the iteration will start from the root of the binary tree.
1871
- * @returns The `*[Symbol.iterator]` method returns a generator object that yields the keys of the
1872
- * binary tree nodes in a specific order.
1829
+ * The `print` function is used to display a binary tree structure in a visually appealing way.
1830
+ * @param {K | N | null | undefined} [beginRoot=this.root] - The `root` parameter is of type `K | N | null |
1831
+ * undefined`. It represents the root node of a binary tree. The root node can have one of the
1832
+ * following types:
1833
+ * @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.
1873
1834
  */
1874
- * [Symbol.iterator](node = this.root): Generator<[BTNKey, V | undefined], void, undefined> {
1835
+ print(beginRoot: BTNodeKeyOrNode<K, N> = this.root, options?: BinaryTreePrintOptions): void {
1836
+ const opts = { isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false, ...options };
1837
+ beginRoot = this.ensureNode(beginRoot);
1838
+ if (!beginRoot) return;
1839
+
1840
+ if (opts.isShowUndefined) console.log(`U for undefined
1841
+ `);
1842
+ if (opts.isShowNull) console.log(`N for null
1843
+ `);
1844
+ if (opts.isShowRedBlackNIL) console.log(`S for Sentinel Node
1845
+ `);
1846
+
1847
+ const display = (root: N | null | undefined): void => {
1848
+ const [lines, , ,] = this._displayAux(root, opts);
1849
+ for (const line of lines) {
1850
+ console.log(line);
1851
+ }
1852
+ };
1853
+
1854
+ display(beginRoot);
1855
+ }
1856
+
1857
+ protected* _getIterator(node = this.root): IterableIterator<[K, V | undefined]> {
1875
1858
  if (!node) return;
1876
1859
 
1877
1860
  if (this.iterationType === IterationType.ITERATIVE) {
@@ -1879,58 +1862,29 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1879
1862
  let current: N | null | undefined = node;
1880
1863
 
1881
1864
  while (current || stack.length > 0) {
1882
- while (current && !isNaN(current.key)) {
1865
+ while (current && !isNaN(this.extractor(current.key))) {
1883
1866
  stack.push(current);
1884
1867
  current = current.left;
1885
1868
  }
1886
1869
 
1887
1870
  current = stack.pop();
1888
1871
 
1889
- if (current && !isNaN(current.key)) {
1872
+ if (current && !isNaN(this.extractor(current.key))) {
1890
1873
  yield [current.key, current.value];
1891
1874
  current = current.right;
1892
1875
  }
1893
1876
  }
1894
1877
  } else {
1895
- if (node.left && !isNaN(node.key)) {
1878
+ if (node.left && !isNaN(this.extractor(node.key))) {
1896
1879
  yield* this[Symbol.iterator](node.left);
1897
1880
  }
1898
1881
  yield [node.key, node.value];
1899
- if (node.right && !isNaN(node.key)) {
1882
+ if (node.right && !isNaN(this.extractor(node.key))) {
1900
1883
  yield* this[Symbol.iterator](node.right);
1901
1884
  }
1902
1885
  }
1903
1886
  }
1904
1887
 
1905
- /**
1906
- * The `print` function is used to display a binary tree structure in a visually appealing way.
1907
- * @param {BTNKey | N | null | undefined} [beginRoot=this.root] - The `root` parameter is of type `BTNKey | N | null |
1908
- * undefined`. It represents the root node of a binary tree. The root node can have one of the
1909
- * following types:
1910
- * @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.
1911
- */
1912
- print(beginRoot: BTNodeKeyOrNode<N> = this.root, options?: BinaryTreePrintOptions): void {
1913
- const opts = { isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false, ...options };
1914
- beginRoot = this.ensureNode(beginRoot);
1915
- if (!beginRoot) return;
1916
-
1917
- if (opts.isShowUndefined) console.log(`U for undefined
1918
- `);
1919
- if (opts.isShowNull) console.log(`N for null
1920
- `);
1921
- if (opts.isShowRedBlackNIL) console.log(`S for Sentinel Node
1922
- `);
1923
-
1924
- const display = (root: N | null | undefined): void => {
1925
- const [lines, , ,] = this._displayAux(root, opts);
1926
- for (const line of lines) {
1927
- console.log(line);
1928
- }
1929
- };
1930
-
1931
- display(beginRoot);
1932
- }
1933
-
1934
1888
  protected _displayAux(node: N | null | undefined, options: BinaryTreePrintOptions): NodeDisplayLayout {
1935
1889
  const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
1936
1890
  const emptyDisplayLayout = <NodeDisplayLayout>[['─'], 1, 0, 0];
@@ -1940,12 +1894,13 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1940
1894
  return emptyDisplayLayout;
1941
1895
  } else if (node === undefined && !isShowUndefined) {
1942
1896
  return emptyDisplayLayout;
1943
- } else if (node !== null && node !== undefined && isNaN(node.key) && !isShowRedBlackNIL) {
1897
+ } else if (node !== null && node !== undefined && isNaN(this.extractor(node.key)) && !isShowRedBlackNIL) {
1944
1898
  return emptyDisplayLayout;
1945
1899
  } else if (node !== null && node !== undefined) {
1946
1900
  // Display logic of normal nodes
1947
1901
 
1948
- const key = node.key, line = isNaN(key) ? 'S' : key.toString(), width = line.length;
1902
+ const key = node.key, line = isNaN(this.extractor(key)) ? 'S' : this.extractor(key).toString(),
1903
+ width = line.length;
1949
1904
 
1950
1905
  return _buildNodeDisplay(line, width, this._displayAux(node.left, options), this._displayAux(node.right, options))
1951
1906
 
@@ -1989,7 +1944,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1989
1944
  * @param {N} destNode - The destination node to swap.
1990
1945
  * @returns {N} - The destination node after the swap.
1991
1946
  */
1992
- protected _swapProperties(srcNode: BTNodeKeyOrNode<N>, destNode: BTNodeKeyOrNode<N>): N | undefined {
1947
+ protected _swapProperties(srcNode: BTNodeKeyOrNode<K, N>, destNode: BTNodeKeyOrNode<K, N>): N | undefined {
1993
1948
  srcNode = this.ensureNode(srcNode);
1994
1949
  destNode = this.ensureNode(destNode);
1995
1950
 
@@ -2047,8 +2002,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
2047
2002
  * the binary tree. If neither the left nor right child is available, the function returns undefined.
2048
2003
  * If the parent node is null, the function also returns undefined.
2049
2004
  */
2050
- protected _addTo(newNode: N | null | undefined, parent: BTNodeKeyOrNode<N>): N | null | undefined {
2051
- if (this.isNodeKey(parent)) parent = this.getNode(parent);
2005
+ protected _addTo(newNode: N | null | undefined, parent: BTNodeKeyOrNode<K, N>): N | null | undefined {
2006
+ if (this.isNotNodeInstance(parent)) parent = this.getNode(parent);
2052
2007
 
2053
2008
  if (parent) {
2054
2009
  // When all leaf nodes are null, it will no longer be possible to add new entity nodes to this binary tree.