avl-tree-typed 1.54.2 → 2.0.0

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 (85) hide show
  1. package/README.md +64 -0
  2. package/dist/data-structures/base/iterable-element-base.d.ts +14 -40
  3. package/dist/data-structures/base/iterable-element-base.js +14 -11
  4. package/dist/data-structures/base/linear-base.d.ts +277 -0
  5. package/dist/data-structures/base/linear-base.js +552 -0
  6. package/dist/data-structures/binary-tree/avl-tree-counter.d.ts +21 -20
  7. package/dist/data-structures/binary-tree/avl-tree-counter.js +8 -7
  8. package/dist/data-structures/binary-tree/avl-tree-multi-map.d.ts +23 -19
  9. package/dist/data-structures/binary-tree/avl-tree-multi-map.js +51 -38
  10. package/dist/data-structures/binary-tree/avl-tree.d.ts +89 -21
  11. package/dist/data-structures/binary-tree/avl-tree.js +76 -8
  12. package/dist/data-structures/binary-tree/binary-tree.d.ts +173 -225
  13. package/dist/data-structures/binary-tree/binary-tree.js +244 -149
  14. package/dist/data-structures/binary-tree/bst.d.ts +62 -56
  15. package/dist/data-structures/binary-tree/bst.js +89 -133
  16. package/dist/data-structures/binary-tree/red-black-tree.d.ts +19 -25
  17. package/dist/data-structures/binary-tree/red-black-tree.js +7 -13
  18. package/dist/data-structures/binary-tree/tree-counter.d.ts +19 -19
  19. package/dist/data-structures/binary-tree/tree-counter.js +12 -12
  20. package/dist/data-structures/binary-tree/tree-multi-map.d.ts +186 -25
  21. package/dist/data-structures/binary-tree/tree-multi-map.js +211 -41
  22. package/dist/data-structures/graph/abstract-graph.js +2 -2
  23. package/dist/data-structures/heap/heap.d.ts +3 -11
  24. package/dist/data-structures/heap/heap.js +0 -10
  25. package/dist/data-structures/heap/max-heap.d.ts +2 -2
  26. package/dist/data-structures/heap/min-heap.d.ts +2 -2
  27. package/dist/data-structures/linked-list/doubly-linked-list.d.ts +65 -94
  28. package/dist/data-structures/linked-list/doubly-linked-list.js +131 -146
  29. package/dist/data-structures/linked-list/singly-linked-list.d.ts +79 -75
  30. package/dist/data-structures/linked-list/singly-linked-list.js +217 -169
  31. package/dist/data-structures/priority-queue/max-priority-queue.d.ts +2 -2
  32. package/dist/data-structures/priority-queue/min-priority-queue.d.ts +2 -2
  33. package/dist/data-structures/priority-queue/priority-queue.d.ts +2 -2
  34. package/dist/data-structures/queue/deque.d.ts +130 -91
  35. package/dist/data-structures/queue/deque.js +269 -169
  36. package/dist/data-structures/queue/queue.d.ts +84 -40
  37. package/dist/data-structures/queue/queue.js +134 -50
  38. package/dist/data-structures/stack/stack.d.ts +3 -11
  39. package/dist/data-structures/stack/stack.js +0 -10
  40. package/dist/data-structures/trie/trie.d.ts +4 -3
  41. package/dist/data-structures/trie/trie.js +3 -0
  42. package/dist/types/data-structures/base/base.d.ts +9 -4
  43. package/dist/types/data-structures/binary-tree/avl-tree-multi-map.d.ts +1 -1
  44. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +1 -0
  45. package/dist/types/data-structures/binary-tree/bst.d.ts +1 -1
  46. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +1 -1
  47. package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +2 -2
  48. package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +2 -2
  49. package/dist/types/data-structures/queue/deque.d.ts +2 -3
  50. package/dist/types/data-structures/queue/queue.d.ts +2 -2
  51. package/dist/utils/utils.d.ts +2 -2
  52. package/package.json +2 -2
  53. package/src/data-structures/base/iterable-element-base.ts +29 -20
  54. package/src/data-structures/base/linear-base.ts +649 -0
  55. package/src/data-structures/binary-tree/avl-tree-counter.ts +30 -23
  56. package/src/data-structures/binary-tree/avl-tree-multi-map.ts +74 -49
  57. package/src/data-structures/binary-tree/avl-tree.ts +99 -29
  58. package/src/data-structures/binary-tree/binary-tree.ts +474 -257
  59. package/src/data-structures/binary-tree/bst.ts +150 -152
  60. package/src/data-structures/binary-tree/red-black-tree.ts +27 -35
  61. package/src/data-structures/binary-tree/tree-counter.ts +33 -27
  62. package/src/data-structures/binary-tree/tree-multi-map.ts +235 -53
  63. package/src/data-structures/graph/abstract-graph.ts +2 -2
  64. package/src/data-structures/heap/heap.ts +3 -14
  65. package/src/data-structures/heap/max-heap.ts +2 -2
  66. package/src/data-structures/heap/min-heap.ts +2 -2
  67. package/src/data-structures/linked-list/doubly-linked-list.ts +144 -160
  68. package/src/data-structures/linked-list/singly-linked-list.ts +241 -185
  69. package/src/data-structures/priority-queue/max-priority-queue.ts +2 -5
  70. package/src/data-structures/priority-queue/min-priority-queue.ts +2 -5
  71. package/src/data-structures/priority-queue/priority-queue.ts +2 -2
  72. package/src/data-structures/queue/deque.ts +286 -183
  73. package/src/data-structures/queue/queue.ts +149 -63
  74. package/src/data-structures/stack/stack.ts +3 -18
  75. package/src/data-structures/trie/trie.ts +7 -3
  76. package/src/types/data-structures/base/base.ts +17 -8
  77. package/src/types/data-structures/binary-tree/avl-tree-multi-map.ts +1 -1
  78. package/src/types/data-structures/binary-tree/binary-tree.ts +1 -0
  79. package/src/types/data-structures/binary-tree/bst.ts +1 -1
  80. package/src/types/data-structures/binary-tree/tree-multi-map.ts +1 -1
  81. package/src/types/data-structures/linked-list/doubly-linked-list.ts +2 -2
  82. package/src/types/data-structures/linked-list/singly-linked-list.ts +2 -2
  83. package/src/types/data-structures/queue/deque.ts +2 -3
  84. package/src/types/data-structures/queue/queue.ts +2 -2
  85. package/src/utils/utils.ts +2 -2
