min-heap-typed 1.38.5 → 1.38.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.
@@ -15,7 +15,7 @@ import type {
15
15
  MapCallback,
16
16
  MapCallbackReturn
17
17
  } from '../../types';
18
- import {BinaryTreeDeletedResult, DFSOrderPattern, FamilyPosition, IterationType} from '../../types';
18
+ import {BinaryTreeDeletedResult, DefaultMapCallback, DFSOrderPattern, FamilyPosition, IterationType} from '../../types';
19
19
  import {IBinaryTree} from '../../interfaces';
20
20
  import {trampoline} from '../../utils';
21
21
  import {Queue} from '../queue';
@@ -23,9 +23,9 @@ import {Queue} from '../queue';
23
23
  /**
24
24
  * Represents a node in a binary tree.
25
25
  * @template V - The type of data stored in the node.
26
- * @template FAMILY - The type of the family relationship in the binary tree.
26
+ * @template N - The type of the family relationship in the binary tree.
27
27
  */
28
- export class BinaryTreeNode<V = any, FAMILY extends BinaryTreeNode<V, FAMILY> = BinaryTreeNodeNested<V>> {
28
+ export class BinaryTreeNode<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode<V, BinaryTreeNodeNested<V>>> {
29
29
  /**
30
30
  * The key associated with the node.
31
31
  */
@@ -39,7 +39,7 @@ export class BinaryTreeNode<V = any, FAMILY extends BinaryTreeNode<V, FAMILY> =
39
39
  /**
40
40
  * The parent node of the current node.
41
41
  */
42
- parent: FAMILY | null | undefined;
42
+ parent: N | null | undefined;
43
43
 
44
44
  /**
45
45
  * Creates a new instance of BinaryTreeNode.
@@ -51,42 +51,42 @@ export class BinaryTreeNode<V = any, FAMILY extends BinaryTreeNode<V, FAMILY> =
51
51
  this.val = val;
52
52
  }
53
53
 
54
- private _left: FAMILY | null | undefined;
54
+ private _left: N | null | undefined;
55
55
 
56
56
  /**
57
57
  * Get the left child node.
58
58
  */
59
- get left(): FAMILY | null | undefined {
59
+ get left(): N | null | undefined {
60
60
  return this._left;
61
61
  }
62
62
 
63
63
  /**
64
64
  * Set the left child node.
65
- * @param {FAMILY | null | undefined} v - The left child node.
65
+ * @param {N | null | undefined} v - The left child node.
66
66
  */
67
- set left(v: FAMILY | null | undefined) {
67
+ set left(v: N | null | undefined) {
68
68
  if (v) {
69
- v.parent = this as unknown as FAMILY;
69
+ v.parent = this as unknown as N;
70
70
  }
71
71
  this._left = v;
72
72
  }
73
73
 
74
- private _right: FAMILY | null | undefined;
74
+ private _right: N | null | undefined;
75
75
 
76
76
  /**
77
77
  * Get the right child node.
78
78
  */
79
- get right(): FAMILY | null | undefined {
79
+ get right(): N | null | undefined {
80
80
  return this._right;
81
81
  }
82
82
 
83
83
  /**
84
84
  * Set the right child node.
85
- * @param {FAMILY | null | undefined} v - The right child node.
85
+ * @param {N | null | undefined} v - The right child node.
86
86
  */
87
- set right(v: FAMILY | null | undefined) {
87
+ set right(v: N | null | undefined) {
88
88
  if (v) {
89
- v.parent = this as unknown as FAMILY;
89
+ v.parent = this as unknown as N;
90
90
  }
91
91
  this._right = v;
92
92
  }
@@ -96,30 +96,18 @@ export class BinaryTreeNode<V = any, FAMILY extends BinaryTreeNode<V, FAMILY> =
96
96
  * @returns {FamilyPosition} - The family position of the node.
97
97
  */
98
98
  get familyPosition(): FamilyPosition {
99
- const that = this as unknown as FAMILY;
100
- if (that.parent) {
101
- if (that.parent.left === that) {
102
- if (that.left || that.right) {
103
- return FamilyPosition.ROOT_LEFT;
104
- } else {
105
- return FamilyPosition.LEFT;
106
- }
107
- } else if (that.parent.right === that) {
108
- if (that.left || that.right) {
109
- return FamilyPosition.ROOT_RIGHT;
110
- } else {
111
- return FamilyPosition.RIGHT;
112
- }
113
- } else {
114
- return FamilyPosition.MAL_NODE;
115
- }
116
- } else {
117
- if (that.left || that.right) {
118
- return FamilyPosition.ROOT;
119
- } else {
120
- return FamilyPosition.ISOLATED;
121
- }
99
+ const that = this as unknown as N;
100
+ if (!this.parent) {
101
+ return this.left || this.right ? FamilyPosition.ROOT : FamilyPosition.ISOLATED;
122
102
  }
103
+
104
+ if (this.parent.left === that) {
105
+ return this.left || this.right ? FamilyPosition.ROOT_LEFT : FamilyPosition.LEFT;
106
+ } else if (this.parent.right === that) {
107
+ return this.left || this.right ? FamilyPosition.ROOT_RIGHT : FamilyPosition.RIGHT;
108
+ }
109
+
110
+ return FamilyPosition.MAL_NODE;
123
111
  }
124
112
  }
125
113
 
@@ -127,9 +115,7 @@ export class BinaryTreeNode<V = any, FAMILY extends BinaryTreeNode<V, FAMILY> =
127
115
  * Represents a binary tree data structure.
128
116
  * @template N - The type of the binary tree's nodes.
129
117
  */
130
- export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode> implements IBinaryTree<N> {
131
- private _loopType: IterationType = IterationType.ITERATIVE;
132
-
118
+ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode> implements IBinaryTree<V, N> {
133
119
  /**
134
120
  * Creates a new instance of BinaryTree.
135
121
  * @param {BinaryTreeOptions} [options] - The options for the binary tree.
@@ -137,10 +123,27 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
137
123
  constructor(options?: BinaryTreeOptions) {
138
124
  if (options !== undefined) {
139
125
  const {iterationType = IterationType.ITERATIVE} = options;
140
- this._loopType = iterationType;
126
+ this._iterationType = iterationType;
141
127
  }
142
128
  }
143
129
 
130
+ private _iterationType: IterationType = IterationType.ITERATIVE;
131
+
132
+ /**
133
+ * Get the iteration type used in the binary tree.
134
+ */
135
+ get iterationType(): IterationType {
136
+ return this._iterationType;
137
+ }
138
+
139
+ /**
140
+ * Set the iteration type for the binary tree.
141
+ * @param {IterationType} v - The new iteration type to set.
142
+ */
143
+ set iterationType(v: IterationType) {
144
+ this._iterationType = v;
145
+ }
146
+
144
147
  private _root: N | null = null;
145
148
 
146
149
  /**
@@ -159,29 +162,14 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
159
162
  return this._size;
160
163
  }
161
164
 
162
- /**
163
- * Get the iteration type used in the binary tree.
164
- */
165
- get iterationType(): IterationType {
166
- return this._loopType;
167
- }
168
-
169
- /**
170
- * Set the iteration type for the binary tree.
171
- * @param {IterationType} v - The new iteration type to set.
172
- */
173
- set iterationType(v: IterationType) {
174
- this._loopType = v;
175
- }
176
-
177
165
  /**
178
166
  * Creates a new instance of BinaryTreeNode with the given key and value.
179
167
  * @param {BinaryTreeNodeKey} key - The key for the new node.
180
- * @param {N['val']} val - The value for the new node.
168
+ * @param {V} val - The value for the new node.
181
169
  * @returns {N} - The newly created BinaryTreeNode.
182
170
  */
183
- createNode(key: BinaryTreeNodeKey, val?: N['val']): N {
184
- return new BinaryTreeNode<N['val'], N>(key, val) as N;
171
+ createNode(key: BinaryTreeNodeKey, val?: V): N {
172
+ return new BinaryTreeNode<V, N>(key, val) as N;
185
173
  }
186
174
 
187
175
  /**
@@ -203,10 +191,10 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
203
191
  /**
204
192
  * Add a node with the given key and value to the binary tree.
205
193
  * @param {BinaryTreeNodeKey | N | null} keyOrNode - The key or node to add to the binary tree.
206
- * @param {N['val']} val - The value for the new node (optional).
194
+ * @param {V} val - The value for the new node (optional).
207
195
  * @returns {N | null | undefined} - The inserted node, or null if nothing was inserted, or undefined if the operation failed.
208
196
  */
209
- add(keyOrNode: BinaryTreeNodeKey | N | null, val?: N['val']): N | null | undefined {
197
+ add(keyOrNode: BinaryTreeNodeKey | N | null, val?: V): N | null | undefined {
210
198
  const _bfs = (root: N, newNode: N | null): N | undefined | null => {
211
199
  const queue = new Queue<N | null>([root]);
212
200
  while (queue.size > 0) {
@@ -234,7 +222,8 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
234
222
  return;
235
223
  }
236
224
 
237
- const existNode = keyOrNode ? this.get(keyOrNode, this._defaultCallbackByKey) : undefined;
225
+ const key = typeof keyOrNode === 'number' ? keyOrNode : keyOrNode ? keyOrNode.key : undefined;
226
+ const existNode = key !== undefined ? this.get(key, this._defaultCallbackByKey) : undefined;
238
227
 
239
228
  if (this.root) {
240
229
  if (existNode) {
@@ -260,60 +249,68 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
260
249
  * values, and adds them to the binary tree.
261
250
  * @param {(BinaryTreeNodeKey | null)[] | (N | null)[]} keysOrNodes - An array of BinaryTreeNodeKey or BinaryTreeNode
262
251
  * objects, or null values.
263
- * @param {N['val'][]} [values] - The `values` parameter is an optional array of values (`N['val'][]`) that corresponds to
252
+ * @param {V[]} [values] - The `values` parameter is an optional array of values (`V[]`) that corresponds to
264
253
  * the nodes or node IDs being added. It is used to set the value of each node being added. If `values` is not provided,
265
254
  * the value of the nodes will be `undefined`.
266
255
  * @returns The function `addMany` returns an array of `N`, `null`, or `undefined` values.
267
256
  */
268
- addMany(keysOrNodes: (BinaryTreeNodeKey | null)[] | (N | null)[], values?: N['val'][]): (N | null | undefined)[] {
257
+ addMany(keysOrNodes: (BinaryTreeNodeKey | null)[] | (N | null)[], values?: V[]): (N | null | undefined)[] {
269
258
  // TODO not sure addMany not be run multi times
270
- const inserted: (N | null | undefined)[] = [];
271
-
272
- for (let i = 0; i < keysOrNodes.length; i++) {
273
- const keyOrNode = keysOrNodes[i];
259
+ return keysOrNodes.map((keyOrNode, i) => {
274
260
  if (keyOrNode instanceof BinaryTreeNode) {
275
- inserted.push(this.add(keyOrNode.key, keyOrNode.val));
276
- continue;
261
+ return this.add(keyOrNode.key, keyOrNode.val);
277
262
  }
278
263
 
279
264
  if (keyOrNode === null) {
280
- inserted.push(this.add(null));
281
- continue;
265
+ return this.add(null);
282
266
  }
283
267
 
284
268
  const val = values?.[i];
285
- inserted.push(this.add(keyOrNode, val));
286
- }
287
- return inserted;
269
+ return this.add(keyOrNode, val);
270
+ });
288
271
  }
289
272
 
290
273
  /**
291
274
  * The `refill` function clears the binary tree and adds multiple nodes with the given IDs or nodes and optional data.
292
275
  * @param {(BinaryTreeNodeKey | N)[]} keysOrNodes - The `keysOrNodes` parameter is an array that can contain either
293
276
  * `BinaryTreeNodeKey` or `N` values.
294
- * @param {N[] | Array<N['val']>} [data] - The `data` parameter is an optional array of values that will be assigned to
277
+ * @param {N[] | Array<V>} [data] - The `data` parameter is an optional array of values that will be assigned to
295
278
  * the nodes being added. If provided, the length of the `data` array should be equal to the length of the `keysOrNodes`
296
279
  * array. Each value in the `data` array will be assigned to the
297
280
  * @returns The method is returning a boolean value.
298
281
  */
299
- refill(keysOrNodes: (BinaryTreeNodeKey | null)[] | (N | null)[], data?: N[] | Array<N['val']>): boolean {
282
+ refill(keysOrNodes: (BinaryTreeNodeKey | null)[] | (N | null)[], data?: Array<V>): boolean {
300
283
  this.clear();
301
284
  return keysOrNodes.length === this.addMany(keysOrNodes, data).length;
302
285
  }
303
286
 
287
+ delete<C extends MapCallback<N>>(identifier: ReturnType<C> | N): BinaryTreeDeletedResult<N>[];
288
+
289
+ delete<C extends MapCallback<N>>(identifier: ReturnType<C> | N, callback: C): BinaryTreeDeletedResult<N>[];
290
+
304
291
  /**
305
292
  * The `delete` function removes a node from a binary search tree and returns the deleted node along
306
293
  * with the parent node that needs to be balanced.
307
- * @param {N | BinaryTreeNodeKey} nodeOrKey - The `nodeOrKey` parameter can be either a node (`N`) or
308
294
  * a key (`BinaryTreeNodeKey`). If it is a key, the function will find the corresponding node in the
309
295
  * binary tree.
310
296
  * @returns an array of `BinaryTreeDeletedResult<N>` objects.
297
+ * @param {ReturnType<C>} identifier - The `identifier` parameter is either a
298
+ * `BinaryTreeNodeKey` or a generic type `N`. It represents the property of the node that we are
299
+ * searching for. It can be a specific key value or any other property of the node.
300
+ * @param callback - The `callback` parameter is a function that takes a node as input and returns a
301
+ * value. This value is compared with the `identifier` parameter to determine if the node should be
302
+ * included in the result. The `callback` parameter has a default value of
303
+ * `this._defaultCallbackByKey`, which
311
304
  */
312
- delete(nodeOrKey: N | BinaryTreeNodeKey): BinaryTreeDeletedResult<N>[] {
305
+ delete<C extends MapCallback<N>>(
306
+ identifier: ReturnType<C> | N,
307
+ callback: C = this._defaultCallbackByKey as C
308
+ ): BinaryTreeDeletedResult<N>[] {
313
309
  const bstDeletedResult: BinaryTreeDeletedResult<N>[] = [];
314
310
  if (!this.root) return bstDeletedResult;
311
+ if (identifier instanceof BinaryTreeNode) callback = (node => node) as C;
315
312
 
316
- const curr: N | null = typeof nodeOrKey === 'number' ? this.get(nodeOrKey) : nodeOrKey;
313
+ const curr = this.get(identifier, callback);
317
314
  if (!curr) return bstDeletedResult;
318
315
 
319
316
  const parent: N | null = curr?.parent ? curr.parent : null;
@@ -354,16 +351,16 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
354
351
  /**
355
352
  * The function `getDepth` calculates the depth of a given node in a binary tree relative to a
356
353
  * specified root node.
357
- * @param {N | BinaryTreeNodeKey | null} distNode - The `distNode` parameter represents the node
354
+ * @param {BinaryTreeNodeKey | N | null} distNode - The `distNode` parameter represents the node
358
355
  * whose depth we want to find in the binary tree. It can be either a node object (`N`), a key value
359
356
  * of the node (`BinaryTreeNodeKey`), or `null`.
360
- * @param {N | BinaryTreeNodeKey | null} beginRoot - The `beginRoot` parameter represents the
357
+ * @param {BinaryTreeNodeKey | N | null} beginRoot - The `beginRoot` parameter represents the
361
358
  * starting node from which we want to calculate the depth. It can be either a node object or the key
362
359
  * of a node in the binary tree. If no value is provided for `beginRoot`, it defaults to the root
363
360
  * node of the binary tree.
364
361
  * @returns the depth of the `distNode` relative to the `beginRoot`.
365
362
  */
366
- getDepth(distNode: N | BinaryTreeNodeKey | null, beginRoot: N | BinaryTreeNodeKey | null = this.root): number {
363
+ getDepth(distNode: BinaryTreeNodeKey | N | null, beginRoot: BinaryTreeNodeKey | N | null = this.root): number {
367
364
  if (typeof distNode === 'number') distNode = this.get(distNode);
368
365
  if (typeof beginRoot === 'number') beginRoot = this.get(beginRoot);
369
366
  let depth = 0;
@@ -380,7 +377,7 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
380
377
  /**
381
378
  * The `getHeight` function calculates the maximum height of a binary tree using either recursive or
382
379
  * iterative approach.
383
- * @param {N | BinaryTreeNodeKey | null} beginRoot - The `beginRoot` parameter represents the
380
+ * @param {BinaryTreeNodeKey | N | null} beginRoot - The `beginRoot` parameter represents the
384
381
  * starting node from which the height of the binary tree is calculated. It can be either a node
385
382
  * object (`N`), a key value of a node in the tree (`BinaryTreeNodeKey`), or `null` if no starting
386
383
  * node is specified. If `
@@ -389,7 +386,7 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
389
386
  * possible values:
390
387
  * @returns the height of the binary tree.
391
388
  */
392
- getHeight(beginRoot: N | BinaryTreeNodeKey | null = this.root, iterationType = this.iterationType): number {
389
+ getHeight(beginRoot: BinaryTreeNodeKey | N | null = this.root, iterationType = this.iterationType): number {
393
390
  if (typeof beginRoot === 'number') beginRoot = this.get(beginRoot);
394
391
  if (!beginRoot) return -1;
395
392
 
@@ -491,18 +488,41 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
491
488
  return this.getMinHeight(beginRoot) + 1 >= this.getHeight(beginRoot);
492
489
  }
493
490
 
491
+ getNodes<C extends MapCallback<N>>(identifier: ReturnType<C> | N): N[];
492
+
493
+ getNodes<C extends MapCallback<N>>(identifier: ReturnType<C> | N, callback: C): N[];
494
+
495
+ getNodes<C extends MapCallback<N>>(identifier: ReturnType<C> | N, onlyOne: boolean): N[];
496
+
497
+ getNodes<C extends MapCallback<N>>(identifier: ReturnType<C> | N, callback: C, onlyOne: boolean): N[];
498
+
499
+ getNodes<C extends MapCallback<N>>(
500
+ identifier: ReturnType<C> | N,
501
+ callback: C,
502
+ onlyOne: boolean,
503
+ beginRoot: N | null
504
+ ): N[];
505
+
506
+ getNodes<C extends MapCallback<N>>(
507
+ identifier: ReturnType<C> | N,
508
+ callback: C,
509
+ onlyOne: boolean,
510
+ beginRoot: N | null,
511
+ iterationType: IterationType
512
+ ): N[];
513
+
494
514
  /**
495
515
  * The function `getNodes` returns an array of nodes that match a given node property, using either
496
516
  * recursive or iterative traversal.
497
- * @param {BinaryTreeNodeKey | N} nodeProperty - The `nodeProperty` parameter is either a
517
+ * @param {ReturnType<C>} identifier - The `identifier` parameter is either a
498
518
  * `BinaryTreeNodeKey` or a generic type `N`. It represents the property of the node that we are
499
519
  * searching for. It can be a specific key value or any other property of the node.
500
520
  * @param callback - The `callback` parameter is a function that takes a node as input and returns a
501
- * value. This value is compared with the `nodeProperty` parameter to determine if the node should be
521
+ * value. This value is compared with the `identifier` parameter to determine if the node should be
502
522
  * included in the result. The `callback` parameter has a default value of
503
523
  * `this._defaultCallbackByKey`, which
504
524
  * @param [onlyOne=false] - A boolean value indicating whether to stop searching after finding the
505
- * first node that matches the nodeProperty. If set to true, the function will return an array with
525
+ * first node that matches the identifier. If set to true, the function will return an array with
506
526
  * only one element (or an empty array if no matching node is found). If set to false (default), the
507
527
  * function will continue searching for all
508
528
  * @param {N | null} beginRoot - The `beginRoot` parameter is the starting node from which the
@@ -512,20 +532,20 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
512
532
  * traverse the binary tree. It can have two possible values:
513
533
  * @returns The function `getNodes` returns an array of nodes (`N[]`).
514
534
  */
515
- getNodes<C extends MapCallback<N> = MapCallback<N, BinaryTreeNodeKey>>(
516
- nodeProperty: BinaryTreeNodeKey | N,
535
+ getNodes<C extends MapCallback<N>>(
536
+ identifier: ReturnType<C> | N,
517
537
  callback: C = this._defaultCallbackByKey as C,
518
538
  onlyOne = false,
519
539
  beginRoot: N | null = this.root,
520
540
  iterationType = this.iterationType
521
541
  ): N[] {
522
542
  if (!beginRoot) return [];
523
-
543
+ if (identifier instanceof BinaryTreeNode) callback = (node => node) as C;
524
544
  const ans: N[] = [];
525
545
 
526
546
  if (iterationType === IterationType.RECURSIVE) {
527
547
  const _traverse = (cur: N) => {
528
- if (callback(cur) === nodeProperty) {
548
+ if (callback(cur) === identifier) {
529
549
  ans.push(cur);
530
550
  if (onlyOne) return;
531
551
  }
@@ -540,7 +560,7 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
540
560
  while (queue.size > 0) {
541
561
  const cur = queue.shift();
542
562
  if (cur) {
543
- if (callback(cur) === nodeProperty) {
563
+ if (callback(cur) === identifier) {
544
564
  ans.push(cur);
545
565
  if (onlyOne) return ans;
546
566
  }
@@ -553,9 +573,17 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
553
573
  return ans;
554
574
  }
555
575
 
576
+ has<C extends MapCallback<N>>(identifier: ReturnType<C> | N): boolean;
577
+
578
+ has<C extends MapCallback<N>>(identifier: ReturnType<C> | N, callback: C): boolean;
579
+
580
+ has<C extends MapCallback<N>>(identifier: ReturnType<C> | N, beginRoot: N | null): boolean;
581
+
582
+ has<C extends MapCallback<N>>(identifier: ReturnType<C> | N, callback: C, beginRoot: N | null): boolean;
583
+
556
584
  /**
557
585
  * The function checks if a binary tree has a node with a given property or key.
558
- * @param {BinaryTreeNodeKey | N} nodeProperty - The `nodeProperty` parameter is the key or value of
586
+ * @param {BinaryTreeNodeKey | N} identifier - The `identifier` parameter is the key or value of
559
587
  * the node that you want to find in the binary tree. It can be either a `BinaryTreeNodeKey` or a
560
588
  * generic type `N`.
561
589
  * @param callback - The `callback` parameter is a function that is used to determine whether a node
@@ -570,19 +598,35 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
570
598
  * performed when searching for nodes in the binary tree. It can have one of the following values:
571
599
  * @returns a boolean value.
572
600
  */
573
- has<C extends MapCallback<N> = MapCallback<N, BinaryTreeNodeKey>>(
574
- nodeProperty: BinaryTreeNodeKey | N,
601
+ has<C extends MapCallback<N>>(
602
+ identifier: ReturnType<C> | N,
575
603
  callback: C = this._defaultCallbackByKey as C,
576
604
  beginRoot = this.root,
577
605
  iterationType = this.iterationType
578
606
  ): boolean {
607
+ if (identifier instanceof BinaryTreeNode) callback = (node => node) as C;
579
608
  // TODO may support finding node by value equal
580
- return this.getNodes(nodeProperty, callback, true, beginRoot, iterationType).length > 0;
609
+ return this.getNodes(identifier, callback, true, beginRoot, iterationType).length > 0;
581
610
  }
582
611
 
612
+ get<C extends MapCallback<N>>(identifier: ReturnType<C> | N): N | null;
613
+
614
+ get<C extends MapCallback<N>>(identifier: ReturnType<C> | N, callback: C): N | null;
615
+
616
+ get<C extends MapCallback<N>>(identifier: ReturnType<C> | N, beginRoot: N | null): N | null;
617
+
618
+ get<C extends MapCallback<N>>(identifier: ReturnType<C> | N, callback: C, beginRoot: N | null): N | null;
619
+
620
+ get<C extends MapCallback<N>>(
621
+ identifier: ReturnType<C> | N,
622
+ callback: C,
623
+ beginRoot: N | null,
624
+ iterationType: IterationType
625
+ ): N | null;
626
+
583
627
  /**
584
628
  * The function `get` returns the first node in a binary tree that matches the given property or key.
585
- * @param {BinaryTreeNodeKey | N} nodeProperty - The `nodeProperty` parameter is the key or value of
629
+ * @param {BinaryTreeNodeKey | N} identifier - The `identifier` parameter is the key or value of
586
630
  * the node that you want to find in the binary tree. It can be either a `BinaryTreeNodeKey` or `N`
587
631
  * type.
588
632
  * @param callback - The `callback` parameter is a function that is used to determine whether a node
@@ -595,14 +639,15 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
595
639
  * performed when searching for a node in the binary tree. It can have one of the following values:
596
640
  * @returns either the found node (of type N) or null if no node is found.
597
641
  */
598
- get<C extends MapCallback<N> = MapCallback<N, BinaryTreeNodeKey>>(
599
- nodeProperty: BinaryTreeNodeKey | N,
642
+ get<C extends MapCallback<N>>(
643
+ identifier: ReturnType<C> | N,
600
644
  callback: C = this._defaultCallbackByKey as C,
601
645
  beginRoot = this.root,
602
646
  iterationType = this.iterationType
603
647
  ): N | null {
648
+ if (identifier instanceof BinaryTreeNode) callback = (node => node) as C;
604
649
  // TODO may support finding node by value equal
605
- return this.getNodes(nodeProperty, callback, true, beginRoot, iterationType)[0] ?? null;
650
+ return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? null;
606
651
  }
607
652
 
608
653
  /**
@@ -631,7 +676,7 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
631
676
  /**
632
677
  * The function `getLeftMost` returns the leftmost node in a binary tree, either using recursive or
633
678
  * iterative traversal.
634
- * @param {N | BinaryTreeNodeKey | null} beginRoot - The `beginRoot` parameter is the starting point
679
+ * @param {BinaryTreeNodeKey | N | null} beginRoot - The `beginRoot` parameter is the starting point
635
680
  * for finding the leftmost node in a binary tree. It can be either a node object (`N`), a key value
636
681
  * of a node (`BinaryTreeNodeKey`), or `null` if the tree is empty.
637
682
  * @param iterationType - The `iterationType` parameter is used to determine the type of iteration to
@@ -639,7 +684,7 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
639
684
  * @returns The function `getLeftMost` returns the leftmost node (`N`) in a binary tree. If there is
640
685
  * no leftmost node, it returns `null`.
641
686
  */
642
- getLeftMost(beginRoot: N | BinaryTreeNodeKey | null = this.root, iterationType = this.iterationType): N | null {
687
+ getLeftMost(beginRoot: BinaryTreeNodeKey | N | null = this.root, iterationType = this.iterationType): N | null {
643
688
  if (typeof beginRoot === 'number') beginRoot = this.get(beginRoot);
644
689
 
645
690
  if (!beginRoot) return beginRoot;
@@ -754,16 +799,16 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
754
799
  * subtree traversal. It takes a single argument, which is the current node being traversed, and
755
800
  * returns a value. The return values from each callback invocation will be collected and returned as
756
801
  * an array.
757
- * @param {N | BinaryTreeNodeKey | null} beginRoot - The `beginRoot` parameter is the starting point
802
+ * @param {BinaryTreeNodeKey | N | null} beginRoot - The `beginRoot` parameter is the starting point
758
803
  * for traversing the subtree. It can be either a node object, a key value of a node, or `null` to
759
804
  * start from the root of the tree.
760
805
  * @param iterationType - The `iterationType` parameter determines the type of traversal to be
761
806
  * performed on the binary tree. It can have two possible values:
762
807
  * @returns The function `subTreeTraverse` returns an array of `MapCallbackReturn<N>`.
763
808
  */
764
- subTreeTraverse<C extends MapCallback<N> = MapCallback<N, BinaryTreeNodeKey>>(
809
+ subTreeTraverse<C extends MapCallback<N>>(
765
810
  callback: C = this._defaultCallbackByKey as C,
766
- beginRoot: N | BinaryTreeNodeKey | null = this.root,
811
+ beginRoot: BinaryTreeNodeKey | N | null = this.root,
767
812
  iterationType = this.iterationType
768
813
  ): ReturnType<C>[] {
769
814
  if (typeof beginRoot === 'number') beginRoot = this.get(beginRoot);
@@ -808,7 +853,7 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
808
853
  * iteration used in the depth-first search algorithm. It can have two possible values:
809
854
  * @returns The function `dfs` returns an array of `MapCallbackReturn<N>` values.
810
855
  */
811
- dfs<C extends MapCallback<N> = MapCallback<N, BinaryTreeNodeKey>>(
856
+ dfs<C extends MapCallback<N>>(
812
857
  callback: C = this._defaultCallbackByKey as C,
813
858
  pattern: DFSOrderPattern = 'in',
814
859
  beginRoot: N | null = this.root,
@@ -886,7 +931,7 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
886
931
  * breadth-first search. It takes a node of type `N` as its argument and returns a value of type
887
932
  * `BFSCallbackReturn<N>`. The default value for this parameter is `this._defaultCallbackByKey
888
933
  * @param {boolean} [withLevel=false] - The `withLevel` parameter is a boolean flag that determines
889
- * whether or not to include the level of each node in the callback function. If `withLevel` is set
934
+ * whether to include the level of each node in the callback function. If `withLevel` is set
890
935
  * to `true`, the level of each node will be passed as an argument to the callback function. If
891
936
  * `withLevel` is
892
937
  * @param {N | null} beginRoot - The `beginRoot` parameter is the starting node for the breadth-first
@@ -964,7 +1009,7 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
964
1009
  * `beginRoot` is `null`, an empty array will be returned.
965
1010
  * @returns The `morris` function returns an array of `MapCallbackReturn<N>` values.
966
1011
  */
967
- morris<C extends MapCallback<N> = MapCallback<N, BinaryTreeNodeKey>>(
1012
+ morris<C extends MapCallback<N>>(
968
1013
  callback: C = this._defaultCallbackByKey as C,
969
1014
  pattern: DFSOrderPattern = 'in',
970
1015
  beginRoot: N | null = this.root
@@ -1077,8 +1122,7 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
1077
1122
  * the tree's structure should be restored to its original state to maintain the tree's integrity.
1078
1123
  * This is because the purpose of the Morris algorithm is to save space rather than permanently alter the tree's shape.
1079
1124
  */
1080
-
1081
- protected _defaultCallbackByKey: (node: N) => number = node => node.key;
1125
+ protected _defaultCallbackByKey: DefaultMapCallback<N> = node => node.key;
1082
1126
 
1083
1127
  /**
1084
1128
  * The function `_addTo` adds a new node to a binary tree if there is an available position.