data-structure-typed 1.52.4 → 1.52.6

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 (183) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/README.md +13 -13
  3. package/README_zh-CN.md +216 -26
  4. package/benchmark/report.html +13 -13
  5. package/benchmark/report.json +158 -158
  6. package/dist/cjs/data-structures/base/iterable-element-base.d.ts +1 -37
  7. package/dist/cjs/data-structures/base/iterable-element-base.js +1 -37
  8. package/dist/cjs/data-structures/base/iterable-element-base.js.map +1 -1
  9. package/dist/cjs/data-structures/base/iterable-entry-base.d.ts +2 -54
  10. package/dist/cjs/data-structures/base/iterable-entry-base.js +1 -49
  11. package/dist/cjs/data-structures/base/iterable-entry-base.js.map +1 -1
  12. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.d.ts +0 -32
  13. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js +9 -41
  14. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
  15. package/dist/cjs/data-structures/binary-tree/avl-tree.d.ts +0 -46
  16. package/dist/cjs/data-structures/binary-tree/avl-tree.js +0 -46
  17. package/dist/cjs/data-structures/binary-tree/avl-tree.js.map +1 -1
  18. package/dist/cjs/data-structures/binary-tree/binary-tree.d.ts +82 -147
  19. package/dist/cjs/data-structures/binary-tree/binary-tree.js +300 -332
  20. package/dist/cjs/data-structures/binary-tree/binary-tree.js.map +1 -1
  21. package/dist/cjs/data-structures/binary-tree/bst.d.ts +1 -40
  22. package/dist/cjs/data-structures/binary-tree/bst.js +12 -44
  23. package/dist/cjs/data-structures/binary-tree/bst.js.map +1 -1
  24. package/dist/cjs/data-structures/binary-tree/rb-tree.d.ts +0 -48
  25. package/dist/cjs/data-structures/binary-tree/rb-tree.js +2 -50
  26. package/dist/cjs/data-structures/binary-tree/rb-tree.js.map +1 -1
  27. package/dist/cjs/data-structures/binary-tree/tree-multi-map.d.ts +0 -32
  28. package/dist/cjs/data-structures/binary-tree/tree-multi-map.js +9 -41
  29. package/dist/cjs/data-structures/binary-tree/tree-multi-map.js.map +1 -1
  30. package/dist/cjs/data-structures/graph/abstract-graph.d.ts +0 -75
  31. package/dist/cjs/data-structures/graph/abstract-graph.js +0 -75
  32. package/dist/cjs/data-structures/graph/abstract-graph.js.map +1 -1
  33. package/dist/cjs/data-structures/graph/directed-graph.d.ts +0 -98
  34. package/dist/cjs/data-structures/graph/directed-graph.js +0 -98
  35. package/dist/cjs/data-structures/graph/directed-graph.js.map +1 -1
  36. package/dist/cjs/data-structures/graph/undirected-graph.d.ts +0 -50
  37. package/dist/cjs/data-structures/graph/undirected-graph.js +0 -50
  38. package/dist/cjs/data-structures/graph/undirected-graph.js.map +1 -1
  39. package/dist/cjs/data-structures/hash/hash-map.d.ts +5 -92
  40. package/dist/cjs/data-structures/hash/hash-map.js +27 -111
  41. package/dist/cjs/data-structures/hash/hash-map.js.map +1 -1
  42. package/dist/cjs/data-structures/heap/heap.d.ts +0 -32
  43. package/dist/cjs/data-structures/heap/heap.js +0 -32
  44. package/dist/cjs/data-structures/heap/heap.js.map +1 -1
  45. package/dist/cjs/data-structures/linked-list/doubly-linked-list.d.ts +5 -88
  46. package/dist/cjs/data-structures/linked-list/doubly-linked-list.js +5 -88
  47. package/dist/cjs/data-structures/linked-list/doubly-linked-list.js.map +1 -1
  48. package/dist/cjs/data-structures/linked-list/singly-linked-list.d.ts +1 -83
  49. package/dist/cjs/data-structures/linked-list/singly-linked-list.js +2 -84
  50. package/dist/cjs/data-structures/linked-list/singly-linked-list.js.map +1 -1
  51. package/dist/cjs/data-structures/linked-list/skip-linked-list.d.ts +1 -35
  52. package/dist/cjs/data-structures/linked-list/skip-linked-list.js +1 -35
  53. package/dist/cjs/data-structures/linked-list/skip-linked-list.js.map +1 -1
  54. package/dist/cjs/data-structures/queue/deque.d.ts +1 -98
  55. package/dist/cjs/data-structures/queue/deque.js +3 -99
  56. package/dist/cjs/data-structures/queue/deque.js.map +1 -1
  57. package/dist/cjs/data-structures/queue/queue.d.ts +1 -54
  58. package/dist/cjs/data-structures/queue/queue.js +0 -53
  59. package/dist/cjs/data-structures/queue/queue.js.map +1 -1
  60. package/dist/cjs/data-structures/stack/stack.d.ts +1 -34
  61. package/dist/cjs/data-structures/stack/stack.js +1 -34
  62. package/dist/cjs/data-structures/stack/stack.js.map +1 -1
  63. package/dist/cjs/data-structures/tree/tree.js +2 -1
  64. package/dist/cjs/data-structures/tree/tree.js.map +1 -1
  65. package/dist/cjs/data-structures/trie/trie.d.ts +0 -64
  66. package/dist/cjs/data-structures/trie/trie.js +0 -64
  67. package/dist/cjs/data-structures/trie/trie.js.map +1 -1
  68. package/dist/cjs/types/data-structures/binary-tree/binary-tree.d.ts +8 -0
  69. package/dist/cjs/types/data-structures/binary-tree/binary-tree.js +6 -0
  70. package/dist/cjs/types/data-structures/binary-tree/binary-tree.js.map +1 -1
  71. package/dist/cjs/types/utils/utils.d.ts +13 -12
  72. package/dist/cjs/utils/number.d.ts +13 -0
  73. package/dist/cjs/utils/number.js +13 -0
  74. package/dist/cjs/utils/number.js.map +1 -1
  75. package/dist/cjs/utils/utils.d.ts +125 -3
  76. package/dist/cjs/utils/utils.js +177 -21
  77. package/dist/cjs/utils/utils.js.map +1 -1
  78. package/dist/mjs/data-structures/base/iterable-element-base.d.ts +1 -37
  79. package/dist/mjs/data-structures/base/iterable-element-base.js +1 -37
  80. package/dist/mjs/data-structures/base/iterable-entry-base.d.ts +2 -54
  81. package/dist/mjs/data-structures/base/iterable-entry-base.js +1 -49
  82. package/dist/mjs/data-structures/binary-tree/avl-tree-multi-map.d.ts +0 -32
  83. package/dist/mjs/data-structures/binary-tree/avl-tree-multi-map.js +9 -41
  84. package/dist/mjs/data-structures/binary-tree/avl-tree.d.ts +0 -46
  85. package/dist/mjs/data-structures/binary-tree/avl-tree.js +0 -46
  86. package/dist/mjs/data-structures/binary-tree/binary-tree.d.ts +82 -147
  87. package/dist/mjs/data-structures/binary-tree/binary-tree.js +299 -333
  88. package/dist/mjs/data-structures/binary-tree/bst.d.ts +1 -40
  89. package/dist/mjs/data-structures/binary-tree/bst.js +12 -44
  90. package/dist/mjs/data-structures/binary-tree/rb-tree.d.ts +0 -48
  91. package/dist/mjs/data-structures/binary-tree/rb-tree.js +2 -50
  92. package/dist/mjs/data-structures/binary-tree/tree-multi-map.d.ts +0 -32
  93. package/dist/mjs/data-structures/binary-tree/tree-multi-map.js +9 -41
  94. package/dist/mjs/data-structures/graph/abstract-graph.d.ts +0 -75
  95. package/dist/mjs/data-structures/graph/abstract-graph.js +0 -75
  96. package/dist/mjs/data-structures/graph/directed-graph.d.ts +0 -98
  97. package/dist/mjs/data-structures/graph/directed-graph.js +0 -98
  98. package/dist/mjs/data-structures/graph/undirected-graph.d.ts +0 -50
  99. package/dist/mjs/data-structures/graph/undirected-graph.js +0 -50
  100. package/dist/mjs/data-structures/hash/hash-map.d.ts +5 -92
  101. package/dist/mjs/data-structures/hash/hash-map.js +27 -111
  102. package/dist/mjs/data-structures/heap/heap.d.ts +0 -32
  103. package/dist/mjs/data-structures/heap/heap.js +0 -32
  104. package/dist/mjs/data-structures/linked-list/doubly-linked-list.d.ts +5 -88
  105. package/dist/mjs/data-structures/linked-list/doubly-linked-list.js +5 -88
  106. package/dist/mjs/data-structures/linked-list/singly-linked-list.d.ts +1 -83
  107. package/dist/mjs/data-structures/linked-list/singly-linked-list.js +2 -84
  108. package/dist/mjs/data-structures/linked-list/skip-linked-list.d.ts +1 -35
  109. package/dist/mjs/data-structures/linked-list/skip-linked-list.js +1 -35
  110. package/dist/mjs/data-structures/queue/deque.d.ts +1 -98
  111. package/dist/mjs/data-structures/queue/deque.js +3 -99
  112. package/dist/mjs/data-structures/queue/queue.d.ts +1 -54
  113. package/dist/mjs/data-structures/queue/queue.js +0 -53
  114. package/dist/mjs/data-structures/stack/stack.d.ts +1 -34
  115. package/dist/mjs/data-structures/stack/stack.js +1 -34
  116. package/dist/mjs/data-structures/tree/tree.js +2 -1
  117. package/dist/mjs/data-structures/trie/trie.d.ts +0 -64
  118. package/dist/mjs/data-structures/trie/trie.js +0 -64
  119. package/dist/mjs/types/data-structures/binary-tree/binary-tree.d.ts +8 -0
  120. package/dist/mjs/types/data-structures/binary-tree/binary-tree.js +5 -1
  121. package/dist/mjs/types/utils/utils.d.ts +13 -12
  122. package/dist/mjs/utils/number.d.ts +13 -0
  123. package/dist/mjs/utils/number.js +13 -0
  124. package/dist/mjs/utils/utils.d.ts +125 -3
  125. package/dist/mjs/utils/utils.js +177 -21
  126. package/dist/umd/data-structure-typed.js +411 -1475
  127. package/dist/umd/data-structure-typed.min.js +5 -4
  128. package/dist/umd/data-structure-typed.min.js.map +1 -1
  129. package/package.json +6 -6
  130. package/src/data-structures/base/iterable-element-base.ts +2 -42
  131. package/src/data-structures/base/iterable-entry-base.ts +3 -62
  132. package/src/data-structures/binary-tree/avl-tree-multi-map.ts +8 -48
  133. package/src/data-structures/binary-tree/avl-tree.ts +0 -57
  134. package/src/data-structures/binary-tree/binary-tree.ts +330 -359
  135. package/src/data-structures/binary-tree/bst.ts +11 -54
  136. package/src/data-structures/binary-tree/rb-tree.ts +2 -62
  137. package/src/data-structures/binary-tree/tree-multi-map.ts +8 -48
  138. package/src/data-structures/graph/abstract-graph.ts +0 -92
  139. package/src/data-structures/graph/directed-graph.ts +0 -122
  140. package/src/data-structures/graph/undirected-graph.ts +0 -62
  141. package/src/data-structures/hash/hash-map.ts +29 -133
  142. package/src/data-structures/heap/heap.ts +0 -40
  143. package/src/data-structures/linked-list/doubly-linked-list.ts +5 -112
  144. package/src/data-structures/linked-list/singly-linked-list.ts +2 -104
  145. package/src/data-structures/linked-list/skip-linked-list.ts +1 -44
  146. package/src/data-structures/queue/deque.ts +2 -125
  147. package/src/data-structures/queue/queue.ts +1 -68
  148. package/src/data-structures/stack/stack.ts +1 -43
  149. package/src/data-structures/tree/tree.ts +1 -1
  150. package/src/data-structures/trie/trie.ts +0 -80
  151. package/src/types/data-structures/binary-tree/binary-tree.ts +8 -1
  152. package/src/types/utils/utils.ts +17 -15
  153. package/src/utils/number.ts +13 -0
  154. package/src/utils/utils.ts +174 -18
  155. package/test/config.ts +8 -0
  156. package/test/integration/all-in-one.test.ts +1 -1
  157. package/test/integration/avl-tree.test.ts +1 -1
  158. package/test/integration/bst.test.ts +2 -2
  159. package/test/unit/data-structures/binary-tree/avl-tree-multi-map.test.ts +13 -13
  160. package/test/unit/data-structures/binary-tree/avl-tree.test.ts +18 -13
  161. package/test/unit/data-structures/binary-tree/binary-tree.test.ts +577 -167
  162. package/test/unit/data-structures/binary-tree/bst.test.ts +167 -23
  163. package/test/unit/data-structures/binary-tree/overall.test.ts +1 -1
  164. package/test/unit/data-structures/binary-tree/rb-tree.test.ts +136 -13
  165. package/test/unit/data-structures/binary-tree/tree-multi-map.test.ts +18 -13
  166. package/test/unit/data-structures/graph/directed-graph.test.ts +46 -32
  167. package/test/unit/data-structures/graph/map-graph.test.ts +24 -2
  168. package/test/unit/data-structures/graph/undirected-graph.test.ts +24 -24
  169. package/test/unit/data-structures/hash/hash-map.test.ts +225 -35
  170. package/test/unit/data-structures/heap/heap.test.ts +47 -39
  171. package/test/unit/data-structures/heap/min-heap.test.ts +5 -5
  172. package/test/unit/data-structures/linked-list/doubly-linked-list.test.ts +34 -4
  173. package/test/unit/data-structures/linked-list/singly-linked-list.test.ts +32 -0
  174. package/test/unit/data-structures/matrix/matrix.test.ts +35 -5
  175. package/test/unit/data-structures/priority-queue/max-priority-queue.test.ts +31 -0
  176. package/test/unit/data-structures/priority-queue/min-priority-queue.test.ts +18 -0
  177. package/test/unit/data-structures/priority-queue/priority-queue.test.ts +17 -0
  178. package/test/unit/data-structures/queue/deque.test.ts +288 -47
  179. package/test/unit/data-structures/queue/queue.test.ts +62 -37
  180. package/test/unit/data-structures/stack/stack.test.ts +30 -5
  181. package/test/unit/data-structures/tree/tree.test.ts +58 -0
  182. package/test/unit/data-structures/trie/trie.test.ts +46 -5
  183. package/test/unit/utils/utils.test.ts +169 -0
