heap-typed 1.47.5 → 1.47.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 (71) hide show
  1. package/dist/data-structures/binary-tree/avl-tree.d.ts +36 -18
  2. package/dist/data-structures/binary-tree/avl-tree.js +46 -29
  3. package/dist/data-structures/binary-tree/binary-tree.d.ts +158 -129
  4. package/dist/data-structures/binary-tree/binary-tree.js +182 -184
  5. package/dist/data-structures/binary-tree/bst.d.ts +73 -63
  6. package/dist/data-structures/binary-tree/bst.js +168 -169
  7. package/dist/data-structures/binary-tree/rb-tree.d.ts +54 -17
  8. package/dist/data-structures/binary-tree/rb-tree.js +77 -31
  9. package/dist/data-structures/binary-tree/tree-multimap.d.ts +29 -40
  10. package/dist/data-structures/binary-tree/tree-multimap.js +66 -136
  11. package/dist/data-structures/graph/abstract-graph.js +1 -1
  12. package/dist/data-structures/hash/hash-map.d.ts +2 -6
  13. package/dist/data-structures/hash/hash-map.js +5 -8
  14. package/dist/data-structures/heap/heap.d.ts +19 -21
  15. package/dist/data-structures/heap/heap.js +52 -34
  16. package/dist/data-structures/heap/max-heap.d.ts +2 -5
  17. package/dist/data-structures/heap/max-heap.js +2 -2
  18. package/dist/data-structures/heap/min-heap.d.ts +2 -5
  19. package/dist/data-structures/heap/min-heap.js +2 -2
  20. package/dist/data-structures/linked-list/doubly-linked-list.d.ts +2 -1
  21. package/dist/data-structures/linked-list/doubly-linked-list.js +9 -1
  22. package/dist/data-structures/linked-list/singly-linked-list.d.ts +2 -1
  23. package/dist/data-structures/linked-list/singly-linked-list.js +8 -1
  24. package/dist/data-structures/priority-queue/max-priority-queue.d.ts +2 -5
  25. package/dist/data-structures/priority-queue/max-priority-queue.js +2 -2
  26. package/dist/data-structures/priority-queue/min-priority-queue.d.ts +2 -5
  27. package/dist/data-structures/priority-queue/min-priority-queue.js +2 -2
  28. package/dist/data-structures/priority-queue/priority-queue.d.ts +2 -5
  29. package/dist/data-structures/priority-queue/priority-queue.js +2 -2
  30. package/dist/data-structures/queue/deque.d.ts +1 -0
  31. package/dist/data-structures/queue/deque.js +3 -0
  32. package/dist/data-structures/queue/queue.d.ts +1 -0
  33. package/dist/data-structures/queue/queue.js +3 -0
  34. package/dist/data-structures/stack/stack.d.ts +2 -1
  35. package/dist/data-structures/stack/stack.js +10 -2
  36. package/dist/data-structures/trie/trie.d.ts +3 -0
  37. package/dist/data-structures/trie/trie.js +19 -4
  38. package/dist/interfaces/binary-tree.d.ts +4 -2
  39. package/dist/types/common.d.ts +7 -0
  40. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +1 -1
  41. package/dist/types/data-structures/binary-tree/bst.d.ts +2 -2
  42. package/dist/types/data-structures/hash/hash-map.d.ts +1 -2
  43. package/dist/types/data-structures/heap/heap.d.ts +4 -1
  44. package/dist/types/data-structures/priority-queue/priority-queue.d.ts +2 -1
  45. package/package.json +2 -2
  46. package/src/data-structures/binary-tree/avl-tree.ts +61 -31
  47. package/src/data-structures/binary-tree/binary-tree.ts +283 -254
  48. package/src/data-structures/binary-tree/bst.ts +193 -170
  49. package/src/data-structures/binary-tree/rb-tree.ts +87 -32
  50. package/src/data-structures/binary-tree/tree-multimap.ts +76 -136
  51. package/src/data-structures/graph/abstract-graph.ts +1 -1
  52. package/src/data-structures/hash/hash-map.ts +8 -8
  53. package/src/data-structures/heap/heap.ts +57 -39
  54. package/src/data-structures/heap/max-heap.ts +5 -5
  55. package/src/data-structures/heap/min-heap.ts +5 -5
  56. package/src/data-structures/linked-list/doubly-linked-list.ts +10 -1
  57. package/src/data-structures/linked-list/singly-linked-list.ts +9 -1
  58. package/src/data-structures/priority-queue/max-priority-queue.ts +4 -3
  59. package/src/data-structures/priority-queue/min-priority-queue.ts +12 -12
  60. package/src/data-structures/priority-queue/priority-queue.ts +3 -3
  61. package/src/data-structures/queue/deque.ts +4 -0
  62. package/src/data-structures/queue/queue.ts +4 -0
  63. package/src/data-structures/stack/stack.ts +12 -3
  64. package/src/data-structures/trie/trie.ts +23 -4
  65. package/src/interfaces/binary-tree.ts +14 -2
  66. package/src/types/common.ts +15 -1
  67. package/src/types/data-structures/binary-tree/binary-tree.ts +1 -1
  68. package/src/types/data-structures/binary-tree/bst.ts +2 -3
  69. package/src/types/data-structures/hash/hash-map.ts +1 -2
  70. package/src/types/data-structures/heap/heap.ts +3 -1
  71. package/src/types/data-structures/priority-queue/priority-queue.ts +3 -1
@@ -6,7 +6,15 @@
6
6
  * @license MIT License
7
7
  */
8
8
 