@@ -11,7 +11,6 @@ import type {
11
11
  BinaryTreeOptions,
12
12
  BinaryTreePrintOptions,
13
13
  BTNEntry,
14
- BTNRep,
15
14
  DFSOrderPattern,
16
15
  DFSStackItem,
17
16
  EntryCallback,
@@ -36,6 +35,10 @@ import { DFSOperation, Range } from '../../common';
36
35
  * @template BinaryTreeNode<K, V> - The type of the family relationship in the binary tree.
37
36
  */
38
37
  export class BinaryTreeNode<K = any, V = any> {
38
+ key: K;
39
+ value?: V;
40
+ parent?: BinaryTreeNode<K, V> = undefined;
41
+
39
42
  /**
40
43
  * The constructor function initializes an object with a key and an optional value in TypeScript.
41
44
  * @param {K} key - The `key` parameter in the constructor function is used to store the key value
@@ -49,32 +52,26 @@ export class BinaryTreeNode<K = any, V = any> {
49
52
  this.value = value;
50
53
  }
51
54
 
52
- key: K;
53
-
54
- value?: V;
55
-
56
- parent?: BinaryTreeNode<K, V> = undefined;
55
+ _left?: BinaryTreeNode<K, V> | null | undefined = undefined;
57
56
 
58
- _left?: OptNodeOrNull<BinaryTreeNode<K, V>> = undefined;
59
-
60
- get left(): OptNodeOrNull<BinaryTreeNode<K, V>> {
57
+ get left(): BinaryTreeNode<K, V> | null | undefined {
61
58
  return this._left;
62
59
  }
63
60
 
64
- set left(v: OptNodeOrNull<BinaryTreeNode<K, V>>) {
61
+ set left(v: BinaryTreeNode<K, V> | null | undefined) {
65
62
  if (v) {
66
63
  v.parent = this as unknown as BinaryTreeNode<K, V>;
67
64
  }
68
65
  this._left = v;
69
66
  }
70
67
 
71
- _right?: OptNodeOrNull<BinaryTreeNode<K, V>> = undefined;
68
+ _right?: BinaryTreeNode<K, V> | null | undefined = undefined;
72
69
 
73
- get right(): OptNodeOrNull<BinaryTreeNode<K, V>> {
70
+ get right(): BinaryTreeNode<K, V> | null | undefined {
74
71
  return this._right;
75
72
  }
76
73
 
77
- set right(v: OptNodeOrNull<BinaryTreeNode<K, V>>) {
74
+ set right(v: BinaryTreeNode<K, V> | null | undefined) {
78
75
  if (v) {
79
76
  v.parent = this;
80
77
  }
@@ -132,29 +129,96 @@ export class BinaryTreeNode<K = any, V = any> {
132
129
  * 3. Depth and Height: Depth is the number of edges from the root to a node; height is the maximum depth in the tree.
133
130
  * 4. Subtrees: Each child of a node forms the root of a subtree.
134
131
  * 5. Leaf Nodes: Nodes without children are leaves.
132
+ * @example
133
+ * // determine loan approval using a decision tree
134
+ * // Decision tree structure
135
+ * const loanDecisionTree = new BinaryTree<string>(
136
+ * ['stableIncome', 'goodCredit', 'Rejected', 'Approved', 'Rejected'],
137
+ * { isDuplicate: true }
138
+ * );
139
+ *
140
+ * function determineLoanApproval(
141
+ * node?: BinaryTreeNode<string> | null,
142
+ * conditions?: { [key: string]: boolean }
143
+ * ): string {
144
+ * if (!node) throw new Error('Invalid node');
145
+ *
146
+ * // If it's a leaf node, return the decision result
147
+ * if (!node.left && !node.right) return node.key;
148
+ *
149
+ * // Check if a valid condition exists for the current node's key
150
+ * return conditions?.[node.key]
151
+ * ? determineLoanApproval(node.left, conditions)
152
+ * : determineLoanApproval(node.right, conditions);
153
+ * }
154
+ *
155
+ * // Test case 1: Stable income and good credit score
156
+ * console.log(determineLoanApproval(loanDecisionTree.root, { stableIncome: true, goodCredit: true })); // 'Approved'
157
+ *
158
+ * // Test case 2: Stable income but poor credit score
159
+ * console.log(determineLoanApproval(loanDecisionTree.root, { stableIncome: true, goodCredit: false })); // 'Rejected'
160
+ *
161
+ * // Test case 3: No stable income
162
+ * console.log(determineLoanApproval(loanDecisionTree.root, { stableIncome: false, goodCredit: true })); // 'Rejected'
163
+ *
164
+ * // Test case 4: No stable income and poor credit score
165
+ * console.log(determineLoanApproval(loanDecisionTree.root, { stableIncome: false, goodCredit: false })); // 'Rejected'
166
+ * @example
167
+ * // evaluate the arithmetic expression represented by the binary tree
168
+ * const expressionTree = new BinaryTree<number | string>(['+', 3, '*', null, null, 5, '-', null, null, 2, 8]);
169
+ *
170
+ * function evaluate(node?: BinaryTreeNode<number | string> | null): number {
171
+ * if (!node) return 0;
172
+ *
173
+ * if (typeof node.key === 'number') return node.key;
174
+ *
175
+ * const leftValue = evaluate(node.left); // Evaluate the left subtree
176
+ * const rightValue = evaluate(node.right); // Evaluate the right subtree
177
+ *
178
+ * // Perform the operation based on the current node's operator
179
+ * switch (node.key) {
180
+ * case '+':
181
+ * return leftValue + rightValue;
182
+ * case '-':
183
+ * return leftValue - rightValue;
184
+ * case '*':
185
+ * return leftValue * rightValue;
186
+ * case '/':
187
+ * return rightValue !== 0 ? leftValue / rightValue : 0; // Handle division by zero
188
+ * default:
189
+ * throw new Error(`Unsupported operator: ${node.key}`);
190
+ * }
191
+ * }
192
+ *
193
+ * console.log(evaluate(expressionTree.root)); // -27
135
194
  */
136
195
  export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = object>
137
196
  extends IterableEntryBase<K, V | undefined>
138
197
  implements IBinaryTree<K, V, R, MK, MV, MR>
139
198
  {
199
+ iterationType: IterationType = 'ITERATIVE';
200
+
140
201
  /**
141
202
  * This TypeScript constructor function initializes a binary tree with optional options and adds
142
203
  * elements based on the provided input.
143
204
  * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the constructor is an
144
- * iterable that can contain either objects of type `BTNRep<K, V, BinaryTreeNode<K, V>>` or `R`. It
205
+ * iterable that can contain either objects of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. It
145
206
  * is used to initialize the binary tree with keys, nodes, entries, or raw data.
146
207
  * @param [options] - The `options` parameter in the constructor is an optional object that can
147
208
  * contain the following properties:
148
209
  */
149
210
  constructor(
150
- keysNodesEntriesOrRaws: Iterable<BTNRep<K, V, BinaryTreeNode<K, V>> | R> = [],
211
+ keysNodesEntriesOrRaws: Iterable<
212
+ K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R
213
+ > = [],
151
214
  options?: BinaryTreeOptions<K, V, R>
152
215
  ) {
153
216
  super();
154
217
  if (options) {
155
- const { iterationType, toEntryFn, isMapMode } = options;
218
+ const { iterationType, toEntryFn, isMapMode, isDuplicate } = options;
156
219
  if (iterationType) this.iterationType = iterationType;
157
220
  if (isMapMode !== undefined) this._isMapMode = isMapMode;
221
+ if (isDuplicate !== undefined) this._isDuplicate = isDuplicate;
158
222
  if (typeof toEntryFn === 'function') this._toEntryFn = toEntryFn;
159
223
  else if (toEntryFn) throw TypeError('toEntryFn must be a function type');
160
224
  }
@@ -162,23 +226,27 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
162
226
  if (keysNodesEntriesOrRaws) this.addMany(keysNodesEntriesOrRaws);
163
227
  }
164
228
 
165
- iterationType: IterationType = 'ITERATIVE';
166
-
167
229
  protected _isMapMode = true;
168
230
 
169
231
  get isMapMode() {
170
232
  return this._isMapMode;
171
233
  }
172
234
 
235
+ protected _isDuplicate = false;
236
+
237
+ get isDuplicate() {
238
+ return this._isDuplicate;
239
+ }
240
+
173
241
  protected _store = new Map<K, V | undefined>();
174
242
 
175
243
  get store() {
176
244
  return this._store;
177
245
  }
178
246
 
179
- protected _root?: OptNodeOrNull<BinaryTreeNode<K, V>>;
247
+ protected _root?: BinaryTreeNode<K, V> | null | undefined;
180
248
 
181
- get root(): OptNodeOrNull<BinaryTreeNode<K, V>> {
249
+ get root(): BinaryTreeNode<K, V> | null | undefined {
182
250
  return this._root;
183
251
  }
184
252
 
@@ -242,8 +310,8 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
242
310
  *
243
311
  * The function `ensureNode` in TypeScript checks if a given input is a node, entry, key, or raw
244
312
  * value and returns the corresponding node or null.
245
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} keyNodeOrEntry - The `keyNodeOrEntry`
246
- * parameter in the `ensureNode` function can be of type `BTNRep<K, V, BinaryTreeNode<K, V>>` or `R`. It
313
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `keyNodeOrEntry`
314
+ * parameter in the `ensureNode` function can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. It
247
315
  * is used to determine whether the input is a key, node, entry, or raw data. The
248
316
  * @param {IterationType} iterationType - The `iterationType` parameter in the `ensureNode` function
249
317
  * is used to specify the type of iteration to be performed. It has a default value of
@@ -252,9 +320,9 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
252
320
  * conditions specified in the code snippet.
253
321
  */
254
322
  ensureNode(
255
- keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>,
323
+ keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
256
324
  iterationType: IterationType = this.iterationType
257
- ): OptNodeOrNull<BinaryTreeNode<K, V>> {
325
+ ): BinaryTreeNode<K, V> | null | undefined {
258
326
  if (keyNodeOrEntry === null) return null;
259
327
  if (keyNodeOrEntry === undefined) return;
260
328
  if (keyNodeOrEntry === this._NIL) return;
@@ -276,7 +344,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
276
344
  * Space Complexity: O(1)
277
345
  *
278
346
  * The function isNode checks if the input is an instance of BinaryTreeNode.
279
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} keyNodeOrEntry - The parameter
347
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter
280
348
  * `keyNodeOrEntry` can be either a key, a node, an entry, or raw data. The function is
281
349
  * checking if the input is an instance of a `BinaryTreeNode` and returning a boolean value
282
350
  * accordingly.
@@ -285,7 +353,9 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
285
353
  * it is not an instance of `BinaryTreeNode`, the function returns `false`, indicating that the input
286
354
  * is not a node.
287
355
  */
288
- isNode(keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>): keyNodeOrEntry is BinaryTreeNode<K, V> {
356
+ isNode(
357
+ keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
358
+ ): keyNodeOrEntry is BinaryTreeNode<K, V> {
289
359
  return keyNodeOrEntry instanceof BinaryTreeNode;
290
360
  }
291
361
 
@@ -294,12 +364,14 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
294
364
  * Space Complexity: O(1)
295
365
  *
296
366
  * The function `isRaw` checks if the input parameter is of type `R` by verifying if it is an object.
297
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>> | R} keyNodeEntryOrRaw - BTNRep<K, V, BinaryTreeNode<K, V>>
367
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R} keyNodeEntryOrRaw - K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
298
368
  * @returns The function `isRaw` is checking if the `keyNodeEntryOrRaw` parameter is of type `R` by
299
369
  * checking if it is an object. If the parameter is an object, the function will return `true`,
300
370
  * indicating that it is of type `R`.
301
371
  */
302
- isRaw(keyNodeEntryOrRaw: BTNRep<K, V, BinaryTreeNode<K, V>> | R): keyNodeEntryOrRaw is R {
372
+ isRaw(
373
+ keyNodeEntryOrRaw: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R
374
+ ): keyNodeEntryOrRaw is R {
303
375
  return this._toEntryFn !== undefined && typeof keyNodeEntryOrRaw === 'object';
304
376
  }
305
377
 
@@ -308,15 +380,17 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
308
380
  * Space Complexity: O(1)
309
381
  *
310
382
  * The function `isRealNode` checks if a given input is a valid node in a binary tree.
311
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} keyNodeOrEntry - The `keyNodeOrEntry`
312
- * parameter in the `isRealNode` function can be of type `BTNRep<K, V, BinaryTreeNode<K, V>>` or `R`.
383
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `keyNodeOrEntry`
384
+ * parameter in the `isRealNode` function can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`.
313
385
  * The function checks if the input parameter is a `BinaryTreeNode<K, V>` type by verifying if it is not equal
314
386
  * @returns The function `isRealNode` is checking if the input `keyNodeOrEntry` is a valid
315
387
  * node by comparing it to `this._NIL`, `null`, and `undefined`. If the input is not one of these
316
388
  * values, it then calls the `isNode` method to further determine if the input is a node. The
317
389
  * function will return a boolean value indicating whether the
318
390
  */
319
- isRealNode(keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>): keyNodeOrEntry is BinaryTreeNode<K, V> {
391
+ isRealNode(
392
+ keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
393
+ ): keyNodeOrEntry is BinaryTreeNode<K, V> {
320
394
  if (keyNodeOrEntry === this._NIL || keyNodeOrEntry === null || keyNodeOrEntry === undefined) return false;
321
395
  return this.isNode(keyNodeOrEntry);
322
396
  }
@@ -326,14 +400,16 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
326
400
  * Space Complexity: O(1)
327
401
  *
328
402
  * The function checks if a given input is a valid node or null.
329
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} keyNodeOrEntry - The parameter
403
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter
330
404
  * `keyNodeOrEntry` in the `isRealNodeOrNull` function can be of type `BTNRep<K,
331
405
  * V, BinaryTreeNode<K, V>>` or `R`. It is a union type that can either be a key, a node, an entry, or
332
406
  * @returns The function `isRealNodeOrNull` is returning a boolean value. It checks if the input
333
407
  * `keyNodeOrEntry` is either `null` or a real node, and returns `true` if it is a node or
334
408
  * `null`, and `false` otherwise.
335
409
  */
336
- isRealNodeOrNull(keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>): keyNodeOrEntry is BinaryTreeNode<K, V> | null {
410
+ isRealNodeOrNull(
411
+ keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
412
+ ): keyNodeOrEntry is BinaryTreeNode<K, V> | null {
337
413
  return keyNodeOrEntry === null || this.isRealNode(keyNodeOrEntry);
338
414
  }
339
415
 
@@ -342,12 +418,12 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
342
418
  * Space Complexity: O(1)
343
419
  *
344
420
  * The function isNIL checks if a given key, node, entry, or raw value is equal to the _NIL value.
345
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} keyNodeOrEntry - BTNRep<K, V,
421
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - BTNRep<K, V,
346
422
  * BinaryTreeNode<K, V>>
347
423
  * @returns The function is checking if the `keyNodeOrEntry` parameter is equal to the `_NIL`
348
424
  * property of the current object and returning a boolean value based on that comparison.
349
425
  */
350
- isNIL(keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>): boolean {
426
+ isNIL(keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined): boolean {
351
427
  return keyNodeOrEntry === this._NIL;
352
428
  }
353
429
 
@@ -356,9 +432,9 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
356
432
  * Space Complexity: O(1)
357
433
  *
358
434
  * The function `isRange` checks if the input parameter is an instance of the `Range` class.
359
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>> | Range<K>}
360
- * keyNodeEntryOrPredicate - The `keyNodeEntryOrPredicate` parameter in the `isRange` function can be
361
- * of type `BTNRep<K, V, BinaryTreeNode<K, V>>`, `NodePredicate<BinaryTreeNode<K, V>>`, or
435
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>> | Range<K>} keyNodeEntryOrPredicate
436
+ * - The `keyNodeEntryOrPredicate` parameter in the `isRange` function can be
437
+ * of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `, `NodePredicate<BinaryTreeNode<K, V>>`, or
362
438
  * `Range<K>`. The function checks if the `keyNodeEntry
363
439
  * @returns The `isRange` function is checking if the `keyNodeEntryOrPredicate` parameter is an
364
440
  * instance of the `Range` class. If it is an instance of `Range`, the function will return `true`,
@@ -366,7 +442,14 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
366
442
  * will return `false`.
367
443
  */
368
444
  isRange(
369
- keyNodeEntryOrPredicate: BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>> | Range<K>
445
+ keyNodeEntryOrPredicate:
446
+ | K
447
+ | BinaryTreeNode<K, V>
448
+ | [K | null | undefined, V | undefined]
449
+ | null
450
+ | undefined
451
+ | NodePredicate<BinaryTreeNode<K, V>>
452
+ | Range<K>
370
453
  ): keyNodeEntryOrPredicate is Range<K> {
371
454
  return keyNodeEntryOrPredicate instanceof Range;
372
455
  }
@@ -377,14 +460,14 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
377
460
  *
378
461
  * The function determines whether a given key, node, entry, or raw data is a leaf node in a binary
379
462
  * tree.
380
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} keyNodeOrEntry - The parameter
381
- * `keyNodeOrEntry` can be of type `BTNRep<K, V, BinaryTreeNode<K, V>>` or `R`. It represents a
463
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter
464
+ * `keyNodeOrEntry` can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. It represents a
382
465
  * key, node, entry, or raw data in a binary tree structure. The function `isLeaf` checks whether the
383
466
  * provided
384
467
  * @returns The function `isLeaf` returns a boolean value indicating whether the input
385
468
  * `keyNodeOrEntry` is a leaf node in a binary tree.
386
469
  */
387
- isLeaf(keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>): boolean {
470
+ isLeaf(keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined): boolean {
388
471
  keyNodeOrEntry = this.ensureNode(keyNodeOrEntry);
389
472
  if (keyNodeOrEntry === undefined) return false;
390
473
  if (keyNodeOrEntry === null) return true;
@@ -397,14 +480,16 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
397
480
  *
398
481
  * The function `isEntry` checks if the input is a BTNEntry object by verifying if it is an array
399
482
  * with a length of 2.
400
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} keyNodeOrEntry - The `keyNodeOrEntry`
401
- * parameter in the `isEntry` function can be of type `BTNRep<K, V, BinaryTreeNode<K, V>>` or type `R`.
483
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `keyNodeOrEntry`
484
+ * parameter in the `isEntry` function can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or type `R`.
402
485
  * The function checks if the provided `keyNodeOrEntry` is of type `BTN
403
486
  * @returns The `isEntry` function is checking if the `keyNodeOrEntry` parameter is an array
404
487
  * with a length of 2. If it is, then it returns `true`, indicating that the parameter is of type
405
488
  * `BTNEntry<K, V>`. If the condition is not met, it returns `false`.
406
489
  */
407
- isEntry(keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>): keyNodeOrEntry is BTNEntry<K, V> {
490
+ isEntry(
491
+ keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
492
+ ): keyNodeOrEntry is BTNEntry<K, V> {
408
493
  return Array.isArray(keyNodeOrEntry) && keyNodeOrEntry.length === 2;
409
494
  }
410
495
 
@@ -430,7 +515,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
430
515
  *
431
516
  * The `add` function in TypeScript adds a new node to a binary tree while handling duplicate keys
432
517
  * and finding the correct insertion position.
433
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} keyNodeOrEntry - The `add` method you provided
518
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `add` method you provided
434
519
  * seems to be for adding a new node to a binary tree structure. The `keyNodeOrEntry`
435
520
  * parameter in the method can accept different types of values:
436
521
  * @param {V} [value] - The `value` parameter in the `add` method represents the value associated
@@ -441,7 +526,10 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
441
526
  * node was successful, and `false` if the insertion position could not be found or if a duplicate
442
527
  * key was found and the node was replaced instead of inserted.
443
528
  */
444
- add(keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>, value?: V): boolean {
529
+ add(
530
+ keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
531
+ value?: V
532
+ ): boolean {
445
533
  const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
446
534
  if (newNode === undefined) return false;
447
535
 
@@ -456,16 +544,18 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
456
544
  const queue = new Queue<BinaryTreeNode<K, V>>([this._root]);
457
545
  let potentialParent: BinaryTreeNode<K, V> | undefined; // Record the parent node of the potential insertion location
458
546
 
459
- while (queue.size > 0) {
547
+ while (queue.length > 0) {
460
548
  const cur = queue.shift();
461
549
 
462
550
  if (!cur) continue;
463
551
 
464
- // Check for duplicate keys when newNode is not null
465
- if (newNode !== null && cur.key === newNode.key) {
466
- this._replaceNode(cur, newNode);
467
- if (this._isMapMode) this._setValue(cur.key, newValue);
468
- return true; // If duplicate keys are found, no insertion is performed
552
+ if (!this._isDuplicate) {
553
+ // Check for duplicate keys when newNode is not null
554
+ if (newNode !== null && cur.key === newNode.key) {
555
+ this._replaceNode(cur, newNode);
556
+ if (this._isMapMode) this._setValue(cur.key, newValue);
557
+ return true; // If duplicate keys are found, no insertion is performed
558
+ }
469
559
  }
470
560
 
471
561
  // Record the first possible insertion location found
@@ -506,7 +596,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
506
596
  * each insertion was successful.
507
597
  * @param keysNodesEntriesOrRaws - `keysNodesEntriesOrRaws` is an iterable that can contain a
508
598
  * mix of keys, nodes, entries, or raw values. Each element in this iterable can be of type
509
- * `BTNRep<K, V, BinaryTreeNode<K, V>>` or `R`.
599
+ * `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`.
510
600
  * @param [values] - The `values` parameter in the `addMany` function is an optional parameter that
511
601
  * accepts an iterable of values. These values correspond to the keys or nodes being added in the
512
602
  * `keysNodesEntriesOrRaws` parameter. If provided, the function will iterate over the values and
@@ -516,7 +606,9 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
516
606
  * corresponds to the success of adding the corresponding key or value in the input iterable.
517
607
  */
518
608
  addMany(
519
- keysNodesEntriesOrRaws: Iterable<BTNRep<K, V, BinaryTreeNode<K, V>> | R>,
609
+ keysNodesEntriesOrRaws: Iterable<
610
+ K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R
611
+ >,
520
612
  values?: Iterable<V | undefined>
521
613
  ): boolean[] {
522
614
  // TODO not sure addMany not be run multi times
@@ -562,13 +654,15 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
562
654
  * The `refill` function clears the existing data structure and then adds new key-value pairs based
563
655
  * on the provided input.
564
656
  * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the `refill`
565
- * method can accept an iterable containing a mix of `BTNRep<K, V, BinaryTreeNode<K, V>>` objects or `R`
657
+ * method can accept an iterable containing a mix of `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` objects or `R`
566
658
  * objects.
567
659
  * @param [values] - The `values` parameter in the `refill` method is an optional parameter that
568
660
  * accepts an iterable of values of type `V` or `undefined`.
569
661
  */
570
662
  refill(
571
- keysNodesEntriesOrRaws: Iterable<BTNRep<K, V, BinaryTreeNode<K, V>> | R>,
663
+ keysNodesEntriesOrRaws: Iterable<
664
+ K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R
665
+ >,
572
666
  values?: Iterable<V | undefined>
573
667
  ): void {
574
668
  this.clear();
@@ -581,7 +675,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
581
675
  *
582
676
  * The function `delete` in TypeScript implements the deletion of a node in a binary tree and returns
583
677
  * the deleted node along with information for tree balancing.
584
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} keyNodeOrEntry
678
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry
585
679
  * - The `delete` method you provided is used to delete a node from a binary tree based on the key,
586
680
  * node, entry or raw data. The method returns an array of
587
681
  * `BinaryTreeDeleteResult` objects containing information about the deleted node and whether
@@ -590,7 +684,9 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
590
684
  * the array contains information about the node that was deleted (`deleted`) and the node that may
591
685
  * need to be balanced (`needBalanced`).
592
686
  */
593
- delete(keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>): BinaryTreeDeleteResult<BinaryTreeNode<K, V>>[] {
687
+ delete(
688
+ keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
689
+ ): BinaryTreeDeleteResult<BinaryTreeNode<K, V>>[] {
594
690
  const deletedResult: BinaryTreeDeleteResult<BinaryTreeNode<K, V>>[] = [];
595
691
  if (!this._root) return deletedResult;
596
692
 
@@ -641,15 +737,15 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
641
737
  *
642
738
  * The `search` function in TypeScript performs a depth-first or breadth-first search on a tree
643
739
  * structure based on a given predicate or key, with options to return multiple results or just one.
644
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate - The
740
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate - The
645
741
  * `keyNodeEntryOrPredicate` parameter in the `search` function can accept three types of values:
646
742
  * @param [onlyOne=false] - The `onlyOne` parameter in the `search` function is a boolean flag that
647
743
  * determines whether the search should stop after finding the first matching node. If `onlyOne` is
648
744
  * set to `true`, the search will return as soon as a matching node is found. If `onlyOne` is
649
745
  * @param {C} callback - The `callback` parameter in the `search` function is a callback function
650
746
  * that will be called on each node that matches the search criteria. It is of type `C`, which
651
- * extends `NodeCallback<BinaryTreeNode<K, V>>`. The default value for `callback` is `this._DEFAULT_NODE_CALLBACK` if
652
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the `search` function is
747
+ * extends `NodeCallback<BinaryTreeNode<K, V> | null>`. The default value for `callback` is `this._DEFAULT_NODE_CALLBACK` if
748
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `search` function is
653
749
  * used to specify the node from which the search operation should begin. It represents the starting
654
750
  * point in the binary tree where the search will be performed. If no specific `startNode` is
655
751
  * provided, the search operation will start from the root
@@ -659,11 +755,17 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
659
755
  * @returns The `search` function returns an array of values that match the provided criteria based
660
756
  * on the search algorithm implemented within the function.
661
757
  */
662
- search<C extends NodeCallback<BinaryTreeNode<K, V>>>(
663
- keyNodeEntryOrPredicate: BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>>,
758
+ search<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
759
+ keyNodeEntryOrPredicate:
760
+ | K
761
+ | BinaryTreeNode<K, V>
762
+ | [K | null | undefined, V | undefined]
763
+ | null
764
+ | undefined
765
+ | NodePredicate<BinaryTreeNode<K, V> | null>,
664
766
  onlyOne = false,
665
767
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
666
- startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
768
+ startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
667
769
  iterationType: IterationType = this.iterationType
668
770
  ): ReturnType<C>[] {
669
771
  if (keyNodeEntryOrPredicate === undefined) return [];
@@ -704,18 +806,31 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
704
806
  return ans;
705
807
  }
706
808
 
809
+ getNodes(
810
+ keyNodeEntryOrPredicate:
811
+ | K
812
+ | BinaryTreeNode<K, V>
813
+ | [K | null | undefined, V | undefined]
814
+ | null
815
+ | undefined
816
+ | NodePredicate<BinaryTreeNode<K, V>>,
817
+ onlyOne?: boolean,
818
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
819
+ iterationType?: IterationType
820
+ ): BinaryTreeNode<K, V>[];
821
+
707
822
  /**
708
823
  * Time Complexity: O(n)
709
824
  * Space Complexity: O(k + log n)
710
825
  *
711
826
  * The function `getNodes` retrieves nodes from a binary tree based on a key, node, entry, raw data,
712
827
  * or predicate, with options for recursive or iterative traversal.
713
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate
828
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate
714
829
  * - The `getNodes` function you provided takes several parameters:
715
830
  * @param [onlyOne=false] - The `onlyOne` parameter in the `getNodes` function is a boolean flag that
716
831
  * determines whether to return only the first node that matches the criteria specified by the
717
832
  * `keyNodeEntryOrPredicate` parameter. If `onlyOne` is set to `true`, the function will
718
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
833
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
719
834
  * `getNodes` function is used to specify the starting point for traversing the binary tree. It
720
835
  * represents the root node of the binary tree or the node from which the traversal should begin. If
721
836
  * not provided, the default value is set to `this._root
@@ -726,11 +841,17 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
726
841
  * based on the input parameters and the iteration type specified.
727
842
  */
728
843
  getNodes(
729
- keyNodeEntryOrPredicate: BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>>,
844
+ keyNodeEntryOrPredicate:
845
+ | K
846
+ | BinaryTreeNode<K, V>
847
+ | [K | null | undefined, V | undefined]
848
+ | null
849
+ | undefined
850
+ | NodePredicate<BinaryTreeNode<K, V> | null>,
730
851
  onlyOne = false,
731
- startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
852
+ startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
732
853
  iterationType: IterationType = this.iterationType
733
- ): BinaryTreeNode<K, V>[] {
854
+ ): (BinaryTreeNode<K, V> | null)[] {
734
855
  return this.search(keyNodeEntryOrPredicate, onlyOne, node => node, startNode, iterationType);
735
856
  }
736
857
 
@@ -740,10 +861,10 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
740
861
  *
741
862
  * The `getNode` function retrieves a node based on the provided key, node, entry, raw data, or
742
863
  * predicate.
743
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate
864
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate
744
865
  * - The `keyNodeEntryOrPredicate` parameter in the `getNode` function can accept a key,
745
866
  * node, entry, raw data, or a predicate function.
746
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
867
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
747
868
  * `getNode` function is used to specify the starting point for searching for a node in a binary
748
869
  * tree. If no specific starting point is provided, the default value is set to `this._root`, which
749
870
  * is typically the root node of the binary tree.
@@ -755,10 +876,16 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
755
876
  * or `null` if no matching node is found.
756
877
  */
757
878
  getNode(
758
- keyNodeEntryOrPredicate: BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>>,
759
- startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
879
+ keyNodeEntryOrPredicate:
880
+ | K
881
+ | BinaryTreeNode<K, V>
882
+ | [K | null | undefined, V | undefined]
883
+ | null
884
+ | undefined
885
+ | NodePredicate<BinaryTreeNode<K, V> | null>,
886
+ startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
760
887
  iterationType: IterationType = this.iterationType
761
- ): OptNodeOrNull<BinaryTreeNode<K, V>> {
888
+ ): BinaryTreeNode<K, V> | null | undefined {
762
889
  return this.search(keyNodeEntryOrPredicate, true, node => node, startNode, iterationType)[0];
763
890
  }
764
891
 
@@ -768,10 +895,10 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
768
895
  *
769
896
  * This function overrides the `get` method to retrieve the value associated with a specified key,
770
897
  * node, entry, raw data, or predicate in a data structure.
771
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate
898
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate
772
899
  * - The `keyNodeEntryOrPredicate` parameter in the `get` method can accept one of the
773
900
  * following types:
774
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the `get`
901
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `get`
775
902
  * method is used to specify the starting point for searching for a key or node in the binary tree.
776
903
  * If no specific starting point is provided, the default starting point is the root of the binary
777
904
  * tree (`this._root`).
@@ -785,8 +912,8 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
785
912
  * `undefined`.
786
913
  */
787
914
  override get(
788
- keyNodeEntryOrPredicate: BTNRep<K, V, BinaryTreeNode<K, V>>,
789
- startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
915
+ keyNodeEntryOrPredicate: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
916
+ startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
790
917
  iterationType: IterationType = this.iterationType
791
918
  ): V | undefined {
792
919
  if (this._isMapMode) {
@@ -797,16 +924,28 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
797
924
  return this.getNode(keyNodeEntryOrPredicate, startNode, iterationType)?.value;
798
925
  }
799
926
 
927
+ override has(
928
+ keyNodeEntryOrPredicate?:
929
+ | K
930
+ | BinaryTreeNode<K, V>
931
+ | [K | null | undefined, V | undefined]
932
+ | null
933
+ | undefined
934
+ | NodePredicate<BinaryTreeNode<K, V>>,
935
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
936
+ iterationType?: IterationType
937
+ ): boolean;
938
+
800
939
  /**
801
940
  * Time Complexity: O(n)
802
941
  * Space Complexity: O(log n)
803
942
  *
804
943
  * The `has` function in TypeScript checks if a specified key, node, entry, raw data, or predicate
805
944
  * exists in the data structure.
806
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate
945
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate
807
946
  * - The `keyNodeEntryOrPredicate` parameter in the `override has` method can accept one of
808
947
  * the following types:
809
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
948
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
810
949
  * `override` method is used to specify the starting point for the search operation within the data
811
950
  * structure. It defaults to `this._root` if not provided explicitly.
812
951
  * @param {IterationType} iterationType - The `iterationType` parameter in the `override has` method
@@ -819,8 +958,14 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
819
958
  * Otherwise, it returns `false`.
820
959
  */
821
960
  override has(
822
- keyNodeEntryOrPredicate: BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>>,
823
- startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
961
+ keyNodeEntryOrPredicate:
962
+ | K
963
+ | BinaryTreeNode<K, V>
964
+ | [K | null | undefined, V | undefined]
965
+ | null
966
+ | undefined
967
+ | NodePredicate<BinaryTreeNode<K, V> | null>,
968
+ startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
824
969
  iterationType: IterationType = this.iterationType
825
970
  ): boolean {
826
971
  return this.search(keyNodeEntryOrPredicate, true, node => node, startNode, iterationType).length > 0;
@@ -856,7 +1001,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
856
1001
  *
857
1002
  * The function checks if a binary tree is perfectly balanced by comparing its minimum height with
858
1003
  * its height.
859
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter is the starting
1004
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter is the starting
860
1005
  * point for checking if the binary tree is perfectly balanced. It represents the root node of the
861
1006
  * binary tree or a specific node from which the balance check should begin.
862
1007
  * @returns The method `isPerfectlyBalanced` is returning a boolean value, which indicates whether
@@ -865,7 +1010,9 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
865
1010
  * height plus 1 is greater than or equal to the height of the tree, then it is considered perfectly
866
1011
  * balanced and
867
1012
  */
868
- isPerfectlyBalanced(startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root): boolean {
1013
+ isPerfectlyBalanced(
1014
+ startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root
1015
+ ): boolean {
869
1016
  return this.getMinHeight(startNode) + 1 >= this.getHeight(startNode);
870
1017
  }
871
1018
 
@@ -875,7 +1022,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
875
1022
  *
876
1023
  * The function `isBST` in TypeScript checks if a binary search tree is valid using either recursive
877
1024
  * or iterative methods.
878
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the `isBST`
1025
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `isBST`
879
1026
  * function represents the starting point for checking whether a binary search tree (BST) is valid.
880
1027
  * It can be a node in the BST or a reference to the root of the BST. If no specific node is
881
1028
  * provided, the function will default to
@@ -888,7 +1035,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
888
1035
  * less than the node's key, and all nodes in its right subtree have keys greater than the node's
889
1036
  */
890
1037
  isBST(
891
- startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
1038
+ startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
892
1039
  iterationType: IterationType = this.iterationType
893
1040
  ): boolean {
894
1041
  // TODO there is a bug
@@ -896,7 +1043,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
896
1043
  if (!startNode) return true;
897
1044
 
898
1045
  if (iterationType === 'RECURSIVE') {
899
- const dfs = (cur: OptNodeOrNull<BinaryTreeNode<K, V>>, min: number, max: number): boolean => {
1046
+ const dfs = (cur: BinaryTreeNode<K, V> | null | undefined, min: number, max: number): boolean => {
900
1047
  if (!this.isRealNode(cur)) return true;
901
1048
  const numKey = Number(cur.key);
902
1049
  if (numKey <= min || numKey >= max) return false;
@@ -911,7 +1058,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
911
1058
  const stack = [];
912
1059
  let prev = checkMax ? Number.MAX_SAFE_INTEGER : Number.MIN_SAFE_INTEGER;
913
1060
  // @ts-ignore
914
- let curr: OptNodeOrNull<BinaryTreeNode<K, V>> = startNode;
1061
+ let curr: BinaryTreeNode<K, V> | null | undefined = startNode;
915
1062
  while (this.isRealNode(curr) || stack.length > 0) {
916
1063
  while (this.isRealNode(curr)) {
917
1064
  stack.push(curr);
@@ -936,10 +1083,10 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
936
1083
  * Space Complexity: O(log n)
937
1084
  *
938
1085
  * The `getDepth` function calculates the depth between two nodes in a binary tree.
939
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} dist - The `dist` parameter in the `getDepth`
1086
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } dist - The `dist` parameter in the `getDepth`
940
1087
  * function represents the node or entry in a binary tree map, or a reference to a node in the tree.
941
1088
  * It is the target node for which you want to calculate the depth from the `startNode` node.
942
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
1089
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
943
1090
  * `getDepth` function represents the starting point from which you want to calculate the depth of a
944
1091
  * given node or entry in a binary tree. If no specific starting point is provided, the default value
945
1092
  * for `startNode` is set to the root of the binary
@@ -948,8 +1095,8 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
948
1095
  * node, it returns the depth of the `dist` node from the root of the tree.
949
1096
  */
950
1097
  getDepth(
951
- dist: BTNRep<K, V, BinaryTreeNode<K, V>>,
952
- startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root
1098
+ dist: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
1099
+ startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root
953
1100
  ): number {
954
1101
  let distEnsured = this.ensureNode(dist);
955
1102
  const beginRootEnsured = this.ensureNode(startNode);
@@ -970,7 +1117,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
970
1117
  *
971
1118
  * The `getHeight` function calculates the maximum height of a binary tree using either a recursive
972
1119
  * or iterative approach in TypeScript.
973
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter is the starting
1120
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter is the starting
974
1121
  * point from which the height of the binary tree will be calculated. It can be a node in the binary
975
1122
  * tree or a reference to the root of the tree. If not provided, it defaults to the root of the
976
1123
  * binary tree data structure.
@@ -982,14 +1129,14 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
982
1129
  * recursive approach or an iterative approach depending on the `iterationType` parameter.
983
1130
  */
984
1131
  getHeight(
985
- startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
1132
+ startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
986
1133
  iterationType: IterationType = this.iterationType
987
1134
  ): number {
988
1135
  startNode = this.ensureNode(startNode);
989
1136
  if (!this.isRealNode(startNode)) return -1;
990
1137
 
991
1138
  if (iterationType === 'RECURSIVE') {
992
- const _getMaxHeight = (cur: OptNodeOrNull<BinaryTreeNode<K, V>>): number => {
1139
+ const _getMaxHeight = (cur: BinaryTreeNode<K, V> | null | undefined): number => {
993
1140
  if (!this.isRealNode(cur)) return -1;
994
1141
  const leftHeight = _getMaxHeight(cur.left);
995
1142
  const rightHeight = _getMaxHeight(cur.right);
@@ -1020,7 +1167,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1020
1167
  *
1021
1168
  * The `getMinHeight` function calculates the minimum height of a binary tree using either a
1022
1169
  * recursive or iterative approach in TypeScript.
1023
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
1170
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
1024
1171
  * `getMinHeight` function represents the starting node from which the minimum height of the binary
1025
1172
  * tree will be calculated. It is either a node in the binary tree or a reference to the root of the
1026
1173
  * tree. If not provided, the default value is the root
@@ -1033,14 +1180,14 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1033
1180
  * a stack) based on the `iterationType` parameter.
1034
1181
  */
1035
1182
  getMinHeight(
1036
- startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
1183
+ startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
1037
1184
  iterationType: IterationType = this.iterationType
1038
1185
  ): number {
1039
1186
  startNode = this.ensureNode(startNode);
1040
1187
  if (!startNode) return -1;
1041
1188
 
1042
1189
  if (iterationType === 'RECURSIVE') {
1043
- const _getMinHeight = (cur: OptNodeOrNull<BinaryTreeNode<K, V>>): number => {
1190
+ const _getMinHeight = (cur: BinaryTreeNode<K, V> | null | undefined): number => {
1044
1191
  if (!this.isRealNode(cur)) return 0;
1045
1192
  if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return 0;
1046
1193
  const leftMinHeight = _getMinHeight(cur.left);
@@ -1051,8 +1198,8 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1051
1198
  return _getMinHeight(startNode);
1052
1199
  } else {
1053
1200
  const stack: BinaryTreeNode<K, V>[] = [];
1054
- let node: OptNodeOrNull<BinaryTreeNode<K, V>> = startNode,
1055
- last: OptNodeOrNull<BinaryTreeNode<K, V>> = null;
1201
+ let node: BinaryTreeNode<K, V> | null | undefined = startNode,
1202
+ last: BinaryTreeNode<K, V> | null | undefined = null;
1056
1203
  const depths: Map<BinaryTreeNode<K, V>, number> = new Map();
1057
1204
 
1058
1205
  while (stack.length > 0 || node) {
@@ -1088,7 +1235,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1088
1235
  * the path to the root. It is expected to be a function that takes a node as an argument and returns
1089
1236
  * a value based on that node. The return type of the callback function is determined by the generic
1090
1237
  * type `C
1091
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} beginNode - The `beginNode` parameter in the
1238
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } beginNode - The `beginNode` parameter in the
1092
1239
  * `getPathToRoot` function can be either a key, a node, an entry, or any other value of type `R`.
1093
1240
  * @param [isReverse=true] - The `isReverse` parameter in the `getPathToRoot` function determines
1094
1241
  * whether the resulting path from the given `beginNode` to the root should be in reverse order or
@@ -1099,7 +1246,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1099
1246
  * parameter.
1100
1247
  */
1101
1248
  getPathToRoot<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(
1102
- beginNode: BTNRep<K, V, BinaryTreeNode<K, V>>,
1249
+ beginNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
1103
1250
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
1104
1251
  isReverse = false
1105
1252
  ): ReturnType<C>[] {
@@ -1126,7 +1273,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1126
1273
  * @param {C} callback - The `callback` parameter is a function that will be called with the leftmost
1127
1274
  * node of a binary tree or with `undefined` if the tree is empty. It is provided with a default
1128
1275
  * value of `_DEFAULT_NODE_CALLBACK` if not specified.
1129
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
1276
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
1130
1277
  * `getLeftMost` function represents the starting point for finding the leftmost node in a binary
1131
1278
  * tree. It can be either a key, a node, or an entry in the binary tree structure. If no specific
1132
1279
  * starting point is provided, the function will default
@@ -1140,7 +1287,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1140
1287
  */
1141
1288
  getLeftMost<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(
1142
1289
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
1143
- startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
1290
+ startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
1144
1291
  iterationType: IterationType = this.iterationType
1145
1292
  ): ReturnType<C> {
1146
1293
  if (this.isNIL(startNode)) return callback(undefined);
@@ -1176,7 +1323,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1176
1323
  * of finding the rightmost node in a binary tree. It is of type `NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>`,
1177
1324
  * which means it is a callback function that can accept either an optional binary tree node or null
1178
1325
  * as
1179
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
1326
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
1180
1327
  * `getRightMost` function represents the starting point for finding the rightmost node in a binary
1181
1328
  * tree. It can be either a key, a node, or an entry in the binary tree structure. If no specific
1182
1329
  * starting point is provided, the function will default
@@ -1190,7 +1337,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1190
1337
  */
1191
1338
  getRightMost<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(
1192
1339
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
1193
- startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
1340
+ startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
1194
1341
  iterationType: IterationType = this.iterationType
1195
1342
  ): ReturnType<C> {
1196
1343
  if (this.isNIL(startNode)) return callback(undefined);
@@ -1230,7 +1377,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1230
1377
  */
1231
1378
  getPredecessor(node: BinaryTreeNode<K, V>): BinaryTreeNode<K, V> {
1232
1379
  if (this.isRealNode(node.left)) {
1233
- let predecessor: OptNodeOrNull<BinaryTreeNode<K, V>> = node.left;
1380
+ let predecessor: BinaryTreeNode<K, V> | null | undefined = node.left;
1234
1381
  while (!this.isRealNode(predecessor) || (this.isRealNode(predecessor.right) && predecessor.right !== node)) {
1235
1382
  if (this.isRealNode(predecessor)) {
1236
1383
  predecessor = predecessor.right;
@@ -1255,7 +1402,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1255
1402
  * have a right child, the function traverses up the parent nodes until it finds a node that is not
1256
1403
  * the right child of its parent, and returns that node
1257
1404
  */
1258
- getSuccessor(x?: K | BinaryTreeNode<K, V> | null): OptNodeOrNull<BinaryTreeNode<K, V>> {
1405
+ getSuccessor(x?: K | BinaryTreeNode<K, V> | null): BinaryTreeNode<K, V> | null | undefined {
1259
1406
  x = this.ensureNode(x);
1260
1407
  if (!this.isRealNode(x)) return undefined;
1261
1408
 
@@ -1263,7 +1410,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1263
1410
  return this.getLeftMost(node => node, x.right);
1264
1411
  }
1265
1412
 
1266
- let y: OptNodeOrNull<BinaryTreeNode<K, V>> = x.parent;
1413
+ let y: BinaryTreeNode<K, V> | null | undefined = x.parent;
1267
1414
  while (this.isRealNode(y) && x === y.right) {
1268
1415
  x = y;
1269
1416
  y = y.parent;
@@ -1274,14 +1421,16 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1274
1421
  dfs<C extends NodeCallback<BinaryTreeNode<K, V>>>(
1275
1422
  callback?: C,
1276
1423
  pattern?: DFSOrderPattern,
1277
- startNode?: BTNRep<K, V, BinaryTreeNode<K, V>>,
1424
+ onlyOne?: boolean,
1425
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
1278
1426
  iterationType?: IterationType
1279
1427
  ): ReturnType<C>[];
1280
1428
 
1281
1429
  dfs<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
1282
1430
  callback?: C,
1283
1431
  pattern?: DFSOrderPattern,
1284
- startNode?: BTNRep<K, V, BinaryTreeNode<K, V>>,
1432
+ onlyOne?: boolean,
1433
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
1285
1434
  iterationType?: IterationType,
1286
1435
  includeNull?: boolean
1287
1436
  ): ReturnType<C>[];
@@ -1290,50 +1439,53 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1290
1439
  * Time complexity: O(n)
1291
1440
  * Space complexity: O(n)
1292
1441
  *
1293
- * The function `dfs` performs a depth-first search traversal on a binary tree structure based on the
1294
- * specified parameters.
1295
- * @param {C} callback - The `callback` parameter is a generic type `C` that extends the
1296
- * `NodeCallback` interface with a type parameter of `OptNodeOrNull<BinaryTreeNode<K, V>>`. It has a default value of
1297
- * `this._DEFAULT_NODE_CALLBACK as C`.
1298
- * @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `dfs` method specifies the
1299
- * order in which the Depth-First Search (DFS) algorithm should traverse the nodes in the tree. The
1300
- * possible values for the `pattern` parameter are:
1301
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the `dfs`
1302
- * method is used to specify the starting point for the Depth-First Search traversal. It can be
1303
- * either a `BTNRep` object representing a key, node, or entry in the binary tree map,
1304
- * or it can be a
1305
- * @param {IterationType} iterationType - The `iterationType` parameter in the `dfs` method specifies
1306
- * the type of iteration to be performed during the depth-first search traversal. It is used to
1307
- * determine the order in which nodes are visited during the traversal.
1308
- * @param [includeNull=false] - The `includeNull` parameter in the `dfs` method is a boolean flag
1309
- * that determines whether null values should be included in the traversal or not. If `includeNull`
1310
- * is set to `true`, then null values will be included in the traversal process. If it is set to
1311
- * `false`,
1312
- * @returns The `dfs` method is returning an array of the return type specified by the generic type
1313
- * parameter `C`. The return type is determined by the callback function provided to the method.
1442
+ * The function performs a depth-first search on a binary tree structure based on the specified
1443
+ * parameters.
1444
+ * @param {C} callback - The `callback` parameter is a function that will be called for each node
1445
+ * visited during the depth-first search. It should accept a `BinaryTreeNode` as an argument and
1446
+ * return an optional node or null. The default value for this parameter is `_DEFAULT_NODE_CALLBACK`.
1447
+ * @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `dfs` function specifies
1448
+ * the order in which the nodes are visited during a depth-first search traversal. The possible
1449
+ * values for the `pattern` parameter are:
1450
+ * @param {boolean} [onlyOne=false] - The `onlyOne` parameter in the `dfs` function is a boolean flag
1451
+ * that determines whether the depth-first search should stop after finding the first matching node
1452
+ * or continue searching for all matching nodes. If `onlyOne` is set to `true`, the search will stop
1453
+ * after finding the first matching node
1454
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined}
1455
+ * startNode - The `startNode` parameter in the `dfs` function can be one of the following types:
1456
+ * @param {IterationType} iterationType - The `iterationType` parameter in the `dfs` function
1457
+ * specifies the type of iteration to be performed during the Depth-First Search traversal. It is
1458
+ * used to determine the order in which nodes are visited during the traversal. The possible values
1459
+ * for `iterationType` are typically defined as an enum or a
1460
+ * @param [includeNull=false] - The `includeNull` parameter in the `dfs` function determines whether
1461
+ * null nodes should be included in the depth-first search traversal. If `includeNull` is set to
1462
+ * `true`, null nodes will be included in the traversal process. If it is set to `false`, null nodes
1463
+ * will be skipped
1464
+ * @returns The `dfs` method is returning an array of the return type of the callback function `C`.
1314
1465
  */
1315
1466
  dfs<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(
1316
1467
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
1317
1468
  pattern: DFSOrderPattern = 'IN',
1318
- startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
1469
+ onlyOne: boolean = false,
1470
+ startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
1319
1471
  iterationType: IterationType = this.iterationType,
1320
1472
  includeNull = false
1321
1473
  ): ReturnType<C>[] {
1322
1474
  startNode = this.ensureNode(startNode);
1323
1475
  if (!startNode) return [];
1324
- return this._dfs(callback, pattern, startNode, iterationType, includeNull);
1476
+ return this._dfs(callback, pattern, onlyOne, startNode, iterationType, includeNull);
1325
1477
  }
1326
1478
 
1327
1479
  bfs<C extends NodeCallback<BinaryTreeNode<K, V>>>(
1328
1480
  callback?: C,
1329
- startNode?: BTNRep<K, V, BinaryTreeNode<K, V>>,
1481
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
1330
1482
  iterationType?: IterationType,
1331
1483
  includeNull?: false
1332
1484
  ): ReturnType<C>[];
1333
1485
 
1334
1486
  bfs<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
1335
1487
  callback?: C,
1336
- startNode?: BTNRep<K, V, BinaryTreeNode<K, V>>,
1488
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
1337
1489
  iterationType?: IterationType,
1338
1490
  includeNull?: true
1339
1491
  ): ReturnType<C>[];
@@ -1347,7 +1499,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1347
1499
  * @param {C} callback - The `callback` parameter in the `bfs` function is a function that will be
1348
1500
  * called on each node visited during the breadth-first search traversal. It is a generic type `C`
1349
1501
  * that extends the `NodeCallback` type, which takes a parameter of type `BinaryTreeNode<K, V>` or `null`.
1350
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the `bfs`
1502
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `bfs`
1351
1503
  * function represents the starting point for the breadth-first search traversal in a binary tree. It
1352
1504
  * can be specified as a key, node, or entry in the binary tree structure. If not provided, the
1353
1505
  * default value is the root node of the binary
@@ -1363,14 +1515,14 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1363
1515
  */
1364
1516
  bfs<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
1365
1517
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
1366
- startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
1518
+ startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
1367
1519
  iterationType: IterationType = this.iterationType,
1368
1520
  includeNull = false
1369
1521
  ): ReturnType<C>[] {
1370
1522
  startNode = this.ensureNode(startNode);
1371
1523
  if (!startNode) return [];
1372
1524
 
1373
- const ans: ReturnType<NodeCallback<BinaryTreeNode<K, V>>>[] = [];
1525
+ const ans: ReturnType<NodeCallback<BinaryTreeNode<K, V> | null>>[] = [];
1374
1526
 
1375
1527
  if (iterationType === 'RECURSIVE') {
1376
1528
  const queue: Queue<OptNodeOrNull<BinaryTreeNode<K, V>>> = new Queue<OptNodeOrNull<BinaryTreeNode<K, V>>>([
@@ -1378,7 +1530,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1378
1530
  ]);
1379
1531
 
1380
1532
  const dfs = (level: number) => {
1381
- if (queue.size === 0) return;
1533
+ if (queue.length === 0) return;
1382
1534
 
1383
1535
  const current = queue.shift()!;
1384
1536
  ans.push(callback(current));
@@ -1397,8 +1549,8 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1397
1549
  dfs(0);
1398
1550
  } else {
1399
1551
  const queue = new Queue<OptNodeOrNull<BinaryTreeNode<K, V>>>([startNode]);
1400
- while (queue.size > 0) {
1401
- const levelSize = queue.size;
1552
+ while (queue.length > 0) {
1553
+ const levelSize = queue.length;
1402
1554
 
1403
1555
  for (let i = 0; i < levelSize; i++) {
1404
1556
  const current = queue.shift()!;
@@ -1425,7 +1577,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1425
1577
  * structure based on a specified callback and iteration type.
1426
1578
  * @param {C} callback - The `callback` parameter is a function that will be called on each leaf node
1427
1579
  * in the binary tree. It is optional and defaults to a default callback function if not provided.
1428
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the `leaves`
1580
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `leaves`
1429
1581
  * method is used to specify the starting point for finding and processing the leaves of a binary
1430
1582
  * tree. It can be provided as either a key, a node, or an entry in the binary tree structure. If not
1431
1583
  * explicitly provided, the default value
@@ -1437,11 +1589,11 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1437
1589
  */
1438
1590
  leaves<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
1439
1591
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
1440
- startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
1592
+ startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
1441
1593
  iterationType: IterationType = this.iterationType
1442
1594
  ): ReturnType<C>[] {
1443
1595
  startNode = this.ensureNode(startNode);
1444
- const leaves: ReturnType<NodeCallback<BinaryTreeNode<K, V>>>[] = [];
1596
+ const leaves: ReturnType<NodeCallback<BinaryTreeNode<K, V> | null>>[] = [];
1445
1597
  if (!this.isRealNode(startNode)) return [];
1446
1598
 
1447
1599
  if (iterationType === 'RECURSIVE') {
@@ -1457,7 +1609,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1457
1609
  dfs(startNode);
1458
1610
  } else {
1459
1611
  const queue = new Queue([startNode]);
1460
- while (queue.size > 0) {
1612
+ while (queue.length > 0) {
1461
1613
  const cur = queue.shift();
1462
1614
  if (this.isRealNode(cur)) {
1463
1615
  if (this.isLeaf(cur)) {
@@ -1474,14 +1626,14 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1474
1626
 
1475
1627
  listLevels<C extends NodeCallback<BinaryTreeNode<K, V>>>(
1476
1628
  callback?: C,
1477
- startNode?: BTNRep<K, V, BinaryTreeNode<K, V>>,
1629
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
1478
1630
  iterationType?: IterationType,
1479
1631
  includeNull?: false
1480
1632
  ): ReturnType<C>[][];
1481
1633
 
1482
1634
  listLevels<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
1483
1635
  callback?: C,
1484
- startNode?: BTNRep<K, V, BinaryTreeNode<K, V>>,
1636
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
1485
1637
  iterationType?: IterationType,
1486
1638
  includeNull?: true
1487
1639
  ): ReturnType<C>[][];
@@ -1495,7 +1647,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1495
1647
  * @param {C} callback - The `callback` parameter is a function that will be applied to each node in
1496
1648
  * the binary tree during the traversal. It is used to process each node and determine what
1497
1649
  * information to include in the output for each level of the tree.
1498
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
1650
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
1499
1651
  * `listLevels` function represents the starting point for traversing the binary tree. It can be
1500
1652
  * either a key, a node, or an entry in the binary tree. If not provided, the default value is the
1501
1653
  * root of the binary tree.
@@ -1512,7 +1664,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1512
1664
  */
1513
1665
  listLevels<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
1514
1666
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
1515
- startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
1667
+ startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
1516
1668
  iterationType: IterationType = this.iterationType,
1517
1669
  includeNull = false
1518
1670
  ): ReturnType<C>[][] {
@@ -1557,6 +1709,12 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1557
1709
  return levelsNodes;
1558
1710
  }
1559
1711
 
1712
+ morris<C extends NodeCallback<BinaryTreeNode<K, V>>>(
1713
+ callback?: C,
1714
+ pattern?: DFSOrderPattern,
1715
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
1716
+ ): ReturnType<C>[];
1717
+
1560
1718
  /**
1561
1719
  * Time complexity: O(n)
1562
1720
  * Space complexity: O(n)
@@ -1565,11 +1723,11 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1565
1723
  * Morris Traversal algorithm with different order patterns.
1566
1724
  * @param {C} callback - The `callback` parameter in the `morris` function is a function that will be
1567
1725
  * called on each node in the binary tree during the traversal. It is of type `C`, which extends the
1568
- * `NodeCallback<BinaryTreeNode<K, V>>` type. The default value for `callback` is `this._DEFAULT
1726
+ * `NodeCallback<BinaryTreeNode<K, V> | null>` type. The default value for `callback` is `this._DEFAULT
1569
1727
  * @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `morris` function specifies
1570
1728
  * the type of Depth-First Search (DFS) order pattern to traverse the binary tree. The possible
1571
1729
  * values for the `pattern` parameter are:
1572
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the `morris`
1730
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `morris`
1573
1731
  * function is the starting point for the Morris traversal algorithm. It represents the root node of
1574
1732
  * the binary tree or the node from which the traversal should begin. It can be provided as either a
1575
1733
  * key, a node, an entry, or a reference
@@ -1577,19 +1735,19 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1577
1735
  * provided callback function to each node in the binary tree in the specified order pattern (IN,
1578
1736
  * PRE, or POST).
1579
1737
  */
1580
- morris<C extends NodeCallback<BinaryTreeNode<K, V>>>(
1738
+ morris<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
1581
1739
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
1582
1740
  pattern: DFSOrderPattern = 'IN',
1583
- startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root
1741
+ startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root
1584
1742
  ): ReturnType<C>[] {
1585
1743
  startNode = this.ensureNode(startNode);
1586
1744
  if (!startNode) return [];
1587
- const ans: ReturnType<NodeCallback<BinaryTreeNode<K, V>>>[] = [];
1745
+ const ans: ReturnType<NodeCallback<BinaryTreeNode<K, V> | null>>[] = [];
1588
1746
 
1589
- let cur: OptNodeOrNull<BinaryTreeNode<K, V>> = startNode;
1590
- const _reverseEdge = (node: OptNodeOrNull<BinaryTreeNode<K, V>>) => {
1591
- let pre: OptNodeOrNull<BinaryTreeNode<K, V>> = null;
1592
- let next: OptNodeOrNull<BinaryTreeNode<K, V>> = null;
1747
+ let cur: BinaryTreeNode<K, V> | null | undefined = startNode;
1748
+ const _reverseEdge = (node: BinaryTreeNode<K, V> | null | undefined) => {
1749
+ let pre: BinaryTreeNode<K, V> | null | undefined = null;
1750
+ let next: BinaryTreeNode<K, V> | null | undefined = null;
1593
1751
  while (node) {
1594
1752
  next = node.right;
1595
1753
  node.right = pre;
@@ -1598,9 +1756,9 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1598
1756
  }
1599
1757
  return pre;
1600
1758
  };
1601
- const _printEdge = (node: OptNodeOrNull<BinaryTreeNode<K, V>>) => {
1602
- const tail: OptNodeOrNull<BinaryTreeNode<K, V>> = _reverseEdge(node);
1603
- let cur: OptNodeOrNull<BinaryTreeNode<K, V>> = tail;
1759
+ const _printEdge = (node: BinaryTreeNode<K, V> | null | undefined) => {
1760
+ const tail: BinaryTreeNode<K, V> | null | undefined = _reverseEdge(node);
1761
+ let cur: BinaryTreeNode<K, V> | null | undefined = tail;
1604
1762
  while (cur) {
1605
1763
  ans.push(callback(cur));
1606
1764
  cur = cur.right;
@@ -1680,22 +1838,6 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1680
1838
  return cloned;
1681
1839
  }
1682
1840
 
1683
- protected _clone(cloned: BinaryTree<K, V, R, MK, MV, MR>) {
1684
- this.bfs(
1685
- node => {
1686
- if (node === null) cloned.add(null);
1687
- else {
1688
- if (this._isMapMode) cloned.add([node.key, this._store.get(node.key)]);
1689
- else cloned.add([node.key, node.value]);
1690
- }
1691
- },
1692
- this._root,
1693
- this.iterationType,
1694
- true
1695
- );
1696
- if (this._isMapMode) cloned._store = this._store;
1697
- }
1698
-
1699
1841
  /**
1700
1842
  * Time Complexity: O(n)
1701
1843
  * Space Complexity: O(n)
@@ -1761,7 +1903,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1761
1903
  *
1762
1904
  * The function `toVisual` in TypeScript overrides the visual representation of a binary tree with
1763
1905
  * customizable options for displaying undefined, null, and sentinel nodes.
1764
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
1906
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
1765
1907
  * `toVisual` method is used to specify the starting point for visualizing the binary tree structure.
1766
1908
  * It can be a node, key, entry, or the root of the tree. If no specific starting point is provided,
1767
1909
  * the default is set to the root
@@ -1774,7 +1916,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1774
1916
  * binary tree with the specified options.
1775
1917
  */
1776
1918
  override toVisual(
1777
- startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
1919
+ startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
1778
1920
  options?: BinaryTreePrintOptions
1779
1921
  ): string {
1780
1922
  const opts = { isShowUndefined: false, isShowNull: true, isShowRedBlackNIL: false, ...options };
@@ -1786,7 +1928,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1786
1928
  if (opts.isShowNull) output += `N for null\n`;
1787
1929
  if (opts.isShowRedBlackNIL) output += `S for Sentinel Node(NIL)\n`;
1788
1930
 
1789
- const display = (root: OptNodeOrNull<BinaryTreeNode<K, V>>): void => {
1931
+ const display = (root: BinaryTreeNode<K, V> | null | undefined): void => {
1790
1932
  const [lines] = this._displayAux(root, opts);
1791
1933
  let paragraph = '';
1792
1934
  for (const line of lines) {
@@ -1809,37 +1951,56 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1809
1951
  * printing options for the binary tree. It is an optional parameter that allows you to customize how
1810
1952
  * the binary tree is printed, such as choosing between different traversal orders or formatting
1811
1953
  * options.
1812
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
1954
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
1813
1955
  * `override print` method is used to specify the starting point for printing the binary tree. It can
1814
1956
  * be either a key, a node, an entry, or the root of the tree. If no specific starting point is
1815
1957
  * provided, the default value is set to
1816
1958
  */
1817
- override print(options?: BinaryTreePrintOptions, startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root) {
1959
+ override print(
1960
+ options?: BinaryTreePrintOptions,
1961
+ startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root
1962
+ ) {
1818
1963
  console.log(this.toVisual(startNode, options));
1819
1964
  }
1820
1965
 
1966
+ protected _clone(cloned: BinaryTree<K, V, R, MK, MV, MR>) {
1967
+ this.bfs(
1968
+ node => {
1969
+ if (node === null) cloned.add(null);
1970
+ else {
1971
+ if (this._isMapMode) cloned.add([node.key, this._store.get(node.key)]);
1972
+ else cloned.add([node.key, node.value]);
1973
+ }
1974
+ },
1975
+ this._root,
1976
+ this.iterationType,
1977
+ true
1978
+ );
1979
+ if (this._isMapMode) cloned._store = this._store;
1980
+ }
1981
+
1821
1982
  /**
1822
1983
  * Time Complexity: O(1)
1823
1984
  * Space Complexity: O(1)
1824
1985
  *
1825
1986
  * The function `keyValueNodeEntryRawToNodeAndValue` converts various input types into a node object
1826
1987
  * or returns null.
1827
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} keyNodeOrEntry - The
1988
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The
1828
1989
  * `keyValueNodeEntryRawToNodeAndValue` function takes in a parameter `keyNodeOrEntry`, which
1829
- * can be of type `BTNRep<K, V, BinaryTreeNode<K, V>>` or `R`. This parameter represents either a key, a
1990
+ * can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. This parameter represents either a key, a
1830
1991
  * node, an entry
1831
1992
  * @param {V} [value] - The `value` parameter in the `keyValueNodeEntryRawToNodeAndValue` function is
1832
1993
  * an optional parameter of type `V`. It represents the value associated with the key in the node
1833
1994
  * being created. If a `value` is provided, it will be used when creating the node. If
1834
1995
  * @returns The `keyValueNodeEntryRawToNodeAndValue` function returns an optional node
1835
- * (`OptNodeOrNull<BinaryTreeNode<K, V>>`) based on the input parameters provided. The function checks the type of the
1996
+ * (`BinaryTreeNode<K, V> | null | undefined`) based on the input parameters provided. The function checks the type of the
1836
1997
  * input parameter (`keyNodeOrEntry`) and processes it accordingly to return a node or null
1837
1998
  * value.
1838
1999
  */
1839
2000
  protected _keyValueNodeOrEntryToNodeAndValue(
1840
- keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>,
2001
+ keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
1841
2002
  value?: V
1842
- ): [OptNodeOrNull<BinaryTreeNode<K, V>>, V | undefined] {
2003
+ ): [BinaryTreeNode<K, V> | null | undefined, V | undefined] {
1843
2004
  if (keyNodeOrEntry === undefined) return [undefined, undefined];
1844
2005
  if (keyNodeOrEntry === null) return [null, undefined];
1845
2006
 
@@ -1856,92 +2017,118 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1856
2017
  return [this.createNode(keyNodeOrEntry, value), value];
1857
2018
  }
1858
2019
 
2020
+ protected _dfs<C extends NodeCallback<BinaryTreeNode<K, V>>>(
2021
+ callback: C,
2022
+ pattern?: DFSOrderPattern,
2023
+ onlyOne?: boolean,
2024
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
2025
+ iterationType?: IterationType,
2026
+ includeNull?: boolean,
2027
+ shouldVisitLeft?: (node: BinaryTreeNode<K, V> | null | undefined) => boolean,
2028
+ shouldVisitRight?: (node: BinaryTreeNode<K, V> | null | undefined) => boolean,
2029
+ shouldVisitRoot?: (node: BinaryTreeNode<K, V> | null | undefined) => boolean,
2030
+ shouldProcessRoot?: (node: BinaryTreeNode<K, V> | null | undefined) => boolean
2031
+ ): ReturnType<C>[];
2032
+
1859
2033
  /**
1860
2034
  * Time complexity: O(n)
1861
2035
  * Space complexity: O(n)
1862
2036
  *
1863
- * The `_dfs` function performs a depth-first search traversal on a binary tree structure based on
1864
- * the specified order pattern and callback function.
2037
+ * The `_dfs` function performs a depth-first search traversal on a binary tree, with customizable
2038
+ * options for traversal order and node processing.
1865
2039
  * @param {C} callback - The `callback` parameter in the `_dfs` method is a function that will be
1866
- * called on each node visited during the depth-first search traversal. It is of type `C`, which
1867
- * extends `NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>`. The default value for this parameter is `this._DEFAULT
2040
+ * called on each node visited during the depth-first search traversal. It is a generic type `C` that
2041
+ * extends `NodeCallback<BinaryTreeNode<K, V> | null>`. The default value for `callback`
1868
2042
  * @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `_dfs` method specifies the
1869
- * order in which the nodes are visited during the Depth-First Search traversal. It can have one of
1870
- * the following values:
1871
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the `_dfs`
1872
- * method is used to specify the starting point for the depth-first search traversal in a binary
1873
- * tree. It can be provided as either a `BTNRep` object or a reference to the root node
1874
- * of the tree. If no specific
2043
+ * order in which the nodes are visited during a depth-first search traversal. It can have one of the
2044
+ * following values:
2045
+ * @param {boolean} [onlyOne=false] - The `onlyOne` parameter in the `_dfs` method is a boolean flag
2046
+ * that determines whether the traversal should stop after processing a single node. If `onlyOne` is
2047
+ * set to `true`, the traversal will return as soon as a single node is processed. If it is set to
2048
+ * `false
2049
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined}
2050
+ * startNode - The `startNode` parameter in the `_dfs` method is used to specify the starting node
2051
+ * for the depth-first search traversal. It can be provided in different forms:
1875
2052
  * @param {IterationType} iterationType - The `iterationType` parameter in the `_dfs` method
1876
- * specifies the type of iteration to be performed during the Depth-First Search (DFS) traversal of a
1877
- * binary tree. It can have two possible values:
1878
- * @param [includeNull=false] - The `includeNull` parameter in the `_dfs` method is a boolean flag
1879
- * that determines whether null nodes should be included in the depth-first search traversal. If
1880
- * `includeNull` is set to `true`, null nodes will be considered during the traversal process. If it
1881
- * is set to `false`,
1882
- * @param shouldVisitLeft - The `shouldVisitLeft` parameter is a function that takes a node as input
1883
- * and returns a boolean value. It is used to determine whether the left child of a node should be
1884
- * visited during the depth-first search traversal. By default, it checks if the node is truthy (not
1885
- * null or undefined
1886
- * @param shouldVisitRight - The `shouldVisitRight` parameter is a function that takes a node as an
1887
- * argument and returns a boolean value. It is used to determine whether the right child of a node
1888
- * should be visited during the depth-first search traversal. The default implementation checks if
1889
- * the node is truthy before visiting the right child
1890
- * @param shouldVisitRoot - The `shouldVisitRoot` parameter is a function that takes a node as an
1891
- * argument and returns a boolean value. It is used to determine whether the root node should be
1892
- * visited during the depth-first search traversal based on certain conditions. The default
1893
- * implementation checks if the node is a real node or null based
1894
- * @param shouldProcessRoot - The `shouldProcessRoot` parameter is a function that takes a node as an
1895
- * argument and returns a boolean value indicating whether the node should be processed during the
1896
- * depth-first search traversal. The default implementation checks if the node is a real node or null
1897
- * based on the `includeNull` flag. If `
1898
- * @returns The function `_dfs` returns an array of the return type of the callback function provided
1899
- * as input.
2053
+ * specifies whether the traversal should be done recursively or iteratively. It can have two
2054
+ * possible values:
2055
+ * @param [includeNull=false] - The `includeNull` parameter in the `_dfs` method determines whether
2056
+ * null nodes should be included in the traversal process. If `includeNull` is set to `true`, the
2057
+ * method will consider null nodes as valid nodes to visit or process. If `includeNull` is set to
2058
+ * `false`,
2059
+ * @param shouldVisitLeft - The `shouldVisitLeft` parameter in the `_dfs` method is a function that
2060
+ * determines whether the left child of a node should be visited during the Depth-First Search
2061
+ * traversal. By default, it checks if the node is not null or undefined before visiting the left
2062
+ * child. You can customize this behavior
2063
+ * @param shouldVisitRight - The `shouldVisitRight` parameter in the `_dfs` method is a function that
2064
+ * determines whether to visit the right child node of the current node during a depth-first search
2065
+ * traversal. The default implementation of this function checks if the node is not null or undefined
2066
+ * before deciding to visit it.
2067
+ * @param shouldVisitRoot - The `shouldVisitRoot` parameter in the `_dfs` method is a function that
2068
+ * determines whether a given node should be visited during the depth-first search traversal. The
2069
+ * function takes a node as an argument and returns a boolean value indicating whether the node
2070
+ * should be visited.
2071
+ * @param shouldProcessRoot - The `shouldProcessRoot` parameter in the `_dfs` method is a function
2072
+ * that determines whether the root node should be processed during the Depth-First Search traversal.
2073
+ * It takes a node (BinaryTreeNode<K, V> | null | undefined) as input and returns a boolean value. If
2074
+ * the function
2075
+ * @returns The `_dfs` method returns an array of the return type of the provided callback function
2076
+ * `C`.
1900
2077
  */
1901
- protected _dfs<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(
2078
+ protected _dfs<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
1902
2079
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
1903
2080
  pattern: DFSOrderPattern = 'IN',
1904
- startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
2081
+ onlyOne: boolean = false,
2082
+ startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
1905
2083
  iterationType: IterationType = this.iterationType,
1906
2084
  includeNull = false,
1907
- shouldVisitLeft: (node: OptNodeOrNull<BinaryTreeNode<K, V>>) => boolean = node => !!node,
1908
- shouldVisitRight: (node: OptNodeOrNull<BinaryTreeNode<K, V>>) => boolean = node => !!node,
1909
- shouldVisitRoot: (node: OptNodeOrNull<BinaryTreeNode<K, V>>) => boolean = node => {
2085
+ shouldVisitLeft: (node: BinaryTreeNode<K, V> | null | undefined) => boolean = node => !!node,
2086
+ shouldVisitRight: (node: BinaryTreeNode<K, V> | null | undefined) => boolean = node => !!node,
2087
+ shouldVisitRoot: (node: BinaryTreeNode<K, V> | null | undefined) => boolean = node => {
1910
2088
  if (includeNull) return this.isRealNodeOrNull(node);
1911
2089
  return this.isRealNode(node);
1912
2090
  },
1913
- shouldProcessRoot: (node: OptNodeOrNull<BinaryTreeNode<K, V>>) => boolean = node => this.isRealNodeOrNull(node)
2091
+ shouldProcessRoot: (node: BinaryTreeNode<K, V> | null | undefined) => boolean = node => this.isRealNodeOrNull(node)
1914
2092
  ): ReturnType<C>[] {
1915
2093
  startNode = this.ensureNode(startNode);
1916
2094
  if (!startNode) return [];
1917
2095
  const ans: ReturnType<C>[] = [];
1918
2096
 
1919
2097
  if (iterationType === 'RECURSIVE') {
1920
- const dfs = (node: OptNodeOrNull<BinaryTreeNode<K, V>>) => {
2098
+ const dfs = (node: BinaryTreeNode<K, V> | null) => {
1921
2099
  if (!shouldVisitRoot(node)) return;
1922
2100
 
1923
2101
  const visitLeft = () => {
1924
- if (shouldVisitLeft(node)) dfs(node?.left);
2102
+ if (shouldVisitLeft(node) && node?.left !== undefined) dfs(node?.left);
1925
2103
  };
1926
2104
  const visitRight = () => {
1927
- if (shouldVisitRight(node)) dfs(node?.right);
2105
+ if (shouldVisitRight(node) && node?.right !== undefined) dfs(node?.right);
1928
2106
  };
1929
2107
 
1930
2108
  switch (pattern) {
1931
2109
  case 'IN':
1932
2110
  visitLeft();
1933
- if (shouldProcessRoot(node)) ans.push(callback(node));
2111
+ if (shouldProcessRoot(node)) {
2112
+ ans.push(callback(node));
2113
+ if (onlyOne) return;
2114
+ }
1934
2115
  visitRight();
1935
2116
  break;
1936
2117
  case 'PRE':
1937
- if (shouldProcessRoot(node)) ans.push(callback(node));
2118
+ if (shouldProcessRoot(node)) {
2119
+ ans.push(callback(node));
2120
+ if (onlyOne) return;
2121
+ }
1938
2122
  visitLeft();
1939
2123
  visitRight();
1940
2124
  break;
1941
2125
  case 'POST':
1942
2126
  visitLeft();
1943
2127
  visitRight();
1944
- if (shouldProcessRoot(node)) ans.push(callback(node));
2128
+ if (shouldProcessRoot(node)) {
2129
+ ans.push(callback(node));
2130
+ if (onlyOne) return;
2131
+ }
1945
2132
  break;
1946
2133
  }
1947
2134
  };
@@ -1965,7 +2152,10 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1965
2152
  if (cur === undefined) continue;
1966
2153
  if (!shouldVisitRoot(cur.node)) continue;
1967
2154
  if (cur.opt === DFSOperation.PROCESS) {
1968
- if (shouldProcessRoot(cur.node)) ans.push(callback(cur.node));
2155
+ if (shouldProcessRoot(cur.node) && cur.node !== undefined) {
2156
+ ans.push(callback(cur.node));
2157
+ if (onlyOne) return ans;
2158
+ }
1969
2159
  } else {
1970
2160
  switch (pattern) {
1971
2161
  case 'IN':
@@ -2010,8 +2200,8 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
2010
2200
  if (!node) return;
2011
2201
 
2012
2202
  if (this.iterationType === 'ITERATIVE') {
2013
- const stack: OptNodeOrNull<BinaryTreeNode<K, V>>[] = [];
2014
- let current: OptNodeOrNull<BinaryTreeNode<K, V>> = node;
2203
+ const stack: (BinaryTreeNode<K, V> | null | undefined)[] = [];
2204
+ let current: BinaryTreeNode<K, V> | null | undefined = node;
2015
2205
 
2016
2206
  while (current || stack.length > 0) {
2017
2207
  while (this.isRealNode(current)) {
@@ -2054,7 +2244,10 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
2054
2244
  * information about how to display a node in a binary tree. The `NodeDisplayLayout` consists of four
2055
2245
  * elements:
2056
2246
  */
2057
- protected _displayAux(node: OptNodeOrNull<BinaryTreeNode<K, V>>, options: BinaryTreePrintOptions): NodeDisplayLayout {
2247
+ protected _displayAux(
2248
+ node: BinaryTreeNode<K, V> | null | undefined,
2249
+ options: BinaryTreePrintOptions
2250
+ ): NodeDisplayLayout {
2058
2251
  const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
2059
2252
  const emptyDisplayLayout = <NodeDisplayLayout>[['─'], 1, 0, 0];
2060
2253
 
@@ -2122,26 +2315,26 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
2122
2315
  }
2123
2316
  }
2124
2317
 
2125
- protected _DEFAULT_NODE_CALLBACK = (node: OptNodeOrNull<BinaryTreeNode<K, V>>) => (node ? node.key : undefined);
2318
+ protected _DEFAULT_NODE_CALLBACK = (node: BinaryTreeNode<K, V> | null | undefined) => (node ? node.key : undefined);
2126
2319
 
2127
2320
  /**
2128
2321
  * Time Complexity: O(1)
2129
2322
  * Space Complexity: O(1)
2130
2323
  *
2131
2324
  * The _swapProperties function swaps key and value properties between two nodes in a binary tree.
2132
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} srcNode - The `srcNode` parameter in the
2325
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } srcNode - The `srcNode` parameter in the
2133
2326
  * `_swapProperties` method can be either a BTNRep object containing key and value
2134
2327
  * properties, or it can be of type R.
2135
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} destNode - The `destNode` parameter in the
2328
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } destNode - The `destNode` parameter in the
2136
2329
  * `_swapProperties` method represents the node or entry where the properties will be swapped with
2137
- * the `srcNode`. It can be of type `BTNRep<K, V, BinaryTreeNode<K, V>>` or `R`. The method ensures that
2330
+ * the `srcNode`. It can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. The method ensures that
2138
2331
  * both `srcNode
2139
2332
  * @returns The `_swapProperties` method returns either the `destNode` with its key and value swapped
2140
2333
  * with the `srcNode`, or `undefined` if either `srcNode` or `destNode` is falsy.
2141
2334
  */
2142
2335
  protected _swapProperties(
2143
- srcNode: BTNRep<K, V, BinaryTreeNode<K, V>>,
2144
- destNode: BTNRep<K, V, BinaryTreeNode<K, V>>
2336
+ srcNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
2337
+ destNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
2145
2338
  ): BinaryTreeNode<K, V> | undefined {
2146
2339
  srcNode = this.ensureNode(srcNode);
2147
2340
  destNode = this.ensureNode(destNode);
@@ -2201,45 +2394,67 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
2201
2394
  *
2202
2395
  * The function _setRoot sets the root node of a data structure while updating the parent reference
2203
2396
  * of the previous root node.
2204
- * @param v - The parameter `v` in the `_setRoot` method is of type `OptNodeOrNull<BinaryTreeNode<K, V>>`, which means
2397
+ * @param v - The parameter `v` in the `_setRoot` method is of type `BinaryTreeNode<K, V> | null | undefined`, which means
2205
2398
  * it can either be an optional `BinaryTreeNode<K, V>` type or `null`.
2206
2399
  */
2207
- protected _setRoot(v: OptNodeOrNull<BinaryTreeNode<K, V>>) {
2400
+ protected _setRoot(v: BinaryTreeNode<K, V> | null | undefined) {
2208
2401
  if (v) {
2209
2402
  v.parent = undefined;
2210
2403
  }
2211
2404
  this._root = v;
2212
2405
  }
2213
2406
 
2407
+ protected _ensurePredicate(
2408
+ keyNodeEntryOrPredicate:
2409
+ | K
2410
+ | BinaryTreeNode<K, V>
2411
+ | [K | null | undefined, V | undefined]
2412
+ | null
2413
+ | undefined
2414
+ | NodePredicate<BinaryTreeNode<K, V>>
2415
+ ): NodePredicate<BinaryTreeNode<K, V>>;
2416
+
2214
2417
  /**
2215
2418
  * Time Complexity: O(1)
2216
2419
  * Space Complexity: O(1)
2217
2420
  *
2218
2421
  * The function `_ensurePredicate` in TypeScript ensures that the input is converted into a valid
2219
2422
  * predicate function for a binary tree node.
2220
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate - The
2423
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate - The
2221
2424
  * `_ensurePredicate` method in the provided code snippet is responsible for ensuring that the input
2222
2425
  * parameter `keyNodeEntryOrPredicate` is transformed into a valid predicate function that can be
2223
2426
  * used for filtering nodes in a binary tree.
2224
2427
  * @returns A NodePredicate<BinaryTreeNode<K, V>> function is being returned.
2225
2428
  */
2226
2429
  protected _ensurePredicate(
2227
- keyNodeEntryOrPredicate: BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>>
2228
- ): NodePredicate<BinaryTreeNode<K, V>> {
2430
+ keyNodeEntryOrPredicate:
2431
+ | K
2432
+ | BinaryTreeNode<K, V>
2433
+ | [K | null | undefined, V | undefined]
2434
+ | null
2435
+ | undefined
2436
+ | NodePredicate<BinaryTreeNode<K, V> | null>
2437
+ ): NodePredicate<BinaryTreeNode<K, V> | null> {
2229
2438
  if (keyNodeEntryOrPredicate === null || keyNodeEntryOrPredicate === undefined)
2230
- return (node: BinaryTreeNode<K, V>) => (node ? false : false);
2439
+ return (node: BinaryTreeNode<K, V> | null | undefined) => (node ? false : false);
2231
2440
 
2232
2441
  if (this._isPredicate(keyNodeEntryOrPredicate)) return keyNodeEntryOrPredicate;
2233
2442
 
2234
2443
  if (this.isRealNode(keyNodeEntryOrPredicate))
2235
- return (node: BinaryTreeNode<K, V>) => node === keyNodeEntryOrPredicate;
2444
+ return (node: BinaryTreeNode<K, V> | null) => node === keyNodeEntryOrPredicate;
2236
2445
 
2237
2446
  if (this.isEntry(keyNodeEntryOrPredicate)) {
2238
2447
  const [key] = keyNodeEntryOrPredicate;
2239
- return (node: BinaryTreeNode<K, V>) => node.key === key;
2448
+ return (node: BinaryTreeNode<K, V> | null) => {
2449
+ if (!node) return false;
2450
+ return node.key === key;
2451
+ };
2240
2452
  }
2241
2453
 
2242
- return (node: BinaryTreeNode<K, V>) => node.key === keyNodeEntryOrPredicate;
2454
+ return (node: BinaryTreeNode<K, V> | null) => {
2455
+ if (!node) return false;
2456
+ return node.key === keyNodeEntryOrPredicate;
2457
+ };
2243
2458
  }
2244
2459
 
2245
2460
  /**
@@ -2264,14 +2479,16 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
2264
2479
  *
2265
2480
  * The function `_extractKey` in TypeScript returns the key from a given input, which can be a node,
2266
2481
  * entry, raw data, or null/undefined.
2267
- * @param {BTNRep<K, V, BinaryTreeNode<K, V>>} keyNodeOrEntry - The `_extractKey` method you provided is a
2268
- * TypeScript method that takes in a parameter `keyNodeOrEntry` of type `BTNRep<K, V, BinaryTreeNode<K, V>>`,
2482
+ * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `_extractKey` method you provided is a
2483
+ * TypeScript method that takes in a parameter `keyNodeOrEntry` of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `,
2269
2484
  * where `BTNRep` is a generic type with keys `K`, `V`, and `BinaryTreeNode<K, V>`, and `
2270
2485
  * @returns The `_extractKey` method returns the key value extracted from the `keyNodeOrEntry`
2271
2486
  * parameter. The return value can be a key value of type `K`, `null`, or `undefined`, depending on
2272
2487
  * the conditions checked in the method.
2273
2488
  */
2274
- protected _extractKey(keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>): K | null | undefined {
2489
+ protected _extractKey(
2490
+ keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
2491
+ ): K | null | undefined {
2275
2492
  if (keyNodeOrEntry === null) return null;
2276
2493
  if (keyNodeOrEntry === undefined) return;
2277
2494
  if (keyNodeOrEntry === this._NIL) return;