data-structure-typed 1.42.6 → 1.42.7

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 (50) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/README.md +122 -122
  3. package/benchmark/report.html +12 -12
  4. package/benchmark/report.json +101 -101
  5. package/dist/cjs/src/data-structures/binary-tree/avl-tree.d.ts +5 -5
  6. package/dist/cjs/src/data-structures/binary-tree/avl-tree.js +19 -14
  7. package/dist/cjs/src/data-structures/binary-tree/avl-tree.js.map +1 -1
  8. package/dist/cjs/src/data-structures/binary-tree/binary-tree.d.ts +108 -60
  9. package/dist/cjs/src/data-structures/binary-tree/binary-tree.js +189 -89
  10. package/dist/cjs/src/data-structures/binary-tree/binary-tree.js.map +1 -1
  11. package/dist/cjs/src/data-structures/binary-tree/bst.d.ts +30 -8
  12. package/dist/cjs/src/data-structures/binary-tree/bst.js +77 -28
  13. package/dist/cjs/src/data-structures/binary-tree/bst.js.map +1 -1
  14. package/dist/cjs/src/data-structures/binary-tree/rb-tree.d.ts +35 -28
  15. package/dist/cjs/src/data-structures/binary-tree/rb-tree.js +44 -45
  16. package/dist/cjs/src/data-structures/binary-tree/rb-tree.js.map +1 -1
  17. package/dist/cjs/src/data-structures/binary-tree/tree-multimap.d.ts +7 -12
  18. package/dist/cjs/src/data-structures/binary-tree/tree-multimap.js +38 -37
  19. package/dist/cjs/src/data-structures/binary-tree/tree-multimap.js.map +1 -1
  20. package/dist/cjs/src/interfaces/binary-tree.d.ts +2 -2
  21. package/dist/cjs/src/types/data-structures/binary-tree/binary-tree.d.ts +1 -1
  22. package/dist/cjs/src/types/data-structures/binary-tree/binary-tree.js +6 -0
  23. package/dist/cjs/src/types/data-structures/binary-tree/binary-tree.js.map +1 -1
  24. package/dist/cjs/src/types/data-structures/binary-tree/rb-tree.d.ts +2 -2
  25. package/dist/mjs/src/data-structures/binary-tree/avl-tree.d.ts +5 -5
  26. package/dist/mjs/src/data-structures/binary-tree/avl-tree.js +19 -14
  27. package/dist/mjs/src/data-structures/binary-tree/binary-tree.d.ts +108 -60
  28. package/dist/mjs/src/data-structures/binary-tree/binary-tree.js +191 -89
  29. package/dist/mjs/src/data-structures/binary-tree/bst.d.ts +30 -8
  30. package/dist/mjs/src/data-structures/binary-tree/bst.js +78 -27
  31. package/dist/mjs/src/data-structures/binary-tree/rb-tree.d.ts +35 -28
  32. package/dist/mjs/src/data-structures/binary-tree/rb-tree.js +43 -45
  33. package/dist/mjs/src/data-structures/binary-tree/tree-multimap.d.ts +7 -12
  34. package/dist/mjs/src/data-structures/binary-tree/tree-multimap.js +38 -37
  35. package/dist/mjs/src/interfaces/binary-tree.d.ts +2 -2
  36. package/dist/mjs/src/types/data-structures/binary-tree/binary-tree.d.ts +1 -1
  37. package/dist/mjs/src/types/data-structures/binary-tree/binary-tree.js +6 -0
  38. package/dist/mjs/src/types/data-structures/binary-tree/rb-tree.d.ts +2 -2
  39. package/dist/umd/data-structure-typed.min.js +1 -1
  40. package/dist/umd/data-structure-typed.min.js.map +1 -1
  41. package/package.json +1 -1
  42. package/src/data-structures/binary-tree/avl-tree.ts +24 -18
  43. package/src/data-structures/binary-tree/binary-tree.ts +248 -142
  44. package/src/data-structures/binary-tree/bst.ts +88 -38
  45. package/src/data-structures/binary-tree/rb-tree.ts +52 -58
  46. package/src/data-structures/binary-tree/tree-multimap.ts +50 -54
  47. package/src/interfaces/binary-tree.ts +2 -2
  48. package/src/types/data-structures/binary-tree/binary-tree.ts +7 -1
  49. package/src/types/data-structures/binary-tree/rb-tree.ts +2 -2
  50. package/test/unit/data-structures/binary-tree/rb-tree.test.ts +9 -9