@@ -5,7 +5,8 @@
5
5
  * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
6
6
  * @license MIT License
7
7
  */
8
- import { trampoline } from '../../utils';
8
+ import { DFSOperation } from '../../types';
9
+ import { isComparable, trampoline } from '../../utils';
9
10
  import { Queue } from '../queue';
10
11
  import { IterableEntryBase } from '../base';
11
12
  /**
@@ -189,30 +190,26 @@ export class BinaryTree extends IterableEntryBase {
189
190
  return null;
190
191
  if (this.isNode(keyOrNodeOrEntryOrRawElement))
191
192
  return keyOrNodeOrEntryOrRawElement;
192
- if (this.toEntryFn) {
193
- const [key, entryValue] = this.toEntryFn(keyOrNodeOrEntryOrRawElement);
194
- if (key)
195
- return this.createNode(key, entryValue ?? value);
196
- else
197
- return;
198
- }
199
193
  if (this.isEntry(keyOrNodeOrEntryOrRawElement)) {
200
- const [key, value] = keyOrNodeOrEntryOrRawElement;
194
+ const [key, entryValue] = keyOrNodeOrEntryOrRawElement;
201
195
  if (key === undefined)
202
196
  return;
203
197
  else if (key === null)
204
198
  return null;
199
+ if (this.isKey(key))
200
+ return this.createNode(key, value ?? entryValue);
201
+ }
202
+ if (this.toEntryFn) {
203
+ const [key, entryValue] = this.toEntryFn(keyOrNodeOrEntryOrRawElement);
204
+ if (this.isKey(key))
205
+ return this.createNode(key, value ?? entryValue);
205
206
  else
206
- return this.createNode(key, value);
207
+ return;
207
208
  }
208
209
  if (this.isKey(keyOrNodeOrEntryOrRawElement))
209
210
  return this.createNode(keyOrNodeOrEntryOrRawElement, value);
210
211
  return;
211
212
  }
212
- /**
213
- * Time Complexity: O(n)
214
- * Space Complexity: O(log n)
215
- */
216
213
  /**
217
214
  * Time Complexity: O(n)
218
215
  * Space Complexity: O(log n)
@@ -227,7 +224,7 @@ export class BinaryTree extends IterableEntryBase {
227
224
  * default value of `'ITERATIVE'`.
228
225
  * @returns The function `ensureNode` returns either a `NODE` object, `null`, or `undefined`.
229
226
  */