9
- import type { BinaryTreeNodeNested, BinaryTreeOptions, BTNCallback, BTNKey } from '../../types';
9
+ import type {
10
+ BinaryTreeNodeNested,
11
+ BinaryTreeOptions,
12
+ BTNCallback,
13
+ BTNKey,
14
+ BTNodeEntry,
15
+ BTNodeExemplar,
16
+ BTNodeKeyOrNode
17
+ } from '../../types';
10
18
  import {
11
19
  BinaryTreeNested,
12
20
  BinaryTreePrintOptions,
@@ -26,26 +34,12 @@ import { Queue } from '../queue';
26
34
  * @template N - The type of the family relationship in the binary tree.
27
35
  */
28
36
  export class BinaryTreeNode<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode<V, BinaryTreeNodeNested<V>>> {
29
- /**
30
- * The key associated with the node.
31
- */
32
37
  key: BTNKey;
33
38
 
34
- /**
35
- * The value stored in the node.
36
- */
37
39
  value?: V;
38
40
 
39
- /**
40
- * The parent node of the current node.
41
- */
42
- parent?: N | null;
41
+ parent?: N;
43
42
 
44
- /**
45
- * Creates a new instance of BinaryTreeNode.
46
- * @param {BTNKey} key - The key associated with the node.
47
- * @param {V} value - The value stored in the node.
48
- */
49
43
  constructor(key: BTNKey, value?: V) {
50
44
  this.key = key;
51
45
  this.value = value;
@@ -53,17 +47,10 @@ export class BinaryTreeNode<V = any, N extends BinaryTreeNode<V, N> = BinaryTree
53
47
 
54
48
  protected _left?: N | null;
55
49
 
56
- /**
57
- * Get the left child node.
58
- */
59
50
  get left(): N | null | undefined {
60
51
  return this._left;
61
52
  }
62
53
 
63
- /**
64
- * Set the left child node.
65
- * @param {N | null | undefined} v - The left child node.
66
- */
67
54
  set left(v: N | null | undefined) {
68
55
  if (v) {
69
56
  v.parent = this as unknown as N;
@@ -73,17 +60,10 @@ export class BinaryTreeNode<V = any, N extends BinaryTreeNode<V, N> = BinaryTree
73
60
 
74
61
  protected _right?: N | null;
75
62
 
76
- /**
77
- * Get the right child node.
78
- */
79
63
  get right(): N | null | undefined {
80
64
  return this._right;
81
65
  }
82
66
 
83
- /**
84
- * Set the right child node.
85
- * @param {N | null | undefined} v - The right child node.
86
- */
87
67
  set right(v: N | null | undefined) {
88
68
  if (v) {
89
69
  v.parent = this as unknown as N;
@@ -112,42 +92,52 @@ export class BinaryTreeNode<V = any, N extends BinaryTreeNode<V, N> = BinaryTree
112
92
  }
113
93
 
114
94
  /**
115
- * Represents a binary tree data structure.
116
- * @template N - The type of the binary tree's nodes.
95
+ * 1. Two Children Maximum: Each node has at most two children.
96
+ * 2. Left and Right Children: Nodes have distinct left and right children.
97
+ * 3. Depth and Height: Depth is the number of edges from the root to a node; height is the maximum depth in the tree.
98
+ * 4. Subtrees: Each child of a node forms the root of a subtree.
99
+ * 5. Leaf Nodes: Nodes without children are leaves.
100
+ * 6. Internal Nodes: Nodes with at least one child are internal.
101
+ * 7. Balanced Trees: The heights of the left and right subtrees of any node differ by no more than one.
102
+ * 8. Full Trees: Every node has either 0 or 2 children.
103
+ * 9. Complete Trees: All levels are fully filled except possibly the last, filled from left to right.
117
104
  */
118
105
  export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode<V, BinaryTreeNodeNested<V>>, TREE extends BinaryTree<V, N, TREE> = BinaryTree<V, N, BinaryTreeNested<V, N>>>
119
106
  implements IBinaryTree<V, N, TREE> {
120
107
 
121
- options: BinaryTreeOptions;
108
+ iterationType = IterationType.ITERATIVE
122
109
 
123
110
  /**
124
- * Creates a new instance of BinaryTree.
125
- * @param {BinaryTreeOptions} [options] - The options for the binary tree.
111
+ * The constructor function initializes a binary tree object with optional elements and options.
112
+ * @param [elements] - An optional iterable of BTNodeExemplar objects. These objects represent the
113
+ * elements to be added to the binary tree.
114
+ * @param [options] - The `options` parameter is an optional object that can contain additional
115
+ * configuration options for the binary tree. In this case, it is of type
116
+ * `Partial<BinaryTreeOptions>`, which means that not all properties of `BinaryTreeOptions` are
117
+ * required.
126
118
  */
127
- constructor(options?: BinaryTreeOptions) {
119
+ constructor(elements?: Iterable<BTNodeExemplar<V, N>>, options?: Partial<BinaryTreeOptions>) {
120
+
128
121
  if (options) {
129
- this.options = { iterationType: IterationType.ITERATIVE, ...options }
130
- } else {
131
- this.options = { iterationType: IterationType.ITERATIVE };
122
+ const { iterationType } = options;
123
+ if (iterationType) {
124
+ this.iterationType = iterationType;
125
+ }
132
126
  }
133
127
 
134
128
  this._size = 0;
129
+
130
+ if (elements) this.addMany(elements);
135
131
  }
136
132
 
137
133
  protected _root?: N | null;
138
134
 
139
- /**
140
- * Get the root node of the binary tree.
141
- */
142
135
  get root(): N | null | undefined {
143
136
  return this._root;
144
137
  }
145
138
 
146
139
  protected _size: number;
147
140
 
148
- /**
149
- * Get the number of nodes in the binary tree.
150
- */
151
141
  get size(): number {
152
142
  return this._size;
153
143
  }
@@ -162,37 +152,51 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
162
152
  return new BinaryTreeNode<V, N>(key, value) as N;
163
153
  }
164
154
 
165
- createTree(options?: BinaryTreeOptions): TREE {
166
- return new BinaryTree<V, N, TREE>({ ...this.options, ...options }) as TREE;
155
+ /**
156
+ * The function creates a binary tree with the given options.
157
+ * @param [options] - The `options` parameter is an optional object that allows you to customize the
158
+ * behavior of the `BinaryTree` class. It is of type `Partial<BinaryTreeOptions>`, which means that
159
+ * you can provide only a subset of the properties defined in the `BinaryTreeOptions` interface.
160
+ * @returns a new instance of a binary tree.
161
+ */
162
+ createTree(options?: Partial<BinaryTreeOptions>): TREE {
163
+ return new BinaryTree<V, N, TREE>([], { iterationType: this.iterationType, ...options }) as TREE;
167
164
  }
168
165
 
169
166
  /**
170
- * Time Complexity: O(n)
171
- * Space Complexity: O(1)
172
- * 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.
167
+ * The function checks if a given value is an entry in a binary tree node.
168
+ * @param kne - BTNodeExemplar<V, N> - A generic type representing a node in a binary tree. It has
169
+ * two type parameters V and N, representing the value and node type respectively.
170
+ * @returns a boolean value.
173
171
  */
172
+ isEntry(kne: BTNodeExemplar<V, N>): kne is BTNodeEntry<V> {
173
+ return Array.isArray(kne) && kne.length === 2;
174
+ }
174
175
 
175
176
  /**
176
- * Time Complexity: O(n)
177
- * Space Complexity: O(1)
177
+ * Time Complexity O(log n) - O(n)
178
+ * Space Complexity O(1)
179
+ */
180
+
181
+ /**
182
+ * Time Complexity O(log n) - O(n)
183
+ * Space Complexity O(1)
178
184
  *
179
- * The `add` function adds a new node with a key and value to a binary tree, or updates the value of
180
- * an existing node with the same key.
181
- * @param {BTNKey | N | null | undefined} keyOrNode - The `keyOrNode` parameter can be one of the
182
- * following types:
183
- * @param {V} [value] - The value to be associated with the key or node being added to the binary
184
- * tree.
185
- * @returns The function `add` returns a node (`N`) if it was successfully inserted into the binary
186
- * tree, or `null` or `undefined` if the insertion was not successful.
185
+ * The `add` function adds a new node to a binary tree, either by key or by providing a node object.
186
+ * @param keyOrNodeOrEntry - The parameter `keyOrNodeOrEntry` can be one of the following:
187
+ * @returns The function `add` returns the inserted node (`N`), `null`, or `undefined`.
187
188
  */
188
- add(keyOrNode: BTNKey | N | null | undefined, value?: V): N | null | undefined {
189
+ add(keyOrNodeOrEntry: BTNodeExemplar<V, N>): N | null | undefined {
190
+
191
+ let inserted: N | null | undefined, needInsert: N | null | undefined;
192
+
189
193
  const _bfs = (root: N, newNode: N | null): N | undefined | null => {
190
194
  const queue = new Queue<N>([root]);
191
195
  while (queue.size > 0) {
192
196
  const cur = queue.shift()!;
193
197
  if (newNode && cur.key === newNode.key) {
194
- cur.value = newNode.value;
195
- return;
198
+ this._replaceNode(cur, newNode);
199
+ return newNode;
196
200
  }
197
201
  const inserted = this._addTo(newNode, cur);
198
202
  if (inserted !== undefined) return inserted;
@@ -201,14 +205,21 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
201
205
  }
202
206
  };
203
207
 
204
- let inserted: N | null | undefined, needInsert: N | null | undefined;
205
-
206
- if (keyOrNode === null) {
208
+ if (keyOrNodeOrEntry === null) {
207
209
  needInsert = null;
208
- } else if (this.isNodeKey(keyOrNode)) {
209
- needInsert = this.createNode(keyOrNode, value);
210
- } else if (keyOrNode instanceof BinaryTreeNode) {
211
- needInsert = keyOrNode;
210
+ } else if (this.isNodeKey(keyOrNodeOrEntry)) {
211
+ needInsert = this.createNode(keyOrNodeOrEntry);
212
+ } else if (keyOrNodeOrEntry instanceof BinaryTreeNode) {
213
+ needInsert = keyOrNodeOrEntry;
214
+ } else if (this.isEntry(keyOrNodeOrEntry)) {
215
+ const [key, value] = keyOrNodeOrEntry;
216
+ if (key === undefined) {
217
+ return;
218
+ } else if (key === null) {
219
+ needInsert = null;
220
+ } else {
221
+ needInsert = this.createNode(key, value);
222
+ }
212
223
  } else {
213
224
  return;
214
225
  }
@@ -228,38 +239,30 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
228
239
  }
229
240
 
230
241
  /**
231
- * Time Complexity: O(k * n) "n" is the number of nodes in the tree, and "k" is the number of keys to be inserted.
242
+ * Time Complexity: O(k log n) - O(k * n)
232
243
  * Space Complexity: O(1)
244
+ * 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.
233
245
  */
234
246
 
247
+
235
248
  /**
236
- * Time Complexity: O(k * n) "n" is the number of nodes in the tree, and "k" is the number of keys to be inserted.
249
+ * Time Complexity: O(k log n) - O(k * n)
237
250
  * Space Complexity: O(1)
238
251
  *
239
- * The `addMany` function takes an array of keys or nodes and an optional array of values, and adds
240
- * each key-value pair to a data structure.
241
- * @param {(BTNKey | N |null | undefined)[]} keysOrNodes - An array of keys or nodes to be added to
242
- * the binary search tree. Each element can be of type `BTNKey` (a key value), `N` (a node), `null`,
243
- * or `undefined`.
244
- * @param {(V | undefined)[]} [values] - The `values` parameter is an optional array of values that
245
- * correspond to the keys or nodes being added. If provided, the values will be associated with the
246
- * keys or nodes during the add operation.
247
- * @returns The function `addMany` returns an array of `N`, `null`, or `undefined` values.
248
- */
249
- addMany(keysOrNodes: (BTNKey | N | null | undefined)[], values?: (V | undefined)[]): (N | null | undefined)[] {
252
+ * The function `addMany` takes in an iterable of `BTNodeExemplar` objects, adds each object to the
253
+ * current instance, and returns an array of the inserted nodes.
254
+ * @param nodes - The `nodes` parameter is an iterable (such as an array or a set) of
255
+ * `BTNodeExemplar<V, N>` objects.
256
+ * @returns The function `addMany` returns an array of values, where each value is either of type
257
+ * `N`, `null`, or `undefined`.
258
+ */
259
+ addMany(nodes: Iterable<BTNodeExemplar<V, N>>): (N | null | undefined)[] {
250
260
  // TODO not sure addMany not be run multi times
251
- return keysOrNodes.map((keyOrNode, i) => {
252
- if (keyOrNode instanceof BinaryTreeNode) {
253
- return this.add(keyOrNode.key, keyOrNode.value);
254
- }
255
-
256
- if (keyOrNode === null) {
257
- return this.add(null);
258
- }
259
-
260
- const value = values?.[i];
261
- return this.add(keyOrNode, value);
262
- });
261
+ const inserted: (N | null | undefined)[] = [];
262
+ for (const kne of nodes) {
263
+ inserted.push(this.add(kne));
264
+ }
265
+ return inserted;
263
266
  }
264
267
 
265
268
  /**
@@ -271,30 +274,26 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
271
274
  * Time Complexity: O(k * n) "n" is the number of nodes in the tree, and "k" is the number of keys to be inserted.
272
275
  * Space Complexity: O(1)
273
276
  *
274
- * The `refill` function clears the binary tree and adds multiple nodes with the given IDs or nodes and optional data.
275
- * @param {(BTNKey | N)[]} keysOrNodes - The `keysOrNodes` parameter is an array that can contain either
276
- * `BTNKey` or `N` values.
277
- * @param {N[] | Array<V>} [values] - The `data` parameter is an optional array of values that will be assigned to
278
- * the nodes being added. If provided, the length of the `data` array should be equal to the length of the `keysOrNodes`
279
- * array. Each value in the `data` array will be assigned to the
280
- * @returns The method is returning a boolean value.
281
- */
282
- refill(keysOrNodes: (BTNKey | N | null | undefined)[], values?: (V | undefined)[]): boolean {
277
+ * The `refill` function clears the current collection and adds new nodes, keys, or entries to it.
278
+ * @param nodesOrKeysOrEntries - The parameter `nodesOrKeysOrEntries` is an iterable object that can
279
+ * contain either `BTNodeExemplar` objects, keys, or entries.
280
+ */
281
+ refill(nodesOrKeysOrEntries: Iterable<BTNodeExemplar<V, N>>): void {
283
282
  this.clear();
284
- return keysOrNodes.length === this.addMany(keysOrNodes, values).length;
283
+ this.addMany(nodesOrKeysOrEntries);
285
284
  }
286
285
 
286
+ /**
287
+ * Time Complexity: O(k * n) "n" is the number of nodes in the tree, and "k" is the number of keys to be inserted.
288
+ * Space Complexity: O(1)
289
+ */
290
+
287
291
  delete<C extends BTNCallback<N, BTNKey>>(identifier: BTNKey, callback?: C): BiTreeDeleteResult<N>[];
288
292
 
289
293
  delete<C extends BTNCallback<N, N>>(identifier: N | null | undefined, callback?: C): BiTreeDeleteResult<N>[];
290
294
 
291
295
  delete<C extends BTNCallback<N>>(identifier: ReturnType<C>, callback: C): BiTreeDeleteResult<N>[];
292
296
 
293
- /**
294
- * Time Complexity: O(n)
295
- * Space Complexity: O(1)
296
- */
297
-
298
297
  /**
299
298
  * Time Complexity: O(n)
300
299
  * Space Complexity: O(1)
@@ -344,7 +343,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
344
343
  const leftSubTreeRightMost = this.getRightMost(curr.left);
345
344
  if (leftSubTreeRightMost) {
346
345
  const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;
347
- orgCurrent = this._swap(curr, leftSubTreeRightMost);
346
+ orgCurrent = this._swapProperties(curr, leftSubTreeRightMost);
348
347
  if (parentOfLeftSubTreeMax) {
349
348
  if (parentOfLeftSubTreeMax.right === leftSubTreeRightMost)
350
349
  parentOfLeftSubTreeMax.right = leftSubTreeRightMost.left;
@@ -378,9 +377,9 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
378
377
  * `N` (binary tree node) or `null` or `undefined`. If no value is provided for `beginRoot
379
378
  * @returns the depth of the `distNode` relative to the `beginRoot`.
380
379
  */
381
- getDepth(distNode: BTNKey | N | null | undefined, beginRoot: BTNKey | N | null | undefined = this.root): number {
382
- distNode = this.ensureNotKey(distNode);
383
- beginRoot = this.ensureNotKey(beginRoot);
380
+ getDepth(distNode: BTNodeKeyOrNode<N>, beginRoot: BTNodeKeyOrNode<N> = this.root): number {
381
+ distNode = this.ensureNode(distNode);
382
+ beginRoot = this.ensureNode(beginRoot);
384
383
  let depth = 0;
385
384
  while (distNode?.parent) {
386
385
  if (distNode === beginRoot) {
@@ -394,8 +393,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
394
393
 
395
394
  /**
396
395
  * Time Complexity: O(n)
397
- * Space Complexity: O(log n)
398
- * Best Case - O(log n) (when using recursive iterationType), Worst Case - O(n) (when using iterative iterationType)
396
+ * Space Complexity: O(1)
399
397
  */
400
398
 
401
399
  /**
@@ -412,8 +410,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
412
410
  * values:
413
411
  * @returns the height of the binary tree.
414
412
  */
415
- getHeight(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.options.iterationType): number {
416
- beginRoot = this.ensureNotKey(beginRoot);
413
+ getHeight(beginRoot: BTNodeKeyOrNode<N> = this.root, iterationType = this.iterationType): number {
414
+ beginRoot = this.ensureNode(beginRoot);
417
415
  if (!beginRoot) return -1;
418
416
 
419
417
  if (iterationType === IterationType.RECURSIVE) {
@@ -461,8 +459,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
461
459
  * to calculate the minimum height of a binary tree. It can have two possible values:
462
460
  * @returns The function `getMinHeight` returns the minimum height of a binary tree.
463
461
  */
464
- getMinHeight(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.options.iterationType): number {
465
- beginRoot = this.ensureNotKey(beginRoot);
462
+ getMinHeight(beginRoot: BTNodeKeyOrNode<N> = this.root, iterationType = this.iterationType): number {
463
+ beginRoot = this.ensureNode(beginRoot);
466
464
  if (!beginRoot) return -1;
467
465
 
468
466
  if (iterationType === IterationType.RECURSIVE) {
@@ -507,6 +505,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
507
505
  /**
508
506
  * Time Complexity: O(n)
509
507
  * Space Complexity: O(log n)
508
+ * Best Case - O(log n) (when using recursive iterationType), Worst Case - O(n) (when using iterative iterationType)
510
509
  */
511
510
 
512
511
  /**
@@ -520,15 +519,20 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
520
519
  * value of a binary tree node), `N` (a node of a binary tree), `null`, or `undefined`. If
521
520
  * @returns a boolean value.
522
521
  */
523
- isPerfectlyBalanced(beginRoot: BTNKey | N | null | undefined = this.root): boolean {
522
+ isPerfectlyBalanced(beginRoot: BTNodeKeyOrNode<N> = this.root): boolean {
524
523
  return this.getMinHeight(beginRoot) + 1 >= this.getHeight(beginRoot);
525
524
  }
526
525
 
526
+ /**
527
+ * Time Complexity: O(n)
528
+ * Space Complexity: O(log n)
529
+ */
530
+
527
531
  getNodes<C extends BTNCallback<N, BTNKey>>(
528
532
  identifier: BTNKey,
529
533
  callback?: C,
530
534
  onlyOne?: boolean,
531
- beginRoot?: BTNKey | N | null | undefined,
535
+ beginRoot?: BTNodeKeyOrNode<N>,
532
536
  iterationType?: IterationType
533
537
  ): N[];
534
538
 
@@ -536,7 +540,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
536
540
  identifier: N | null | undefined,
537
541
  callback?: C,
538
542
  onlyOne?: boolean,
539
- beginRoot?: BTNKey | N | null | undefined,
543
+ beginRoot?: BTNodeKeyOrNode<N>,
540
544
  iterationType?: IterationType
541
545
  ): N[];
542
546
 
@@ -544,15 +548,10 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
544
548
  identifier: ReturnType<C>,
545
549
  callback: C,
546
550
  onlyOne?: boolean,
547
- beginRoot?: BTNKey | N | null | undefined,
551
+ beginRoot?: BTNodeKeyOrNode<N>,
548
552
  iterationType?: IterationType
549
553
  ): N[];
550
554
 
551
- /**
552
- * Time Complexity: O(n)
553
- * Space Complexity: O(log n).
554
- */
555
-
556
555
  /**
557
556
  * Time Complexity: O(n)
558
557
  * Space Complexity: O(log n).
@@ -582,12 +581,12 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
582
581
  identifier: ReturnType<C> | null | undefined,
583
582
  callback: C = this._defaultOneParamCallback as C,
584
583
  onlyOne = false,
585
- beginRoot: BTNKey | N | null | undefined = this.root,
586
- iterationType = this.options.iterationType
584
+ beginRoot: BTNodeKeyOrNode<N> = this.root,
585
+ iterationType = this.iterationType
587
586
  ): N[] {
588
587
  if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
589
588
  callback = (node => node) as C;
590
- beginRoot = this.ensureNotKey(beginRoot);
589
+ beginRoot = this.ensureNode(beginRoot);
591
590
  if (!beginRoot) return [];
592
591
 
593
592
  const ans: N[] = [];
@@ -622,32 +621,32 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
622
621
  return ans;
623
622
  }
624
623
 
624
+ /**
625
+ * Time Complexity: O(n)
626
+ * Space Complexity: O(log n).
627
+ */
628
+
625
629
  has<C extends BTNCallback<N, BTNKey>>(
626
630
  identifier: BTNKey,
627
631
  callback?: C,
628
- beginRoot?: BTNKey | N | null | undefined,
632
+ beginRoot?: BTNodeKeyOrNode<N>,
629
633
  iterationType?: IterationType
630
634
  ): boolean;
631
635
 
632
636
  has<C extends BTNCallback<N, N>>(
633
637
  identifier: N | null | undefined,
634
638
  callback?: C,
635
- beginRoot?: BTNKey | N | null | undefined,
639
+ beginRoot?: BTNodeKeyOrNode<N>,
636
640
  iterationType?: IterationType
637
641
  ): boolean;
638
642
 
639
643
  has<C extends BTNCallback<N>>(
640
644
  identifier: ReturnType<C> | null | undefined,
641
645
  callback: C,
642
- beginRoot?: BTNKey | N | null | undefined,
646
+ beginRoot?: BTNodeKeyOrNode<N>,
643
647
  iterationType?: IterationType
644
648
  ): boolean;
645
649
 
646
- /**
647
- * Time Complexity: O(n)
648
- * Space Complexity: O(log n).
649
- */
650
-
651
650
  /**
652
651
  * Time Complexity: O(n)
653
652
  *
@@ -671,8 +670,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
671
670
  has<C extends BTNCallback<N>>(
672
671
  identifier: ReturnType<C> | null | undefined,
673
672
  callback: C = this._defaultOneParamCallback as C,
674
- beginRoot: BTNKey | N | null | undefined = this.root,
675
- iterationType = this.options.iterationType
673
+ beginRoot: BTNodeKeyOrNode<N> = this.root,
674
+ iterationType = this.iterationType
676
675
  ): boolean {
677
676
  if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
678
677
  callback = (node => node) as C;
@@ -680,32 +679,32 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
680
679
  return this.getNodes(identifier, callback, true, beginRoot, iterationType).length > 0;
681
680
  }
682
681
 
682
+ /**
683
+ * Time Complexity: O(n)
684
+ * Space Complexity: O(log n).
685
+ */
686
+
683
687
  getNode<C extends BTNCallback<N, BTNKey>>(
684
688
  identifier: BTNKey,
685
689
  callback?: C,
686
- beginRoot?: BTNKey | N | null | undefined,
690
+ beginRoot?: BTNodeKeyOrNode<N>,
687
691
  iterationType?: IterationType
688
692
  ): N | null | undefined;
689
693
 
690
694
  getNode<C extends BTNCallback<N, N>>(
691
695
  identifier: N | null | undefined,
692
696
  callback?: C,
693
- beginRoot?: BTNKey | N | null | undefined,
697
+ beginRoot?: BTNodeKeyOrNode<N>,
694
698
  iterationType?: IterationType
695
699
  ): N | null | undefined;
696
700
 
697
701
  getNode<C extends BTNCallback<N>>(
698
702
  identifier: ReturnType<C>,
699
703
  callback: C,
700
- beginRoot?: BTNKey | N | null | undefined,
704
+ beginRoot?: BTNodeKeyOrNode<N>,
701
705
  iterationType?: IterationType
702
706
  ): N | null | undefined;
703
707
 
704
- /**
705
- * Time Complexity: O(n)
706
- * Space Complexity: O(log n)
707
- */
708
-
709
708
  /**
710
709
  * Time Complexity: O(n)
711
710
  * Space Complexity: O(log n)
@@ -730,8 +729,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
730
729
  getNode<C extends BTNCallback<N>>(
731
730
  identifier: ReturnType<C> | null | undefined,
732
731
  callback: C = this._defaultOneParamCallback as C,
733
- beginRoot: BTNKey | N | null | undefined = this.root,
734
- iterationType = this.options.iterationType
732
+ beginRoot: BTNodeKeyOrNode<N> = this.root,
733
+ iterationType = this.iterationType
735
734
  ): N | null | undefined {
736
735
  if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
737
736
  callback = (node => node) as C;
@@ -784,7 +783,12 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
784
783
  }
785
784
 
786
785
  /**
787
- * The function `ensureNotKey` returns the node corresponding to the given key if it is a valid node
786
+ * Time Complexity: O(n)
787
+ * Space Complexity: O(log n)
788
+ */
789
+
790
+ /**
791
+ * The function `ensureNode` returns the node corresponding to the given key if it is a valid node
788
792
  * key, otherwise it returns the key itself.
789
793
  * @param {BTNKey | N | null | undefined} key - The `key` parameter can be of type `BTNKey`, `N`,
790
794
  * `null`, or `undefined`. It represents a key used to identify a node in a binary tree.
@@ -794,36 +798,31 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
794
798
  * @returns either the node corresponding to the given key if it is a valid node key, or the key
795
799
  * itself if it is not a valid node key.
796
800
  */
797
- ensureNotKey(key: BTNKey | N | null | undefined, iterationType = IterationType.ITERATIVE): N | null | undefined {
801
+ ensureNode(key: BTNodeKeyOrNode<N>, iterationType = IterationType.ITERATIVE): N | null | undefined {
798
802
  return this.isNodeKey(key) ? this.getNodeByKey(key, iterationType) : key;
799
803
  }
800
804
 
801
805
  get<C extends BTNCallback<N, BTNKey>>(
802
806
  identifier: BTNKey,
803
807
  callback?: C,
804
- beginRoot?: BTNKey | N | null | undefined,
808
+ beginRoot?: BTNodeKeyOrNode<N>,
805
809
  iterationType?: IterationType
806
810
  ): V | undefined;
807
811
 
808
812
  get<C extends BTNCallback<N, N>>(
809
813
  identifier: N | null | undefined,
810
814
  callback?: C,
811
- beginRoot?: BTNKey | N | null | undefined,
815
+ beginRoot?: BTNodeKeyOrNode<N>,
812
816
  iterationType?: IterationType
813
817
  ): V | undefined;
814
818
 
815
819
  get<C extends BTNCallback<N>>(
816
820
  identifier: ReturnType<C>,
817
821
  callback: C,
818
- beginRoot?: BTNKey | N | null | undefined,
822
+ beginRoot?: BTNodeKeyOrNode<N>,
819
823
  iterationType?: IterationType
820
824
  ): V | undefined;
821
825
 
822
- /**
823
- * Time Complexity: O(n)
824
- * Space Complexity: O(log n)
825
- */
826
-
827
826
  /**
828
827
  * Time Complexity: O(n)
829
828
  * Space Complexity: O(log n)
@@ -849,8 +848,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
849
848
  get<C extends BTNCallback<N>>(
850
849
  identifier: ReturnType<C> | null | undefined,
851
850
  callback: C = this._defaultOneParamCallback as C,
852
- beginRoot: BTNKey | N | null | undefined = this.root,
853
- iterationType = this.options.iterationType
851
+ beginRoot: BTNodeKeyOrNode<N> = this.root,
852
+ iterationType = this.iterationType
854
853
  ): V | undefined {
855
854
  if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
856
855
  callback = (node => node) as C;
@@ -858,6 +857,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
858
857
  return this.getNode(identifier, callback, beginRoot, iterationType)?.value ?? undefined;
859
858
  }
860
859
 
860
+ /**
861
+ * Time Complexity: O(n)
862
+ * Space Complexity: O(log n)
863
+ */
864
+
861
865
  /**
862
866
  * Clear the binary tree, removing all nodes.
863
867
  */
@@ -874,11 +878,6 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
874
878
  return this.size === 0;
875
879
  }
876
880
 
877
- /**
878
- * Time Complexity: O(log n)
879
- * Space Complexity: O(log n)
880
- */
881
-
882
881
  /**
883
882
  * Time Complexity: O(log n)
884
883
  * Space Complexity: O(log n)
@@ -893,10 +892,10 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
893
892
  * reversed before returning it. If `isReverse` is set to `false`, the path will be returned as is
894
893
  * @returns The function `getPathToRoot` returns an array of nodes (`N[]`).
895
894
  */
896
- getPathToRoot(beginRoot: BTNKey | N | null | undefined, isReverse = true): N[] {
895
+ getPathToRoot(beginRoot: BTNodeKeyOrNode<N>, isReverse = true): N[] {
897
896
  // TODO to support get path through passing key
898
897
  const result: N[] = [];
899
- beginRoot = this.ensureNotKey(beginRoot);
898
+ beginRoot = this.ensureNode(beginRoot);
900
899
 
901
900
  if (!beginRoot) return result;
902
901
 
@@ -912,7 +911,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
912
911
 
913
912
  /**
914
913
  * Time Complexity: O(log n)
915
- * Space Complexity: O(1)
914
+ * Space Complexity: O(log n)
916
915
  */
917
916
 
918
917
  /**
@@ -930,10 +929,10 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
930
929
  * is no leftmost node, it returns `null` or `undefined` depending on the input.
931
930
  */
932
931
  getLeftMost(
933
- beginRoot: BTNKey | N | null | undefined = this.root,
934
- iterationType = this.options.iterationType
932
+ beginRoot: BTNodeKeyOrNode<N> = this.root,
933
+ iterationType = this.iterationType
935
934
  ): N | null | undefined {
936
- beginRoot = this.ensureNotKey(beginRoot);
935
+ beginRoot = this.ensureNode(beginRoot);
937
936
 
938
937
  if (!beginRoot) return beginRoot;
939
938
 
@@ -976,11 +975,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
976
975
  * is no rightmost node, it returns `null` or `undefined`, depending on the input.
977
976
  */
978
977
  getRightMost(
979
- beginRoot: BTNKey | N | null | undefined = this.root,
980
- iterationType = this.options.iterationType
978
+ beginRoot: BTNodeKeyOrNode<N> = this.root,
979
+ iterationType = this.iterationType
981
980
  ): N | null | undefined {
982
981
  // TODO support get right most by passing key in
983
- beginRoot = this.ensureNotKey(beginRoot);
982
+ beginRoot = this.ensureNode(beginRoot);
984
983
  if (!beginRoot) return beginRoot;
985
984
 
986
985
  if (iterationType === IterationType.RECURSIVE) {
@@ -1002,7 +1001,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1002
1001
  }
1003
1002
 
1004
1003
  /**
1005
- * Time Complexity: O(n)
1004
+ * Time Complexity: O(log n)
1006
1005
  * Space Complexity: O(1)
1007
1006
  */
1008
1007
 
@@ -1018,9 +1017,9 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1018
1017
  * possible values:
1019
1018
  * @returns a boolean value.
1020
1019
  */
1021
- isSubtreeBST(beginRoot: BTNKey | N | null | undefined, iterationType = this.options.iterationType): boolean {
1020
+ isSubtreeBST(beginRoot: BTNodeKeyOrNode<N>, iterationType = this.iterationType): boolean {
1022
1021
  // TODO there is a bug
1023
- beginRoot = this.ensureNotKey(beginRoot);
1022
+ beginRoot = this.ensureNode(beginRoot);
1024
1023
  if (!beginRoot) return true;
1025
1024
 
1026
1025
  if (iterationType === IterationType.RECURSIVE) {
@@ -1065,37 +1064,37 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1065
1064
  * expected to be
1066
1065
  * @returns a boolean value.
1067
1066
  */
1068
- isBST(iterationType = this.options.iterationType): boolean {
1067
+ isBST(iterationType = this.iterationType): boolean {
1069
1068
  if (this.root === null) return true;
1070
1069
  return this.isSubtreeBST(this.root, iterationType);
1071
1070
  }
1072
1071
 
1072
+ /**
1073
+ * Time Complexity: O(n)
1074
+ * Space Complexity: O(1)
1075
+ */
1076
+
1073
1077
  subTreeTraverse<C extends BTNCallback<N>>(
1074
1078
  callback?: C,
1075
- beginRoot?: BTNKey | N | null | undefined,
1079
+ beginRoot?: BTNodeKeyOrNode<N>,
1076
1080
  iterationType?: IterationType,
1077
1081
  includeNull?: false
1078
1082
  ): ReturnType<C>[];
1079
1083
 
1080
1084
  subTreeTraverse<C extends BTNCallback<N>>(
1081
1085
  callback?: C,
1082
- beginRoot?: BTNKey | N | null | undefined,
1086
+ beginRoot?: BTNodeKeyOrNode<N>,
1083
1087
  iterationType?: IterationType,
1084
1088
  includeNull?: undefined
1085
1089
  ): ReturnType<C>[];
1086
1090
 
1087
1091
  subTreeTraverse<C extends BTNCallback<N | null | undefined>>(
1088
1092
  callback?: C,
1089
- beginRoot?: BTNKey | N | null | undefined,
1093
+ beginRoot?: BTNodeKeyOrNode<N>,
1090
1094
  iterationType?: IterationType,
1091
1095
  includeNull?: true
1092
1096
  ): ReturnType<C>[];
1093
1097
 
1094
- /**
1095
- * Time complexity: O(n)
1096
- * Space complexity: O(log n)
1097
- */
1098
-
1099
1098
  /**
1100
1099
  * Time complexity: O(n)
1101
1100
  * Space complexity: O(log n)
@@ -1120,11 +1119,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1120
1119
  */
1121
1120
  subTreeTraverse<C extends BTNCallback<N | null | undefined>>(
1122
1121
  callback: C = this._defaultOneParamCallback as C,
1123
- beginRoot: BTNKey | N | null | undefined = this.root,
1124
- iterationType = this.options.iterationType,
1122
+ beginRoot: BTNodeKeyOrNode<N> = this.root,
1123
+ iterationType = this.iterationType,
1125
1124
  includeNull = false
1126
1125
  ): ReturnType<C>[] {
1127
- beginRoot = this.ensureNotKey(beginRoot);
1126
+ beginRoot = this.ensureNode(beginRoot);
1128
1127
 
1129
1128
  const ans: (ReturnType<BTNCallback<N>> | null | undefined)[] = [];
1130
1129
  if (!beginRoot) return ans;
@@ -1164,6 +1163,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1164
1163
  return ans;
1165
1164
  }
1166
1165
 
1166
+ /**
1167
+ * Time complexity: O(n)
1168
+ * Space complexity: O(log n)
1169
+ */
1170
+
1167
1171
  /**
1168
1172
  * The function checks if a given node is a real node by verifying if it is an instance of
1169
1173
  * BinaryTreeNode and its key is not NaN.
@@ -1205,7 +1209,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1205
1209
  dfs<C extends BTNCallback<N>>(
1206
1210
  callback?: C,
1207
1211
  pattern?: DFSOrderPattern,
1208
- beginRoot?: BTNKey | N | null | undefined,
1212
+ beginRoot?: BTNodeKeyOrNode<N>,
1209
1213
  iterationType?: IterationType,
1210
1214
  includeNull?: false
1211
1215
  ): ReturnType<C>[];
@@ -1213,7 +1217,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1213
1217
  dfs<C extends BTNCallback<N>>(
1214
1218
  callback?: C,
1215
1219
  pattern?: DFSOrderPattern,
1216
- beginRoot?: BTNKey | N | null | undefined,
1220
+ beginRoot?: BTNodeKeyOrNode<N>,
1217
1221
  iterationType?: IterationType,
1218
1222
  includeNull?: undefined
1219
1223
  ): ReturnType<C>[];
@@ -1221,16 +1225,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1221
1225
  dfs<C extends BTNCallback<N | null | undefined>>(
1222
1226
  callback?: C,
1223
1227
  pattern?: DFSOrderPattern,
1224
- beginRoot?: BTNKey | N | null | undefined,
1228
+ beginRoot?: BTNodeKeyOrNode<N>,
1225
1229
  iterationType?: IterationType,
1226
1230
  includeNull?: true
1227
1231
  ): ReturnType<C>[];
1228
1232
 
1229
- /**
1230
- * Time complexity: O(n)
1231
- * Space complexity: O(n)
1232
- */
1233
-
1234
1233
  /**
1235
1234
  * Time complexity: O(n)
1236
1235
  * Space complexity: O(n)
@@ -1257,11 +1256,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1257
1256
  dfs<C extends BTNCallback<N | null | undefined>>(
1258
1257
  callback: C = this._defaultOneParamCallback as C,
1259
1258
  pattern: DFSOrderPattern = 'in',
1260
- beginRoot: BTNKey | N | null | undefined = this.root,
1259
+ beginRoot: BTNodeKeyOrNode<N> = this.root,
1261
1260
  iterationType: IterationType = IterationType.ITERATIVE,
1262
1261
  includeNull = false
1263
1262
  ): ReturnType<C>[] {
1264
- beginRoot = this.ensureNotKey(beginRoot);
1263
+ beginRoot = this.ensureNode(beginRoot);
1265
1264
  if (!beginRoot) return [];
1266
1265
  const ans: ReturnType<C>[] = [];
1267
1266
  if (iterationType === IterationType.RECURSIVE) {
@@ -1349,32 +1348,32 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1349
1348
  return ans;
1350
1349
  }
1351
1350
 
1351
+ /**
1352
+ * Time complexity: O(n)
1353
+ * Space complexity: O(n)
1354
+ */
1355
+
1352
1356
  bfs<C extends BTNCallback<N>>(
1353
1357
  callback?: C,
1354
- beginRoot?: BTNKey | N | null | undefined,
1358
+ beginRoot?: BTNodeKeyOrNode<N>,
1355
1359
  iterationType?: IterationType,
1356
1360
  includeNull?: false
1357
1361
  ): ReturnType<C>[];
1358
1362
 
1359
1363
  bfs<C extends BTNCallback<N>>(
1360
1364
  callback?: C,
1361
- beginRoot?: BTNKey | N | null | undefined,
1365
+ beginRoot?: BTNodeKeyOrNode<N>,
1362
1366
  iterationType?: IterationType,
1363
1367
  includeNull?: undefined
1364
1368
  ): ReturnType<C>[];
1365
1369
 
1366
1370
  bfs<C extends BTNCallback<N | null | undefined>>(
1367
1371
  callback?: C,
1368
- beginRoot?: BTNKey | N | null | undefined,
1372
+ beginRoot?: BTNodeKeyOrNode<N>,
1369
1373
  iterationType?: IterationType,
1370
1374
  includeNull?: true
1371
1375
  ): ReturnType<C>[];
1372
1376
 
1373
- /**
1374
- * Time complexity: O(n)
1375
- * Space complexity: O(n)
1376
- */
1377
-
1378
1377
  /**
1379
1378
  * Time complexity: O(n)
1380
1379
  * Space complexity: O(n)
@@ -1398,11 +1397,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1398
1397
  */
1399
1398
  bfs<C extends BTNCallback<N | null | undefined>>(
1400
1399
  callback: C = this._defaultOneParamCallback as C,
1401
- beginRoot: BTNKey | N | null | undefined = this.root,
1402
- iterationType = this.options.iterationType,
1400
+ beginRoot: BTNodeKeyOrNode<N> = this.root,
1401
+ iterationType = this.iterationType,
1403
1402
  includeNull = false
1404
1403
  ): ReturnType<C>[] {
1405
- beginRoot = this.ensureNotKey(beginRoot);
1404
+ beginRoot = this.ensureNode(beginRoot);
1406
1405
  if (!beginRoot) return [];
1407
1406
 
1408
1407
  const ans: ReturnType<BTNCallback<N>>[] = [];
@@ -1450,32 +1449,32 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1450
1449
  return ans;
1451
1450
  }
1452
1451
 
1452
+ /**
1453
+ * Time complexity: O(n)
1454
+ * Space complexity: O(n)
1455
+ */
1456
+
1453
1457
  listLevels<C extends BTNCallback<N>>(
1454
1458
  callback?: C,
1455
- beginRoot?: BTNKey | N | null | undefined,
1459
+ beginRoot?: BTNodeKeyOrNode<N>,
1456
1460
  iterationType?: IterationType,
1457
1461
  includeNull?: false
1458
1462
  ): ReturnType<C>[][];
1459
1463
 
1460
1464
  listLevels<C extends BTNCallback<N>>(
1461
1465
  callback?: C,
1462
- beginRoot?: BTNKey | N | null | undefined,
1466
+ beginRoot?: BTNodeKeyOrNode<N>,
1463
1467
  iterationType?: IterationType,
1464
1468
  includeNull?: undefined
1465
1469
  ): ReturnType<C>[][];
1466
1470
 
1467
1471
  listLevels<C extends BTNCallback<N | null | undefined>>(
1468
1472
  callback?: C,
1469
- beginRoot?: BTNKey | N | null | undefined,
1473
+ beginRoot?: BTNodeKeyOrNode<N>,
1470
1474
  iterationType?: IterationType,
1471
1475
  includeNull?: true
1472
1476
  ): ReturnType<C>[][];
1473
1477
 
1474
- /**
1475
- * Time complexity: O(n)
1476
- * Space complexity: O(n)
1477
- */
1478
-
1479
1478
  /**
1480
1479
  * Time complexity: O(n)
1481
1480
  * Space complexity: O(n)
@@ -1499,11 +1498,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1499
1498
  */
1500
1499
  listLevels<C extends BTNCallback<N | null | undefined>>(
1501
1500
  callback: C = this._defaultOneParamCallback as C,
1502
- beginRoot: BTNKey | N | null | undefined = this.root,
1503
- iterationType = this.options.iterationType,
1501
+ beginRoot: BTNodeKeyOrNode<N> = this.root,
1502
+ iterationType = this.iterationType,
1504
1503
  includeNull = false
1505
1504
  ): ReturnType<C>[][] {
1506
- beginRoot = this.ensureNotKey(beginRoot);
1505
+ beginRoot = this.ensureNode(beginRoot);
1507
1506
  const levelsNodes: ReturnType<C>[][] = [];
1508
1507
  if (!beginRoot) return levelsNodes;
1509
1508
 
@@ -1544,6 +1543,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1544
1543
  return levelsNodes;
1545
1544
  }
1546
1545
 
1546
+ /**
1547
+ * Time complexity: O(n)
1548
+ * Space complexity: O(n)
1549
+ */
1550
+
1547
1551
  getPredecessor(node: N): N;
1548
1552
 
1549
1553
  /**
@@ -1552,8 +1556,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1552
1556
  * `null`, or `undefined`.
1553
1557
  * @returns The function `getPredecessor` returns a value of type `N | undefined`.
1554
1558
  */
1555
- getPredecessor(node: BTNKey | N | null | undefined): N | undefined {
1556
- node = this.ensureNotKey(node);
1559
+ getPredecessor(node: BTNodeKeyOrNode<N>): N | undefined {
1560
+ node = this.ensureNode(node);
1557
1561
  if (!this.isRealNode(node)) return undefined;
1558
1562
 
1559
1563
  if (node.left) {
@@ -1576,7 +1580,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1576
1580
  * after the given node in the inorder traversal of the binary tree.
1577
1581
  */
1578
1582
  getSuccessor(x?: BTNKey | N | null): N | null | undefined {
1579
- x = this.ensureNotKey(x);
1583
+ x = this.ensureNode(x);
1580
1584
  if (!x) return undefined;
1581
1585
 
1582
1586
  if (x.right) {
@@ -1591,11 +1595,6 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1591
1595
  return y;
1592
1596
  }
1593
1597
 
1594
- /**
1595
- * Time complexity: O(n)
1596
- * Space complexity: O(1)
1597
- */
1598
-
1599
1598
  /**
1600
1599
  * Time complexity: O(n)
1601
1600
  * Space complexity: O(1)
@@ -1617,9 +1616,9 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1617
1616
  morris<C extends BTNCallback<N>>(
1618
1617
  callback: C = this._defaultOneParamCallback as C,
1619
1618
  pattern: DFSOrderPattern = 'in',
1620
- beginRoot: BTNKey | N | null | undefined = this.root
1619
+ beginRoot: BTNodeKeyOrNode<N> = this.root
1621
1620
  ): ReturnType<C>[] {
1622
- beginRoot = this.ensureNotKey(beginRoot);
1621
+ beginRoot = this.ensureNode(beginRoot);
1623
1622
  if (beginRoot === null) return [];
1624
1623
  const ans: ReturnType<BTNCallback<N>>[] = [];
1625
1624
 
@@ -1700,6 +1699,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1700
1699
  return ans;
1701
1700
  }
1702
1701
 
1702
+ /**
1703
+ * Time complexity: O(n)
1704
+ * Space complexity: O(1)
1705
+ */
1706
+
1703
1707
  /**
1704
1708
  * The `forEach` function iterates over each entry in a tree and calls a callback function with the
1705
1709
  * entry and the tree as arguments.
@@ -1724,21 +1728,12 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1724
1728
  const newTree = this.createTree();
1725
1729
  for (const [key, value] of this) {
1726
1730
  if (predicate([key, value], this)) {
1727
- newTree.add(key, value);
1731
+ newTree.add([key, value]);
1728
1732
  }
1729
1733
  }
1730
1734
  return newTree;
1731
1735
  }
1732
1736
 
1733
- // TODO Type error, need to return a TREE<NV> that is a value type only for callback function.
1734
- // map<NV>(callback: (entry: [BTNKey, V | undefined], tree: this) => NV) {
1735
- // const newTree = this.createTree();
1736
- // for (const [key, value] of this) {
1737
- // newTree.add(key, callback([key, value], this));
1738
- // }
1739
- // return newTree;
1740
- // }
1741
-
1742
1737
  /**
1743
1738
  * The `map` function creates a new tree by applying a callback function to each entry in the current
1744
1739
  * tree.
@@ -1748,11 +1743,20 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1748
1743
  map(callback: (entry: [BTNKey, V | undefined], tree: this) => V) {
1749
1744
  const newTree = this.createTree();
1750
1745
  for (const [key, value] of this) {
1751
- newTree.add(key, callback([key, value], this));
1746
+ newTree.add([key, callback([key, value], this)]);
1752
1747
  }
1753
1748
  return newTree;
1754
1749
  }
1755
1750
 
1751
+ // TODO Type error, need to return a TREE<NV> that is a value type only for callback function.
1752
+ // map<NV>(callback: (entry: [BTNKey, V | undefined], tree: this) => NV) {
1753
+ // const newTree = this.createTree();
1754
+ // for (const [key, value] of this) {
1755
+ // newTree.add(key, callback([key, value], this));
1756
+ // }
1757
+ // return newTree;
1758
+ // }
1759
+
1756
1760
  /**
1757
1761
  * The `reduce` function iterates over the entries of a tree and applies a callback function to each
1758
1762
  * entry, accumulating a single value.
@@ -1773,7 +1777,6 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1773
1777
  return accumulator;
1774
1778
  }
1775
1779
 
1776
-
1777
1780
  /**
1778
1781
  * The above function is an iterator for a binary tree that can be used to traverse the tree in
1779
1782
  * either an iterative or recursive manner.
@@ -1786,7 +1789,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1786
1789
  * [Symbol.iterator](node = this.root): Generator<[BTNKey, V | undefined], void, undefined> {
1787
1790
  if (!node) return;
1788
1791
 
1789
- if (this.options.iterationType === IterationType.ITERATIVE) {
1792
+ if (this.iterationType === IterationType.ITERATIVE) {
1790
1793
  const stack: (N | null | undefined)[] = [];
1791
1794
  let current: N | null | undefined = node;
1792
1795
 
@@ -1821,9 +1824,9 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1821
1824
  * following types:
1822
1825
  * @param {BinaryTreePrintOptions} [options={ isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false}] - Options object that controls printing behavior. You can specify whether to display undefined, null, or sentinel nodes.
1823
1826
  */
1824
- print(beginRoot: BTNKey | N | null | undefined = this.root, options?: BinaryTreePrintOptions): void {
1827
+ print(beginRoot: BTNodeKeyOrNode<N> = this.root, options?: BinaryTreePrintOptions): void {
1825
1828
  const opts = { isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false, ...options };
1826
- beginRoot = this.ensureNotKey(beginRoot);
1829
+ beginRoot = this.ensureNode(beginRoot);
1827
1830
  if (!beginRoot) return;
1828
1831
 
1829
1832
  if (opts.isShowUndefined) console.log(`U for undefined
@@ -1901,9 +1904,9 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1901
1904
  * @param {N} destNode - The destination node to swap.
1902
1905
  * @returns {N} - The destination node after the swap.
1903
1906
  */
1904
- protected _swap(srcNode: BTNKey | N | null | undefined, destNode: BTNKey | N | null | undefined): N | undefined {
1905
- srcNode = this.ensureNotKey(srcNode);
1906
- destNode = this.ensureNotKey(destNode);
1907
+ protected _swapProperties(srcNode: BTNodeKeyOrNode<N>, destNode: BTNodeKeyOrNode<N>): N | undefined {
1908
+ srcNode = this.ensureNode(srcNode);
1909
+ destNode = this.ensureNode(destNode);
1907
1910
 
1908
1911
  if (srcNode && destNode) {
1909
1912
  const { key, value } = destNode;
@@ -1922,6 +1925,32 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1922
1925
  return undefined;
1923
1926
  }
1924
1927
 
1928
+ /**
1929
+ * The function replaces an old node with a new node in a binary tree.
1930
+ * @param {N} oldNode - The oldNode parameter represents the node that needs to be replaced in the
1931
+ * tree.
1932
+ * @param {N} newNode - The `newNode` parameter is the node that will replace the `oldNode` in the
1933
+ * tree.
1934
+ * @returns The method is returning the newNode.
1935
+ */
1936
+ protected _replaceNode(oldNode: N, newNode: N): N {
1937
+ if (oldNode.parent) {
1938
+ if (oldNode.parent.left === oldNode) {
1939
+ oldNode.parent.left = newNode;
1940
+ } else if (oldNode.parent.right === oldNode) {
1941
+ oldNode.parent.right = newNode;
1942
+ }
1943
+ }
1944
+ newNode.left = oldNode.left;
1945
+ newNode.right = oldNode.right;
1946
+ newNode.parent = oldNode.parent;
1947
+ if (this.root === oldNode) {
1948
+ this._root = newNode;
1949
+ }
1950
+
1951
+ return newNode;
1952
+ }
1953
+
1925
1954
  /**
1926
1955
  * The function `_addTo` adds a new node to a binary tree if there is an available position.
1927
1956
  * @param {N | null | undefined} newNode - The `newNode` parameter represents the node that you want to add to
@@ -1933,7 +1962,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
1933
1962
  * the binary tree. If neither the left nor right child is available, the function returns undefined.
1934
1963
  * If the parent node is null, the function also returns undefined.
1935
1964
  */
1936
- protected _addTo(newNode: N | null | undefined, parent: BTNKey | N | null | undefined): N | null | undefined {
1965
+ protected _addTo(newNode: N | null | undefined, parent: BTNodeKeyOrNode<N>): N | null | undefined {
1937
1966
  if (this.isNodeKey(parent)) parent = this.getNode(parent);
1938
1967
 
1939
1968
  if (parent) {