@@ -102,19 +102,20 @@ class BinaryTree {
102
102
  * @param {BinaryTreeOptions} [options] - The options for the binary tree.
103
103
  */
104
104
  constructor(options) {
105
- if (options !== undefined) {
105
+ if (options) {
106
106
  const { iterationType = types_1.IterationType.ITERATIVE } = options;
107
107
  this.iterationType = iterationType;
108
108
  }
109
+ this._size = 0;
109
110
  }
110
- _root = undefined;
111
+ _root;
111
112
  /**
112
113
  * Get the root node of the binary tree.
113
114
  */
114
115
  get root() {
115
116
  return this._root;
116
117
  }
117
- _size = 0;
118
+ _size;
118
119
  /**
119
120
  * Get the number of nodes in the binary tree.
120
121
  */
@@ -130,20 +131,6 @@ class BinaryTree {
130
131
  createNode(key, value) {
131
132
  return new BinaryTreeNode(key, value);
132
133
  }
133
- /**
134
- * Clear the binary tree, removing all nodes.
135
- */
136
- clear() {
137
- this._setRoot(undefined);
138
- this._size = 0;
139
- }
140
- /**
141
- * Check if the binary tree is empty.
142
- * @returns {boolean} - True if the binary tree is empty, false otherwise.
143
- */
144
- isEmpty() {
145
- return this.size === 0;
146
- }
147
134
  /**
148
135
  * Add a node with the given key and value to the binary tree.
149
136
  * @param {BTNKey | N | null} keyOrNode - The key or node to add to the binary tree.
@@ -177,7 +164,7 @@ class BinaryTree {
177
164
  if (keyOrNode === null) {
178
165
  needInsert = null;
179
166
  }
180
- else if (typeof keyOrNode === 'number') {
167
+ else if (this.isNodeKey(keyOrNode)) {
181
168
  needInsert = this.createNode(keyOrNode, value);
182
169
  }
183
170
  else if (keyOrNode instanceof BinaryTreeNode) {
@@ -186,19 +173,12 @@ class BinaryTree {
186
173
  else {
187
174
  return;
188
175
  }
189
- // const key = typeof keyOrNode === 'number' ? keyOrNode : keyOrNode ? keyOrNode.key : undefined;
190
- // const existNode = key !== undefined ? this.getNode(key, (node: N) => node.key) : undefined;
191
176
  if (this.root) {
192
- // if (existNode) {
193
- // existNode.value = value;
194
- // inserted = existNode;
195
- // } else {
196
177
  inserted = _bfs(this.root, needInsert);
197
- // }
198
178
  }
199
179
  else {
200
180
  this._setRoot(needInsert);
201
- if (needInsert !== null) {
181
+ if (needInsert) {
202
182
  this._size = 1;
203
183
  }
204
184
  else {
@@ -235,40 +215,41 @@ class BinaryTree {
235
215
  * The `refill` function clears the binary tree and adds multiple nodes with the given IDs or nodes and optional data.
236
216
  * @param {(BTNKey | N)[]} keysOrNodes - The `keysOrNodes` parameter is an array that can contain either
237
217
  * `BTNKey` or `N` values.
238
- * @param {N[] | Array<V>} [data] - The `data` parameter is an optional array of values that will be assigned to
218
+ * @param {N[] | Array<V>} [values] - The `data` parameter is an optional array of values that will be assigned to
239
219
  * the nodes being added. If provided, the length of the `data` array should be equal to the length of the `keysOrNodes`
240
220
  * array. Each value in the `data` array will be assigned to the
241
221
  * @returns The method is returning a boolean value.
242
222
  */
243
- refill(keysOrNodes, data) {
223
+ refill(keysOrNodes, values) {
244
224
  this.clear();
245
- return keysOrNodes.length === this.addMany(keysOrNodes, data).length;
225
+ return keysOrNodes.length === this.addMany(keysOrNodes, values).length;
246
226
  }
247
227
  /**
248
228
  * The `delete` function removes a node from a binary search tree and returns the deleted node along
249
229
  * with the parent node that needs to be balanced.
250
230
  * a key (`BTNKey`). If it is a key, the function will find the corresponding node in the
251
231
  * binary tree.
252
- * @returns an array of `BinaryTreeDeletedResult<N>` objects.
232
+ * @returns an array of `BiTreeDeleteResult<N>` objects.
253
233
  * @param {ReturnType<C>} identifier - The `identifier` parameter is either a
254
234
  * `BTNKey` or a generic type `N`. It represents the property of the node that we are
255
235
  * searching for. It can be a specific key value or any other property of the node.
256
236
  * @param callback - The `callback` parameter is a function that takes a node as input and returns a
257
237
  * value. This value is compared with the `identifier` parameter to determine if the node should be
258
238
  * included in the result. The `callback` parameter has a default value of
259
- * `this.defaultOneParamCallback`, which
239
+ * `this._defaultOneParamCallback`, which
260
240
  */
261
- delete(identifier, callback = this.defaultOneParamCallback) {
262
- const bstDeletedResult = [];
241
+ delete(identifier, callback = this._defaultOneParamCallback) {
242
+ const deletedResult = [];
263
243
  if (!this.root)
264
- return bstDeletedResult;
244
+ return deletedResult;
265
245
  if (identifier instanceof BinaryTreeNode)
266
246
  callback = (node => node);
267
247
  const curr = this.getNode(identifier, callback);
268
248
  if (!curr)
269
- return bstDeletedResult;
249
+ return deletedResult;
270
250
  const parent = curr?.parent ? curr.parent : null;
271
- let needBalanced = null, orgCurrent = curr;
251
+ let needBalanced = undefined;
252
+ let orgCurrent = curr;
272
253
  if (!curr.left) {
273
254
  if (!parent) {
274
255
  // Handle the case when there's only one root node
@@ -300,8 +281,8 @@ class BinaryTree {
300
281
  }
301
282
  }
302
283
  this._size = this.size - 1;
303
- bstDeletedResult.push({ deleted: orgCurrent, needBalanced });
304
- return bstDeletedResult;
284
+ deletedResult.push({ deleted: orgCurrent, needBalanced });
285
+ return deletedResult;
305
286
  }
306
287
  /**
307
288
  * The function `getDepth` calculates the depth of a given node in a binary tree relative to a
@@ -316,10 +297,8 @@ class BinaryTree {
316
297
  * @returns the depth of the `distNode` relative to the `beginRoot`.
317
298
  */
318
299
  getDepth(distNode, beginRoot = this.root) {
319
- if (typeof distNode === 'number')
320
- distNode = this.getNode(distNode);
321
- if (typeof beginRoot === 'number')
322
- beginRoot = this.getNode(beginRoot);
300
+ distNode = this.ensureNotKey(distNode);
301
+ beginRoot = this.ensureNotKey(beginRoot);
323
302
  let depth = 0;
324
303
  while (distNode?.parent) {
325
304
  if (distNode === beginRoot) {
@@ -343,8 +322,7 @@ class BinaryTree {
343
322
  * @returns the height of the binary tree.
344
323
  */
345
324
  getHeight(beginRoot = this.root, iterationType = this.iterationType) {
346
- if (typeof beginRoot === 'number')
347
- beginRoot = this.getNode(beginRoot);
325
+ beginRoot = this.ensureNotKey(beginRoot);
348
326
  if (!beginRoot)
349
327
  return -1;
350
328
  if (iterationType === types_1.IterationType.RECURSIVE) {
@@ -365,12 +343,10 @@ class BinaryTree {
365
343
  let maxHeight = 0;
366
344
  while (stack.length > 0) {
367
345
  const { node, depth } = stack.pop();
368
- if (node.left) {
346
+ if (node.left)
369
347
  stack.push({ node: node.left, depth: depth + 1 });
370
- }
371
- if (node.right) {
348
+ if (node.right)
372
349
  stack.push({ node: node.right, depth: depth + 1 });
373
- }
374
350
  maxHeight = Math.max(maxHeight, depth);
375
351
  }
376
352
  return maxHeight;
@@ -387,6 +363,7 @@ class BinaryTree {
387
363
  * @returns The function `getMinHeight` returns the minimum height of a binary tree.
388
364
  */
389
365
  getMinHeight(beginRoot = this.root, iterationType = this.iterationType) {
366
+ beginRoot = this.ensureNotKey(beginRoot);
390
367
  if (!beginRoot)
391
368
  return -1;
392
369
  if (iterationType === types_1.IterationType.RECURSIVE) {
@@ -448,7 +425,7 @@ class BinaryTree {
448
425
  * @param callback - The `callback` parameter is a function that takes a node as input and returns a
449
426
  * value. This value is compared with the `identifier` parameter to determine if the node should be
450
427
  * included in the result. The `callback` parameter has a default value of
451
- * `this.defaultOneParamCallback`, which
428
+ * `this._defaultOneParamCallback`, which
452
429
  * @param [onlyOne=false] - A boolean value indicating whether to stop searching after finding the
453
430
  * first node that matches the identifier. If set to true, the function will return an array with
454
431
  * only one element (or an empty array if no matching node is found). If set to false (default), the
@@ -460,11 +437,14 @@ class BinaryTree {
460
437
  * traverse the binary tree. It can have two possible values:
461
438
  * @returns The function `getNodes` returns an array of nodes (`N[]`).
462
439
  */
463
- getNodes(identifier, callback = this.defaultOneParamCallback, onlyOne = false, beginRoot = this.root, iterationType = this.iterationType) {
440
+ getNodes(identifier, callback = this._defaultOneParamCallback, onlyOne = false, beginRoot = this.root, iterationType = this.iterationType) {
464
441
  if (!beginRoot)
465
442
  return [];
466
443
  if (identifier instanceof BinaryTreeNode)
467
444
  callback = (node => node);
445
+ beginRoot = this.ensureNotKey(beginRoot);
446
+ if (!beginRoot)
447
+ return [];
468
448
  const ans = [];
469
449
  if (iterationType === types_1.IterationType.RECURSIVE) {
470
450
  const _traverse = (cur) => {
@@ -505,7 +485,7 @@ class BinaryTree {
505
485
  * @param callback - The `callback` parameter is a function that is used to determine whether a node
506
486
  * matches the desired criteria. It takes a node as input and returns a boolean value indicating
507
487
  * whether the node matches the criteria or not. The default callback function
508
- * `this.defaultOneParamCallback` is used if no callback function is
488
+ * `this._defaultOneParamCallback` is used if no callback function is
509
489
  * @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies
510
490
  * the node from which the search should begin. By default, it is set to `this.root`, which means the
511
491
  * search will start from the root node of the binary tree. However, you can provide a different node
@@ -514,7 +494,7 @@ class BinaryTree {
514
494
  * performed when searching for nodes in the binary tree. It can have one of the following values:
515
495
  * @returns a boolean value.
516
496
  */
517
- has(identifier, callback = this.defaultOneParamCallback, beginRoot = this.root, iterationType = this.iterationType) {
497
+ has(identifier, callback = this._defaultOneParamCallback, beginRoot = this.root, iterationType = this.iterationType) {
518
498
  if (identifier instanceof BinaryTreeNode)
519
499
  callback = (node => node);
520
500
  return this.getNodes(identifier, callback, true, beginRoot, iterationType).length > 0;
@@ -527,18 +507,72 @@ class BinaryTree {
527
507
  * @param callback - The `callback` parameter is a function that is used to determine whether a node
528
508
  * matches the desired criteria. It takes a node as input and returns a boolean value indicating
529
509
  * whether the node matches the criteria or not. The default callback function
530
- * (`this.defaultOneParamCallback`) is used if no callback function is
510
+ * (`this._defaultOneParamCallback`) is used if no callback function is
531
511
  * @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies
532
512
  * the root node from which the search should begin.
533
513
  * @param iterationType - The `iterationType` parameter specifies the type of iteration to be
534
514
  * performed when searching for a node in the binary tree. It can have one of the following values:
535
515
  * @returns either the found node (of type N) or null if no node is found.
536
516
  */
537
- getNode(identifier, callback = this.defaultOneParamCallback, beginRoot = this.root, iterationType = this.iterationType) {
517
+ getNode(identifier, callback = this._defaultOneParamCallback, beginRoot = this.root, iterationType = this.iterationType) {
538
518
  if (identifier instanceof BinaryTreeNode)
539
519
  callback = (node => node);
540
520
  return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? null;
541
521
  }
522
+ /**
523
+ * The function `getNodeByKey` searches for a node in a binary tree by its key, using either
524
+ * recursive or iterative iteration.
525
+ * @param {BTNKey} key - The `key` parameter is the key value that we are searching for in the tree.
526
+ * It is used to find the node with the matching key value.
527
+ * @param iterationType - The `iterationType` parameter is used to determine whether the search for
528
+ * the node with the given key should be performed iteratively or recursively. It has two possible
529
+ * values:
530
+ * @returns The function `getNodeByKey` returns a node (`N`) if a node with the specified key is
531
+ * found in the binary tree. If no node is found, it returns `undefined`.
532
+ */
533
+ getNodeByKey(key, iterationType = types_1.IterationType.ITERATIVE) {
534
+ if (!this.root)
535
+ return undefined;
536
+ if (iterationType === types_1.IterationType.RECURSIVE) {
537
+ const _dfs = (cur) => {
538
+ if (cur.key === key)
539
+ return cur;
540
+ if (!cur.left && !cur.right)
541
+ return;
542
+ if (cur.left)
543
+ return _dfs(cur.left);
544
+ if (cur.right)
545
+ return _dfs(cur.right);
546
+ };
547
+ return _dfs(this.root);
548
+ }
549
+ else {
550
+ const queue = new queue_1.Queue([this.root]);
551
+ while (queue.size > 0) {
552
+ const cur = queue.shift();
553
+ if (cur) {
554
+ if (cur.key === key)
555
+ return cur;
556
+ cur.left && queue.push(cur.left);
557
+ cur.right && queue.push(cur.right);
558
+ }
559
+ }
560
+ }
561
+ }
562
+ /**
563
+ * The function `ensureNotKey` returns the node corresponding to the given key if it is a valid node
564
+ * key, otherwise it returns the key itself.
565
+ * @param {BTNKey | N | null | undefined} key - The `key` parameter can be of type `BTNKey`, `N`,
566
+ * `null`, or `undefined`. It represents a key used to identify a node in a binary tree.
567
+ * @param iterationType - The `iterationType` parameter is an optional parameter that specifies the
568
+ * type of iteration to be used when searching for a node by key. It has a default value of
569
+ * `IterationType.ITERATIVE`.
570
+ * @returns either the node corresponding to the given key if it is a valid node key, or the key
571
+ * itself if it is not a valid node key.
572
+ */
573
+ ensureNotKey(key, iterationType = types_1.IterationType.ITERATIVE) {
574
+ return this.isNodeKey(key) ? this.getNodeByKey(key, iterationType) : key;
575
+ }
542
576
  /**
543
577
  * The function `get` returns the first node value in a binary tree that matches the given property or key.
544
578
  * @param {BTNKey | N} identifier - The `identifier` parameter is the key or value of
@@ -547,18 +581,32 @@ class BinaryTree {
547
581
  * @param callback - The `callback` parameter is a function that is used to determine whether a node
548
582
  * matches the desired criteria. It takes a node as input and returns a boolean value indicating
549
583
  * whether the node matches the criteria or not. The default callback function
550
- * (`this.defaultOneParamCallback`) is used if no callback function is
584
+ * (`this._defaultOneParamCallback`) is used if no callback function is
551
585
  * @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies
552
586
  * the root node from which the search should begin.
553
587
  * @param iterationType - The `iterationType` parameter specifies the type of iteration to be
554
588
  * performed when searching for a node in the binary tree. It can have one of the following values:
555
589
  * @returns either the found value (of type V) or undefined if no node value is found.
556
590
  */
557
- get(identifier, callback = this.defaultOneParamCallback, beginRoot = this.root, iterationType = this.iterationType) {
591
+ get(identifier, callback = this._defaultOneParamCallback, beginRoot = this.root, iterationType = this.iterationType) {
558
592
  if (identifier instanceof BinaryTreeNode)
559
593
  callback = (node => node);
560
594
  return this.getNode(identifier, callback, beginRoot, iterationType)?.value ?? undefined;
561
595
  }
596
+ /**
597
+ * Clear the binary tree, removing all nodes.
598
+ */
599
+ clear() {
600
+ this._setRoot(undefined);
601
+ this._size = 0;
602
+ }
603
+ /**
604
+ * Check if the binary tree is empty.
605
+ * @returns {boolean} - True if the binary tree is empty, false otherwise.
606
+ */
607
+ isEmpty() {
608
+ return this.size === 0;
609
+ }
562
610
  /**
563
611
  * The function `getPathToRoot` returns an array of nodes starting from a given node and traversing
564
612
  * up to the root node, with the option to reverse the order of the nodes.
@@ -572,6 +620,9 @@ class BinaryTree {
572
620
  getPathToRoot(beginRoot, isReverse = true) {
573
621
  // TODO to support get path through passing key
574
622
  const result = [];
623
+ beginRoot = this.ensureNotKey(beginRoot);
624
+ if (!beginRoot)
625
+ return result;
575
626
  while (beginRoot.parent) {
576
627
  // Array.push + Array.reverse is more efficient than Array.unshift
577
628
  // TODO may consider using Deque, so far this is not the performance bottleneck
@@ -593,13 +644,12 @@ class BinaryTree {
593
644
  * no leftmost node, it returns `null`.
594
645
  */
595
646
  getLeftMost(beginRoot = this.root, iterationType = this.iterationType) {
596
- if (typeof beginRoot === 'number')
597
- beginRoot = this.getNode(beginRoot);
647
+ beginRoot = this.ensureNotKey(beginRoot);
598
648
  if (!beginRoot)
599
649
  return beginRoot;
600
650
  if (iterationType === types_1.IterationType.RECURSIVE) {
601
651
  const _traverse = (cur) => {
602
- if (!cur.left)
652
+ if (!this.isRealNode(cur.left))
603
653
  return cur;
604
654
  return _traverse(cur.left);
605
655
  };
@@ -608,7 +658,7 @@ class BinaryTree {
608
658
  else {
609
659
  // Indirect implementation of iteration using tail recursion optimization
610
660
  const _traverse = (0, utils_1.trampoline)((cur) => {
611
- if (!cur.left)
661
+ if (!this.isRealNode(cur.left))
612
662
  return cur;
613
663
  return _traverse.cont(cur.left);
614
664
  });
@@ -628,11 +678,12 @@ class BinaryTree {
628
678
  */
629
679
  getRightMost(beginRoot = this.root, iterationType = this.iterationType) {
630
680
  // TODO support get right most by passing key in
681
+ beginRoot = this.ensureNotKey(beginRoot);
631
682
  if (!beginRoot)
632
683
  return beginRoot;
633
684
  if (iterationType === types_1.IterationType.RECURSIVE) {
634
685
  const _traverse = (cur) => {
635
- if (!cur.right)
686
+ if (!this.isRealNode(cur.right))
636
687
  return cur;
637
688
  return _traverse(cur.right);
638
689
  };
@@ -641,7 +692,7 @@ class BinaryTree {
641
692
  else {
642
693
  // Indirect implementation of iteration using tail recursion optimization
643
694
  const _traverse = (0, utils_1.trampoline)((cur) => {
644
- if (!cur.right)
695
+ if (!this.isRealNode(cur.right))
645
696
  return cur;
646
697
  return _traverse.cont(cur.right);
647
698
  });
@@ -659,6 +710,7 @@ class BinaryTree {
659
710
  */
660
711
  isSubtreeBST(beginRoot, iterationType = this.iterationType) {
661
712
  // TODO there is a bug
713
+ beginRoot = this.ensureNotKey(beginRoot);
662
714
  if (!beginRoot)
663
715
  return true;
664
716
  if (iterationType === types_1.IterationType.RECURSIVE) {
@@ -716,9 +768,8 @@ class BinaryTree {
716
768
  * @param includeNull - The choice to output null values during binary tree traversal should be provided.
717
769
  * @returns The function `subTreeTraverse` returns an array of `ReturnType<BTNCallback<N>>`.
718
770
  */
719
- subTreeTraverse(callback = this.defaultOneParamCallback, beginRoot = this.root, iterationType = this.iterationType, includeNull = false) {
720
- if (typeof beginRoot === 'number')
721
- beginRoot = this.getNode(beginRoot);
771
+ subTreeTraverse(callback = this._defaultOneParamCallback, beginRoot = this.root, iterationType = this.iterationType, includeNull = false) {
772
+ beginRoot = this.ensureNotKey(beginRoot);
722
773
  const ans = [];
723
774
  if (!beginRoot)
724
775
  return ans;
@@ -757,21 +808,46 @@ class BinaryTree {
757
808
  }
758
809
  return ans;
759
810
  }
760
- isNode(node) {
811
+ /**
812
+ * The function checks if a given node is a real node by verifying if it is an instance of
813
+ * BinaryTreeNode and its key is not NaN.
814
+ * @param {any} node - The parameter `node` is of type `any`, which means it can be any data type.
815
+ * @returns a boolean value.
816
+ */
817
+ isRealNode(node) {
761
818
  return node instanceof BinaryTreeNode && node.key.toString() !== 'NaN';
762
819
  }
820
+ /**
821
+ * The function checks if a given node is a BinaryTreeNode instance and has a key value of NaN.
822
+ * @param {any} node - The parameter `node` is of type `any`, which means it can be any data type.
823
+ * @returns a boolean value.
824
+ */
763
825
  isNIL(node) {
764
826
  return node instanceof BinaryTreeNode && node.key.toString() === 'NaN';
765
827
  }
828
+ /**
829
+ * The function checks if a given node is a real node or null.
830
+ * @param {any} node - The parameter `node` is of type `any`, which means it can be any data type.
831
+ * @returns a boolean value.
832
+ */
766
833
  isNodeOrNull(node) {
767
- return this.isNode(node) || node === null;
834
+ return this.isRealNode(node) || node === null;
835
+ }
836
+ /**
837
+ * The function "isNodeKey" checks if a potential key is a number.
838
+ * @param {any} potentialKey - The potentialKey parameter is of type any, which means it can be any
839
+ * data type.
840
+ * @returns a boolean value indicating whether the potentialKey is of type number or not.
841
+ */
842
+ isNodeKey(potentialKey) {
843
+ return typeof potentialKey === 'number';
768
844
  }
769
845
  /**
770
846
  * The `dfs` function performs a depth-first search traversal on a binary tree, executing a callback
771
847
  * function on each node according to a specified order pattern.
772
848
  * @param callback - The `callback` parameter is a function that will be called on each node during
773
849
  * the depth-first search traversal. It takes a node as input and returns a value. The default value
774
- * is `this.defaultOneParamCallback`, which is a callback function defined elsewhere in the code.
850
+ * is `this._defaultOneParamCallback`, which is a callback function defined elsewhere in the code.
775
851
  * @param {DFSOrderPattern} [pattern=in] - The `pattern` parameter determines the order in which the
776
852
  * nodes are visited during the depth-first search. There are three possible values for `pattern`:
777
853
  * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node for the depth-first
@@ -782,7 +858,8 @@ class BinaryTree {
782
858
  * @param includeNull - The choice to output null values during binary tree traversal should be provided.
783
859
  * @returns The function `dfs` returns an array of `ReturnType<BTNCallback<N>>` values.
784
860
  */
785
- dfs(callback = this.defaultOneParamCallback, pattern = 'in', beginRoot = this.root, iterationType = types_1.IterationType.ITERATIVE, includeNull = false) {
861
+ dfs(callback = this._defaultOneParamCallback, pattern = 'in', beginRoot = this.root, iterationType = types_1.IterationType.ITERATIVE, includeNull = false) {
862
+ beginRoot = this.ensureNotKey(beginRoot);
786
863
  if (!beginRoot)
787
864
  return [];
788
865
  const ans = [];
@@ -800,7 +877,7 @@ class BinaryTree {
800
877
  else {
801
878
  if (node && node.left)
802
879
  _traverse(node.left);
803
- this.isNode(node) && ans.push(callback(node));
880
+ this.isRealNode(node) && ans.push(callback(node));
804
881
  if (node && node.right)
805
882
  _traverse(node.right);
806
883
  }
@@ -814,7 +891,7 @@ class BinaryTree {
814
891
  _traverse(node.right);
815
892
  }
816
893
  else {
817
- this.isNode(node) && ans.push(callback(node));
894
+ this.isRealNode(node) && ans.push(callback(node));
818
895
  if (node && node.left)
819
896
  _traverse(node.left);
820
897
  if (node && node.right)
@@ -834,7 +911,7 @@ class BinaryTree {
834
911
  _traverse(node.left);
835
912
  if (node && node.right)
836
913
  _traverse(node.right);
837
- this.isNode(node) && ans.push(callback(node));
914
+ this.isRealNode(node) && ans.push(callback(node));
838
915
  }
839
916
  break;
840
917
  }
@@ -892,7 +969,7 @@ class BinaryTree {
892
969
  * function on each node.
893
970
  * @param callback - The `callback` parameter is a function that will be called for each node in the
894
971
  * breadth-first search. It takes a node of type `N` as its argument and returns a value of type
895
- * `ReturnType<BTNCallback<N>>`. The default value for this parameter is `this.defaultOneParamCallback
972
+ * `ReturnType<BTNCallback<N>>`. The default value for this parameter is `this._defaultOneParamCallback
896
973
  * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node for the breadth-first
897
974
  * search. It determines from which node the search will begin. If `beginRoot` is `null`, the search
898
975
  * will not be performed and an empty array will be returned.
@@ -901,7 +978,8 @@ class BinaryTree {
901
978
  * @param includeNull - The choice to output null values during binary tree traversal should be provided.
902
979
  * @returns The function `bfs` returns an array of `ReturnType<BTNCallback<N>>[]`.
903
980
  */
904
- bfs(callback = this.defaultOneParamCallback, beginRoot = this.root, iterationType = this.iterationType, includeNull = false) {
981
+ bfs(callback = this._defaultOneParamCallback, beginRoot = this.root, iterationType = this.iterationType, includeNull = false) {
982
+ beginRoot = this.ensureNotKey(beginRoot);
905
983
  if (!beginRoot)
906
984
  return [];
907
985
  const ans = [];
@@ -968,10 +1046,11 @@ class BinaryTree {
968
1046
  * level in a binary tree. Each inner array contains the return type of the provided callback
969
1047
  * function `C` applied to the nodes at that level.
970
1048
  */
971
- listLevels(callback = this.defaultOneParamCallback, beginRoot = this.root, iterationType = this.iterationType, includeNull = false) {
972
- if (!beginRoot)
973
- return [];
1049
+ listLevels(callback = this._defaultOneParamCallback, beginRoot = this.root, iterationType = this.iterationType, includeNull = false) {
1050
+ beginRoot = this.ensureNotKey(beginRoot);
974
1051
  const levelsNodes = [];
1052
+ if (!beginRoot)
1053
+ return levelsNodes;
975
1054
  if (iterationType === types_1.IterationType.RECURSIVE) {
976
1055
  const _recursive = (node, level) => {
977
1056
  if (!levelsNodes[level])
@@ -1022,9 +1101,12 @@ class BinaryTree {
1022
1101
  * @returns The function `getPredecessor` returns the predecessor node of the given node `node`.
1023
1102
  */
1024
1103
  getPredecessor(node) {
1104
+ node = this.ensureNotKey(node);
1105
+ if (!this.isRealNode(node))
1106
+ return undefined;
1025
1107
  if (node.left) {
1026
1108
  let predecessor = node.left;
1027
- while (!predecessor || (predecessor.right && predecessor.right !== node)) {
1109
+ while (!this.isRealNode(predecessor) || (this.isRealNode(predecessor.right) && predecessor.right !== node)) {
1028
1110
  if (predecessor) {
1029
1111
  predecessor = predecessor.right;
1030
1112
  }
@@ -1043,6 +1125,9 @@ class BinaryTree {
1043
1125
  * if there is no successor, or `undefined` if the input `x` is `undefined`.
1044
1126
  */
1045
1127
  getSuccessor(x) {
1128
+ x = this.ensureNotKey(x);
1129
+ if (!x)
1130
+ return undefined;
1046
1131
  if (x.right) {
1047
1132
  return this.getLeftMost(x.right);
1048
1133
  }
@@ -1058,7 +1143,7 @@ class BinaryTree {
1058
1143
  * algorithm and returns an array of values obtained by applying a callback function to each node.
1059
1144
  * @param callback - The `callback` parameter is a function that will be called on each node in the
1060
1145
  * tree. It takes a node of type `N` as input and returns a value of type `ReturnType<BTNCallback<N>>`. The
1061
- * default value for this parameter is `this.defaultOneParamCallback`.
1146
+ * default value for this parameter is `this._defaultOneParamCallback`.
1062
1147
  * @param {DFSOrderPattern} [pattern=in] - The `pattern` parameter in the `morris` function
1063
1148
  * determines the order in which the nodes of a binary tree are traversed. It can have one of the
1064
1149
  * following values:
@@ -1067,7 +1152,8 @@ class BinaryTree {
1067
1152
  * `beginRoot` is `null`, an empty array will be returned.
1068
1153
  * @returns The `morris` function returns an array of `ReturnType<BTNCallback<N>>` values.
1069
1154
  */
1070
- morris(callback = this.defaultOneParamCallback, pattern = 'in', beginRoot = this.root) {
1155
+ morris(callback = this._defaultOneParamCallback, pattern = 'in', beginRoot = this.root) {
1156
+ beginRoot = this.ensureNotKey(beginRoot);
1071
1157
  if (beginRoot === null)
1072
1158
  return [];
1073
1159
  const ans = [];
@@ -1192,7 +1278,7 @@ class BinaryTree {
1192
1278
  }
1193
1279
  }
1194
1280
  }
1195
- defaultOneParamCallback = (node) => node.key;
1281
+ _defaultOneParamCallback = (node) => node.key;
1196
1282
  /**
1197
1283
  * Swap the data of two nodes in the binary tree.
1198
1284
  * @param {N} srcNode - The source node to swap.
@@ -1200,15 +1286,20 @@ class BinaryTree {
1200
1286
  * @returns {N} - The destination node after the swap.
1201
1287
  */
1202
1288
  _swap(srcNode, destNode) {
1203
- const { key, value } = destNode;
1204
- const tempNode = this.createNode(key, value);
1205
- if (tempNode) {
1206
- destNode.key = srcNode.key;
1207
- destNode.value = srcNode.value;
1208
- srcNode.key = tempNode.key;
1209
- srcNode.value = tempNode.value;
1289
+ srcNode = this.ensureNotKey(srcNode);
1290
+ destNode = this.ensureNotKey(destNode);
1291
+ if (srcNode && destNode) {
1292
+ const { key, value } = destNode;
1293
+ const tempNode = this.createNode(key, value);
1294
+ if (tempNode) {
1295
+ destNode.key = srcNode.key;
1296
+ destNode.value = srcNode.value;
1297
+ srcNode.key = tempNode.key;
1298
+ srcNode.value = tempNode.value;
1299
+ }
1300
+ return destNode;
1210
1301
  }
1211
- return destNode;
1302
+ return undefined;
1212
1303
  }
1213
1304
  /**
1214
1305
  * The function `_addTo` adds a new node to a binary tree if there is an available position.
@@ -1222,6 +1313,8 @@ class BinaryTree {
1222
1313
  * If the parent node is null, the function also returns undefined.
1223
1314
  */
1224
1315
  _addTo(newNode, parent) {
1316
+ if (this.isNodeKey(parent))
1317
+ parent = this.getNode(parent);
1225
1318
  if (parent) {
1226
1319
  // When all leaf nodes are null, it will no longer be possible to add new entity nodes to this binary tree.
1227
1320
  // In this scenario, null nodes serve as "sentinel nodes," "virtual nodes," or "placeholder nodes."
@@ -1259,7 +1352,16 @@ class BinaryTree {
1259
1352
  }
1260
1353
  this._root = v;
1261
1354
  }
1355
+ /**
1356
+ * The `print` function is used to display a binary tree structure in a visually appealing way.
1357
+ * @param {N | null | undefined} root - The `root` parameter in the `print` function represents the
1358
+ * root node of a binary tree. It can have one of the following types: `BTNKey`, `N`, `null`, or
1359
+ * `undefined`. The default value is `this.root`, which suggests that `this.root` is the
1360
+ */
1262
1361
  print(beginRoot = this.root) {
1362
+ beginRoot = this.ensureNotKey(beginRoot);
1363
+ if (!beginRoot)
1364
+ return;
1263
1365
  const display = (root) => {
1264
1366
  const [lines, , ,] = _displayAux(root);
1265
1367
  for (const line of lines) {