230
- ensureNode(keyOrNodeOrEntryOrRawElement, iterationType = 'ITERATIVE') {
227
+ ensureNode(keyOrNodeOrEntryOrRawElement, iterationType = this.iterationType) {
231
228
  if (keyOrNodeOrEntryOrRawElement === null)
232
229
  return null;
233
230
  if (keyOrNodeOrEntryOrRawElement === undefined)
@@ -238,7 +235,7 @@ export class BinaryTree extends IterableEntryBase {
238
235
  return keyOrNodeOrEntryOrRawElement;
239
236
  if (this.toEntryFn) {
240
237
  const [key] = this.toEntryFn(keyOrNodeOrEntryOrRawElement);
241
- if (key)
238
+ if (this.isKey(key))
242
239
  return this.getNodeByKey(key);
243
240
  }
244
241
  if (this.isEntry(keyOrNodeOrEntryOrRawElement)) {
@@ -280,8 +277,8 @@ export class BinaryTree extends IterableEntryBase {
280
277
  * `BTNKeyOrNodeOrEntry<K, V, NODE>`.
281
278
  * @returns a boolean value.
282
279
  */
283
- isNodeOrNull(node) {
284
- return this.isRealNode(node) || node === null;
280
+ isRealNodeOrNull(node) {
281
+ return node === null || this.isRealNode(node);
285
282
  }
286
283
  /**
287
284
  * The function checks if a given node is equal to the NIL value.
@@ -292,6 +289,23 @@ export class BinaryTree extends IterableEntryBase {
292
289
  isNIL(node) {
293
290
  return node === this.NIL;
294
291
  }
292
+ /**
293
+ * The function `isLeaf` determines whether a given node is a leaf node in a binary tree structure.
294
+ * @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} node - The `node` parameter in the `isLeaf` function
295
+ * can be either a regular node (`R`) or a `BTNKeyOrNodeOrEntry<K, V, NODE>`.
296
+ * @returns The `isLeaf` function is checking if the provided node is a leaf node in a binary tree.
297
+ * If the node is `undefined`, it returns `false`. If the node is `null`, it returns `true`.
298
+ * Otherwise, it checks if both the left and right children of the node are not real nodes, and
299
+ * returns `true` if they are not, indicating that the node is a
300
+ */
301
+ isLeaf(node) {
302
+ node = this.ensureNode(node);
303
+ if (node === undefined)
304
+ return false;
305
+ if (node === null)
306
+ return true;
307
+ return !this.isRealNode(node.left) && !this.isRealNode(node.right);
308
+ }
295
309
  /**
296
310
  * The function checks if the input is an array with two elements, indicating it is a binary tree
297
311
  * node entry.
@@ -303,41 +317,21 @@ export class BinaryTree extends IterableEntryBase {
303
317
  return Array.isArray(keyOrNodeOrEntryOrRawElement) && keyOrNodeOrEntryOrRawElement.length === 2;
304
318
  }
305
319
  /**
306
- * The function checks if a given value is a valid key by evaluating its type and value.
307
- * @param {any} key - The `key` parameter can be of any type. It is the value that we want to check
308
- * if it is a valid key.
309
- * @param [isCheckValueOf=true] - The `isCheckValueOf` parameter is a boolean flag that determines
310
- * whether the function should check the valueOf() method of an object when the key is of type
311
- * 'object'. If `isCheckValueOf` is true, the function will recursively call itself with the value
312
- * returned by key.valueOf().
313
- * @returns a boolean value.
314
- */
315
- isKey(key, isCheckValueOf = true) {
320
+ * Time Complexity O(1)
321
+ * Space Complexity O(1)
322
+ *
323
+ * The function `isKey` checks if a given key is comparable.
324
+ * @param {any} key - The `key` parameter is of type `any`, which means it can be any data type in
325
+ * TypeScript.
326
+ * @returns The function `isKey` is checking if the `key` parameter is `null` or if it is comparable.
327
+ * If the `key` is `null`, the function returns `true`. Otherwise, it returns the result of the
328
+ * `isComparable` function, which is not provided in the code snippet.
329
+ */
330
+ isKey(key) {
316
331
  if (key === null)
317
332
  return true;
318
- const keyType = typeof key;
319
- if (keyType === 'string' || keyType === 'bigint' || keyType === 'boolean')
320
- return true;
321
- if (keyType === 'number')
322
- return !isNaN(key);
323
- if (keyType === 'symbol' || keyType === 'undefined')
324
- return false;
325
- if (keyType === 'function')
326
- return this.isKey(key());
327
- if (keyType === 'object') {
328
- if (typeof key.toString === 'function')
329
- return true;
330
- if (isCheckValueOf && typeof key.valueOf === 'function') {
331
- this.isKey(key.valueOf(), false);
332
- }
333
- return false;
334
- }
335
- return false;
333
+ return isComparable(key);
336
334
  }
337
- /**
338
- * Time Complexity O(n)
339
- * Space Complexity O(1)
340
- */
341
335
  /**
342
336
  * Time Complexity O(n)
343
337
  * Space Complexity O(1)
@@ -400,11 +394,6 @@ export class BinaryTree extends IterableEntryBase {
400
394
  }
401
395
  return false; // If the insertion position cannot be found, return undefined
402
396
  }
403
- /**
404
- * Time Complexity: O(k * n)
405
- * Space Complexity: O(1)
406
- * Comments: The time complexity for adding a node depends on the depth of the tree. In the best case (when the tree is empty), it's O(1). In the worst case (when the tree is a degenerate tree), it's O(n). The space complexity is constant.
407
- */
408
397
  /**
409
398
  * Time Complexity: O(k * n)
410
399
  * Space Complexity: O(1)
@@ -438,11 +427,6 @@ export class BinaryTree extends IterableEntryBase {
438
427
  }
439
428
  return inserted;
440
429
  }
441
- /**
442
- * Time Complexity: O(k * n)
443
- * Space Complexity: O(1)
444
- * "n" is the number of nodes in the tree, and "k" is the number of keys to be inserted.
445
- */
446
430
  /**
447
431
  * Time Complexity: O(k * n)
448
432
  * Space Complexity: O(1)
@@ -458,10 +442,6 @@ export class BinaryTree extends IterableEntryBase {
458
442
  this.clear();
459
443
  this.addMany(keysOrNodesOrEntriesOrRawElements, values);
460
444
  }
461
- /**
462
- * Time Complexity: O(n)
463
- * Space Complexity: O(1)
464
- */
465
445
  /**
466
446
  * Time Complexity: O(n)
467
447
  * Space Complexity: O(1)
@@ -492,7 +472,7 @@ export class BinaryTree extends IterableEntryBase {
492
472
  this._setRoot(undefined);
493
473
  }
494
474
  else if (curr.left) {
495
- const leftSubTreeRightMost = this.getRightMost(curr.left);
475
+ const leftSubTreeRightMost = this.getRightMost(node => node, curr.left);
496
476
  if (leftSubTreeRightMost) {
497
477
  const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;
498
478
  orgCurrent = this._swapProperties(curr, leftSubTreeRightMost);
@@ -523,10 +503,6 @@ export class BinaryTree extends IterableEntryBase {
523
503
  deletedResult.push({ deleted: orgCurrent, needBalanced });
524
504
  return deletedResult;
525
505
  }
526
- /**
527
- * Time Complexity: O(n)
528
- * Space Complexity: O(k + log n)
529
- */
530
506
  /**
531
507
  * Time Complexity: O(n)
532
508
  * Space Complexity: O(k + log n)
@@ -552,6 +528,10 @@ export class BinaryTree extends IterableEntryBase {
552
528
  * @returns an array of NODE objects.
553
529
  */
554
530
  getNodes(identifier, callback = this._DEFAULT_CALLBACK, onlyOne = false, beginRoot = this.root, iterationType = this.iterationType) {
531
+ if (identifier === undefined)
532
+ return [];
533
+ if (identifier === null)
534
+ return [];
555
535
  beginRoot = this.ensureNode(beginRoot);
556
536
  if (!beginRoot)
557
537
  return [];
@@ -588,10 +568,6 @@ export class BinaryTree extends IterableEntryBase {
588
568
  }
589
569
  return ans;
590
570
  }
591
- /**
592
- * Time Complexity: O(n)
593
- * Space Complexity: O(log n).
594
- */
595
571
  /**
596
572
  * Time Complexity: O(n)
597
573
  * Space Complexity: O(log n).
@@ -613,10 +589,6 @@ export class BinaryTree extends IterableEntryBase {
613
589
  getNode(identifier, callback = this._DEFAULT_CALLBACK, beginRoot = this.root, iterationType = this.iterationType) {
614
590
  return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? null;
615
591
  }
616
- /**
617
- * Time Complexity: O(n)
618
- * Space Complexity: O(log n)
619
- */
620
592
  /**
621
593
  * Time Complexity: O(n)
622
594
  * Space Complexity: O(log n)
@@ -629,13 +601,9 @@ export class BinaryTree extends IterableEntryBase {
629
601
  * It has a default value of `'ITERATIVE'`.
630
602
  * @returns a value of type NODE, null, or undefined.
631
603
  */
632
- getNodeByKey(key, iterationType = 'ITERATIVE') {
604
+ getNodeByKey(key, iterationType = this.iterationType) {
633
605
  return this.getNode(key, this._DEFAULT_CALLBACK, this.root, iterationType);
634
606
  }
635
- /**
636
- * Time Complexity: O(n)
637
- * Space Complexity: O(log n)
638
- */
639
607
  /**
640
608
  * Time Complexity: O(n)
641
609
  * Space Complexity: O(log n)
@@ -660,10 +628,6 @@ export class BinaryTree extends IterableEntryBase {
660
628
  get(identifier, callback = this._DEFAULT_CALLBACK, beginRoot = this.root, iterationType = this.iterationType) {
661
629
  return this.getNode(identifier, callback, beginRoot, iterationType)?.value;
662
630
  }
663
- /**
664
- * Time Complexity: O(n)
665
- * Space Complexity: O(log n)
666
- */
667
631
  /**
668
632
  * Time Complexity: O(n)
669
633
  * Space Complexity: O(log n)
@@ -688,10 +652,6 @@ export class BinaryTree extends IterableEntryBase {
688
652
  callback = this._ensureCallback(identifier, callback);
689
653
  return this.getNodes(identifier, callback, true, beginRoot, iterationType).length > 0;
690
654
  }
691
- /**
692
- * Time Complexity: O(1)
693
- * Space Complexity: O(1)
694
- */
695
655
  /**
696
656
  * Time Complexity: O(1)
697
657
  * Space Complexity: O(1)
@@ -702,10 +662,6 @@ export class BinaryTree extends IterableEntryBase {
702
662
  this._setRoot(undefined);
703
663
  this._size = 0;
704
664
  }
705
- /**
706
- * Time Complexity: O(1)
707
- * Space Complexity: O(1)
708
- */
709
665
  /**
710
666
  * Time Complexity: O(1)
711
667
  * Space Complexity: O(1)
@@ -716,10 +672,6 @@ export class BinaryTree extends IterableEntryBase {
716
672
  isEmpty() {
717
673
  return this.size === 0;
718
674
  }
719
- /**
720
- * Time Complexity: O(n)
721
- * Space Complexity: O(log n)
722
- */
723
675
  /**
724
676
  * Time Complexity: O(n)
725
677
  * Space Complexity: O(log n)
@@ -735,10 +687,6 @@ export class BinaryTree extends IterableEntryBase {
735
687
  isPerfectlyBalanced(beginRoot = this.root) {
736
688
  return this.getMinHeight(beginRoot) + 1 >= this.getHeight(beginRoot);
737
689
  }
738
- /**
739
- * Time Complexity: O(n)
740
- * Space Complexity: O(1)
741
- */
742
690
  /**
743
691
  * Time Complexity: O(n)
744
692
  * Space Complexity: O(1)
@@ -795,10 +743,6 @@ export class BinaryTree extends IterableEntryBase {
795
743
  return isStandardBST || isInverseBST;
796
744
  }
797
745
  }
798
- /**
799
- * Time Complexity: O(n)
800
- * Space Complexity: O(1)
801
- */
802
746
  /**
803
747
  * Time Complexity: O(n)
804
748
  * Space Complexity: O(1)
@@ -826,10 +770,6 @@ export class BinaryTree extends IterableEntryBase {
826
770
  }
827
771
  return depth;
828
772
  }
829
- /**
830
- * Time Complexity: O(n)
831
- * Space Complexity: O(1)
832
- */
833
773
  /**
834
774
  * Time Complexity: O(n)
835
775
  * Space Complexity: O(1)
@@ -871,10 +811,6 @@ export class BinaryTree extends IterableEntryBase {
871
811
  return maxHeight;
872
812
  }
873
813
  }
874
- /**
875
- * Time Complexity: O(n)
876
- * Space Complexity: O(log n)
877
- */
878
814
  /**
879
815
  * Time Complexity: O(n)
880
816
  * Space Complexity: O(log n)
@@ -935,10 +871,6 @@ export class BinaryTree extends IterableEntryBase {
935
871
  return depths.get(beginRoot) ?? -1;
936
872
  }
937
873
  }
938
- /**
939
- * Time Complexity: O(log n)
940
- * Space Complexity: O(log n)
941
- */
942
874
  /**
943
875
  * Time Complexity: O(log n)
944
876
  * Space Complexity: O(log n)
@@ -965,36 +897,40 @@ export class BinaryTree extends IterableEntryBase {
965
897
  result.push(beginNodeEnsured);
966
898
  return isReverse ? result.reverse() : result;
967
899
  }
968
- /**
969
- * Time Complexity: O(log n)
970
- * Space Complexity: O(1)
971
- */
972
900
  /**
973
901
  * Time Complexity: O(log n)
974
902
  * Space Complexity: O(1)
975
903
  *
976
- * The `getLeftMost` function returns the leftmost node in a binary tree, either using recursive or
977
- * iterative traversal.
978
- * @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} beginRoot - The `beginRoot` parameter represents the
979
- * starting point for finding the leftmost node in a binary tree. It can be either a root node (`R`),
980
- * a key or node or entry (`BTNKeyOrNodeOrEntry<K, V, NODE>`), or `null` or `undefined`.
981
- * @param {IterationType} iterationType - The `iterationType` parameter is used to specify the type
982
- * of iteration to be performed. It can have two possible values:
983
- * @returns The function `getLeftMost` returns the leftmost node in a binary tree.
904
+ * The function `getLeftMost` retrieves the leftmost node in a binary tree using either recursive or
905
+ * tail-recursive iteration.
906
+ * @param {C} callback - The `callback` parameter is a function that will be called with the leftmost
907
+ * node of a binary tree or null if the tree is empty. It has a default value of `_DEFAULT_CALLBACK`
908
+ * if not provided explicitly.
909
+ * @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} beginRoot - The `beginRoot` parameter in the
910
+ * `getLeftMost` function represents the starting point for finding the leftmost node in a binary
911
+ * tree. It can be either a reference to the root node of the tree (`R`), or a key, node, or entry in
912
+ * the binary tree structure (`
913
+ * @param {IterationType} iterationType - The `iterationType` parameter in the `getLeftMost` function
914
+ * specifies the type of iteration to be used when traversing the binary tree nodes. It can have two
915
+ * possible values:
916
+ * @returns The `getLeftMost` function returns the result of the callback function `C` applied to the
917
+ * leftmost node in the binary tree starting from the `beginRoot` node. If the `beginRoot` is `NIL`,
918
+ * it returns the result of the callback function applied to `undefined`. If the `beginRoot` is not a
919
+ * real node, it returns the result of the callback function applied
984
920
  */
985
- getLeftMost(beginRoot = this.root, iterationType = this.iterationType) {
921
+ getLeftMost(callback = this._DEFAULT_CALLBACK, beginRoot = this.root, iterationType = this.iterationType) {
986
922
  if (this.isNIL(beginRoot))
987
- return beginRoot;
923
+ return callback(undefined);
988
924
  beginRoot = this.ensureNode(beginRoot);
989
925
  if (!this.isRealNode(beginRoot))
990
- return beginRoot;
926
+ return callback(beginRoot);
991
927
  if (iterationType === 'RECURSIVE') {
992
928
  const dfs = (cur) => {
993
929
  if (!this.isRealNode(cur.left))
994
930
  return cur;
995
931
  return dfs(cur.left);
996
932
  };
997
- return dfs(beginRoot);
933
+ return callback(dfs(beginRoot));
998
934
  }
999
935
  else {
1000
936
  // Indirect implementation of iteration using tail recursion optimization
@@ -1003,41 +939,45 @@ export class BinaryTree extends IterableEntryBase {
1003
939
  return cur;
1004
940
  return dfs.cont(cur.left);
1005
941
  });
1006
- return dfs(beginRoot);
942
+ return callback(dfs(beginRoot));
1007
943
  }
1008
944
  }
1009
- /**
1010
- * Time Complexity: O(log n)
1011
- * Space Complexity: O(1)
1012
- */
1013
945
  /**
1014
946
  * Time Complexity: O(log n)
1015
947
  * Space Complexity: O(1)
1016
948
  *
1017
- * The `getRightMost` function returns the rightmost node in a binary tree, either recursively or
1018
- * iteratively.
1019
- * @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} beginRoot - The `beginRoot` parameter represents the
1020
- * starting point for finding the rightmost node in a binary tree. It can be either a root node
1021
- * (`R`), a key or node or entry (`BTNKeyOrNodeOrEntry<K, V, NODE>`), or `null` or `undefined`.
1022
- * @param {IterationType} iterationType - The `iterationType` parameter is used to specify the type
1023
- * of iteration to be performed when finding the rightmost node in a binary tree. It can have two
1024
- * possible values:
1025
- * @returns The function `getRightMost` returns a NODE object, `null`, or `undefined`.
1026
- */
1027
- getRightMost(beginRoot = this.root, iterationType = this.iterationType) {
949
+ * The function `getRightMost` retrieves the rightmost node in a binary tree using either recursive
950
+ * or iterative traversal methods.
951
+ * @param {C} callback - The `callback` parameter is a function that will be called with the result
952
+ * of the operation. It has a generic type `C` which extends `BTNCallback<OptBTNOrNull<NODE>>`. The
953
+ * default value for `callback` is `this._DEFAULT_CALLBACK` if it is not provided.
954
+ * @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} beginRoot - The `beginRoot` parameter in the
955
+ * `getRightMost` function represents the starting point for finding the rightmost node in a binary
956
+ * tree. It can be either a reference to the root node of the tree (`this.root`) or a specific key,
957
+ * node, or entry in the tree. If
958
+ * @param {IterationType} iterationType - The `iterationType` parameter in the `getRightMost`
959
+ * function specifies the type of iteration to be used when finding the rightmost node in a binary
960
+ * tree. It can have two possible values:
961
+ * @returns The `getRightMost` function returns the result of the callback function `C` applied to
962
+ * the rightmost node in the binary tree. The rightmost node is found either through a recursive
963
+ * depth-first search (if `iterationType` is 'RECURSIVE') or through an indirect implementation of
964
+ * iteration using tail recursion optimization. The result of the callback function applied to the
965
+ * rightmost node is returned
966
+ */
967
+ getRightMost(callback = this._DEFAULT_CALLBACK, beginRoot = this.root, iterationType = this.iterationType) {
1028
968
  if (this.isNIL(beginRoot))
1029
- return beginRoot;
969
+ return callback(undefined);
1030
970
  // TODO support get right most by passing key in
1031
971
  beginRoot = this.ensureNode(beginRoot);
1032
972
  if (!beginRoot)
1033
- return beginRoot;
973
+ return callback(beginRoot);
1034
974
  if (iterationType === 'RECURSIVE') {
1035
975
  const dfs = (cur) => {
1036
976
  if (!this.isRealNode(cur.right))
1037
977
  return cur;
1038
978
  return dfs(cur.right);
1039
979
  };
1040
- return dfs(beginRoot);
980
+ return callback(dfs(beginRoot));
1041
981
  }
1042
982
  else {
1043
983
  // Indirect implementation of iteration using tail recursion optimization
@@ -1046,13 +986,9 @@ export class BinaryTree extends IterableEntryBase {
1046
986
  return cur;
1047
987
  return dfs.cont(cur.right);
1048
988
  });
1049
- return dfs(beginRoot);
989
+ return callback(dfs(beginRoot));
1050
990
  }
1051
991
  }
1052
- /**
1053
- * Time Complexity: O(log n)
1054
- * Space Complexity: O(1)
1055
- */
1056
992
  /**
1057
993
  * Time Complexity: O(log n)
1058
994
  * Space Complexity: O(1)
@@ -1076,10 +1012,6 @@ export class BinaryTree extends IterableEntryBase {
1076
1012
  return node;
1077
1013
  }
1078
1014
  }
1079
- /**
1080
- * Time Complexity: O(log n)
1081
- * Space Complexity: O(1)
1082
- */
1083
1015
  /**
1084
1016
  * Time Complexity: O(log n)
1085
1017
  * Space Complexity: O(1)
@@ -1094,7 +1026,7 @@ export class BinaryTree extends IterableEntryBase {
1094
1026
  if (!this.isRealNode(x))
1095
1027
  return undefined;
1096
1028
  if (this.isRealNode(x.right)) {
1097
- return this.getLeftMost(x.right);
1029
+ return this.getLeftMost(node => node, x.right);
1098
1030
  }
1099
1031
  let y = x.parent;
1100
1032
  while (this.isRealNode(y) && x === y.right) {
@@ -1103,10 +1035,6 @@ export class BinaryTree extends IterableEntryBase {
1103
1035
  }
1104
1036
  return y;
1105
1037
  }
1106
- /**
1107
- * Time complexity: O(n)
1108
- * Space complexity: O(n)
1109
- */
1110
1038
  /**
1111
1039
  * Time complexity: O(n)
1112
1040
  * Space complexity: O(n)
@@ -1130,116 +1058,12 @@ export class BinaryTree extends IterableEntryBase {
1130
1058
  * values will
1131
1059
  * @returns an array of the return types of the callback function.
1132
1060
  */
1133
- dfs(callback = this._DEFAULT_CALLBACK, pattern = 'IN', beginRoot = this.root, iterationType = 'ITERATIVE', includeNull = false) {
1061
+ dfs(callback = this._DEFAULT_CALLBACK, pattern = 'IN', beginRoot = this.root, iterationType = this.iterationType, includeNull = false) {
1134
1062
  beginRoot = this.ensureNode(beginRoot);
1135
1063
  if (!beginRoot)
1136
1064
  return [];
1137
- const ans = [];
1138
- if (iterationType === 'RECURSIVE') {
1139
- const dfs = (node) => {
1140
- switch (pattern) {
1141
- case 'IN':
1142
- if (includeNull) {
1143
- if (this.isRealNode(node) && this.isNodeOrNull(node.left))
1144
- dfs(node.left);
1145
- this.isNodeOrNull(node) && ans.push(callback(node));
1146
- if (this.isRealNode(node) && this.isNodeOrNull(node.right))
1147
- dfs(node.right);
1148
- }
1149
- else {
1150
- if (this.isRealNode(node) && this.isRealNode(node.left))
1151
- dfs(node.left);
1152
- this.isRealNode(node) && ans.push(callback(node));
1153
- if (this.isRealNode(node) && this.isRealNode(node.right))
1154
- dfs(node.right);
1155
- }
1156
- break;
1157
- case 'PRE':
1158
- if (includeNull) {
1159
- this.isNodeOrNull(node) && ans.push(callback(node));
1160
- if (this.isRealNode(node) && this.isNodeOrNull(node.left))
1161
- dfs(node.left);
1162
- if (this.isRealNode(node) && this.isNodeOrNull(node.right))
1163
- dfs(node.right);
1164
- }
1165
- else {
1166
- this.isRealNode(node) && ans.push(callback(node));
1167
- if (this.isRealNode(node) && this.isRealNode(node.left))
1168
- dfs(node.left);
1169
- if (this.isRealNode(node) && this.isRealNode(node.right))
1170
- dfs(node.right);
1171
- }
1172
- break;
1173
- case 'POST':
1174
- if (includeNull) {
1175
- if (this.isRealNode(node) && this.isNodeOrNull(node.left))
1176
- dfs(node.left);
1177
- if (this.isRealNode(node) && this.isNodeOrNull(node.right))
1178
- dfs(node.right);
1179
- this.isNodeOrNull(node) && ans.push(callback(node));
1180
- }
1181
- else {
1182
- if (this.isRealNode(node) && this.isRealNode(node.left))
1183
- dfs(node.left);
1184
- if (this.isRealNode(node) && this.isRealNode(node.right))
1185
- dfs(node.right);
1186
- this.isRealNode(node) && ans.push(callback(node));
1187
- }
1188
- break;
1189
- }
1190
- };
1191
- dfs(beginRoot);
1192
- }
1193
- else {
1194
- // 0: visit, 1: print
1195
- const stack = [{ opt: 0, node: beginRoot }];
1196
- while (stack.length > 0) {
1197
- const cur = stack.pop();
1198
- if (cur === undefined || this.isNIL(cur.node))
1199
- continue;
1200
- if (includeNull) {
1201
- if (cur.node === undefined)
1202
- continue;
1203
- }
1204
- else {
1205
- if (cur.node === null || cur.node === undefined)
1206
- continue;
1207
- }
1208
- if (cur.opt === 1) {
1209
- ans.push(callback(cur.node));
1210
- }
1211
- else {
1212
- switch (pattern) {
1213
- case 'IN':
1214
- cur.node && stack.push({ opt: 0, node: cur.node.right });
1215
- stack.push({ opt: 1, node: cur.node });
1216
- cur.node && stack.push({ opt: 0, node: cur.node.left });
1217
- break;
1218
- case 'PRE':
1219
- cur.node && stack.push({ opt: 0, node: cur.node.right });
1220
- cur.node && stack.push({ opt: 0, node: cur.node.left });
1221
- stack.push({ opt: 1, node: cur.node });
1222
- break;
1223
- case 'POST':
1224
- stack.push({ opt: 1, node: cur.node });
1225
- cur.node && stack.push({ opt: 0, node: cur.node.right });
1226
- cur.node && stack.push({ opt: 0, node: cur.node.left });
1227
- break;
1228
- default:
1229
- cur.node && stack.push({ opt: 0, node: cur.node.right });
1230
- stack.push({ opt: 1, node: cur.node });
1231
- cur.node && stack.push({ opt: 0, node: cur.node.left });
1232
- break;
1233
- }
1234
- }
1235
- }
1236
- }
1237
- return ans;
1065
+ return this._dfs(callback, pattern, beginRoot, iterationType, includeNull);
1238
1066
  }
1239
- /**
1240
- * Time complexity: O(n)
1241
- * Space complexity: O(n)
1242
- */
1243
1067
  /**
1244
1068
  * Time complexity: O(n)
1245
1069
  * Space complexity: O(n)
@@ -1275,9 +1099,9 @@ export class BinaryTree extends IterableEntryBase {
1275
1099
  const current = queue.shift();
1276
1100
  ans.push(callback(current));
1277
1101
  if (includeNull) {
1278
- if (current && this.isNodeOrNull(current.left))
1102
+ if (current && this.isRealNodeOrNull(current.left))
1279
1103
  queue.push(current.left);
1280
- if (current && this.isNodeOrNull(current.right))
1104
+ if (current && this.isRealNodeOrNull(current.right))
1281
1105
  queue.push(current.right);
1282
1106
  }
1283
1107
  else {
@@ -1298,9 +1122,9 @@ export class BinaryTree extends IterableEntryBase {
1298
1122
  const current = queue.shift();
1299
1123
  ans.push(callback(current));
1300
1124
  if (includeNull) {
1301
- if (current && this.isNodeOrNull(current.left))
1125
+ if (current && this.isRealNodeOrNull(current.left))
1302
1126
  queue.push(current.left);
1303
- if (current && this.isNodeOrNull(current.right))
1127
+ if (current && this.isRealNodeOrNull(current.right))
1304
1128
  queue.push(current.right);
1305
1129
  }
1306
1130
  else {
@@ -1317,7 +1141,55 @@ export class BinaryTree extends IterableEntryBase {
1317
1141
  /**
1318
1142
  * Time complexity: O(n)
1319
1143
  * Space complexity: O(n)
1320
- */
1144
+ *
1145
+ * The `leaves` function in TypeScript iterates through a binary tree to find and return the leaf
1146
+ * nodes based on a specified callback and iteration type.
1147
+ * @param {C} callback - The `callback` parameter is a function that will be called on each leaf node
1148
+ * in the binary tree. It is a generic type `C` that extends `BTNCallback<NODE | null>`, where `NODE`
1149
+ * represents a node in the binary tree. The default value for `callback` is
1150
+ * @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} beginRoot - The `beginRoot` parameter in the `leaves`
1151
+ * method is used to specify the starting point for finding and processing the leaves of a binary
1152
+ * tree. It represents the root node of the binary tree or a specific key, node, or entry within the
1153
+ * tree from which the search for leaves should begin
1154
+ * @param {IterationType} iterationType - The `iterationType` parameter in the `leaves` method
1155
+ * specifies the type of iteration to be performed when collecting the leaves of a binary tree. It
1156
+ * can have two possible values:
1157
+ * @returns The `leaves` method returns an array of values that are the result of applying the
1158
+ * provided callback function to the leaf nodes in the binary tree structure.
1159
+ */
1160
+ leaves(callback = this._DEFAULT_CALLBACK, beginRoot = this.root, iterationType = this.iterationType) {
1161
+ beginRoot = this.ensureNode(beginRoot);
1162
+ const leaves = [];
1163
+ if (!this.isRealNode(beginRoot)) {
1164
+ return [];
1165
+ }
1166
+ if (iterationType === 'RECURSIVE') {
1167
+ const dfs = (cur) => {
1168
+ if (this.isLeaf(cur)) {
1169
+ leaves.push(callback(cur));
1170
+ }
1171
+ if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right))
1172
+ return;
1173
+ this.isRealNode(cur.left) && dfs(cur.left);
1174
+ this.isRealNode(cur.right) && dfs(cur.right);
1175
+ };
1176
+ dfs(beginRoot);
1177
+ }
1178
+ else {
1179
+ const queue = new Queue([beginRoot]);
1180
+ while (queue.size > 0) {
1181
+ const cur = queue.shift();
1182
+ if (this.isRealNode(cur)) {
1183
+ if (this.isLeaf(cur)) {
1184
+ leaves.push(callback(cur));
1185
+ }
1186
+ this.isRealNode(cur.left) && queue.push(cur.left);
1187
+ this.isRealNode(cur.right) && queue.push(cur.right);
1188
+ }
1189
+ }
1190
+ }
1191
+ return leaves;
1192
+ }
1321
1193
  /**
1322
1194
  * Time complexity: O(n)
1323
1195
  * Space complexity: O(n)
@@ -1350,9 +1222,9 @@ export class BinaryTree extends IterableEntryBase {
1350
1222
  levelsNodes[level] = [];
1351
1223
  levelsNodes[level].push(callback(node));
1352
1224
  if (includeNull) {
1353
- if (node && this.isNodeOrNull(node.left))
1225
+ if (node && this.isRealNodeOrNull(node.left))
1354
1226
  _recursive(node.left, level + 1);
1355
- if (node && this.isNodeOrNull(node.right))
1227
+ if (node && this.isRealNodeOrNull(node.right))
1356
1228
  _recursive(node.right, level + 1);
1357
1229
  }
1358
1230
  else {
@@ -1373,9 +1245,9 @@ export class BinaryTree extends IterableEntryBase {
1373
1245
  levelsNodes[level] = [];
1374
1246
  levelsNodes[level].push(callback(node));
1375
1247
  if (includeNull) {
1376
- if (node && this.isNodeOrNull(node.right))
1248
+ if (node && this.isRealNodeOrNull(node.right))
1377
1249
  stack.push([node.right, level + 1]);
1378
- if (node && this.isNodeOrNull(node.left))
1250
+ if (node && this.isRealNodeOrNull(node.left))
1379
1251
  stack.push([node.left, level + 1]);
1380
1252
  }
1381
1253
  else {
@@ -1388,10 +1260,6 @@ export class BinaryTree extends IterableEntryBase {
1388
1260
  }
1389
1261
  return levelsNodes;
1390
1262
  }
1391
- /**
1392
- * Time complexity: O(n)
1393
- * Space complexity: O(n)
1394
- */
1395
1263
  /**
1396
1264
  * Time complexity: O(n)
1397
1265
  * Space complexity: O(n)
@@ -1496,10 +1364,6 @@ export class BinaryTree extends IterableEntryBase {
1496
1364
  }
1497
1365
  return ans;
1498
1366
  }
1499
- /**
1500
- * Time complexity: O(n)
1501
- * Space complexity: O(n)
1502
- */
1503
1367
  /**
1504
1368
  * Time complexity: O(n)
1505
1369
  * Space complexity: O(n)
@@ -1517,10 +1381,6 @@ export class BinaryTree extends IterableEntryBase {
1517
1381
  }, this.root, this.iterationType, true);
1518
1382
  return cloned;
1519
1383
  }
1520
- /**
1521
- * Time Complexity: O(n)
1522
- * Space Complexity: O(n)
1523
- */
1524
1384
  /**
1525
1385
  * Time Complexity: O(n)
1526
1386
  * Space Complexity: O(n)
@@ -1546,10 +1406,6 @@ export class BinaryTree extends IterableEntryBase {
1546
1406
  }
1547
1407
  return newTree;
1548
1408
  }
1549
- /**
1550
- * Time Complexity: O(n)
1551
- * Space Complexity: O(n)
1552
- */
1553
1409
  /**
1554
1410
  * Time Complexity: O(n)
1555
1411
  * Space Complexity: O(n)
@@ -1582,10 +1438,6 @@ export class BinaryTree extends IterableEntryBase {
1582
1438
  // // return newTree;
1583
1439
  // // }
1584
1440
  //
1585
- /**
1586
- * Time Complexity: O(n)
1587
- * Space Complexity: O(n)
1588
- */
1589
1441
  /**
1590
1442
  * Time Complexity: O(n)
1591
1443
  * Space Complexity: O(n)
@@ -1603,29 +1455,163 @@ export class BinaryTree extends IterableEntryBase {
1603
1455
  print(beginRoot = this.root, options) {
1604
1456
  const opts = { isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false, ...options };
1605
1457
  beginRoot = this.ensureNode(beginRoot);
1458
+ let output = '';
1606
1459
  if (!beginRoot)
1607
- return;
1460
+ return output;
1608
1461
  if (opts.isShowUndefined)
1609
- console.log(`U for undefined
1610
- `);
1462
+ output += `U for undefined
1463
+ `;
1611
1464
  if (opts.isShowNull)
1612
- console.log(`N for null
1613
- `);
1465
+ output += `N for null
1466
+ `;
1614
1467
  if (opts.isShowRedBlackNIL)
1615
- console.log(`S for Sentinel Node(NIL)
1616
- `);
1468
+ output += `S for Sentinel Node(NIL)
1469
+ `;
1617
1470
  const display = (root) => {
1618
1471
  const [lines, , ,] = this._displayAux(root, opts);
1472
+ let paragraph = '';
1619
1473
  for (const line of lines) {
1620
- console.log(line);
1474
+ paragraph += line + '\n';
1621
1475
  }
1476
+ output += paragraph;
1622
1477
  };
1623
1478
  display(beginRoot);
1479
+ return output;
1624
1480
  }
1625
1481
  /**
1626
- * Time Complexity: O(1)
1627
- * Space Complexity: O(1)
1628
- */
1482
+ * Time complexity: O(n)
1483
+ * Space complexity: O(n)
1484
+ *
1485
+ * The function `_dfs` performs a depth-first search traversal on a binary tree structure based on
1486
+ * the specified order pattern and callback function.
1487
+ * @param {C} callback - The `callback` parameter is a function that will be called on each node
1488
+ * visited during the depth-first search. It is of type `C`, which extends
1489
+ * `BTNCallback<OptBTNOrNull<NODE>>`. The default value is set to `this._DEFAULT_CALLBACK` if not
1490
+ * provided.
1491
+ * @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `_dfs` method specifies the
1492
+ * order in which the Depth-First Search (DFS) algorithm should traverse the nodes in a binary tree.
1493
+ * It can have one of the following values:
1494
+ * @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} beginRoot - The `beginRoot` parameter in the `_dfs`
1495
+ * method is used to specify the starting point for the depth-first search traversal in a binary
1496
+ * tree. It can be provided as either the root node of the tree or a key, node, or entry that exists
1497
+ * in the tree. If no specific `
1498
+ * @param {IterationType} iterationType - The `iterationType` parameter in the `_dfs` method
1499
+ * specifies the type of iteration to be performed during the Depth-First Search (DFS) traversal. It
1500
+ * can have two possible values:
1501
+ * @param [includeNull=false] - The `includeNull` parameter in the `_dfs` method is a boolean flag
1502
+ * that determines whether null nodes should be included in the depth-first search traversal. If
1503
+ * `includeNull` is set to `true`, the traversal will consider null nodes as valid nodes to visit and
1504
+ * process. If set to `
1505
+ * @param shouldVisitLeft - The `shouldVisitLeft` parameter is a function that takes a node as input
1506
+ * and returns a boolean value. It is used to determine whether the left child of a node should be
1507
+ * visited during the depth-first search traversal. By default, it checks if the node is truthy (not
1508
+ * null or undefined
1509
+ * @param shouldVisitRight - The `shouldVisitRight` parameter is a function that takes a node as
1510
+ * input and returns a boolean value. It is used to determine whether the right child of a node
1511
+ * should be visited during the depth-first search traversal. The default implementation checks if
1512
+ * the node is truthy before visiting the right child.
1513
+ * @param shouldVisitRoot - The `shouldVisitRoot` parameter is a function that takes a node as an
1514
+ * argument and returns a boolean value. It is used to determine whether a given node should be
1515
+ * visited during the depth-first search traversal based on certain conditions. The default
1516
+ * implementation checks if the node is a real node or null based
1517
+ * @param shouldProcessRoot - The `shouldProcessRoot` parameter is a function that takes a node as
1518
+ * input and returns a boolean value indicating whether the node should be processed during the
1519
+ * depth-first search traversal. The default implementation of this function simply returns `true`,
1520
+ * meaning that by default all nodes will be processed. However, you can
1521
+ * @returns The `_dfs` method returns an array of the return type of the callback function provided
1522
+ * as input.
1523
+ */
1524
+ _dfs(callback = this._DEFAULT_CALLBACK, pattern = 'IN', beginRoot = this.root, iterationType = this.iterationType, includeNull = false, shouldVisitLeft = node => !!node, shouldVisitRight = node => !!node, shouldVisitRoot = node => {
1525
+ if (includeNull)
1526
+ return this.isRealNodeOrNull(node);
1527
+ return this.isRealNode(node);
1528
+ }, shouldProcessRoot = node => this.isRealNodeOrNull(node)) {
1529
+ beginRoot = this.ensureNode(beginRoot);
1530
+ if (!beginRoot)
1531
+ return [];
1532
+ const ans = [];
1533
+ if (iterationType === 'RECURSIVE') {
1534
+ const dfs = (node) => {
1535
+ if (!shouldVisitRoot(node))
1536
+ return;
1537
+ const visitLeft = () => {
1538
+ if (shouldVisitLeft(node))
1539
+ dfs(node?.left);
1540
+ };
1541
+ const visitRight = () => {
1542
+ if (shouldVisitRight(node))
1543
+ dfs(node?.right);
1544
+ };
1545
+ switch (pattern) {
1546
+ case 'IN':
1547
+ visitLeft();
1548
+ if (shouldProcessRoot(node))
1549
+ ans.push(callback(node));
1550
+ visitRight();
1551
+ break;
1552
+ case 'PRE':
1553
+ if (shouldProcessRoot(node))
1554
+ ans.push(callback(node));
1555
+ visitLeft();
1556
+ visitRight();
1557
+ break;
1558
+ case 'POST':
1559
+ visitLeft();
1560
+ visitRight();
1561
+ if (shouldProcessRoot(node))
1562
+ ans.push(callback(node));
1563
+ break;
1564
+ }
1565
+ };
1566
+ dfs(beginRoot);
1567
+ }
1568
+ else {
1569
+ const stack = [{ opt: DFSOperation.VISIT, node: beginRoot }];
1570
+ const pushLeft = (cur) => {
1571
+ if (shouldVisitLeft(cur.node))
1572
+ stack.push({ opt: DFSOperation.VISIT, node: cur.node?.left });
1573
+ };
1574
+ const pushRight = (cur) => {
1575
+ if (shouldVisitRight(cur.node))
1576
+ stack.push({ opt: DFSOperation.VISIT, node: cur.node?.right });
1577
+ };
1578
+ const pushRoot = (cur) => {
1579
+ if (shouldVisitRoot(cur.node))
1580
+ stack.push({ opt: DFSOperation.PROCESS, node: cur.node });
1581
+ };
1582
+ while (stack.length > 0) {
1583
+ const cur = stack.pop();
1584
+ if (cur === undefined)
1585
+ continue;
1586
+ if (!shouldVisitRoot(cur.node))
1587
+ continue;
1588
+ if (cur.opt === DFSOperation.PROCESS) {
1589
+ if (shouldProcessRoot(cur.node))
1590
+ ans.push(callback(cur.node));
1591
+ }
1592
+ else {
1593
+ switch (pattern) {
1594
+ case 'IN':
1595
+ pushRight(cur);
1596
+ pushRoot(cur);
1597
+ pushLeft(cur);
1598
+ break;
1599
+ case 'PRE':
1600
+ pushRight(cur);
1601
+ pushLeft(cur);
1602
+ pushRoot(cur);
1603
+ break;
1604
+ case 'POST':
1605
+ pushRoot(cur);
1606
+ pushRight(cur);
1607
+ pushLeft(cur);
1608
+ break;
1609
+ }
1610
+ }
1611
+ }
1612
+ }
1613
+ return ans;
1614
+ }
1629
1615
  /**
1630
1616
  * Time Complexity: O(1)
1631
1617
  * Space Complexity: O(1)
@@ -1664,10 +1650,6 @@ export class BinaryTree extends IterableEntryBase {
1664
1650
  }
1665
1651
  }
1666
1652
  }
1667
- /**
1668
- * Time Complexity: O(n)
1669
- * Space Complexity: O(n)
1670
- */
1671
1653
  /**
1672
1654
  * Time Complexity: O(n)
1673
1655
  * Space Complexity: O(n)
@@ -1738,10 +1720,6 @@ export class BinaryTree extends IterableEntryBase {
1738
1720
  }
1739
1721
  }
1740
1722
  _DEFAULT_CALLBACK = (node) => (node ? node.key : undefined);
1741
- /**
1742
- * Time Complexity: O(1)
1743
- * Space Complexity: O(1)
1744
- */
1745
1723
  /**
1746
1724
  * Time Complexity: O(1)
1747
1725
  * Space Complexity: O(1)
@@ -1771,10 +1749,6 @@ export class BinaryTree extends IterableEntryBase {
1771
1749
  }
1772
1750
  return undefined;
1773
1751
  }
1774
- /**
1775
- * Time Complexity: O(1)
1776
- * Space Complexity: O(1)
1777
- */
1778
1752
  /**
1779
1753
  * Time Complexity: O(1)
1780
1754
  * Space Complexity: O(1)
@@ -1804,10 +1778,6 @@ export class BinaryTree extends IterableEntryBase {
1804
1778
  }
1805
1779
  return newNode;
1806
1780
  }
1807
- /**
1808
- * Time Complexity: O(1)
1809
- * Space Complexity: O(1)
1810
- */
1811
1781
  /**
1812
1782
  * Time Complexity: O(1)
1813
1783
  * Space Complexity: O(1)
@@ -1823,10 +1793,6 @@ export class BinaryTree extends IterableEntryBase {
1823
1793
  }
1824
1794
  this._root = v;
1825
1795
  }
1826
- /**
1827
- * Time Complexity: O(1)
1828
- * Space Complexity: O(1)
1829
- */
1830
1796
  /**
1831
1797
  * Time Complexity: O(1)
1832
1798
  * Space Complexity: O(1)