stack-typed 2.0.5 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/dist/data-structures/base/iterable-element-base.d.ts +186 -83
  2. package/dist/data-structures/base/iterable-element-base.js +149 -107
  3. package/dist/data-structures/base/iterable-entry-base.d.ts +95 -119
  4. package/dist/data-structures/base/iterable-entry-base.js +59 -116
  5. package/dist/data-structures/base/linear-base.d.ts +250 -192
  6. package/dist/data-structures/base/linear-base.js +137 -274
  7. package/dist/data-structures/binary-tree/avl-tree-counter.d.ts +126 -158
  8. package/dist/data-structures/binary-tree/avl-tree-counter.js +171 -205
  9. package/dist/data-structures/binary-tree/avl-tree-multi-map.d.ts +100 -69
  10. package/dist/data-structures/binary-tree/avl-tree-multi-map.js +135 -87
  11. package/dist/data-structures/binary-tree/avl-tree.d.ts +138 -149
  12. package/dist/data-structures/binary-tree/avl-tree.js +208 -195
  13. package/dist/data-structures/binary-tree/binary-tree.d.ts +476 -632
  14. package/dist/data-structures/binary-tree/binary-tree.js +602 -873
  15. package/dist/data-structures/binary-tree/bst.d.ts +258 -306
  16. package/dist/data-structures/binary-tree/bst.js +505 -481
  17. package/dist/data-structures/binary-tree/red-black-tree.d.ts +107 -179
  18. package/dist/data-structures/binary-tree/red-black-tree.js +114 -209
  19. package/dist/data-structures/binary-tree/tree-counter.d.ts +132 -154
  20. package/dist/data-structures/binary-tree/tree-counter.js +172 -203
  21. package/dist/data-structures/binary-tree/tree-multi-map.d.ts +72 -69
  22. package/dist/data-structures/binary-tree/tree-multi-map.js +105 -85
  23. package/dist/data-structures/graph/abstract-graph.d.ts +238 -233
  24. package/dist/data-structures/graph/abstract-graph.js +267 -237
  25. package/dist/data-structures/graph/directed-graph.d.ts +108 -224
  26. package/dist/data-structures/graph/directed-graph.js +146 -233
  27. package/dist/data-structures/graph/map-graph.d.ts +49 -55
  28. package/dist/data-structures/graph/map-graph.js +56 -59
  29. package/dist/data-structures/graph/undirected-graph.d.ts +103 -146
  30. package/dist/data-structures/graph/undirected-graph.js +129 -149
  31. package/dist/data-structures/hash/hash-map.d.ts +164 -338
  32. package/dist/data-structures/hash/hash-map.js +270 -457
  33. package/dist/data-structures/heap/heap.d.ts +214 -289
  34. package/dist/data-structures/heap/heap.js +340 -349
  35. package/dist/data-structures/heap/max-heap.d.ts +11 -47
  36. package/dist/data-structures/heap/max-heap.js +11 -66
  37. package/dist/data-structures/heap/min-heap.d.ts +12 -47
  38. package/dist/data-structures/heap/min-heap.js +11 -66
  39. package/dist/data-structures/linked-list/doubly-linked-list.d.ts +231 -347
  40. package/dist/data-structures/linked-list/doubly-linked-list.js +368 -494
  41. package/dist/data-structures/linked-list/singly-linked-list.d.ts +261 -310
  42. package/dist/data-structures/linked-list/singly-linked-list.js +447 -466
  43. package/dist/data-structures/linked-list/skip-linked-list.d.ts +0 -107
  44. package/dist/data-structures/linked-list/skip-linked-list.js +0 -100
  45. package/dist/data-structures/priority-queue/max-priority-queue.d.ts +12 -56
  46. package/dist/data-structures/priority-queue/max-priority-queue.js +11 -78
  47. package/dist/data-structures/priority-queue/min-priority-queue.d.ts +11 -57
  48. package/dist/data-structures/priority-queue/min-priority-queue.js +10 -79
  49. package/dist/data-structures/priority-queue/priority-queue.d.ts +2 -61
  50. package/dist/data-structures/priority-queue/priority-queue.js +8 -83
  51. package/dist/data-structures/queue/deque.d.ts +227 -254
  52. package/dist/data-structures/queue/deque.js +309 -348
  53. package/dist/data-structures/queue/queue.d.ts +180 -201
  54. package/dist/data-structures/queue/queue.js +265 -248
  55. package/dist/data-structures/stack/stack.d.ts +124 -102
  56. package/dist/data-structures/stack/stack.js +181 -125
  57. package/dist/data-structures/trie/trie.d.ts +164 -165
  58. package/dist/data-structures/trie/trie.js +189 -172
  59. package/dist/interfaces/binary-tree.d.ts +56 -6
  60. package/dist/interfaces/graph.d.ts +16 -0
  61. package/dist/types/data-structures/base/base.d.ts +1 -1
  62. package/dist/types/data-structures/graph/abstract-graph.d.ts +4 -0
  63. package/dist/types/utils/utils.d.ts +1 -0
  64. package/dist/utils/utils.d.ts +1 -1
  65. package/dist/utils/utils.js +2 -1
  66. package/package.json +2 -2
  67. package/src/data-structures/base/iterable-element-base.ts +238 -115
  68. package/src/data-structures/base/iterable-entry-base.ts +96 -120
  69. package/src/data-structures/base/linear-base.ts +271 -277
  70. package/src/data-structures/binary-tree/avl-tree-counter.ts +196 -217
  71. package/src/data-structures/binary-tree/avl-tree-multi-map.ts +188 -102
  72. package/src/data-structures/binary-tree/avl-tree.ts +237 -206
  73. package/src/data-structures/binary-tree/binary-tree.ts +665 -896
  74. package/src/data-structures/binary-tree/bst.ts +565 -572
  75. package/src/data-structures/binary-tree/red-black-tree.ts +157 -223
  76. package/src/data-structures/binary-tree/tree-counter.ts +195 -219
  77. package/src/data-structures/binary-tree/tree-multi-map.ts +127 -98
  78. package/src/data-structures/graph/abstract-graph.ts +339 -264
  79. package/src/data-structures/graph/directed-graph.ts +146 -236
  80. package/src/data-structures/graph/map-graph.ts +63 -60
  81. package/src/data-structures/graph/undirected-graph.ts +129 -152
  82. package/src/data-structures/hash/hash-map.ts +274 -496
  83. package/src/data-structures/heap/heap.ts +389 -402
  84. package/src/data-structures/heap/max-heap.ts +12 -76
  85. package/src/data-structures/heap/min-heap.ts +13 -76
  86. package/src/data-structures/linked-list/doubly-linked-list.ts +426 -530
  87. package/src/data-structures/linked-list/singly-linked-list.ts +495 -517
  88. package/src/data-structures/linked-list/skip-linked-list.ts +1 -108
  89. package/src/data-structures/priority-queue/max-priority-queue.ts +12 -87
  90. package/src/data-structures/priority-queue/min-priority-queue.ts +11 -88
  91. package/src/data-structures/priority-queue/priority-queue.ts +3 -92
  92. package/src/data-structures/queue/deque.ts +381 -357
  93. package/src/data-structures/queue/queue.ts +310 -264
  94. package/src/data-structures/stack/stack.ts +217 -131
  95. package/src/data-structures/trie/trie.ts +240 -175
  96. package/src/interfaces/binary-tree.ts +240 -6
  97. package/src/interfaces/graph.ts +37 -0
  98. package/src/types/data-structures/base/base.ts +5 -5
  99. package/src/types/data-structures/graph/abstract-graph.ts +5 -0
  100. package/src/types/utils/utils.ts +2 -0
  101. package/src/utils/utils.ts +9 -14
@@ -31,9 +31,8 @@ import { IterableEntryBase } from '../base';
31
31
  import { DFSOperation, Range } from '../../common';
32
32
 
33
33
  /**
34
- * Represents a node in a binary tree.
35
- * @template V - The type of data stored in the node.
36
- * @template BinaryTreeNode<K, V> - The type of the family relationship in the binary tree.
34
+ * @template K - The type of the key.
35
+ * @template V - The type of the value.
37
36
  */
