graph-typed 2.0.4 → 2.1.0

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