38
37
  export class BinaryTreeNode<K = any, V = any> {
39
38
  key: K;
@@ -41,12 +40,11 @@ export class BinaryTreeNode<K = any, V = any> {
41
40
  parent?: BinaryTreeNode<K, V> = undefined;
42
41
 
43
42
  /**
44
- * The constructor function initializes an object with a key and an optional value in TypeScript.
45
- * @param {K} key - The `key` parameter in the constructor function is used to store the key value
46
- * for the key-value pair.
47
- * @param {V} [value] - The `value` parameter in the constructor is optional, meaning it does not
48
- * have to be provided when creating an instance of the class. If a `value` is not provided, it will
49
- * default to `undefined`.
43
+ * Creates an instance of BinaryTreeNode.
44
+ * @remarks Time O(1), Space O(1)
45
+ *
46
+ * @param key - The key of the node.
47
+ * @param [value] - The value associated with the key.
50
48
  */
51
49
  constructor(key: K, value?: V) {
52
50
  this.key = key;
@@ -55,10 +53,22 @@ export class BinaryTreeNode<K = any, V = any> {
55
53
 
56
54
  _left?: BinaryTreeNode<K, V> | null | undefined = undefined;
57
55
 
56
+ /**
57
+ * Gets the left child of the node.
58
+ * @remarks Time O(1), Space O(1)
59
+ *
60
+ * @returns The left child.
61
+ */
58
62
  get left(): BinaryTreeNode<K, V> | null | undefined {
59
63
  return this._left;
60
64
  }
61
65
 
66
+ /**
67
+ * Sets the left child of the node and updates its parent reference.
68
+ * @remarks Time O(1), Space O(1)
69
+ *
70
+ * @param v - The node to set as the left child.
71
+ */
62
72
  set left(v: BinaryTreeNode<K, V> | null | undefined) {
63
73
  if (v) {
64
74
  v.parent = this as unknown as BinaryTreeNode<K, V>;
@@ -68,10 +78,22 @@ export class BinaryTreeNode<K = any, V = any> {
68
78
 
69
79
  _right?: BinaryTreeNode<K, V> | null | undefined = undefined;
70
80
 
81
+ /**
82
+ * Gets the right child of the node.
83
+ * @remarks Time O(1), Space O(1)
84
+ *
85
+ * @returns The right child.
86
+ */
71
87
  get right(): BinaryTreeNode<K, V> | null | undefined {
72
88
  return this._right;
73
89
  }
74
90
 
91
+ /**
92
+ * Sets the right child of the node and updates its parent reference.
93
+ * @remarks Time O(1), Space O(1)
94
+ *
95
+ * @param v - The node to set as the right child.
96
+ */
75
97
  set right(v: BinaryTreeNode<K, V> | null | undefined) {
76
98
  if (v) {
77
99
  v.parent = this;
@@ -81,34 +103,76 @@ export class BinaryTreeNode<K = any, V = any> {
81
103
 
82
104
  _height: number = 0;
83
105
 
106
+ /**
107
+ * Gets the height of the node (used in self-balancing trees).
108
+ * @remarks Time O(1), Space O(1)
109
+ *
110
+ * @returns The height.
111
+ */
84
112
  get height(): number {
85
113
  return this._height;
86
114
  }
87
115
 
116
+ /**
117
+ * Sets the height of the node.
118
+ * @remarks Time O(1), Space O(1)
119
+ *
120
+ * @param value - The new height.
121
+ */
88
122
  set height(value: number) {
89
123
  this._height = value;
90
124
  }
91
125
 
92
126
  _color: RBTNColor = 'BLACK';
93
127
 
128
+ /**
129
+ * Gets the color of the node (used in Red-Black trees).
130
+ * @remarks Time O(1), Space O(1)
131
+ *
132
+ * @returns The node's color.
133
+ */
94
134
  get color(): RBTNColor {
95
135
  return this._color;
96
136
  }
97
137
 
138
+ /**
139
+ * Sets the color of the node.
140
+ * @remarks Time O(1), Space O(1)
141
+ *
142
+ * @param value - The new color.
143
+ */
98
144
  set color(value: RBTNColor) {
99
145
  this._color = value;
100
146
  }
101
147
 
102
148
  _count: number = 1;
103
149
 
150
+ /**
151
+ * Gets the count of nodes in the subtree rooted at this node (used in order-statistic trees).
152
+ * @remarks Time O(1), Space O(1)
153
+ *
154
+ * @returns The subtree node count.
155
+ */
104
156
  get count(): number {
105
157
  return this._count;
106
158
  }
107
159
 
160
+ /**
161
+ * Sets the count of nodes in the subtree.
162
+ * @remarks Time O(1), Space O(1)
163
+ *
164
+ * @param value - The new count.
165
+ */
108
166
  set count(value: number) {
109
167
  this._count = value;
110
168
  }
111
169
 
170
+ /**
171
+ * Gets the position of the node relative to its parent.
172
+ * @remarks Time O(1), Space O(1)
173
+ *
174
+ * @returns The family position (e.g., 'ROOT', 'LEFT', 'RIGHT').
175
+ */
112
176
  get familyPosition(): FamilyPosition {
113
177
  if (!this.parent) {
114
178
  return this.left || this.right ? 'ROOT' : 'ISOLATED';
@@ -125,6 +189,15 @@ export class BinaryTreeNode<K = any, V = any> {
125
189
  }
126
190
 
127
191
  /**
192
+ * A general Binary Tree implementation.
193
+ *
194
+ * @remarks
195
+ * This class implements a basic Binary Tree, not a Binary Search Tree.
196
+ * The `add` operation inserts nodes level-by-level (BFS) into the first available slot.
197
+ *
198
+ * @template K - The type of the key.
199
+ * @template V - The type of the value.
200
+ * @template R - The type of the raw data object (if using `toEntryFn`).
128
201
  * 1. Two Children Maximum: Each node has at most two children.
129
202
  * 2. Left and Right Children: Nodes have distinct left and right children.
130
203
  * 3. Depth and Height: Depth is the number of edges from the root to a node; height is the maximum depth in the tree.
@@ -193,20 +266,18 @@ export class BinaryTreeNode<K = any, V = any> {
193
266
  *
194
267
  * console.log(evaluate(expressionTree.root)); // -27
195
268
  */
196
- export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = object>
269
+ export class BinaryTree<K = any, V = any, R = any>
197
270
  extends IterableEntryBase<K, V | undefined>
198
- implements IBinaryTree<K, V, R, MK, MV, MR>
271
+ implements IBinaryTree<K, V, R>
199
272
  {
200
273
  iterationType: IterationType = 'ITERATIVE';
201
274
 
202
275
  /**
203
- * This TypeScript constructor function initializes a binary tree with optional options and adds
204
- * elements based on the provided input.
205
- * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the constructor is an
206
- * iterable that can contain either objects of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. It
207
- * is used to initialize the binary tree with keys, nodes, entries, or raw data.
208
- * @param [options] - The `options` parameter in the constructor is an optional object that can
209
- * contain the following properties:
276
+ * Creates an instance of BinaryTree.
277
+ * @remarks Time O(N * M), where N is the number of items in `keysNodesEntriesOrRaws` and M is the tree size at insertion time (due to O(M) `add` operation). Space O(N) for storing the nodes.
278
+ *
279
+ * @param [keysNodesEntriesOrRaws=[]] - An iterable of items to add.
280
+ * @param [options] - Configuration options for the tree.
210
281
  */
211
282
  constructor(
212
283
  keysNodesEntriesOrRaws: Iterable<
@@ -229,96 +300,118 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
229
300
 
230
301
  protected _isMapMode = true;
231
302
 
303
+ /**
304
+ * Gets whether the tree is in Map mode.
305
+ * @remarks In Map mode (default), values are stored in an external Map, and nodes only hold keys. If false, values are stored directly on the nodes. Time O(1)
306
+ *
307
+ * @returns True if in Map mode, false otherwise.
308
+ */
232
309
  get isMapMode() {
233
310
  return this._isMapMode;
234
311
  }
235
312
 
236
313
  protected _isDuplicate = false;
237
314
 
315
+ /**
316
+ * Gets whether the tree allows duplicate keys.
317
+ * @remarks Time O(1)
318
+ *
319
+ * @returns True if duplicates are allowed, false otherwise.
320
+ */
238
321
  get isDuplicate() {
239
322
  return this._isDuplicate;
240
323
  }
241
324
 
242
325
  protected _store = new Map<K, V | undefined>();
243
326
 
327
+ /**
328
+ * Gets the external value store (used in Map mode).
329
+ * @remarks Time O(1)
330
+ *
331
+ * @returns The map storing key-value pairs.
332
+ */
244
333
  get store() {
245
334
  return this._store;
246
335
  }
247
336
 
248
337
  protected _root?: BinaryTreeNode<K, V> | null | undefined;
249
338
 
339
+ /**
340
+ * Gets the root node of the tree.
341
+ * @remarks Time O(1)
342
+ *
343
+ * @returns The root node.
344
+ */
250
345
  get root(): BinaryTreeNode<K, V> | null | undefined {
251
346
  return this._root;
252
347
  }
253
348
 
254
349
  protected _size: number = 0;
255
350
 
351
+ /**
352
+ * Gets the number of nodes in the tree.
353
+ * @remarks Time O(1)
354
+ *
355
+ * @returns The size of the tree.
356
+ */
256
357
  get size(): number {
257
358
  return this._size;
258
359
  }
259
360
 
260
361
  protected _NIL: BinaryTreeNode<K, V> = new BinaryTreeNode<K, V>(NaN as K) as unknown as BinaryTreeNode<K, V>;
261
362
 
363
+ /**
364
+ * Gets the sentinel NIL node (used in self-balancing trees like Red-Black Tree).
365
+ * @remarks Time O(1)
366
+ *
367
+ * @returns The NIL node.
368
+ */
262
369
  get NIL(): BinaryTreeNode<K, V> {
263
370
  return this._NIL;
264
371
  }
265
372
 
266
373
  protected _toEntryFn?: ToEntryFn<K, V, R>;
267
374
 
375
+ /**
376
+ * Gets the function used to convert raw data objects (R) into [key, value] entries.
377
+ * @remarks Time O(1)
378
+ *
379
+ * @returns The conversion function.
380
+ */
268
381
  get toEntryFn() {
269
382
  return this._toEntryFn;
270
383
  }
271
384
 
272
385
  /**
273
- * Time Complexity: O(1)
274
- * Space Complexity: O(1)
386
+ * (Protected) Creates a new node.
387
+ * @remarks Time O(1), Space O(1)
275
388
  *
276
- * The function creates a new binary tree node with a specified key and optional value.
277
- * @param {K} key - The `key` parameter is the key of the node being created in the binary tree.
278
- * @param {V} [value] - The `value` parameter in the `createNode` function is optional, meaning it is
279
- * not required to be provided when calling the function. If a `value` is provided, it should be of
280
- * type `V`, which is the type of the value associated with the node.
281
- * @returns A new BinaryTreeNode instance with the provided key and value is being returned, casted
282
- * as BinaryTreeNode<K, V>.
389
+ * @param key - The key for the new node.
390
+ * @param [value] - The value for the new node (used if not in Map mode).
391
+ * @returns The newly created node.
283
392
  */
284
- createNode(key: K, value?: V): BinaryTreeNode<K, V> {
393
+ _createNode(key: K, value?: V): BinaryTreeNode<K, V> {
285
394
  return new BinaryTreeNode<K, V>(key, this._isMapMode ? undefined : value);
286
395
  }
287
396
 
288
397
  /**
289
- * Time Complexity: O(1)
290
- * Space Complexity: O(1)
398
+ * Creates a new, empty tree of the same type and configuration.
399
+ * @remarks Time O(1) (excluding options cloning), Space O(1)
291
400
  *
292
- * The function creates a binary tree with the specified options.
293
- * @param [options] - The `options` parameter in the `createTree` function is an optional parameter
294
- * that allows you to provide partial configuration options for creating a binary tree. It is of type
295
- * `Partial<BinaryTreeOptions<K, V, R>>`, which means you can pass in an object containing a subset
296
- * of properties
297
- * @returns A new instance of a binary tree with the specified options is being returned.
401
+ * @param [options] - Optional overrides for the new tree's options.
402
+ * @returns A new, empty tree instance.
298
403
  */
299
- createTree(options?: BinaryTreeOptions<K, V, R>) {
300
- return new BinaryTree<K, V, R, MK, MV, MR>([], {
301
- iterationType: this.iterationType,
302
- isMapMode: this._isMapMode,
303
- toEntryFn: this._toEntryFn,
304
- ...options
305
- });
404
+ createTree(options?: Partial<BinaryTreeOptions<K, V, R>>): this {
405
+ return this._createInstance<K, V, R>(options);
306
406
  }
307
407
 
308
408
  /**
309
- * Time Complexity: O(n)
310
- * Space Complexity: O(log n)
409
+ * Ensures the input is a node. If it's a key or entry, it searches for the node.
410
+ * @remarks Time O(1) if a node is passed. O(N) if a key or entry is passed (due to `getNode` performing a full search). Space O(1) if iterative search, O(H) if recursive (where H is height, O(N) worst-case).
311
411
  *
312
- * The function `ensureNode` in TypeScript checks if a given input is a node, entry, key, or raw
313
- * value and returns the corresponding node or null.
314
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `keyNodeOrEntry`
315
- * parameter in the `ensureNode` function can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. It
316
- * is used to determine whether the input is a key, node, entry, or raw data. The
317
- * @param {IterationType} iterationType - The `iterationType` parameter in the `ensureNode` function
318
- * is used to specify the type of iteration to be performed. It has a default value of
319
- * `this.iterationType` if not explicitly provided.
320
- * @returns The `ensureNode` function returns either a node, `null`, or `undefined` based on the
321
- * conditions specified in the code snippet.
412
+ * @param keyNodeOrEntry - The item to resolve to a node.
413
+ * @param [iterationType=this.iterationType] - The traversal method to use if searching.
414
+ * @returns The resolved node, or null/undefined if not found or input is null/undefined.
322
415
  */
323
416
  ensureNode(
324
417
  keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
@@ -341,18 +434,11 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
341
434
  }
342
435
 
343
436
  /**
344
- * Time Complexity: O(1)
345
- * Space Complexity: O(1)
437
+ * Checks if the given item is a `BinaryTreeNode` instance.
438
+ * @remarks Time O(1), Space O(1)
346
439
  *
347
- * The function isNode checks if the input is an instance of BinaryTreeNode.
348
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter
349
- * `keyNodeOrEntry` can be either a key, a node, an entry, or raw data. The function is
350
- * checking if the input is an instance of a `BinaryTreeNode` and returning a boolean value
351
- * accordingly.
352
- * @returns The function `isNode` is checking if the input `keyNodeOrEntry` is an instance of
353
- * `BinaryTreeNode`. If it is, the function returns `true`, indicating that the input is a node. If
354
- * it is not an instance of `BinaryTreeNode`, the function returns `false`, indicating that the input
355
- * is not a node.
440
+ * @param keyNodeOrEntry - The item to check.
441
+ * @returns True if it's a node, false otherwise.
356
442
  */
357
443
  isNode(
358
444
  keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
@@ -361,14 +447,11 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
361
447
  }
362
448
 
363
449
  /**
364
- * Time Complexity: O(1)
365
- * Space Complexity: O(1)
450
+ * Checks if the given item is a raw data object (R) that needs conversion via `toEntryFn`.
451
+ * @remarks Time O(1), Space O(1)
366
452
  *
367
- * The function `isRaw` checks if the input parameter is of type `R` by verifying if it is an object.
368
- * @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
369
- * @returns The function `isRaw` is checking if the `keyNodeEntryOrRaw` parameter is of type `R` by
370
- * checking if it is an object. If the parameter is an object, the function will return `true`,
371
- * indicating that it is of type `R`.
453
+ * @param keyNodeEntryOrRaw - The item to check.
454
+ * @returns True if it's a raw object, false otherwise.
372
455
  */
373
456
  isRaw(
374
457
  keyNodeEntryOrRaw: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R
@@ -377,17 +460,11 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
377
460
  }
378
461
 
379
462
  /**
380
- * Time Complexity: O(1)
381
- * Space Complexity: O(1)
463
+ * Checks if the given item is a "real" node (i.e., not null, undefined, or NIL).
464
+ * @remarks Time O(1), Space O(1)
382
465
  *
383
- * The function `isRealNode` checks if a given input is a valid node in a binary tree.
384
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `keyNodeOrEntry`
385
- * parameter in the `isRealNode` function can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`.
386
- * The function checks if the input parameter is a `BinaryTreeNode<K, V>` type by verifying if it is not equal
387
- * @returns The function `isRealNode` is checking if the input `keyNodeOrEntry` is a valid
388
- * node by comparing it to `this._NIL`, `null`, and `undefined`. If the input is not one of these
389
- * values, it then calls the `isNode` method to further determine if the input is a node. The
390
- * function will return a boolean value indicating whether the
466
+ * @param keyNodeOrEntry - The item to check.
467
+ * @returns True if it's a real node, false otherwise.
391
468
  */
392
469
  isRealNode(
393
470
  keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
@@ -397,16 +474,11 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
397
474
  }
398
475
 
399
476
  /**
400
- * Time Complexity: O(1)
401
- * Space Complexity: O(1)
477
+ * Checks if the given item is either a "real" node or null.
478
+ * @remarks Time O(1), Space O(1)
402
479
  *
403
- * The function checks if a given input is a valid node or null.
404
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter
405
- * `keyNodeOrEntry` in the `isRealNodeOrNull` function can be of type `BTNRep<K,
406
- * V, BinaryTreeNode<K, V>>` or `R`. It is a union type that can either be a key, a node, an entry, or
407
- * @returns The function `isRealNodeOrNull` is returning a boolean value. It checks if the input
408
- * `keyNodeOrEntry` is either `null` or a real node, and returns `true` if it is a node or
409
- * `null`, and `false` otherwise.
480
+ * @param keyNodeOrEntry - The item to check.
481
+ * @returns True if it's a real node or null, false otherwise.
410
482
  */
411
483
  isRealNodeOrNull(
412
484
  keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
@@ -415,32 +487,22 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
415
487
  }
416
488
 
417
489
  /**
418
- * Time Complexity: O(1)
419
- * Space Complexity: O(1)
490
+ * Checks if the given item is the sentinel NIL node.
491
+ * @remarks Time O(1), Space O(1)
420
492
  *
421
- * The function isNIL checks if a given key, node, entry, or raw value is equal to the _NIL value.
422
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - BTNRep<K, V,
423
- * BinaryTreeNode<K, V>>
424
- * @returns The function is checking if the `keyNodeOrEntry` parameter is equal to the `_NIL`
425
- * property of the current object and returning a boolean value based on that comparison.
493
+ * @param keyNodeOrEntry - The item to check.
494
+ * @returns True if it's the NIL node, false otherwise.
426
495
  */
427
496
  isNIL(keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined): boolean {
428
497
  return keyNodeOrEntry === this._NIL;
429
498
  }
430
499
 
431
500
  /**
432
- * Time Complexity: O(1)
433
- * Space Complexity: O(1)
501
+ * Checks if the given item is a `Range` object.
502
+ * @remarks Time O(1), Space O(1)
434
503
  *
435
- * The function `isRange` checks if the input parameter is an instance of the `Range` class.
436
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>> | Range<K>} keyNodeEntryOrPredicate
437
- * - The `keyNodeEntryOrPredicate` parameter in the `isRange` function can be
438
- * of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `, `NodePredicate<BinaryTreeNode<K, V>>`, or
439
- * `Range<K>`. The function checks if the `keyNodeEntry
440
- * @returns The `isRange` function is checking if the `keyNodeEntryOrPredicate` parameter is an
441
- * instance of the `Range` class. If it is an instance of `Range`, the function will return `true`,
442
- * indicating that the parameter is a `Range<K>`. If it is not an instance of `Range`, the function
443
- * will return `false`.
504
+ * @param keyNodeEntryOrPredicate - The item to check.
505
+ * @returns True if it's a Range, false otherwise.
444
506
  */
445
507
  isRange(
446
508
  keyNodeEntryOrPredicate:
@@ -456,37 +518,25 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
456
518
  }
457
519
 
458
520
  /**
459
- * Time Complexity: O(1)
460
- * Space Complexity: O(1)
521
+ * Checks if a node is a leaf (has no real children).
522
+ * @remarks Time O(N) if a key/entry is passed (due to `ensureNode`). O(1) if a node is passed. Space O(1) or O(H) (from `ensureNode`).
461
523
  *
462
- * The function determines whether a given key, node, entry, or raw data is a leaf node in a binary
463
- * tree.
464
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter
465
- * `keyNodeOrEntry` can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. It represents a
466
- * key, node, entry, or raw data in a binary tree structure. The function `isLeaf` checks whether the
467
- * provided
468
- * @returns The function `isLeaf` returns a boolean value indicating whether the input
469
- * `keyNodeOrEntry` is a leaf node in a binary tree.
524
+ * @param keyNodeOrEntry - The node to check.
525
+ * @returns True if the node is a leaf, false otherwise.
470
526
  */
471
527
  isLeaf(keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined): boolean {
472
528
  keyNodeOrEntry = this.ensureNode(keyNodeOrEntry);
473
529
  if (keyNodeOrEntry === undefined) return false;
474
- if (keyNodeOrEntry === null) return true;
530
+ if (keyNodeOrEntry === null) return true; // A null spot is considered a leaf
475
531
  return !this.isRealNode(keyNodeOrEntry.left) && !this.isRealNode(keyNodeOrEntry.right);
476
532
  }
477
533
 
478
534
  /**
479
- * Time Complexity: O(1)
480
- * Space Complexity: O(1)
535
+ * Checks if the given item is a [key, value] entry pair.
536
+ * @remarks Time O(1), Space O(1)
481
537
  *
482
- * The function `isEntry` checks if the input is a BTNEntry object by verifying if it is an array
483
- * with a length of 2.
484
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `keyNodeOrEntry`
485
- * parameter in the `isEntry` function can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or type `R`.
486
- * The function checks if the provided `keyNodeOrEntry` is of type `BTN
487
- * @returns The `isEntry` function is checking if the `keyNodeOrEntry` parameter is an array
488
- * with a length of 2. If it is, then it returns `true`, indicating that the parameter is of type
489
- * `BTNEntry<K, V>`. If the condition is not met, it returns `false`.
538
+ * @param keyNodeOrEntry - The item to check.
539
+ * @returns True if it's an entry, false otherwise.
490
540
  */
491
541
  isEntry(
492
542
  keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
@@ -495,15 +545,11 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
495
545
  }
496
546
 
497
547
  /**
498
- * Time Complexity O(1)
499
- * Space Complexity O(1)
548
+ * Checks if the given key is valid (comparable or null).
549
+ * @remarks Time O(1), Space O(1)
500
550
  *
501
- * The function `isValidKey` checks if a given key is comparable.
502
- * @param {any} key - The `key` parameter is of type `any`, which means it can be any data type in
503
- * TypeScript.
504
- * @returns The function `isValidKey` is checking if the `key` parameter is `null` or if it is comparable.
505
- * If the `key` is `null`, the function returns `true`. Otherwise, it returns the result of the
506
- * `isComparable` function, which is not provided in the code snippet.
551
+ * @param key - The key to validate.
552
+ * @returns True if the key is valid, false otherwise.
507
553
  */
508
554
  isValidKey(key: any): key is K {
509
555
  if (key === null) return true;
@@ -511,21 +557,12 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
511
557
  }
512
558
 
513
559
  /**
514
- * Time Complexity O(n)
515
- * Space Complexity O(1)
560
+ * Adds a new node to the tree.
561
+ * @remarks Time O(log N), For BST, Red-Black Tree, and AVL Tree subclasses, the worst-case time is O(log N). This implementation adds the node at the first available position in a level-order (BFS) traversal. This is NOT a Binary Search Tree insertion. Time O(N), where N is the number of nodes. It must traverse level-by-level to find an empty slot. Space O(N) in the worst case for the BFS queue (e.g., a full last level).
516
562
  *
517
- * The `add` function in TypeScript adds a new node to a binary tree while handling duplicate keys
518
- * and finding the correct insertion position.
519
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `add` method you provided
520
- * seems to be for adding a new node to a binary tree structure. The `keyNodeOrEntry`
521
- * parameter in the method can accept different types of values:
522
- * @param {V} [value] - The `value` parameter in the `add` method represents the value associated
523
- * with the key that you want to add to the binary tree. When adding a key-value pair to the binary
524
- * tree, you provide the key and its corresponding value. The `add` method then creates a new node
525
- * with this
526
- * @returns The `add` method returns a boolean value. It returns `true` if the insertion of the new
527
- * node was successful, and `false` if the insertion position could not be found or if a duplicate
528
- * key was found and the node was replaced instead of inserted.
563
+ * @param keyNodeOrEntry - The key, node, or entry to add.
564
+ * @param [value] - The value, if providing just a key.
565
+ * @returns True if the addition was successful, false otherwise.
529
566
  */
530
567
  add(
531
568
  keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
@@ -534,7 +571,6 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
534
571
  const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
535
572
  if (newNode === undefined) return false;
536
573
 
537
- // If the tree is empty, directly set the new node as the root node
538
574
  if (!this._root) {
539
575
  this._setRoot(newNode);
540
576
  if (this._isMapMode) this._setValue(newNode?.key, newValue);
@@ -543,28 +579,24 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
543
579
  }
544
580
 
545
581
  const queue = new Queue<BinaryTreeNode<K, V>>([this._root]);
546
- let potentialParent: BinaryTreeNode<K, V> | undefined; // Record the parent node of the potential insertion location
547
-
582
+ let potentialParent: BinaryTreeNode<K, V> | undefined;
548
583
  while (queue.length > 0) {
549
584
  const cur = queue.shift();
550
585
 
551
586
  if (!cur) continue;
552
587
 
553
588
  if (!this._isDuplicate) {
554
- // Check for duplicate keys when newNode is not null
555
589
  if (newNode !== null && cur.key === newNode.key) {
556
590
  this._replaceNode(cur, newNode);
557
591
  if (this._isMapMode) this._setValue(cur.key, newValue);
558
- return true; // If duplicate keys are found, no insertion is performed
592
+ return true; // Replaced existing node
559
593
  }
560
594
  }
561
595
 
562
- // Record the first possible insertion location found
563
596
  if (potentialParent === undefined && (cur.left === undefined || cur.right === undefined)) {
564
597
  potentialParent = cur;
565
598
  }
566
599
 
567
- // Continue traversing the left and right subtrees
568
600
  if (cur.left !== null) {
569
601
  if (cur.left) queue.push(cur.left);
570
602
  }
@@ -573,7 +605,6 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
573
605
  }
574
606
  }
575
607
 
576
- // At the end of the traversal, if the insertion position is found, insert
577
608
  if (potentialParent) {
578
609
  if (potentialParent.left === undefined) {
579
610
  potentialParent.left = newNode;
@@ -585,26 +616,16 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
585
616
  return true;
586
617
  }
587
618
 
588
- return false; // If the insertion position cannot be found, return undefined
619
+ return false; // Should not happen if tree is not full?
589
620
  }
590
621
 
591
622
  /**
592
- * Time Complexity: O(k * n)
593
- * Space Complexity: O(k)
623
+ * Adds multiple items to the tree.
624
+ * @remarks Time O(N * M), where N is the number of items to add and M is the size of the tree at insertion (due to O(M) `add` operation). Space O(M) (from `add`) + O(N) (for the `inserted` array).
594
625
  *
595
- * The `addMany` function takes in multiple keys or nodes or entries or raw values along with
596
- * optional values, and adds them to a data structure while returning an array indicating whether
597
- * each insertion was successful.
598
- * @param keysNodesEntriesOrRaws - `keysNodesEntriesOrRaws` is an iterable that can contain a
599
- * mix of keys, nodes, entries, or raw values. Each element in this iterable can be of type
600
- * `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`.
601
- * @param [values] - The `values` parameter in the `addMany` function is an optional parameter that
602
- * accepts an iterable of values. These values correspond to the keys or nodes being added in the
603
- * `keysNodesEntriesOrRaws` parameter. If provided, the function will iterate over the values and
604
- * assign them
605
- * @returns The `addMany` method returns an array of boolean values indicating whether each key,
606
- * node, entry, or raw value was successfully added to the data structure. Each boolean value
607
- * corresponds to the success of adding the corresponding key or value in the input iterable.
626
+ * @param keysNodesEntriesOrRaws - An iterable of items to add.
627
+ * @param [values] - An optional parallel iterable of values.
628
+ * @returns An array of booleans indicating the success of each individual `add` operation.
608
629
  */
609
630
  addMany(
610
631
  keysNodesEntriesOrRaws: Iterable<
@@ -612,7 +633,6 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
612
633
  >,
613
634
  values?: Iterable<V | undefined>
614
635
  ): boolean[] {
615
- // TODO not sure addMany not be run multi times
616
636
  const inserted: boolean[] = [];
617
637
 
618
638
  let valuesIterator: Iterator<V | undefined> | undefined;
@@ -637,28 +657,21 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
637
657
  }
638
658
 
639
659
  /**
640
- * Time Complexity: O(k * n)
641
- * Space Complexity: O(1)
660
+ * Merges another tree into this one by adding all its nodes.
661
+ * @remarks Time O(N * M), same as `addMany`, where N is the size of `anotherTree` and M is the size of this tree. Space O(M) (from `add`).
642
662
  *
643
- * The `merge` function in TypeScript merges another binary tree into the current tree by adding all
644
- * elements from the other tree.
645
- * @param anotherTree - BinaryTree<K, V, R, MK, MV, MR>
663
+ * @param anotherTree - The tree to merge.
646
664
  */
647
- merge(anotherTree: BinaryTree<K, V, R, MK, MV, MR>) {
665
+ merge(anotherTree: BinaryTree<K, V, R>) {
648
666
  this.addMany(anotherTree, []);
649
667
  }
650
668
 
651
669
  /**
652
- * Time Complexity: O(k * n)
653
- * Space Complexity: O(1)
670
+ * Clears the tree and refills it with new items.
671
+ * @remarks Time O(N) (for `clear`) + O(N * M) (for `addMany`) = O(N * M). Space O(M) (from `addMany`).
654
672
  *
655
- * The `refill` function clears the existing data structure and then adds new key-value pairs based
656
- * on the provided input.
657
- * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the `refill`
658
- * method can accept an iterable containing a mix of `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` objects or `R`
659
- * objects.
660
- * @param [values] - The `values` parameter in the `refill` method is an optional parameter that
661
- * accepts an iterable of values of type `V` or `undefined`.
673
+ * @param keysNodesEntriesOrRaws - An iterable of items to add.
674
+ * @param [values] - An optional parallel iterable of values.
662
675
  */
663
676
  refill(
664
677
  keysNodesEntriesOrRaws: Iterable<
@@ -671,19 +684,11 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
671
684
  }
672
685
 
673
686
  /**
674
- * Time Complexity: O(n)
675
- * Space Complexity: O(1)
687
+ * Deletes a node from the tree.
688
+ * @remarks Time O(log N), For BST, Red-Black Tree, and AVL Tree subclasses, the worst-case time is O(log N). This implementation finds the node, and if it has two children, swaps it with the rightmost node of its left subtree (in-order predecessor) before deleting. Time O(N) in the worst case. O(N) to find the node (`getNode`) and O(H) (which is O(N) worst-case) to find the rightmost node. Space O(1) (if `getNode` is iterative, which it is).
676
689
  *
677
- * The function `delete` in TypeScript implements the deletion of a node in a binary tree and returns
678
- * the deleted node along with information for tree balancing.
679
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry
680
- * - The `delete` method you provided is used to delete a node from a binary tree based on the key,
681
- * node, entry or raw data. The method returns an array of
682
- * `BinaryTreeDeleteResult` objects containing information about the deleted node and whether
683
- * balancing is needed.
684
- * @returns The `delete` method returns an array of `BinaryTreeDeleteResult` objects. Each object in
685
- * the array contains information about the node that was deleted (`deleted`) and the node that may
686
- * need to be balanced (`needBalanced`).
690
+ * @param keyNodeOrEntry - The node to delete.
691
+ * @returns An array containing deletion results (for compatibility with self-balancing trees).
687
692
  */
688
693
  delete(
689
694
  keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
@@ -699,13 +704,19 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
699
704
  let orgCurrent: BinaryTreeNode<K, V> | undefined = curr;
700
705
 
701
706
  if (!curr.left && !curr.right && !parent) {
707
+ // Deleting the root with no children
702
708
  this._setRoot(undefined);
703
709
  } else if (curr.left) {
710
+ // Node has a left child (or two children)
711
+ // Find the rightmost node in the left subtree
704
712
  const leftSubTreeRightMost = this.getRightMost(node => node, curr.left);
705
713
  if (leftSubTreeRightMost) {
706
714
  const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;
715
+ // Swap properties
707
716
  orgCurrent = this._swapProperties(curr, leftSubTreeRightMost);
717
+ // `orgCurrent` is now the node to be physically deleted (which was the rightmost)
708
718
  if (parentOfLeftSubTreeMax) {
719
+ // Unlink the rightmost node
709
720
  if (parentOfLeftSubTreeMax.right === leftSubTreeRightMost)
710
721
  parentOfLeftSubTreeMax.right = leftSubTreeRightMost.left;
711
722
  else parentOfLeftSubTreeMax.left = leftSubTreeRightMost.left;
@@ -713,6 +724,8 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
713
724
  }
714
725
  }
715
726
  } else if (parent) {
727
+ // Node has no left child, but has a parent
728
+ // Promote the right child (which could be null)
716
729
  const { familyPosition: fp } = curr;
717
730
  if (fp === 'LEFT' || fp === 'ROOT_LEFT') {
718
731
  parent.left = curr.right;
@@ -721,6 +734,8 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
721
734
  }
722
735
  needBalanced = parent;
723
736
  } else {
737
+ // Deleting the root, which has no left child
738
+ // Promote the right child as the new root
724
739
  this._setRoot(curr.right);
725
740
  curr.right = undefined;
726
741
  }
@@ -733,28 +748,16 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
733
748
  }
734
749
 
735
750
  /**
736
- * Time Complexity: O(n)
737
- * Space Complexity: O(k + log n)
738
- *
739
- * The `search` function in TypeScript performs a depth-first or breadth-first search on a tree
740
- * structure based on a given predicate or key, with options to return multiple results or just one.
741
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate - The
742
- * `keyNodeEntryOrPredicate` parameter in the `search` function can accept three types of values:
743
- * @param [onlyOne=false] - The `onlyOne` parameter in the `search` function is a boolean flag that
744
- * determines whether the search should stop after finding the first matching node. If `onlyOne` is
745
- * set to `true`, the search will return as soon as a matching node is found. If `onlyOne` is
746
- * @param {C} callback - The `callback` parameter in the `search` function is a callback function
747
- * that will be called on each node that matches the search criteria. It is of type `C`, which
748
- * extends `NodeCallback<BinaryTreeNode<K, V> | null>`. The default value for `callback` is `this._DEFAULT_NODE_CALLBACK` if
749
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `search` function is
750
- * used to specify the node from which the search operation should begin. It represents the starting
751
- * point in the binary tree where the search will be performed. If no specific `startNode` is
752
- * provided, the search operation will start from the root
753
- * @param {IterationType} iterationType - The `iterationType` parameter in the `search` function
754
- * specifies the type of iteration to be used when searching for nodes in a binary tree. It can have
755
- * two possible values:
756
- * @returns The `search` function returns an array of values that match the provided criteria based
757
- * on the search algorithm implemented within the function.
751
+ * Searches the tree for nodes matching a predicate.
752
+ * @remarks Time O(log N), For BST, Red-Black Tree, and AVL Tree subclasses, the worst-case time is O(log N). Performs a full DFS (pre-order) scan of the tree. Time O(N), as it may visit every node. Space O(H) for the call stack (recursive) or explicit stack (iterative), where H is the tree height (O(N) worst-case).
753
+ *
754
+ * @template C - The type of the callback function.
755
+ * @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for.
756
+ * @param [onlyOne=false] - If true, stops after finding the first match.
757
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - A function to call on matching nodes.
758
+ * @param [startNode=this._root] - The node to start the search from.
759
+ * @param [iterationType=this.iterationType] - Whether to use 'RECURSIVE' or 'ITERATIVE' search.
760
+ * @returns An array of results from the callback function for each matching node.
758
761
  */
759
762
  search<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
760
763
  keyNodeEntryOrPredicate:
@@ -791,6 +794,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
791
794
  dfs(startNode);
792
795
  } else {
793
796
  const stack = [startNode];
797
+
794
798
  while (stack.length > 0) {
795
799
  const cur = stack.pop();
796
800
  if (this.isRealNode(cur)) {
@@ -807,6 +811,16 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
807
811
  return ans;
808
812
  }
809
813
 
814
+ /**
815
+ * Gets all nodes matching a predicate.
816
+ * @remarks Time O(N) (via `search`). Space O(H) or O(N) (via `search`).
817
+ *
818
+ * @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for.
819
+ * @param [onlyOne=false] - If true, stops after finding the first match.
820
+ * @param [startNode=this._root] - The node to start the search from.
821
+ * @param [iterationType=this.iterationType] - The traversal method.
822
+ * @returns An array of matching nodes.
823
+ */
810
824
  getNodes(
811
825
  keyNodeEntryOrPredicate:
812
826
  | K
@@ -820,27 +834,6 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
820
834
  iterationType?: IterationType
821
835
  ): BinaryTreeNode<K, V>[];
822
836
 
823
- /**
824
- * Time Complexity: O(n)
825
- * Space Complexity: O(k + log n)
826
- *
827
- * The function `getNodes` retrieves nodes from a binary tree based on a key, node, entry, raw data,
828
- * or predicate, with options for recursive or iterative traversal.
829
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate
830
- * - The `getNodes` function you provided takes several parameters:
831
- * @param [onlyOne=false] - The `onlyOne` parameter in the `getNodes` function is a boolean flag that
832
- * determines whether to return only the first node that matches the criteria specified by the
833
- * `keyNodeEntryOrPredicate` parameter. If `onlyOne` is set to `true`, the function will
834
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
835
- * `getNodes` function is used to specify the starting point for traversing the binary tree. It
836
- * represents the root node of the binary tree or the node from which the traversal should begin. If
837
- * not provided, the default value is set to `this._root
838
- * @param {IterationType} iterationType - The `iterationType` parameter in the `getNodes` function
839
- * determines the type of iteration to be performed when traversing the nodes of a binary tree. It
840
- * can have two possible values:
841
- * @returns The `getNodes` function returns an array of nodes that satisfy the provided condition
842
- * based on the input parameters and the iteration type specified.
843
- */
844
837
  getNodes(
845
838
  keyNodeEntryOrPredicate:
846
839
  | K
@@ -857,24 +850,13 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
857
850
  }
858
851
 
859
852
  /**
860
- * Time Complexity: O(n)
861
- * Space Complexity: O(log n)
853
+ * Gets the first node matching a predicate.
854
+ * @remarks Time O(log N), For BST, Red-Black Tree, and AVL Tree subclasses, the worst-case time is O(log N). Time O(N) in the worst case (via `search`). Space O(H) or O(N) (via `search`).
862
855
  *
863
- * The `getNode` function retrieves a node based on the provided key, node, entry, raw data, or
864
- * predicate.
865
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate
866
- * - The `keyNodeEntryOrPredicate` parameter in the `getNode` function can accept a key,
867
- * node, entry, raw data, or a predicate function.
868
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
869
- * `getNode` function is used to specify the starting point for searching for a node in a binary
870
- * tree. If no specific starting point is provided, the default value is set to `this._root`, which
871
- * is typically the root node of the binary tree.
872
- * @param {IterationType} iterationType - The `iterationType` parameter in the `getNode` method is
873
- * used to specify the type of iteration to be performed when searching for a node. It has a default
874
- * value of `this.iterationType`, which means it will use the iteration type defined in the current
875
- * context if no specific value is provided
876
- * @returns The `getNode` function is returning the first node that matches the specified criteria,
877
- * or `null` if no matching node is found.
856
+ * @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for.
857
+ * @param [startNode=this._root] - The node to start the search from.
858
+ * @param [iterationType=this.iterationType] - The traversal method.
859
+ * @returns The first matching node, or undefined if not found.
878
860
  */
879
861
  getNode(
880
862
  keyNodeEntryOrPredicate:
@@ -891,26 +873,13 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
891
873
  }
892
874
 
893
875
  /**
894
- * Time Complexity: O(n)
895
- * Space Complexity: O(log n)
896
- *
897
- * This function overrides the `get` method to retrieve the value associated with a specified key,
898
- * node, entry, raw data, or predicate in a data structure.
899
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate
900
- * - The `keyNodeEntryOrPredicate` parameter in the `get` method can accept one of the
901
- * following types:
902
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `get`
903
- * method is used to specify the starting point for searching for a key or node in the binary tree.
904
- * If no specific starting point is provided, the default starting point is the root of the binary
905
- * tree (`this._root`).
906
- * @param {IterationType} iterationType - The `iterationType` parameter in the `get` method is used
907
- * to specify the type of iteration to be performed when searching for a key in the binary tree. It
908
- * is an optional parameter with a default value of `this.iterationType`, which means it will use the
909
- * iteration type defined in the
910
- * @returns The `get` method is returning the value associated with the specified key, node, entry,
911
- * raw data, or predicate in the binary tree map. If the specified key or node is found in the tree,
912
- * the method returns the corresponding value. If the key or node is not found, it returns
913
- * `undefined`.
876
+ * Gets the value associated with a key.
877
+ * @remarks Time O(log N), For BST, Red-Black Tree, and AVL Tree subclasses, the worst-case time is O(log N). Time O(1) if in Map mode. O(N) if not in Map mode (uses `getNode`). Space O(1) if in Map mode. O(H) or O(N) otherwise.
878
+ *
879
+ * @param keyNodeEntryOrPredicate - The key, node, or entry to get the value for.
880
+ * @param [startNode=this._root] - The node to start searching from (if not in Map mode).
881
+ * @param [iterationType=this.iterationType] - The traversal method (if not in Map mode).
882
+ * @returns The associated value, or undefined.
914
883
  */
915
884
  override get(
916
885
  keyNodeEntryOrPredicate: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
@@ -925,6 +894,15 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
925
894
  return this.getNode(keyNodeEntryOrPredicate, startNode, iterationType)?.value;
926
895
  }
927
896
 
897
+ /**
898
+ * Checks if a node matching the predicate exists in the tree.
899
+ * @remarks Time O(log N), For BST, Red-Black Tree, and AVL Tree subclasses, the worst-case time is O(log N). Time O(N) in the worst case (via `search`). Space O(H) or O(N) (via `search`).
900
+ *
901
+ * @param [keyNodeEntryOrPredicate] - The key, node, entry, or predicate to check for.
902
+ * @param [startNode] - The node to start the search from.
903
+ * @param [iterationType] - The traversal method.
904
+ * @returns True if a matching node exists, false otherwise.
905
+ */
928
906
  override has(
929
907
  keyNodeEntryOrPredicate?:
930
908
  | K
@@ -937,27 +915,6 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
937
915
  iterationType?: IterationType
938
916
  ): boolean;
939
917
 
940
- /**
941
- * Time Complexity: O(n)
942
- * Space Complexity: O(log n)
943
- *
944
- * The `has` function in TypeScript checks if a specified key, node, entry, raw data, or predicate
945
- * exists in the data structure.
946
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate
947
- * - The `keyNodeEntryOrPredicate` parameter in the `override has` method can accept one of
948
- * the following types:
949
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
950
- * `override` method is used to specify the starting point for the search operation within the data
951
- * structure. It defaults to `this._root` if not provided explicitly.
952
- * @param {IterationType} iterationType - The `iterationType` parameter in the `override has` method
953
- * is used to specify the type of iteration to be performed. It has a default value of
954
- * `this.iterationType`, which means it will use the iteration type defined in the current context if
955
- * no value is provided when calling the method.
956
- * @returns The `override has` method is returning a boolean value. It checks if there are any nodes
957
- * that match the provided key, node, entry, raw data, or predicate in the tree structure. If there
958
- * are matching nodes, it returns `true`, indicating that the tree contains the specified element.
959
- * Otherwise, it returns `false`.
960
- */
961
918
  override has(
962
919
  keyNodeEntryOrPredicate:
963
920
  | K
@@ -973,10 +930,8 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
973
930
  }
974
931
 
975
932
  /**
976
- * Time Complexity: O(1)
977
- * Space Complexity: O(1)
978
- *
979
- * The clear function removes nodes and values in map mode.
933
+ * Clears the tree of all nodes and values.
934
+ * @remarks Time O(N) if in Map mode (due to `_store.clear()`), O(1) otherwise. Space O(1)
980
935
  */
981
936
  clear() {
982
937
  this._clearNodes();
@@ -984,32 +939,21 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
984
939
  }
985
940
 
986
941
  /**
987
- * Time Complexity: O(1)
988
- * Space Complexity: O(1)
942
+ * Checks if the tree is empty.
943
+ * @remarks Time O(1), Space O(1)
989
944
  *
990
- * The `isEmpty` function in TypeScript checks if a data structure has no elements and returns a
991
- * boolean value.
992
- * @returns The `isEmpty()` method is returning a boolean value, specifically `true` if the `_size`
993
- * property is equal to 0, indicating that the data structure is empty, and `false` otherwise.
945
+ * @returns True if the tree has no nodes, false otherwise.
994
946
  */
995
947
  isEmpty(): boolean {
996
948
  return this._size === 0;
997
949
  }
998
950
 
999
951
  /**
1000
- * Time Complexity: O(n)
1001
- * Space Complexity: O(log n)
952
+ * Checks if the tree is perfectly balanced.
953
+ * @remarks A tree is perfectly balanced if the difference between min and max height is at most 1. Time O(N), as it requires two full traversals (`getMinHeight` and `getHeight`). Space O(H) or O(N) (from height calculation).
1002
954
  *
1003
- * The function checks if a binary tree is perfectly balanced by comparing its minimum height with
1004
- * its height.
1005
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter is the starting
1006
- * point for checking if the binary tree is perfectly balanced. It represents the root node of the
1007
- * binary tree or a specific node from which the balance check should begin.
1008
- * @returns The method `isPerfectlyBalanced` is returning a boolean value, which indicates whether
1009
- * the tree starting from the `startNode` node is perfectly balanced or not. The return value is
1010
- * determined by comparing the minimum height of the tree with the height of the tree. If the minimum
1011
- * height plus 1 is greater than or equal to the height of the tree, then it is considered perfectly
1012
- * balanced and
955
+ * @param [startNode=this._root] - The node to start checking from.
956
+ * @returns True if perfectly balanced, false otherwise.
1013
957
  */
1014
958
  isPerfectlyBalanced(
1015
959
  startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root
@@ -1018,30 +962,19 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1018
962
  }
1019
963
 
1020
964
  /**
1021
- * Time Complexity: O(n)
1022
- * Space Complexity: O(log n)
965
+ * Checks if the tree is a valid Binary Search Tree (BST).
966
+ * @remarks Time O(N), as it must visit every node. Space O(H) for the call stack (recursive) or explicit stack (iterative), where H is the tree height (O(N) worst-case).
1023
967
  *
1024
- * The function `isBST` in TypeScript checks if a binary search tree is valid using either recursive
1025
- * or iterative methods.
1026
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `isBST`
1027
- * function represents the starting point for checking whether a binary search tree (BST) is valid.
1028
- * It can be a node in the BST or a reference to the root of the BST. If no specific node is
1029
- * provided, the function will default to
1030
- * @param {IterationType} iterationType - The `iterationType` parameter in the `isBST` function
1031
- * determines whether the function should use a recursive approach or an iterative approach to check
1032
- * if the binary search tree (BST) is valid.
1033
- * @returns The `isBST` method is returning a boolean value, which indicates whether the binary
1034
- * search tree (BST) represented by the given root node is a valid BST or not. The method checks if
1035
- * the tree satisfies the BST property, where for every node, all nodes in its left subtree have keys
1036
- * less than the node's key, and all nodes in its right subtree have keys greater than the node's
968
+ * @param [startNode=this._root] - The node to start checking from.
969
+ * @param [iterationType=this.iterationType] - The traversal method.
970
+ * @returns True if it's a valid BST, false otherwise.
1037
971
  */
1038
972
  isBST(
1039
973
  startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
1040
974
  iterationType: IterationType = this.iterationType
1041
975
  ): boolean {
1042
- // TODO there is a bug
1043
- startNode = this.ensureNode(startNode);
1044
- if (!startNode) return true;
976
+ const startNodeSired = this.ensureNode(startNode);
977
+ if (!startNodeSired) return true;
1045
978
 
1046
979
  if (iterationType === 'RECURSIVE') {
1047
980
  const dfs = (cur: BinaryTreeNode<K, V> | null | undefined, min: number, max: number): boolean => {
@@ -1051,15 +984,15 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1051
984
  return dfs(cur.left, min, numKey) && dfs(cur.right, numKey, max);
1052
985
  };
1053
986
 
1054
- const isStandardBST = dfs(startNode, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);
1055
- const isInverseBST = dfs(startNode, Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER);
987
+ const isStandardBST = dfs(startNodeSired, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);
988
+ const isInverseBST = dfs(startNodeSired, Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER); // Check for reverse BST
1056
989
  return isStandardBST || isInverseBST;
1057
990
  } else {
991
+ // Iterative in-order traversal check
1058
992
  const checkBST = (checkMax = false) => {
1059
- const stack = [];
993
+ const stack: BinaryTreeNode<K, V>[] = [];
1060
994
  let prev = checkMax ? Number.MAX_SAFE_INTEGER : Number.MIN_SAFE_INTEGER;
1061
- // @ts-ignore
1062
- let curr: BinaryTreeNode<K, V> | null | undefined = startNode;
995
+ let curr: BinaryTreeNode<K, V> | null | undefined = startNodeSired;
1063
996
  while (this.isRealNode(curr) || stack.length > 0) {
1064
997
  while (this.isRealNode(curr)) {
1065
998
  stack.push(curr);
@@ -1073,27 +1006,19 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1073
1006
  }
1074
1007
  return true;
1075
1008
  };
1076
- const isStandardBST = checkBST(false),
1077
- isInverseBST = checkBST(true);
1009
+ const isStandardBST = checkBST(false);
1010
+ const isInverseBST = checkBST(true);
1078
1011
  return isStandardBST || isInverseBST;
1079
1012
  }
1080
1013
  }
1081
1014
 
1082
1015
  /**
1083
- * Time Complexity: O(n)
1084
- * Space Complexity: O(log n)
1016
+ * Gets the depth of a node (distance from `startNode`).
1017
+ * @remarks Time O(H), where H is the depth of the `dist` node relative to `startNode`. O(N) worst-case. Space O(1).
1085
1018
  *
1086
- * The `getDepth` function calculates the depth between two nodes in a binary tree.
1087
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } dist - The `dist` parameter in the `getDepth`
1088
- * function represents the node or entry in a binary tree map, or a reference to a node in the tree.
1089
- * It is the target node for which you want to calculate the depth from the `startNode` node.
1090
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
1091
- * `getDepth` function represents the starting point from which you want to calculate the depth of a
1092
- * given node or entry in a binary tree. If no specific starting point is provided, the default value
1093
- * for `startNode` is set to the root of the binary
1094
- * @returns The `getDepth` method returns the depth of a given node `dist` relative to the
1095
- * `startNode` node in a binary tree. If the `dist` node is not found in the path to the `startNode`
1096
- * node, it returns the depth of the `dist` node from the root of the tree.
1019
+ * @param dist - The node to find the depth of.
1020
+ * @param [startNode=this._root] - The node to measure depth from (defaults to root).
1021
+ * @returns The depth (0 if `dist` is `startNode`).
1097
1022
  */
1098
1023
  getDepth(
1099
1024
  dist: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
@@ -1113,21 +1038,12 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1113
1038
  }
1114
1039
 
1115
1040
  /**
1116
- * Time Complexity: O(n)
1117
- * Space Complexity: O(log n)
1041
+ * Gets the maximum height of the tree (longest path from startNode to a leaf).
1042
+ * @remarks Time O(N), as it must visit every node. Space O(H) for recursive stack (O(N) worst-case) or O(N) for iterative stack (storing node + depth).
1118
1043
  *
1119
- * The `getHeight` function calculates the maximum height of a binary tree using either a recursive
1120
- * or iterative approach in TypeScript.
1121
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter is the starting
1122
- * point from which the height of the binary tree will be calculated. It can be a node in the binary
1123
- * tree or a reference to the root of the tree. If not provided, it defaults to the root of the
1124
- * binary tree data structure.
1125
- * @param {IterationType} iterationType - The `iterationType` parameter is used to determine the type
1126
- * of iteration to be performed while calculating the height of the binary tree. It can have two
1127
- * possible values:
1128
- * @returns The `getHeight` method returns the height of the binary tree starting from the specified
1129
- * root node. The height is calculated based on the maximum depth of the tree, considering either a
1130
- * recursive approach or an iterative approach depending on the `iterationType` parameter.
1044
+ * @param [startNode=this._root] - The node to start measuring from.
1045
+ * @param [iterationType=this.iterationType] - The traversal method.
1046
+ * @returns The height ( -1 for an empty tree, 0 for a single-node tree).
1131
1047
  */
1132
1048
  getHeight(
1133
1049
  startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
@@ -1146,6 +1062,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1146
1062
 
1147
1063
  return _getMaxHeight(startNode);
1148
1064
  } else {
1065
+ // Iterative (using DFS)
1149
1066
  const stack: { node: BinaryTreeNode<K, V>; depth: number }[] = [{ node: startNode, depth: 0 }];
1150
1067
  let maxHeight = 0;
1151
1068
 
@@ -1163,22 +1080,12 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1163
1080
  }
1164
1081
 
1165
1082
  /**
1166
- * Time Complexity: O(n)
1167
- * Space Complexity: O(log n)
1083
+ * Gets the minimum height of the tree (shortest path from startNode to a leaf).
1084
+ * @remarks Time O(N), as it must visit every node. Space O(H) for recursive stack (O(N) worst-case) or O(N) for iterative (due to `depths` Map).
1168
1085
  *
1169
- * The `getMinHeight` function calculates the minimum height of a binary tree using either a
1170
- * recursive or iterative approach in TypeScript.
1171
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
1172
- * `getMinHeight` function represents the starting node from which the minimum height of the binary
1173
- * tree will be calculated. It is either a node in the binary tree or a reference to the root of the
1174
- * tree. If not provided, the default value is the root
1175
- * @param {IterationType} iterationType - The `iterationType` parameter in the `getMinHeight` method
1176
- * specifies the type of iteration to use when calculating the minimum height of a binary tree. It
1177
- * can have two possible values:
1178
- * @returns The `getMinHeight` method returns the minimum height of the binary tree starting from the
1179
- * specified root node. The height is calculated based on the shortest path from the root node to a
1180
- * leaf node in the tree. The method uses either a recursive approach or an iterative approach (using
1181
- * a stack) based on the `iterationType` parameter.
1086
+ * @param [startNode=this._root] - The node to start measuring from.
1087
+ * @param [iterationType=this.iterationType] - The traversal method.
1088
+ * @returns The minimum height (-1 for empty, 0 for single node).
1182
1089
  */
1183
1090
  getMinHeight(
1184
1091
  startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
@@ -1190,7 +1097,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1190
1097
  if (iterationType === 'RECURSIVE') {
1191
1098
  const _getMinHeight = (cur: BinaryTreeNode<K, V> | null | undefined): number => {
1192
1099
  if (!this.isRealNode(cur)) return 0;
1193
- if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return 0;
1100
+ if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return 0; // Leaf node
1194
1101
  const leftMinHeight = _getMinHeight(cur.left);
1195
1102
  const rightMinHeight = _getMinHeight(cur.right);
1196
1103
  return Math.min(leftMinHeight, rightMinHeight) + 1;
@@ -1198,6 +1105,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1198
1105
 
1199
1106
  return _getMinHeight(startNode);
1200
1107
  } else {
1108
+ // Iterative (using post-order DFS)
1201
1109
  const stack: BinaryTreeNode<K, V>[] = [];
1202
1110
  let node: BinaryTreeNode<K, V> | null | undefined = startNode,
1203
1111
  last: BinaryTreeNode<K, V> | null | undefined = null;
@@ -1227,26 +1135,16 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1227
1135
  }
1228
1136
 
1229
1137
  /**
1230
- * Time Complexity: O(log n)
1231
- * Space Complexity: O(log n)
1138
+ * Gets the path from a given node up to the root.
1139
+ * @remarks Time O(H), where H is the depth of the `beginNode`. O(N) worst-case. Space O(H) for the result array.
1232
1140
  *
1233
- * The function `getPathToRoot` in TypeScript retrieves the path from a given node to the root of a
1234
- * tree structure, applying a specified callback function along the way.
1235
- * @param {C} callback - The `callback` parameter is a function that is used to process each node in
1236
- * the path to the root. It is expected to be a function that takes a node as an argument and returns
1237
- * a value based on that node. The return type of the callback function is determined by the generic
1238
- * type `C
1239
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } beginNode - The `beginNode` parameter in the
1240
- * `getPathToRoot` function can be either a key, a node, an entry, or any other value of type `R`.
1241
- * @param [isReverse=true] - The `isReverse` parameter in the `getPathToRoot` function determines
1242
- * whether the resulting path from the given `beginNode` to the root should be in reverse order or
1243
- * not. If `isReverse` is set to `true`, the path will be reversed before being returned. If `is
1244
- * @returns The function `getPathToRoot` returns an array of the return values of the callback
1245
- * function `callback` applied to each node in the path from the `beginNode` to the root node. The
1246
- * array is either in reverse order or in the original order based on the value of the `isReverse`
1247
- * parameter.
1141
+ * @template C - The type of the callback function.
1142
+ * @param beginNode - The node to start the path from.
1143
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - A function to call on each node in the path.
1144
+ * @param [isReverse=false] - If true, returns the path from root-to-node.
1145
+ * @returns An array of callback results.
1248
1146
  */
1249
- getPathToRoot<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(
1147
+ getPathToRoot<C extends NodeCallback<BinaryTreeNode<K, V> | undefined>>(
1250
1148
  beginNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
1251
1149
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
1252
1150
  isReverse = false
@@ -1257,44 +1155,32 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1257
1155
  if (!beginNodeEnsured) return result;
1258
1156
 
1259
1157
  while (beginNodeEnsured.parent) {
1260
- // Array.push + Array.reverse is more efficient than Array.unshift
1261
1158
  result.push(callback(beginNodeEnsured));
1262
1159
  beginNodeEnsured = beginNodeEnsured.parent;
1263
1160
  }
1264
- result.push(callback(beginNodeEnsured));
1161
+ result.push(callback(beginNodeEnsured)); // Add the root
1265
1162
  return isReverse ? result.reverse() : result;
1266
1163
  }
1267
1164
 
1268
1165
  /**
1269
- * Time Complexity: O(log n)
1270
- * Space Complexity: O(log n)
1271
- *
1272
- * The function `getLeftMost` retrieves the leftmost node in a binary tree using either recursive or
1273
- * tail-recursive iteration.
1274
- * @param {C} callback - The `callback` parameter is a function that will be called with the leftmost
1275
- * node of a binary tree or with `undefined` if the tree is empty. It is provided with a default
1276
- * value of `_DEFAULT_NODE_CALLBACK` if not specified.
1277
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
1278
- * `getLeftMost` function represents the starting point for finding the leftmost node in a binary
1279
- * tree. It can be either a key, a node, or an entry in the binary tree structure. If no specific
1280
- * starting point is provided, the function will default
1281
- * @param {IterationType} iterationType - The `iterationType` parameter in the `getLeftMost` function
1282
- * specifies the type of iteration to be used when traversing the binary tree nodes. It can have two
1283
- * possible values:
1284
- * @returns The `getLeftMost` function returns the result of the callback function `C` applied to the
1285
- * leftmost node in the binary tree starting from the `startNode` node. If the `startNode` node is
1286
- * `NIL`, it returns the result of the callback function applied to `undefined`. If the `startNode`
1287
- * node is not a real node, it returns the result of the callback
1288
- */
1289
- getLeftMost<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(
1166
+ * Finds the leftmost node in a subtree (the node with the smallest key in a BST).
1167
+ * @remarks Time O(H), where H is the height of the left spine. O(N) worst-case. Space O(H) for recursive/trampoline stack.
1168
+ *
1169
+ * @template C - The type of the callback function.
1170
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - A function to call on the leftmost node.
1171
+ * @param [startNode=this._root] - The subtree root to search from.
1172
+ * @param [iterationType=this.iterationType] - The traversal method.
1173
+ * @returns The callback result for the leftmost node.
1174
+ */
1175
+ getLeftMost<C extends NodeCallback<BinaryTreeNode<K, V> | undefined>>(
1290
1176
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
1291
1177
  startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
1292
1178
  iterationType: IterationType = this.iterationType
1293
1179
  ): ReturnType<C> {
1294
1180
  if (this.isNIL(startNode)) return callback(undefined);
1295
- startNode = this.ensureNode(startNode);
1181
+ const ensuredStartNode = this.ensureNode(startNode);
1296
1182
 
1297
- if (!this.isRealNode(startNode)) return callback(startNode);
1183
+ if (!this.isRealNode(ensuredStartNode)) return callback(undefined);
1298
1184
  if (iterationType === 'RECURSIVE') {
1299
1185
  const dfs = (cur: BinaryTreeNode<K, V>): BinaryTreeNode<K, V> => {
1300
1186
  const { left } = cur;
@@ -1302,49 +1188,37 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1302
1188
  return dfs(left);
1303
1189
  };
1304
1190
 
1305
- return callback(dfs(startNode));
1191
+ return callback(dfs(ensuredStartNode));
1306
1192
  } else {
1307
- // Indirect implementation of iteration using tail recursion optimization
1193
+ // Iterative (trampolined to prevent stack overflow, though 'ITERATIVE' usually means a loop)
1308
1194
  const dfs = makeTrampoline((cur: BinaryTreeNode<K, V>): Trampoline<BinaryTreeNode<K, V>> => {
1309
1195
  const { left } = cur;
1310
1196
  if (!this.isRealNode(left)) return cur;
1311
1197
  return makeTrampolineThunk(() => dfs(left));
1312
1198
  });
1313
1199
 
1314
- return callback(dfs(startNode));
1200
+ return callback(dfs(ensuredStartNode));
1315
1201
  }
1316
1202
  }
1317
1203
 
1318
1204
  /**
1319
- * Time Complexity: O(log n)
1320
- * Space Complexity: O(log n)
1321
- *
1322
- * The function `getRightMost` retrieves the rightmost node in a binary tree using either recursive
1323
- * or iterative traversal methods.
1324
- * @param {C} callback - The `callback` parameter is a function that will be called with the result
1325
- * of finding the rightmost node in a binary tree. It is of type `NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>`,
1326
- * which means it is a callback function that can accept either an optional binary tree node or null
1327
- * as
1328
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
1329
- * `getRightMost` function represents the starting point for finding the rightmost node in a binary
1330
- * tree. It can be either a key, a node, or an entry in the binary tree structure. If no specific
1331
- * starting point is provided, the function will default
1332
- * @param {IterationType} iterationType - The `iterationType` parameter in the `getRightMost`
1333
- * function specifies the type of iteration to be used when traversing the binary tree nodes. It can
1334
- * have two possible values:
1335
- * @returns The `getRightMost` function returns the result of the callback function `C`, which is
1336
- * passed as a parameter to the function. The callback function is called with the rightmost node in
1337
- * the binary tree structure, determined based on the specified iteration type ('RECURSIVE' or
1338
- * other).
1339
- */
1340
- getRightMost<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(
1205
+ * Finds the rightmost node in a subtree (the node with the largest key in a BST).
1206
+ * @remarks Time O(H), where H is the height of the right spine. O(N) worst-case. Space O(H) for recursive/trampoline stack.
1207
+ *
1208
+ * @template C - The type of the callback function.
1209
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - A function to call on the rightmost node.
1210
+ * @param [startNode=this._root] - The subtree root to search from.
1211
+ * @param [iterationType=this.iterationType] - The traversal method.
1212
+ * @returns The callback result for the rightmost node.
1213
+ */
1214
+ getRightMost<C extends NodeCallback<BinaryTreeNode<K, V> | undefined>>(
1341
1215
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
1342
1216
  startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
1343
1217
  iterationType: IterationType = this.iterationType
1344
1218
  ): ReturnType<C> {
1345
1219
  if (this.isNIL(startNode)) return callback(undefined);
1346
1220
  startNode = this.ensureNode(startNode);
1347
- if (!startNode) return callback(startNode);
1221
+ if (!startNode) return callback(undefined);
1348
1222
 
1349
1223
  if (iterationType === 'RECURSIVE') {
1350
1224
  const dfs = (cur: BinaryTreeNode<K, V>): BinaryTreeNode<K, V> => {
@@ -1355,8 +1229,6 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1355
1229
 
1356
1230
  return callback(dfs(startNode));
1357
1231
  } else {
1358
- // Indirect implementation of iteration using tail recursion optimization
1359
-
1360
1232
  const dfs = makeTrampoline((cur: BinaryTreeNode<K, V>): Trampoline<BinaryTreeNode<K, V>> => {
1361
1233
  const { right } = cur;
1362
1234
  if (!this.isRealNode(right)) return cur;
@@ -1368,17 +1240,11 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1368
1240
  }
1369
1241
 
1370
1242
  /**
1371
- * Time Complexity: O(log n)
1372
- * Space Complexity: O(log n)
1243
+ * Gets the Morris traversal predecessor (rightmost node in the left subtree, or node itself).
1244
+ * @remarks This is primarily a helper for Morris traversal. Time O(H), where H is the height of the left subtree. O(N) worst-case. Space O(1).
1373
1245
  *
1374
- * The function `getPredecessor` in TypeScript returns the predecessor node of a given node in a
1375
- * binary tree.
1376
- * @param {BinaryTreeNode<K, V>} node - The `getPredecessor` function you provided seems to be attempting to find the
1377
- * predecessor of a given node in a binary tree. However, there seems to be a logical issue in the
1378
- * while loop condition that might cause an infinite loop.
1379
- * @returns The `getPredecessor` function returns the predecessor node of the input `BinaryTreeNode<K, V>` parameter.
1380
- * If the left child of the input node exists, it traverses to the rightmost node of the left subtree
1381
- * to find the predecessor. If the left child does not exist, it returns the input node itself.
1246
+ * @param node - The node to find the predecessor for.
1247
+ * @returns The Morris predecessor.
1382
1248
  */
1383
1249
  getPredecessor(node: BinaryTreeNode<K, V>): BinaryTreeNode<K, V> {
1384
1250
  if (this.isRealNode(node.left)) {
@@ -1395,17 +1261,11 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1395
1261
  }
1396
1262
 
1397
1263
  /**
1398
- * Time Complexity: O(log n)
1399
- * Space Complexity: O(log n)
1264
+ * Gets the in-order successor of a node in a BST.
1265
+ * @remarks Time O(H), where H is the tree height. O(N) worst-case. Space O(H) (due to `getLeftMost` stack).
1400
1266
  *
1401
- * The function `getSuccessor` in TypeScript returns the next node in an in-order traversal of a
1402
- * binary tree.
1403
- * @param {K | BinaryTreeNode<K, V> | null} [x] - The `getSuccessor` function takes a parameter `x`, which can be of
1404
- * type `K`, `BinaryTreeNode<K, V>`, or `null`.
1405
- * @returns The `getSuccessor` function returns the successor node of the input node `x`. If `x` has
1406
- * a right child, the function returns the leftmost node in the right subtree of `x`. If `x` does not
1407
- * have a right child, the function traverses up the parent nodes until it finds a node that is not
1408
- * the right child of its parent, and returns that node
1267
+ * @param [x] - The node to find the successor of.
1268
+ * @returns The successor node, or null/undefined if none exists.
1409
1269
  */
1410
1270
  getSuccessor(x?: K | BinaryTreeNode<K, V> | null): BinaryTreeNode<K, V> | null | undefined {
1411
1271
  x = this.ensureNode(x);
@@ -1441,34 +1301,19 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1441
1301
  ): ReturnType<C>[];
1442
1302
 
1443
1303
  /**
1444
- * Time complexity: O(n)
1445
- * Space complexity: O(n)
1446
- *
1447
- * The function performs a depth-first search on a binary tree structure based on the specified
1448
- * parameters.
1449
- * @param {C} callback - The `callback` parameter is a function that will be called for each node
1450
- * visited during the depth-first search. It should accept a `BinaryTreeNode` as an argument and
1451
- * return an optional node or null. The default value for this parameter is `_DEFAULT_NODE_CALLBACK`.
1452
- * @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `dfs` function specifies
1453
- * the order in which the nodes are visited during a depth-first search traversal. The possible
1454
- * values for the `pattern` parameter are:
1455
- * @param {boolean} [onlyOne=false] - The `onlyOne` parameter in the `dfs` function is a boolean flag
1456
- * that determines whether the depth-first search should stop after finding the first matching node
1457
- * or continue searching for all matching nodes. If `onlyOne` is set to `true`, the search will stop
1458
- * after finding the first matching node
1459
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined}
1460
- * startNode - The `startNode` parameter in the `dfs` function can be one of the following types:
1461
- * @param {IterationType} iterationType - The `iterationType` parameter in the `dfs` function
1462
- * specifies the type of iteration to be performed during the Depth-First Search traversal. It is
1463
- * used to determine the order in which nodes are visited during the traversal. The possible values
1464
- * for `iterationType` are typically defined as an enum or a
1465
- * @param [includeNull=false] - The `includeNull` parameter in the `dfs` function determines whether
1466
- * null nodes should be included in the depth-first search traversal. If `includeNull` is set to
1467
- * `true`, null nodes will be included in the traversal process. If it is set to `false`, null nodes
1468
- * will be skipped
1469
- * @returns The `dfs` method is returning an array of the return type of the callback function `C`.
1470
- */
1471
- dfs<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(
1304
+ * Performs a Depth-First Search (DFS) traversal.
1305
+ * @remarks Time O(N), visits every node. Space O(H) for the call/explicit stack. O(N) worst-case.
1306
+ *
1307
+ * @template C - The type of the callback function.
1308
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each node.
1309
+ * @param [pattern='IN'] - The traversal order ('IN', 'PRE', 'POST').
1310
+ * @param [onlyOne=false] - If true, stops after the first callback.
1311
+ * @param [startNode=this._root] - The node to start from.
1312
+ * @param [iterationType=this.iterationType] - The traversal method.
1313
+ * @param [includeNull=false] - If true, includes null nodes in the traversal.
1314
+ * @returns An array of callback results.
1315
+ */
1316
+ dfs<C extends NodeCallback<BinaryTreeNode<K, V> | undefined>>(
1472
1317
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
1473
1318
  pattern: DFSOrderPattern = 'IN',
1474
1319
  onlyOne: boolean = false,
@@ -1496,27 +1341,15 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1496
1341
  ): ReturnType<C>[];
1497
1342
 
1498
1343
  /**
1499
- * Time complexity: O(n)
1500
- * Space complexity: O(n)
1501
- *
1502
- * The `bfs` function performs a breadth-first search traversal on a binary tree or binary search
1503
- * tree, executing a specified callback function on each node visited.
1504
- * @param {C} callback - The `callback` parameter in the `bfs` function is a function that will be
1505
- * called on each node visited during the breadth-first search traversal. It is a generic type `C`
1506
- * that extends the `NodeCallback` type, which takes a parameter of type `BinaryTreeNode<K, V>` or `null`.
1507
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `bfs`
1508
- * function represents the starting point for the breadth-first search traversal in a binary tree. It
1509
- * can be specified as a key, node, or entry in the binary tree structure. If not provided, the
1510
- * default value is the root node of the binary
1511
- * @param {IterationType} iterationType - The `iterationType` parameter in the `bfs` function
1512
- * determines the type of iteration to be performed on the binary tree nodes. It can have two
1513
- * possible values:
1514
- * @param [includeNull=false] - The `includeNull` parameter in the `bfs` function determines whether
1515
- * to include `null` values in the breadth-first search traversal of a binary tree. If `includeNull`
1516
- * is set to `true`, the traversal will include `null` values for nodes that do not have children
1517
- * (left
1518
- * @returns The `bfs` function returns an array of values that are the result of applying the
1519
- * provided callback function to each node in the binary tree in a breadth-first search manner.
1344
+ * Performs a Breadth-First Search (BFS) or Level-Order traversal.
1345
+ * @remarks Time O(N), visits every node. Space O(N) in the worst case for the queue (e.g., a full last level).
1346
+ *
1347
+ * @template C - The type of the callback function.
1348
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each node.
1349
+ * @param [startNode=this._root] - The node to start from.
1350
+ * @param [iterationType=this.iterationType] - The traversal method ('RECURSIVE' BFS is less common but supported here).
1351
+ * @param [includeNull=false] - If true, includes null nodes in the traversal.
1352
+ * @returns An array of callback results.
1520
1353
  */
1521
1354
  bfs<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
1522
1355
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
@@ -1530,6 +1363,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1530
1363
  const ans: ReturnType<NodeCallback<BinaryTreeNode<K, V> | null>>[] = [];
1531
1364
 
1532
1365
  if (iterationType === 'RECURSIVE') {
1366
+ // This is a "recursive" BFS, which is atypical. It uses a queue but calls itself.
1533
1367
  const queue: Queue<OptNodeOrNull<BinaryTreeNode<K, V>>> = new Queue<OptNodeOrNull<BinaryTreeNode<K, V>>>([
1534
1368
  startNode
1535
1369
  ]);
@@ -1553,10 +1387,10 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1553
1387
 
1554
1388
  dfs(0);
1555
1389
  } else {
1390
+ // Standard iterative BFS
1556
1391
  const queue = new Queue<OptNodeOrNull<BinaryTreeNode<K, V>>>([startNode]);
1557
1392
  while (queue.length > 0) {
1558
- const levelSize = queue.length;
1559
-
1393
+ const levelSize = queue.length; // Not strictly needed here, but good for level-by-level
1560
1394
  for (let i = 0; i < levelSize; i++) {
1561
1395
  const current = queue.shift()!;
1562
1396
  ans.push(callback(current));
@@ -1575,22 +1409,14 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1575
1409
  }
1576
1410
 
1577
1411
  /**
1578
- * Time complexity: O(n)
1579
- * Space complexity: O(n)
1412
+ * Finds all leaf nodes in the tree.
1413
+ * @remarks Time O(N), visits every node. Space O(H) for recursive stack or O(N) for iterative queue.
1580
1414
  *
1581
- * The `leaves` function in TypeScript returns an array of values from leaf nodes in a binary tree
1582
- * structure based on a specified callback and iteration type.
1583
- * @param {C} callback - The `callback` parameter is a function that will be called on each leaf node
1584
- * in the binary tree. It is optional and defaults to a default callback function if not provided.
1585
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `leaves`
1586
- * method is used to specify the starting point for finding and processing the leaves of a binary
1587
- * tree. It can be provided as either a key, a node, or an entry in the binary tree structure. If not
1588
- * explicitly provided, the default value
1589
- * @param {IterationType} iterationType - The `iterationType` parameter in the `leaves` method
1590
- * specifies the type of iteration to be performed when collecting the leaves of a binary tree. It
1591
- * can have two possible values:
1592
- * @returns The `leaves` method returns an array of values that are the result of applying the
1593
- * provided callback function to each leaf node in the binary tree.
1415
+ * @template C - The type of the callback function.
1416
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each leaf node.
1417
+ * @param [startNode=this._root] - The node to start from.
1418
+ * @param [iterationType=this.iterationType] - The traversal method.
1419
+ * @returns An array of callback results.
1594
1420
  */
1595
1421
  leaves<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
1596
1422
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
@@ -1599,9 +1425,11 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1599
1425
  ): ReturnType<C>[] {
1600
1426
  startNode = this.ensureNode(startNode);
1601
1427
  const leaves: ReturnType<NodeCallback<BinaryTreeNode<K, V> | null>>[] = [];
1428
+
1602
1429
  if (!this.isRealNode(startNode)) return [];
1603
1430
 
1604
1431
  if (iterationType === 'RECURSIVE') {
1432
+ // DFS-based
1605
1433
  const dfs = (cur: BinaryTreeNode<K, V>) => {
1606
1434
  if (this.isLeaf(cur)) {
1607
1435
  leaves.push(callback(cur));
@@ -1613,7 +1441,9 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1613
1441
 
1614
1442
  dfs(startNode);
1615
1443
  } else {
1444
+ // BFS-based
1616
1445
  const queue = new Queue([startNode]);
1446
+
1617
1447
  while (queue.length > 0) {
1618
1448
  const cur = queue.shift();
1619
1449
  if (this.isRealNode(cur)) {
@@ -1644,28 +1474,15 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1644
1474
  ): ReturnType<C>[][];
1645
1475
 
1646
1476
  /**
1647
- * Time complexity: O(n)
1648
- * Space complexity: O(n)
1649
- *
1650
- * The `listLevels` function in TypeScript generates a list of nodes at each level of a binary tree,
1651
- * using either recursive or iterative traversal based on the specified iteration type.
1652
- * @param {C} callback - The `callback` parameter is a function that will be applied to each node in
1653
- * the binary tree during the traversal. It is used to process each node and determine what
1654
- * information to include in the output for each level of the tree.
1655
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
1656
- * `listLevels` function represents the starting point for traversing the binary tree. It can be
1657
- * either a key, a node, or an entry in the binary tree. If not provided, the default value is the
1658
- * root of the binary tree.
1659
- * @param {IterationType} iterationType - The `iterationType` parameter in the `listLevels` function
1660
- * determines the type of iteration to be performed on the binary tree nodes. It can have two
1661
- * possible values:
1662
- * @param [includeNull=false] - The `includeNull` parameter in the `listLevels` method determines
1663
- * whether or not to include null nodes in the traversal of the binary tree. If `includeNull` is set
1664
- * to `true`, the traversal will include null nodes in the levels of the tree. If set to `false`,
1665
- * null
1666
- * @returns The `listLevels` method returns an array of arrays, where each inner array represents a
1667
- * level in a binary tree. Each inner array contains the return value of the provided callback
1668
- * function applied to the nodes at that level.
1477
+ * Returns a 2D array of nodes, grouped by level.
1478
+ * @remarks Time O(N), visits every node. Space O(N) for the result array and the queue/stack.
1479
+ *
1480
+ * @template C - The type of the callback function.
1481
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each node.
1482
+ * @param [startNode=this._root] - The node to start from.
1483
+ * @param [iterationType=this.iterationType] - The traversal method.
1484
+ * @param [includeNull=false] - If true, includes null nodes.
1485
+ * @returns A 2D array of callback results.
1669
1486
  */
1670
1487
  listLevels<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
1671
1488
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
@@ -1675,9 +1492,11 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1675
1492
  ): ReturnType<C>[][] {
1676
1493
  startNode = this.ensureNode(startNode);
1677
1494
  const levelsNodes: ReturnType<C>[][] = [];
1495
+
1678
1496
  if (!startNode) return levelsNodes;
1679
1497
 
1680
1498
  if (iterationType === 'RECURSIVE') {
1499
+ // Pre-order DFS based level listing
1681
1500
  const _recursive = (node: BinaryTreeNode<K, V> | null, level: number) => {
1682
1501
  if (!levelsNodes[level]) levelsNodes[level] = [];
1683
1502
  levelsNodes[level].push(callback(node));
@@ -1692,6 +1511,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1692
1511
 
1693
1512
  _recursive(startNode, 0);
1694
1513
  } else {
1514
+ // Iterative DFS based level listing
1695
1515
  const stack: [BinaryTreeNode<K, V> | null, number][] = [[startNode, 0]];
1696
1516
 
1697
1517
  while (stack.length > 0) {
@@ -1721,24 +1541,14 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1721
1541
  ): ReturnType<C>[];
1722
1542
 
1723
1543
  /**
1724
- * Time complexity: O(n)
1725
- * Space complexity: O(n)
1726
- *
1727
- * The `morris` function in TypeScript performs a Depth-First Search traversal on a binary tree using
1728
- * Morris Traversal algorithm with different order patterns.
1729
- * @param {C} callback - The `callback` parameter in the `morris` function is a function that will be
1730
- * called on each node in the binary tree during the traversal. It is of type `C`, which extends the
1731
- * `NodeCallback<BinaryTreeNode<K, V> | null>` type. The default value for `callback` is `this._DEFAULT
1732
- * @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `morris` function specifies
1733
- * the type of Depth-First Search (DFS) order pattern to traverse the binary tree. The possible
1734
- * values for the `pattern` parameter are:
1735
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `morris`
1736
- * function is the starting point for the Morris traversal algorithm. It represents the root node of
1737
- * the binary tree or the node from which the traversal should begin. It can be provided as either a
1738
- * key, a node, an entry, or a reference
1739
- * @returns The `morris` function is returning an array of values that are the result of applying the
1740
- * provided callback function to each node in the binary tree in the specified order pattern (IN,
1741
- * PRE, or POST).
1544
+ * Performs a Morris (threaded) traversal.
1545
+ * @remarks This traversal uses O(1) extra space (excluding the result array) by temporarily modifying the tree's right child pointers. Time O(N), as each node is visited a constant number of times. Space O(1) (excluding the `ans` array).
1546
+ *
1547
+ * @template C - The type of the callback function.
1548
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each node.
1549
+ * @param [pattern='IN'] - The traversal order ('IN', 'PRE', 'POST').
1550
+ * @param [startNode=this._root] - The node to start from.
1551
+ * @returns An array of callback results.
1742
1552
  */
1743
1553
  morris<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
1744
1554
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
@@ -1746,10 +1556,13 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1746
1556
  startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root
1747
1557
  ): ReturnType<C>[] {
1748
1558
  startNode = this.ensureNode(startNode);
1559
+
1749
1560
  if (!startNode) return [];
1750
1561
  const ans: ReturnType<NodeCallback<BinaryTreeNode<K, V> | null>>[] = [];
1751
1562
 
1752
1563
  let cur: BinaryTreeNode<K, V> | null | undefined = startNode;
1564
+
1565
+ // Helper to reverse a linked list (formed by right pointers)
1753
1566
  const _reverseEdge = (node: BinaryTreeNode<K, V> | null | undefined) => {
1754
1567
  let pre: BinaryTreeNode<K, V> | null | undefined = null;
1755
1568
  let next: BinaryTreeNode<K, V> | null | undefined = null;
@@ -1761,25 +1574,32 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1761
1574
  }
1762
1575
  return pre;
1763
1576
  };
1577
+
1578
+ // Helper to print the reversed edge (for post-order)
1764
1579
  const _printEdge = (node: BinaryTreeNode<K, V> | null | undefined) => {
1765
1580
  const tail: BinaryTreeNode<K, V> | null | undefined = _reverseEdge(node);
1766
1581
  let cur: BinaryTreeNode<K, V> | null | undefined = tail;
1582
+
1767
1583
  while (cur) {
1768
1584
  ans.push(callback(cur));
1769
1585
  cur = cur.right;
1770
1586
  }
1771
- _reverseEdge(tail);
1587
+
1588
+ _reverseEdge(tail); // Restore the edge
1772
1589
  };
1590
+
1773
1591
  switch (pattern) {
1774
1592
  case 'IN':
1775
1593
  while (cur) {
1776
1594
  if (cur.left) {
1777
1595
  const predecessor = this.getPredecessor(cur);
1778
1596
  if (!predecessor.right) {
1597
+ // Create thread
1779
1598
  predecessor.right = cur;
1780
1599
  cur = cur.left;
1781
1600
  continue;
1782
1601
  } else {
1602
+ // Remove thread
1783
1603
  predecessor.right = null;
1784
1604
  }
1785
1605
  }
@@ -1792,11 +1612,13 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1792
1612
  if (cur.left) {
1793
1613
  const predecessor = this.getPredecessor(cur);
1794
1614
  if (!predecessor.right) {
1615
+ // Create thread and visit
1795
1616
  predecessor.right = cur;
1796
1617
  ans.push(callback(cur));
1797
1618
  cur = cur.left;
1798
1619
  continue;
1799
1620
  } else {
1621
+ // Remove thread
1800
1622
  predecessor.right = null;
1801
1623
  }
1802
1624
  } else {
@@ -1810,115 +1632,81 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1810
1632
  if (cur.left) {
1811
1633
  const predecessor = this.getPredecessor(cur);
1812
1634
  if (predecessor.right === null) {
1635
+ // Create thread
1813
1636
  predecessor.right = cur;
1814
1637
  cur = cur.left;
1815
1638
  continue;
1816
1639
  } else {
1640
+ // Remove thread and print right spine of left child
1817
1641
  predecessor.right = null;
1818
1642
  _printEdge(cur.left);
1819
1643
  }
1820
1644
  }
1821
1645
  cur = cur.right;
1822
1646
  }
1823
- _printEdge(startNode);
1647
+ _printEdge(startNode); // Print the right spine of the root
1824
1648
  break;
1825
1649
  }
1826
1650
  return ans;
1827
1651
  }
1828
1652
 
1829
1653
  /**
1830
- * Time complexity: O(n)
1831
- * Space complexity: O(n)
1654
+ * Clones the tree.
1655
+ * @remarks Time O(N * M), where N is the number of nodes and M is the tree size during insertion (due to `bfs` + `add`, and `add` is O(M)). Space O(N) for the new tree and the BFS queue.
1832
1656
  *
1833
- * The `clone` function creates a deep copy of a tree structure by traversing it using breadth-first
1834
- * search.
1835
- * @returns The `clone()` method is returning a cloned copy of the tree with the same structure and
1836
- * values as the original tree. The method creates a new tree, iterates over the nodes of the
1837
- * original tree using breadth-first search (bfs), and adds the nodes to the new tree. If a node in
1838
- * the original tree is null, a null node is added to the cloned tree. If a node
1657
+ * @returns A new, cloned instance of the tree.
1839
1658
  */
1840
- clone() {
1841
- const cloned = this.createTree();
1842
- this._clone(cloned);
1843
- return cloned;
1659
+ clone(): this {
1660
+ const out = this._createInstance<K, V, R>();
1661
+ this._clone(out);
1662
+ return out;
1844
1663
  }
1845
1664
 
1846
1665
  /**
1847
- * Time Complexity: O(n)
1848
- * Space Complexity: O(n)
1666
+ * Creates a new tree containing only the entries that satisfy the predicate.
1667
+ * @remarks Time O(N * M), where N is nodes in this tree, and M is size of the new tree during insertion (O(N) iteration + O(M) `add` for each item). Space O(N) for the new tree.
1849
1668
  *
1850
- * The `filter` function iterates over key-value pairs in a tree data structure and creates a new
1851
- * tree with elements that satisfy a given predicate.
1852
- * @param predicate - The `predicate` parameter in the `filter` method is a function that will be
1853
- * called with four arguments: the `value` of the current entry, the `key` of the current entry, the
1854
- * `index` of the current entry in the iteration, and the reference to the tree itself (`
1855
- * @param {any} [thisArg] - The `thisArg` parameter in the `filter` method allows you to specify the
1856
- * value of `this` that should be used when executing the `predicate` function. This is useful when
1857
- * the `predicate` function relies on the context of a specific object or value. By providing a
1858
- * `thisArg
1859
- * @returns The `filter` method is returning a new tree that contains entries that pass the provided
1860
- * predicate function.
1669
+ * @param predicate - A function to test each [key, value] pair.
1670
+ * @param [thisArg] - `this` context for the predicate.
1671
+ * @returns A new, filtered tree.
1861
1672
  */
1862
- filter(predicate: EntryCallback<K, V | undefined, boolean>, thisArg?: any) {
1863
- const newTree = this.createTree();
1864
- let index = 0;
1865
- for (const [key, value] of this) {
1866
- if (predicate.call(thisArg, key, value, index++, this)) {
1867
- newTree.add([key, value]);
1868
- }
1869
- }
1870
- return newTree;
1871
- }
1872
-
1873
- /**
1874
- * Time Complexity: O(n)
1875
- * Space Complexity: O(n)
1876
- *
1877
- * The `map` function in TypeScript creates a new BinaryTree by applying a callback function to each
1878
- * entry in the original BinaryTree.
1879
- * @param callback - A function that will be called for each entry in the current binary tree. It
1880
- * takes the key, value (which can be undefined), and an array containing the mapped key and value as
1881
- * arguments.
1882
- * @param [options] - The `options` parameter in the `map` method is of type `BinaryTreeOptions<MK,
1883
- * MV, MR>`. It is an optional parameter that allows you to specify additional options for the binary
1884
- * tree being created during the mapping process. These options could include things like custom
1885
- * comparators, initial
1886
- * @param {any} [thisArg] - The `thisArg` parameter in the `map` method is used to specify the value
1887
- * of `this` when executing the `callback` function. It allows you to set the context (value of
1888
- * `this`) within the callback function. If `thisArg` is provided, it will be passed
1889
- * @returns The `map` function is returning a new `BinaryTree` instance filled with entries that are
1890
- * the result of applying the provided `callback` function to each entry in the original tree.
1891
- */
1892
- map(
1893
- callback: EntryCallback<K, V | undefined, [MK, MV]>,
1894
- options?: BinaryTreeOptions<MK, MV, MR>,
1895
- thisArg?: any
1673
+ filter(predicate: EntryCallback<K, V | undefined, boolean>, thisArg?: unknown): this {
1674
+ const out = this._createInstance<K, V, R>();
1675
+ let i = 0;
1676
+ for (const [k, v] of this) if (predicate.call(thisArg, k, v, i++, this)) out.add([k, v]);
1677
+ return out;
1678
+ }
1679
+
1680
+ /**
1681
+ * Creates a new tree by mapping each [key, value] pair to a new entry.
1682
+ * @remarks Time O(N * M), where N is nodes in this tree, and M is size of the new tree during insertion. Space O(N) for the new tree.
1683
+ *
1684
+ * @template MK - New key type.
1685
+ * @template MV - New value type.
1686
+ * @template MR - New raw type.
1687
+ * @param cb - A function to map each [key, value] pair.
1688
+ * @param [options] - Options for the new tree.
1689
+ * @param [thisArg] - `this` context for the callback.
1690
+ * @returns A new, mapped tree.
1691
+ */
1692
+ map<MK = K, MV = V, MR = any>(
1693
+ cb: EntryCallback<K, V | undefined, [MK, MV]>,
1694
+ options?: Partial<BinaryTreeOptions<MK, MV, MR>>,
1695
+ thisArg?: unknown
1896
1696
  ): BinaryTree<MK, MV, MR> {
1897
- const newTree = new BinaryTree<MK, MV, MR>([], options);
1898
- let index = 0;
1899
- for (const [key, value] of this) {
1900
- newTree.add(callback.call(thisArg, key, value, index++, this));
1901
- }
1902
- return newTree;
1697
+ const out = this._createLike<MK, MV, MR>([], options);
1698
+ let i = 0;
1699
+ for (const [k, v] of this) out.add(cb.call(thisArg, k, v, i++, this));
1700
+ return out;
1903
1701
  }
1904
1702
 
1905
1703
  /**
1906
- * Time Complexity: O(n)
1907
- * Space Complexity: O(n)
1704
+ * Generates a string representation of the tree for visualization.
1705
+ * @remarks Time O(N), visits every node. Space O(N*H) or O(N^2) in the worst case, as the string width can grow significantly.
1908
1706
  *
1909
- * The function `toVisual` in TypeScript overrides the visual representation of a binary tree with
1910
- * customizable options for displaying undefined, null, and sentinel nodes.
1911
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
1912
- * `toVisual` method is used to specify the starting point for visualizing the binary tree structure.
1913
- * It can be a node, key, entry, or the root of the tree. If no specific starting point is provided,
1914
- * the default is set to the root
1915
- * @param {BinaryTreePrintOptions} [options] - The `options` parameter in the `toVisual` method is an
1916
- * object that contains the following properties:
1917
- * @returns The `override toVisual` method returns a string that represents the visual display of the
1918
- * binary tree based on the provided options for showing undefined, null, and Red-Black NIL nodes.
1919
- * The method constructs the visual representation by calling the `_displayAux` method and appending
1920
- * the lines to the output string. The final output string contains the visual representation of the
1921
- * binary tree with the specified options.
1707
+ * @param [startNode=this._root] - The node to start printing from.
1708
+ * @param [options] - Options to control the output (e.g., show nulls).
1709
+ * @returns The string representation of the tree.
1922
1710
  */
1923
1711
  override toVisual(
1924
1712
  startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
@@ -1947,19 +1735,11 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1947
1735
  }
1948
1736
 
1949
1737
  /**
1950
- * Time Complexity: O(n)
1951
- * Space Complexity: O(n)
1738
+ * Prints a visual representation of the tree to the console.
1739
+ * @remarks Time O(N) (via `toVisual`). Space O(N*H) or O(N^2) (via `toVisual`).
1952
1740
  *
1953
- * The function `print` in TypeScript overrides the default print behavior to log a visual
1954
- * representation of the binary tree to the console.
1955
- * @param {BinaryTreePrintOptions} [options] - The `options` parameter is used to specify the
1956
- * printing options for the binary tree. It is an optional parameter that allows you to customize how
1957
- * the binary tree is printed, such as choosing between different traversal orders or formatting
1958
- * options.
1959
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
1960
- * `override print` method is used to specify the starting point for printing the binary tree. It can
1961
- * be either a key, a node, an entry, or the root of the tree. If no specific starting point is
1962
- * provided, the default value is set to
1741
+ * @param [options] - Options to control the output.
1742
+ * @param [startNode=this._root] - The node to start printing from.
1963
1743
  */
1964
1744
  override print(
1965
1745
  options?: BinaryTreePrintOptions,
@@ -1968,60 +1748,6 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
1968
1748
  console.log(this.toVisual(startNode, options));
1969
1749
  }
1970
1750
 
1971
- protected _clone(cloned: BinaryTree<K, V, R, MK, MV, MR>) {
1972
- this.bfs(
1973
- node => {
1974
- if (node === null) cloned.add(null);
1975
- else {
1976
- if (this._isMapMode) cloned.add([node.key, this._store.get(node.key)]);
1977
- else cloned.add([node.key, node.value]);
1978
- }
1979
- },
1980
- this._root,
1981
- this.iterationType,
1982
- true
1983
- );
1984
- if (this._isMapMode) cloned._store = this._store;
1985
- }
1986
-
1987
- /**
1988
- * Time Complexity: O(1)
1989
- * Space Complexity: O(1)
1990
- *
1991
- * The function `keyValueNodeEntryRawToNodeAndValue` converts various input types into a node object
1992
- * or returns null.
1993
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The
1994
- * `keyValueNodeEntryRawToNodeAndValue` function takes in a parameter `keyNodeOrEntry`, which
1995
- * can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. This parameter represents either a key, a
1996
- * node, an entry
1997
- * @param {V} [value] - The `value` parameter in the `keyValueNodeEntryRawToNodeAndValue` function is
1998
- * an optional parameter of type `V`. It represents the value associated with the key in the node
1999
- * being created. If a `value` is provided, it will be used when creating the node. If
2000
- * @returns The `keyValueNodeEntryRawToNodeAndValue` function returns an optional node
2001
- * (`BinaryTreeNode<K, V> | null | undefined`) based on the input parameters provided. The function checks the type of the
2002
- * input parameter (`keyNodeOrEntry`) and processes it accordingly to return a node or null
2003
- * value.
2004
- */
2005
- protected _keyValueNodeOrEntryToNodeAndValue(
2006
- keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
2007
- value?: V
2008
- ): [BinaryTreeNode<K, V> | null | undefined, V | undefined] {
2009
- if (keyNodeOrEntry === undefined) return [undefined, undefined];
2010
- if (keyNodeOrEntry === null) return [null, undefined];
2011
-
2012
- if (this.isNode(keyNodeOrEntry)) return [keyNodeOrEntry, value];
2013
-
2014
- if (this.isEntry(keyNodeOrEntry)) {
2015
- const [key, entryValue] = keyNodeOrEntry;
2016
- if (key === undefined) return [undefined, undefined];
2017
- else if (key === null) return [null, undefined];
2018
- const finalValue = value ?? entryValue;
2019
- return [this.createNode(key, finalValue), finalValue];
2020
- }
2021
-
2022
- return [this.createNode(keyNodeOrEntry, value), value];
2023
- }
2024
-
2025
1751
  protected _dfs<C extends NodeCallback<BinaryTreeNode<K, V>>>(
2026
1752
  callback: C,
2027
1753
  pattern?: DFSOrderPattern,
@@ -2036,49 +1762,21 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
2036
1762
  ): ReturnType<C>[];
2037
1763
 
2038
1764
  /**
2039
- * Time complexity: O(n)
2040
- * Space complexity: O(n)
2041
- *
2042
- * The `_dfs` function performs a depth-first search traversal on a binary tree, with customizable
2043
- * options for traversal order and node processing.
2044
- * @param {C} callback - The `callback` parameter in the `_dfs` method is a function that will be
2045
- * called on each node visited during the depth-first search traversal. It is a generic type `C` that
2046
- * extends `NodeCallback<BinaryTreeNode<K, V> | null>`. The default value for `callback`
2047
- * @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `_dfs` method specifies the
2048
- * order in which the nodes are visited during a depth-first search traversal. It can have one of the
2049
- * following values:
2050
- * @param {boolean} [onlyOne=false] - The `onlyOne` parameter in the `_dfs` method is a boolean flag
2051
- * that determines whether the traversal should stop after processing a single node. If `onlyOne` is
2052
- * set to `true`, the traversal will return as soon as a single node is processed. If it is set to
2053
- * `false
2054
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined}
2055
- * startNode - The `startNode` parameter in the `_dfs` method is used to specify the starting node
2056
- * for the depth-first search traversal. It can be provided in different forms:
2057
- * @param {IterationType} iterationType - The `iterationType` parameter in the `_dfs` method
2058
- * specifies whether the traversal should be done recursively or iteratively. It can have two
2059
- * possible values:
2060
- * @param [includeNull=false] - The `includeNull` parameter in the `_dfs` method determines whether
2061
- * null nodes should be included in the traversal process. If `includeNull` is set to `true`, the
2062
- * method will consider null nodes as valid nodes to visit or process. If `includeNull` is set to
2063
- * `false`,
2064
- * @param shouldVisitLeft - The `shouldVisitLeft` parameter in the `_dfs` method is a function that
2065
- * determines whether the left child of a node should be visited during the Depth-First Search
2066
- * traversal. By default, it checks if the node is not null or undefined before visiting the left
2067
- * child. You can customize this behavior
2068
- * @param shouldVisitRight - The `shouldVisitRight` parameter in the `_dfs` method is a function that
2069
- * determines whether to visit the right child node of the current node during a depth-first search
2070
- * traversal. The default implementation of this function checks if the node is not null or undefined
2071
- * before deciding to visit it.
2072
- * @param shouldVisitRoot - The `shouldVisitRoot` parameter in the `_dfs` method is a function that
2073
- * determines whether a given node should be visited during the depth-first search traversal. The
2074
- * function takes a node as an argument and returns a boolean value indicating whether the node
2075
- * should be visited.
2076
- * @param shouldProcessRoot - The `shouldProcessRoot` parameter in the `_dfs` method is a function
2077
- * that determines whether the root node should be processed during the Depth-First Search traversal.
2078
- * It takes a node (BinaryTreeNode<K, V> | null | undefined) as input and returns a boolean value. If
2079
- * the function
2080
- * @returns The `_dfs` method returns an array of the return type of the provided callback function
2081
- * `C`.
1765
+ * (Protected) Core DFS implementation.
1766
+ * @remarks Time O(N), visits every node satisfying predicates. Space O(H) for call/explicit stack. O(N) worst-case.
1767
+ *
1768
+ * @template C - Callback type.
1769
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on nodes.
1770
+ * @param [pattern='IN'] - Traversal order.
1771
+ * @param [onlyOne=false] - Stop after first match.
1772
+ * @param [startNode=this._root] - Starting node.
1773
+ * @param [iterationType=this.iterationType] - Traversal method.
1774
+ * @param [includeNull=false] - Include nulls.
1775
+ * @param [shouldVisitLeft] - Predicate to traverse left.
1776
+ * @param [shouldVisitRight] - Predicate to traverse right.
1777
+ * @param [shouldVisitRoot] - Predicate to visit root.
1778
+ * @param [shouldProcessRoot] - Predicate to process root.
1779
+ * @returns Array of callback results.
2082
1780
  */
2083
1781
  protected _dfs<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
2084
1782
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
@@ -2140,6 +1838,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
2140
1838
 
2141
1839
  dfs(startNode);
2142
1840
  } else {
1841
+ // Iterative
2143
1842
  const stack: DFSStackItem<BinaryTreeNode<K, V>>[] = [{ opt: DFSOperation.VISIT, node: startNode }];
2144
1843
 
2145
1844
  const pushLeft = (cur: DFSStackItem<BinaryTreeNode<K, V>>) => {
@@ -2162,6 +1861,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
2162
1861
  if (onlyOne) return ans;
2163
1862
  }
2164
1863
  } else {
1864
+ // VISIT
2165
1865
  switch (pattern) {
2166
1866
  case 'IN':
2167
1867
  pushRight(cur);
@@ -2187,19 +1887,11 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
2187
1887
  }
2188
1888
 
2189
1889
  /**
2190
- * Time Complexity: O(1)
2191
- * Space Complexity: O(1)
1890
+ * (Protected) Gets the iterator for the tree (default in-order).
1891
+ * @remarks Time O(N) for full iteration. O(H) to get the first element. Space O(H) for the iterative stack. O(H) for recursive stack.
2192
1892
  *
2193
- * The function `_getIterator` returns an iterable iterator for a binary tree data structure, either
2194
- * using an iterative approach or a recursive approach based on the specified iteration type.
2195
- * @param node - The `node` parameter in the `_getIterator` method represents the current node being
2196
- * processed during iteration. It is initially set to the root node of the data structure (or the
2197
- * node passed as an argument), and then it is traversed through the data structure based on the
2198
- * iteration type specified (`ITER
2199
- * @returns The `_getIterator` method returns an IterableIterator containing key-value pairs of nodes
2200
- * in a binary tree structure. The method uses an iterative approach to traverse the tree based on
2201
- * the `iterationType` property. If the `iterationType` is set to 'ITERATIVE', the method uses a
2202
- * stack to perform an in-order traversal of the tree. If the `iterationType` is not 'ITERATIVE
1893
+ * @param [node=this._root] - The node to start iteration from.
1894
+ * @returns An iterator for [key, value] pairs.
2203
1895
  */
2204
1896
  protected *_getIterator(node = this._root): IterableIterator<[K, V | undefined]> {
2205
1897
  if (!node) return;
@@ -2209,25 +1901,31 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
2209
1901
  let current: BinaryTreeNode<K, V> | null | undefined = node;
2210
1902
 
2211
1903
  while (current || stack.length > 0) {
1904
+ // Go to the leftmost node
2212
1905
  while (this.isRealNode(current)) {
2213
1906
  stack.push(current);
2214
1907
  current = current.left;
2215
1908
  }
2216
1909
 
1910
+ // Visit the node
2217
1911
  current = stack.pop();
2218
1912
 
2219
1913
  if (this.isRealNode(current)) {
2220
1914
  if (this._isMapMode) yield [current.key, this._store.get(current.key)];
2221
1915
  else yield [current.key, current.value];
1916
+ // Move to the right subtree
2222
1917
  current = current.right;
2223
1918
  }
2224
1919
  }
2225
1920
  } else {
1921
+ // Recursive in-order traversal
2226
1922
  if (node.left && this.isRealNode(node)) {
2227
1923
  yield* this[Symbol.iterator](node.left);
2228
1924
  }
1925
+
2229
1926
  if (this._isMapMode) yield [node.key, this._store.get(node.key)];
2230
1927
  else yield [node.key, node.value];
1928
+
2231
1929
  if (node.right && this.isRealNode(node)) {
2232
1930
  yield* this[Symbol.iterator](node.right);
2233
1931
  }
@@ -2235,28 +1933,136 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
2235
1933
  }
2236
1934
 
2237
1935
  /**
2238
- * Time Complexity: O(n)
2239
- * Space Complexity: O(n)
1936
+ * (Protected) Default callback function, returns the node's key.
1937
+ * @remarks Time O(1)
1938
+ *
1939
+ * @param node - The node.
1940
+ * @returns The node's key or undefined.
1941
+ */
1942
+ protected _DEFAULT_NODE_CALLBACK = (node: BinaryTreeNode<K, V> | null | undefined) => (node ? node.key : undefined);
1943
+
1944
+ /**
1945
+ * (Protected) Snapshots the current tree's configuration options.
1946
+ * @remarks Time O(1)
2240
1947
  *
2241
- * The function `_displayAux` in TypeScript is responsible for generating the display layout of nodes
2242
- * in a binary tree based on specified options.
2243
- * @param node - The `node` parameter in the `_displayAux` function represents a node in a binary
2244
- * tree. It can be either a valid node containing a key or a special type of node like null,
2245
- * undefined, or a Red-Black tree NIL node. The function checks the type of the node and its
2246
- * @param {BinaryTreePrintOptions} options - The `options` parameter in the `_displayAux` function
2247
- * contains the following properties:
2248
- * @returns The `_displayAux` function returns a `NodeDisplayLayout`, which is an array containing
2249
- * information about how to display a node in a binary tree. The `NodeDisplayLayout` consists of four
2250
- * elements:
1948
+ * @template TK, TV, TR - Generic types for the options.
1949
+ * @returns The options object.
1950
+ */
1951
+ protected _snapshotOptions<TK = K, TV = V, TR = R>(): BinaryTreeOptions<TK, TV, TR> {
1952
+ return {
1953
+ iterationType: this.iterationType,
1954
+ toEntryFn: this.toEntryFn as unknown as BinaryTreeOptions<TK, TV, TR>['toEntryFn'],
1955
+ isMapMode: this.isMapMode,
1956
+ isDuplicate: this.isDuplicate
1957
+ };
1958
+ }
1959
+
1960
+ /**
1961
+ * (Protected) Creates a new, empty instance of the same tree constructor.
1962
+ * @remarks Time O(1)
1963
+ *
1964
+ * @template TK, TV, TR - Generic types for the new instance.
1965
+ * @param [options] - Options for the new tree.
1966
+ * @returns A new, empty tree.
1967
+ */
1968
+ protected _createInstance<TK = K, TV = V, TR = R>(options?: Partial<BinaryTreeOptions<TK, TV, TR>>): this {
1969
+ const Ctor = this.constructor as unknown as new (
1970
+ iter?: Iterable<TK | BinaryTreeNode<TK, TV> | [TK | null | undefined, TV | undefined] | null | undefined | TR>,
1971
+ opts?: BinaryTreeOptions<TK, TV, TR>
1972
+ ) => BinaryTree<TK, TV, TR>;
1973
+ return new Ctor([], { ...this._snapshotOptions<TK, TV, TR>(), ...(options ?? {}) }) as unknown as this;
1974
+ }
1975
+
1976
+ /**
1977
+ * (Protected) Creates a new instance of the same tree constructor, potentially with different generic types.
1978
+ * @remarks Time O(N) (or as per constructor) due to processing the iterable.
1979
+ *
1980
+ * @template TK, TV, TR - Generic types for the new instance.
1981
+ * @param [iter=[]] - An iterable to populate the new tree.
1982
+ * @param [options] - Options for the new tree.
1983
+ * @returns A new tree.
1984
+ */
1985
+ protected _createLike<TK = K, TV = V, TR = R>(
1986
+ iter: Iterable<TK | BinaryTreeNode<TK, TV> | [TK | null | undefined, TV | undefined] | null | undefined | TR> = [],
1987
+ options?: Partial<BinaryTreeOptions<TK, TV, TR>>
1988
+ ): BinaryTree<TK, TV, TR> {
1989
+ const Ctor = this.constructor as unknown as new (
1990
+ iter?: Iterable<TK | BinaryTreeNode<TK, TV> | [TK | null | undefined, TV | undefined] | null | undefined | TR>,
1991
+ opts?: BinaryTreeOptions<TK, TV, TR>
1992
+ ) => BinaryTree<TK, TV, TR>;
1993
+ return new Ctor(iter, { ...this._snapshotOptions<TK, TV, TR>(), ...(options ?? {}) }) as unknown as BinaryTree<
1994
+ TK,
1995
+ TV,
1996
+ TR
1997
+ >;
1998
+ }
1999
+
2000
+ /**
2001
+ * (Protected) Converts a key, node, or entry into a standardized [node, value] tuple.
2002
+ * @remarks Time O(1)
2003
+ *
2004
+ * @param keyNodeOrEntry - The input item.
2005
+ * @param [value] - An optional value (used if input is just a key).
2006
+ * @returns A tuple of [node, value].
2007
+ */
2008
+ protected _keyValueNodeOrEntryToNodeAndValue(
2009
+ keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
2010
+ value?: V
2011
+ ): [BinaryTreeNode<K, V> | null | undefined, V | undefined] {
2012
+ if (keyNodeOrEntry === undefined) return [undefined, undefined];
2013
+ if (keyNodeOrEntry === null) return [null, undefined];
2014
+
2015
+ if (this.isNode(keyNodeOrEntry)) return [keyNodeOrEntry, value];
2016
+
2017
+ if (this.isEntry(keyNodeOrEntry)) {
2018
+ const [key, entryValue] = keyNodeOrEntry;
2019
+ if (key === undefined) return [undefined, undefined];
2020
+ else if (key === null) return [null, undefined];
2021
+ const finalValue = value ?? entryValue;
2022
+ return [this._createNode(key, finalValue), finalValue];
2023
+ }
2024
+
2025
+ return [this._createNode(keyNodeOrEntry, value), value];
2026
+ }
2027
+
2028
+ /**
2029
+ * (Protected) Helper for cloning. Performs a BFS and adds all nodes to the new tree.
2030
+ * @remarks Time O(N * M) (O(N) BFS + O(M) `add` for each node).
2031
+ *
2032
+ * @param cloned - The new, empty tree instance to populate.
2033
+ */
2034
+ protected _clone(cloned: BinaryTree<K, V, R>) {
2035
+ // Use BFS with nulls to preserve the tree structure
2036
+ this.bfs(
2037
+ node => {
2038
+ if (node === null) cloned.add(null);
2039
+ else {
2040
+ if (this._isMapMode) cloned.add([node.key, this._store.get(node.key)]);
2041
+ else cloned.add([node.key, node.value]);
2042
+ }
2043
+ },
2044
+ this._root,
2045
+ this.iterationType,
2046
+ true // Include nulls
2047
+ );
2048
+ if (this._isMapMode) cloned._store = this._store;
2049
+ }
2050
+
2051
+ /**
2052
+ * (Protected) Recursive helper for `toVisual`.
2053
+ * @remarks Time O(N), Space O(N*H) or O(N^2)
2054
+ *
2055
+ * @param node - The current node.
2056
+ * @param options - Print options.
2057
+ * @returns Layout information for this subtree.
2251
2058
  */
2252
2059
  protected _displayAux(
2253
2060
  node: BinaryTreeNode<K, V> | null | undefined,
2254
2061
  options: BinaryTreePrintOptions
2255
2062
  ): NodeDisplayLayout {
2256
2063
  const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
2257
- const emptyDisplayLayout = <NodeDisplayLayout>[['─'], 1, 0, 0];
2064
+ const emptyDisplayLayout = <NodeDisplayLayout>[['─'], 1, 0, 0]; // Represents an empty spot
2258
2065
 
2259
- // Check if node is null or undefined or key is NaN
2260
2066
  if (node === null && !isShowNull) {
2261
2067
  return emptyDisplayLayout;
2262
2068
  } else if (node === undefined && !isShowUndefined) {
@@ -2264,8 +2070,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
2264
2070
  } else if (this.isNIL(node) && !isShowRedBlackNIL) {
2265
2071
  return emptyDisplayLayout;
2266
2072
  } else if (node !== null && node !== undefined) {
2267
- // Display logic of normal nodes
2268
-
2073
+ // Real node
2269
2074
  const key = node.key,
2270
2075
  line = this.isNIL(node) ? 'S' : String(key),
2271
2076
  width = line.length;
@@ -2277,13 +2082,18 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
2277
2082
  this._displayAux(node.right, options)
2278
2083
  );
2279
2084
  } else {
2280
- // For cases where none of the conditions are met, null, undefined, and NaN nodes are not displayed
2085
+ // Null or Undefined
2281
2086
  const line = node === undefined ? 'U' : 'N',
2282
2087
  width = line.length;
2283
2088
 
2089
+ // Treat as a leaf
2284
2090
  return _buildNodeDisplay(line, width, [[''], 1, 0, 0], [[''], 1, 0, 0]);
2285
2091
  }
2286
2092
 
2093
+ /**
2094
+ * (Inner) Builds the display lines for a node.
2095
+ * @remarks Time/Space: Proportional to the width and height of the subtrees.
2096
+ */
2287
2097
  function _buildNodeDisplay(line: string, width: number, left: NodeDisplayLayout, right: NodeDisplayLayout) {
2288
2098
  const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
2289
2099
  const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
@@ -2320,22 +2130,13 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
2320
2130
  }
2321
2131
  }
2322
2132
 
2323
- protected _DEFAULT_NODE_CALLBACK = (node: BinaryTreeNode<K, V> | null | undefined) => (node ? node.key : undefined);
2324
-
2325
2133
  /**
2326
- * Time Complexity: O(1)
2327
- * Space Complexity: O(1)
2134
+ * (Protected) Swaps the key/value properties of two nodes.
2135
+ * @remarks Time O(1)
2328
2136
  *
2329
- * The _swapProperties function swaps key and value properties between two nodes in a binary tree.
2330
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } srcNode - The `srcNode` parameter in the
2331
- * `_swapProperties` method can be either a BTNRep object containing key and value
2332
- * properties, or it can be of type R.
2333
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } destNode - The `destNode` parameter in the
2334
- * `_swapProperties` method represents the node or entry where the properties will be swapped with
2335
- * the `srcNode`. It can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. The method ensures that
2336
- * both `srcNode
2337
- * @returns The `_swapProperties` method returns either the `destNode` with its key and value swapped
2338
- * with the `srcNode`, or `undefined` if either `srcNode` or `destNode` is falsy.
2137
+ * @param srcNode - The source node.
2138
+ * @param destNode - The destination node.
2139
+ * @returns The `destNode` (now holding `srcNode`'s properties).
2339
2140
  */
2340
2141
  protected _swapProperties(
2341
2142
  srcNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
@@ -2346,12 +2147,14 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
2346
2147
 
2347
2148
  if (srcNode && destNode) {
2348
2149
  const { key, value } = destNode;
2349
- const tempNode = this.createNode(key, value);
2150
+ const tempNode = this._createNode(key, value); // Use a temp node to hold dest properties
2350
2151
 
2351
2152
  if (tempNode) {
2153
+ // Copy src to dest
2352
2154
  destNode.key = srcNode.key;
2353
2155
  if (!this._isMapMode) destNode.value = srcNode.value;
2354
2156
 
2157
+ // Copy temp (original dest) to src
2355
2158
  srcNode.key = tempNode.key;
2356
2159
  if (!this._isMapMode) srcNode.value = tempNode.value;
2357
2160
  }
@@ -2362,18 +2165,12 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
2362
2165
  }
2363
2166
 
2364
2167
  /**
2365
- * Time Complexity: O(1)
2366
- * Space Complexity: O(1)
2168
+ * (Protected) Replaces a node in the tree with a new node, maintaining children and parent links.
2169
+ * @remarks Time O(1)
2367
2170
  *
2368
- * The _replaceNode function replaces an old node with a new node in a binary tree structure.
2369
- * @param {BinaryTreeNode<K, V>} oldNode - The `oldNode` parameter represents the node that you want to replace in a
2370
- * tree data structure.
2371
- * @param {BinaryTreeNode<K, V>} newNode - The `newNode` parameter in the `_replaceNode` function represents the node
2372
- * that will replace the `oldNode` in a tree data structure. This function is responsible for
2373
- * updating the parent, left child, right child, and root (if necessary) references when replacing a
2374
- * node in the tree.
2375
- * @returns The method `_replaceNode` is returning the `newNode` that was passed as a parameter after
2376
- * replacing the `oldNode` with it in the binary tree structure.
2171
+ * @param oldNode - The node to be replaced.
2172
+ * @param newNode - The node to insert.
2173
+ * @returns The `newNode`.
2377
2174
  */
2378
2175
  protected _replaceNode(oldNode: BinaryTreeNode<K, V>, newNode: BinaryTreeNode<K, V>): BinaryTreeNode<K, V> {
2379
2176
  if (oldNode.parent) {
@@ -2394,13 +2191,10 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
2394
2191
  }
2395
2192
 
2396
2193
  /**
2397
- * Time Complexity: O(1)
2398
- * Space Complexity: O(1)
2194
+ * (Protected) Sets the root node and clears its parent reference.
2195
+ * @remarks Time O(1)
2399
2196
  *
2400
- * The function _setRoot sets the root node of a data structure while updating the parent reference
2401
- * of the previous root node.
2402
- * @param v - The parameter `v` in the `_setRoot` method is of type `BinaryTreeNode<K, V> | null | undefined`, which means
2403
- * it can either be an optional `BinaryTreeNode<K, V>` type or `null`.
2197
+ * @param v - The node to set as root.
2404
2198
  */
2405
2199
  protected _setRoot(v: BinaryTreeNode<K, V> | null | undefined) {
2406
2200
  if (v) {
@@ -2409,6 +2203,13 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
2409
2203
  this._root = v;
2410
2204
  }
2411
2205
 
2206
+ /**
2207
+ * (Protected) Converts a key, node, entry, or predicate into a standardized predicate function.
2208
+ * @remarks Time O(1)
2209
+ *
2210
+ * @param keyNodeEntryOrPredicate - The item to convert.
2211
+ * @returns A predicate function.
2212
+ */
2412
2213
  protected _ensurePredicate(
2413
2214
  keyNodeEntryOrPredicate:
2414
2215
  | K
@@ -2419,18 +2220,6 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
2419
2220
  | NodePredicate<BinaryTreeNode<K, V>>
2420
2221
  ): NodePredicate<BinaryTreeNode<K, V>>;
2421
2222
 
2422
- /**
2423
- * Time Complexity: O(1)
2424
- * Space Complexity: O(1)
2425
- *
2426
- * The function `_ensurePredicate` in TypeScript ensures that the input is converted into a valid
2427
- * predicate function for a binary tree node.
2428
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate - The
2429
- * `_ensurePredicate` method in the provided code snippet is responsible for ensuring that the input
2430
- * parameter `keyNodeEntryOrPredicate` is transformed into a valid predicate function that can be
2431
- * used for filtering nodes in a binary tree.
2432
- * @returns A NodePredicate<BinaryTreeNode<K, V>> function is being returned.
2433
- */
2434
2223
  protected _ensurePredicate(
2435
2224
  keyNodeEntryOrPredicate:
2436
2225
  | K
@@ -2456,6 +2245,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
2456
2245
  };
2457
2246
  }
2458
2247
 
2248
+ // Assume it's a key
2459
2249
  return (node: BinaryTreeNode<K, V> | null) => {
2460
2250
  if (!node) return false;
2461
2251
  return node.key === keyNodeEntryOrPredicate;
@@ -2463,33 +2253,22 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
2463
2253
  }
2464
2254
 
2465
2255
  /**
2466
- * Time Complexity: O(1)
2467
- * Space Complexity: O(1)
2256
+ * (Protected) Checks if an item is a predicate function.
2257
+ * @remarks Time O(1)
2468
2258
  *
2469
- * The function `_isPredicate` checks if a given parameter is a function.
2470
- * @param {any} p - The parameter `p` is a variable of type `any`, which means it can hold any type
2471
- * of value. In this context, the function `_isPredicate` is checking if `p` is a function that
2472
- * satisfies the type `NodePredicate<BinaryTreeNode<K, V>>`.
2473
- * @returns The function is checking if the input `p` is a function and returning a boolean value
2474
- * based on that check. If `p` is a function, it will return `true`, indicating that `p` is a
2475
- * predicate function for a binary tree node. If `p` is not a function, it will return `false`.
2259
+ * @param p - The item to check.
2260
+ * @returns True if it's a function.
2476
2261
  */
2477
2262
  protected _isPredicate(p: any): p is NodePredicate<BinaryTreeNode<K, V>> {
2478
2263
  return typeof p === 'function';
2479
2264
  }
2480
2265
 
2481
2266
  /**
2482
- * Time Complexity: O(1)
2483
- * Space Complexity: O(1)
2267
+ * (Protected) Extracts the key from a key, node, or entry.
2268
+ * @remarks Time O(1)
2484
2269
  *
2485
- * The function `_extractKey` in TypeScript returns the key from a given input, which can be a node,
2486
- * entry, raw data, or null/undefined.
2487
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `_extractKey` method you provided is a
2488
- * TypeScript method that takes in a parameter `keyNodeOrEntry` of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `,
2489
- * where `BTNRep` is a generic type with keys `K`, `V`, and `BinaryTreeNode<K, V>`, and `
2490
- * @returns The `_extractKey` method returns the key value extracted from the `keyNodeOrEntry`
2491
- * parameter. The return value can be a key value of type `K`, `null`, or `undefined`, depending on
2492
- * the conditions checked in the method.
2270
+ * @param keyNodeOrEntry - The item.
2271
+ * @returns The extracted key.
2493
2272
  */
2494
2273
  protected _extractKey(
2495
2274
  keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
@@ -2505,30 +2284,22 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
2505
2284
  }
2506
2285
 
2507
2286
  /**
2508
- * Time Complexity: O(1)
2509
- * Space Complexity: O(1)
2287
+ * (Protected) Sets a value in the external store (Map mode).
2288
+ * @remarks Time O(1) (average for Map.set).
2510
2289
  *
2511
- * The function `_setValue` sets a value in a store based on a key, handling cases where the key or
2512
- * value is null or undefined.
2513
- * @param {K | null | undefined} key - The `key` parameter can be of type `K`, `null`, or
2514
- * `undefined`.
2515
- * @param {V | undefined} value - The `value` parameter in the `_setValue` method can be of type `V`
2516
- * or `undefined`.
2517
- * @returns The method `_setValue` returns `false` if either the `key` is `null` or `undefined`, or
2518
- * if the `value` is `undefined`. Otherwise, it returns the result of calling the `set` method on the
2519
- * `_store` object with the `key` and `value` arguments.
2290
+ * @param key - The key.
2291
+ * @param value - The value.
2292
+ * @returns True if successful.
2520
2293
  */
2521
2294
  protected _setValue(key: K | null | undefined, value: V | undefined) {
2522
2295
  if (key === null || key === undefined) return false;
2523
- if (value === undefined) return false;
2296
+ if (value === undefined) return false; // Or allow setting undefined?
2524
2297
  return this._store.set(key, value);
2525
2298
  }
2526
2299
 
2527
2300
  /**
2528
- * Time Complexity: O(1)
2529
- * Space Complexity: O(1)
2530
- *
2531
- * The _clearNodes function sets the root node to undefined and resets the size to 0.
2301
+ * (Protected) Clears all nodes from the tree.
2302
+ * @remarks Time O(1)
2532
2303
  */
2533
2304
  protected _clearNodes() {
2534
2305
  this._setRoot(undefined);
@@ -2536,10 +2307,8 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
2536
2307
  }
2537
2308
 
2538
2309
  /**
2539
- * Time Complexity: O(1)
2540
- * Space Complexity: O(1)
2541
- *
2542
- * The _clearValues function clears all values stored in the _store object.
2310
+ * (Protected) Clears all values from the external store.
2311
+ * @remarks Time O(N)
2543
2312
  */
2544
2313
  protected _clearValues() {
2545
2314
  this._store.clear();