stack-typed 1.54.2 → 1.54.3
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.
- package/dist/data-structures/binary-tree/avl-tree-counter.d.ts +21 -20
- package/dist/data-structures/binary-tree/avl-tree-counter.js +8 -7
- package/dist/data-structures/binary-tree/avl-tree-multi-map.d.ts +12 -12
- package/dist/data-structures/binary-tree/avl-tree-multi-map.js +2 -2
- package/dist/data-structures/binary-tree/avl-tree.d.ts +25 -21
- package/dist/data-structures/binary-tree/avl-tree.js +12 -8
- package/dist/data-structures/binary-tree/binary-tree.d.ts +173 -225
- package/dist/data-structures/binary-tree/binary-tree.js +239 -144
- package/dist/data-structures/binary-tree/bst.d.ts +62 -56
- package/dist/data-structures/binary-tree/bst.js +78 -122
- package/dist/data-structures/binary-tree/red-black-tree.d.ts +19 -25
- package/dist/data-structures/binary-tree/red-black-tree.js +7 -13
- package/dist/data-structures/binary-tree/tree-counter.d.ts +19 -19
- package/dist/data-structures/binary-tree/tree-counter.js +12 -12
- package/dist/data-structures/binary-tree/tree-multi-map.d.ts +14 -14
- package/dist/data-structures/binary-tree/tree-multi-map.js +4 -4
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +1 -0
- package/dist/types/data-structures/binary-tree/bst.d.ts +1 -1
- package/dist/utils/utils.d.ts +2 -2
- package/package.json +2 -2
- package/src/data-structures/binary-tree/avl-tree-counter.ts +30 -23
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +25 -15
- package/src/data-structures/binary-tree/avl-tree.ts +35 -29
- package/src/data-structures/binary-tree/binary-tree.ts +469 -252
- package/src/data-structures/binary-tree/bst.ts +141 -143
- package/src/data-structures/binary-tree/red-black-tree.ts +27 -35
- package/src/data-structures/binary-tree/tree-counter.ts +33 -27
- package/src/data-structures/binary-tree/tree-multi-map.ts +25 -17
- package/src/types/data-structures/binary-tree/binary-tree.ts +1 -0
- package/src/types/data-structures/binary-tree/bst.ts +1 -1
- package/src/utils/utils.ts +2 -2
|
@@ -11,7 +11,6 @@ import type {
|
|
|
11
11
|
BinaryTreeOptions,
|
|
12
12
|
BinaryTreePrintOptions,
|
|
13
13
|
BTNEntry,
|
|
14
|
-
BTNRep,
|
|
15
14
|
DFSOrderPattern,
|
|
16
15
|
DFSStackItem,
|
|
17
16
|
EntryCallback,
|
|
@@ -36,6 +35,10 @@ import { DFSOperation, Range } from '../../common';
|
|
|
36
35
|
* @template BinaryTreeNode<K, V> - The type of the family relationship in the binary tree.
|
|
37
36
|
*/
|
|
38
37
|
export class BinaryTreeNode<K = any, V = any> {
|
|
38
|
+
key: K;
|
|
39
|
+
value?: V;
|
|
40
|
+
parent?: BinaryTreeNode<K, V> = undefined;
|
|
41
|
+
|
|
39
42
|
/**
|
|
40
43
|
* The constructor function initializes an object with a key and an optional value in TypeScript.
|
|
41
44
|
* @param {K} key - The `key` parameter in the constructor function is used to store the key value
|
|
@@ -49,32 +52,26 @@ export class BinaryTreeNode<K = any, V = any> {
|
|
|
49
52
|
this.value = value;
|
|
50
53
|
}
|
|
51
54
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
value?: V;
|
|
55
|
-
|
|
56
|
-
parent?: BinaryTreeNode<K, V> = undefined;
|
|
55
|
+
_left?: BinaryTreeNode<K, V> | null | undefined = undefined;
|
|
57
56
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
get left(): OptNodeOrNull<BinaryTreeNode<K, V>> {
|
|
57
|
+
get left(): BinaryTreeNode<K, V> | null | undefined {
|
|
61
58
|
return this._left;
|
|
62
59
|
}
|
|
63
60
|
|
|
64
|
-
set left(v:
|
|
61
|
+
set left(v: BinaryTreeNode<K, V> | null | undefined) {
|
|
65
62
|
if (v) {
|
|
66
63
|
v.parent = this as unknown as BinaryTreeNode<K, V>;
|
|
67
64
|
}
|
|
68
65
|
this._left = v;
|
|
69
66
|
}
|
|
70
67
|
|
|
71
|
-
_right?:
|
|
68
|
+
_right?: BinaryTreeNode<K, V> | null | undefined = undefined;
|
|
72
69
|
|
|
73
|
-
get right():
|
|
70
|
+
get right(): BinaryTreeNode<K, V> | null | undefined {
|
|
74
71
|
return this._right;
|
|
75
72
|
}
|
|
76
73
|
|
|
77
|
-
set right(v:
|
|
74
|
+
set right(v: BinaryTreeNode<K, V> | null | undefined) {
|
|
78
75
|
if (v) {
|
|
79
76
|
v.parent = this;
|
|
80
77
|
}
|
|
@@ -132,29 +129,96 @@ export class BinaryTreeNode<K = any, V = any> {
|
|
|
132
129
|
* 3. Depth and Height: Depth is the number of edges from the root to a node; height is the maximum depth in the tree.
|
|
133
130
|
* 4. Subtrees: Each child of a node forms the root of a subtree.
|
|
134
131
|
* 5. Leaf Nodes: Nodes without children are leaves.
|
|
132
|
+
* @example
|
|
133
|
+
* // determine loan approval using a decision tree
|
|
134
|
+
* // Decision tree structure
|
|
135
|
+
* const loanDecisionTree = new BinaryTree<string>(
|
|
136
|
+
* ['stableIncome', 'goodCredit', 'Rejected', 'Approved', 'Rejected'],
|
|
137
|
+
* { isDuplicate: true }
|
|
138
|
+
* );
|
|
139
|
+
*
|
|
140
|
+
* function determineLoanApproval(
|
|
141
|
+
* node?: BinaryTreeNode<string> | null,
|
|
142
|
+
* conditions?: { [key: string]: boolean }
|
|
143
|
+
* ): string {
|
|
144
|
+
* if (!node) throw new Error('Invalid node');
|
|
145
|
+
*
|
|
146
|
+
* // If it's a leaf node, return the decision result
|
|
147
|
+
* if (!node.left && !node.right) return node.key;
|
|
148
|
+
*
|
|
149
|
+
* // Check if a valid condition exists for the current node's key
|
|
150
|
+
* return conditions?.[node.key]
|
|
151
|
+
* ? determineLoanApproval(node.left, conditions)
|
|
152
|
+
* : determineLoanApproval(node.right, conditions);
|
|
153
|
+
* }
|
|
154
|
+
*
|
|
155
|
+
* // Test case 1: Stable income and good credit score
|
|
156
|
+
* console.log(determineLoanApproval(loanDecisionTree.root, { stableIncome: true, goodCredit: true })); // 'Approved'
|
|
157
|
+
*
|
|
158
|
+
* // Test case 2: Stable income but poor credit score
|
|
159
|
+
* console.log(determineLoanApproval(loanDecisionTree.root, { stableIncome: true, goodCredit: false })); // 'Rejected'
|
|
160
|
+
*
|
|
161
|
+
* // Test case 3: No stable income
|
|
162
|
+
* console.log(determineLoanApproval(loanDecisionTree.root, { stableIncome: false, goodCredit: true })); // 'Rejected'
|
|
163
|
+
*
|
|
164
|
+
* // Test case 4: No stable income and poor credit score
|
|
165
|
+
* console.log(determineLoanApproval(loanDecisionTree.root, { stableIncome: false, goodCredit: false })); // 'Rejected'
|
|
166
|
+
* @example
|
|
167
|
+
* // evaluate the arithmetic expression represented by the binary tree
|
|
168
|
+
* const expressionTree = new BinaryTree<number | string>(['+', 3, '*', null, null, 5, '-', null, null, 2, 8]);
|
|
169
|
+
*
|
|
170
|
+
* function evaluate(node?: BinaryTreeNode<number | string> | null): number {
|
|
171
|
+
* if (!node) return 0;
|
|
172
|
+
*
|
|
173
|
+
* if (typeof node.key === 'number') return node.key;
|
|
174
|
+
*
|
|
175
|
+
* const leftValue = evaluate(node.left); // Evaluate the left subtree
|
|
176
|
+
* const rightValue = evaluate(node.right); // Evaluate the right subtree
|
|
177
|
+
*
|
|
178
|
+
* // Perform the operation based on the current node's operator
|
|
179
|
+
* switch (node.key) {
|
|
180
|
+
* case '+':
|
|
181
|
+
* return leftValue + rightValue;
|
|
182
|
+
* case '-':
|
|
183
|
+
* return leftValue - rightValue;
|
|
184
|
+
* case '*':
|
|
185
|
+
* return leftValue * rightValue;
|
|
186
|
+
* case '/':
|
|
187
|
+
* return rightValue !== 0 ? leftValue / rightValue : 0; // Handle division by zero
|
|
188
|
+
* default:
|
|
189
|
+
* throw new Error(`Unsupported operator: ${node.key}`);
|
|
190
|
+
* }
|
|
191
|
+
* }
|
|
192
|
+
*
|
|
193
|
+
* console.log(evaluate(expressionTree.root)); // -27
|
|
135
194
|
*/
|
|
136
195
|
export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = object>
|
|
137
196
|
extends IterableEntryBase<K, V | undefined>
|
|
138
197
|
implements IBinaryTree<K, V, R, MK, MV, MR>
|
|
139
198
|
{
|
|
199
|
+
iterationType: IterationType = 'ITERATIVE';
|
|
200
|
+
|
|
140
201
|
/**
|
|
141
202
|
* This TypeScript constructor function initializes a binary tree with optional options and adds
|
|
142
203
|
* elements based on the provided input.
|
|
143
204
|
* @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the constructor is an
|
|
144
|
-
* iterable that can contain either objects of type `
|
|
205
|
+
* iterable that can contain either objects of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. It
|
|
145
206
|
* is used to initialize the binary tree with keys, nodes, entries, or raw data.
|
|
146
207
|
* @param [options] - The `options` parameter in the constructor is an optional object that can
|
|
147
208
|
* contain the following properties:
|
|
148
209
|
*/
|
|
149
210
|
constructor(
|
|
150
|
-
keysNodesEntriesOrRaws: Iterable<
|
|
211
|
+
keysNodesEntriesOrRaws: Iterable<
|
|
212
|
+
K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R
|
|
213
|
+
> = [],
|
|
151
214
|
options?: BinaryTreeOptions<K, V, R>
|
|
152
215
|
) {
|
|
153
216
|
super();
|
|
154
217
|
if (options) {
|
|
155
|
-
const { iterationType, toEntryFn, isMapMode } = options;
|
|
218
|
+
const { iterationType, toEntryFn, isMapMode, isDuplicate } = options;
|
|
156
219
|
if (iterationType) this.iterationType = iterationType;
|
|
157
220
|
if (isMapMode !== undefined) this._isMapMode = isMapMode;
|
|
221
|
+
if (isDuplicate !== undefined) this._isDuplicate = isDuplicate;
|
|
158
222
|
if (typeof toEntryFn === 'function') this._toEntryFn = toEntryFn;
|
|
159
223
|
else if (toEntryFn) throw TypeError('toEntryFn must be a function type');
|
|
160
224
|
}
|
|
@@ -162,23 +226,27 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
162
226
|
if (keysNodesEntriesOrRaws) this.addMany(keysNodesEntriesOrRaws);
|
|
163
227
|
}
|
|
164
228
|
|
|
165
|
-
iterationType: IterationType = 'ITERATIVE';
|
|
166
|
-
|
|
167
229
|
protected _isMapMode = true;
|
|
168
230
|
|
|
169
231
|
get isMapMode() {
|
|
170
232
|
return this._isMapMode;
|
|
171
233
|
}
|
|
172
234
|
|
|
235
|
+
protected _isDuplicate = false;
|
|
236
|
+
|
|
237
|
+
get isDuplicate() {
|
|
238
|
+
return this._isDuplicate;
|
|
239
|
+
}
|
|
240
|
+
|
|
173
241
|
protected _store = new Map<K, V | undefined>();
|
|
174
242
|
|
|
175
243
|
get store() {
|
|
176
244
|
return this._store;
|
|
177
245
|
}
|
|
178
246
|
|
|
179
|
-
protected _root?:
|
|
247
|
+
protected _root?: BinaryTreeNode<K, V> | null | undefined;
|
|
180
248
|
|
|
181
|
-
get root():
|
|
249
|
+
get root(): BinaryTreeNode<K, V> | null | undefined {
|
|
182
250
|
return this._root;
|
|
183
251
|
}
|
|
184
252
|
|
|
@@ -242,8 +310,8 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
242
310
|
*
|
|
243
311
|
* The function `ensureNode` in TypeScript checks if a given input is a node, entry, key, or raw
|
|
244
312
|
* value and returns the corresponding node or null.
|
|
245
|
-
* @param {
|
|
246
|
-
* parameter in the `ensureNode` function can be of type `
|
|
313
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `keyNodeOrEntry`
|
|
314
|
+
* parameter in the `ensureNode` function can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. It
|
|
247
315
|
* is used to determine whether the input is a key, node, entry, or raw data. The
|
|
248
316
|
* @param {IterationType} iterationType - The `iterationType` parameter in the `ensureNode` function
|
|
249
317
|
* is used to specify the type of iteration to be performed. It has a default value of
|
|
@@ -252,9 +320,9 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
252
320
|
* conditions specified in the code snippet.
|
|
253
321
|
*/
|
|
254
322
|
ensureNode(
|
|
255
|
-
keyNodeOrEntry:
|
|
323
|
+
keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
|
|
256
324
|
iterationType: IterationType = this.iterationType
|
|
257
|
-
):
|
|
325
|
+
): BinaryTreeNode<K, V> | null | undefined {
|
|
258
326
|
if (keyNodeOrEntry === null) return null;
|
|
259
327
|
if (keyNodeOrEntry === undefined) return;
|
|
260
328
|
if (keyNodeOrEntry === this._NIL) return;
|
|
@@ -276,7 +344,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
276
344
|
* Space Complexity: O(1)
|
|
277
345
|
*
|
|
278
346
|
* The function isNode checks if the input is an instance of BinaryTreeNode.
|
|
279
|
-
* @param {
|
|
347
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter
|
|
280
348
|
* `keyNodeOrEntry` can be either a key, a node, an entry, or raw data. The function is
|
|
281
349
|
* checking if the input is an instance of a `BinaryTreeNode` and returning a boolean value
|
|
282
350
|
* accordingly.
|
|
@@ -285,7 +353,9 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
285
353
|
* it is not an instance of `BinaryTreeNode`, the function returns `false`, indicating that the input
|
|
286
354
|
* is not a node.
|
|
287
355
|
*/
|
|
288
|
-
isNode(
|
|
356
|
+
isNode(
|
|
357
|
+
keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
|
|
358
|
+
): keyNodeOrEntry is BinaryTreeNode<K, V> {
|
|
289
359
|
return keyNodeOrEntry instanceof BinaryTreeNode;
|
|
290
360
|
}
|
|
291
361
|
|
|
@@ -294,12 +364,14 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
294
364
|
* Space Complexity: O(1)
|
|
295
365
|
*
|
|
296
366
|
* The function `isRaw` checks if the input parameter is of type `R` by verifying if it is an object.
|
|
297
|
-
* @param {
|
|
367
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R} keyNodeEntryOrRaw - K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
|
|
298
368
|
* @returns The function `isRaw` is checking if the `keyNodeEntryOrRaw` parameter is of type `R` by
|
|
299
369
|
* checking if it is an object. If the parameter is an object, the function will return `true`,
|
|
300
370
|
* indicating that it is of type `R`.
|
|
301
371
|
*/
|
|
302
|
-
isRaw(
|
|
372
|
+
isRaw(
|
|
373
|
+
keyNodeEntryOrRaw: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R
|
|
374
|
+
): keyNodeEntryOrRaw is R {
|
|
303
375
|
return this._toEntryFn !== undefined && typeof keyNodeEntryOrRaw === 'object';
|
|
304
376
|
}
|
|
305
377
|
|
|
@@ -308,15 +380,17 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
308
380
|
* Space Complexity: O(1)
|
|
309
381
|
*
|
|
310
382
|
* The function `isRealNode` checks if a given input is a valid node in a binary tree.
|
|
311
|
-
* @param {
|
|
312
|
-
* parameter in the `isRealNode` function can be of type `
|
|
383
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `keyNodeOrEntry`
|
|
384
|
+
* parameter in the `isRealNode` function can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`.
|
|
313
385
|
* The function checks if the input parameter is a `BinaryTreeNode<K, V>` type by verifying if it is not equal
|
|
314
386
|
* @returns The function `isRealNode` is checking if the input `keyNodeOrEntry` is a valid
|
|
315
387
|
* node by comparing it to `this._NIL`, `null`, and `undefined`. If the input is not one of these
|
|
316
388
|
* values, it then calls the `isNode` method to further determine if the input is a node. The
|
|
317
389
|
* function will return a boolean value indicating whether the
|
|
318
390
|
*/
|
|
319
|
-
isRealNode(
|
|
391
|
+
isRealNode(
|
|
392
|
+
keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
|
|
393
|
+
): keyNodeOrEntry is BinaryTreeNode<K, V> {
|
|
320
394
|
if (keyNodeOrEntry === this._NIL || keyNodeOrEntry === null || keyNodeOrEntry === undefined) return false;
|
|
321
395
|
return this.isNode(keyNodeOrEntry);
|
|
322
396
|
}
|
|
@@ -326,14 +400,16 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
326
400
|
* Space Complexity: O(1)
|
|
327
401
|
*
|
|
328
402
|
* The function checks if a given input is a valid node or null.
|
|
329
|
-
* @param {
|
|
403
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter
|
|
330
404
|
* `keyNodeOrEntry` in the `isRealNodeOrNull` function can be of type `BTNRep<K,
|
|
331
405
|
* V, BinaryTreeNode<K, V>>` or `R`. It is a union type that can either be a key, a node, an entry, or
|
|
332
406
|
* @returns The function `isRealNodeOrNull` is returning a boolean value. It checks if the input
|
|
333
407
|
* `keyNodeOrEntry` is either `null` or a real node, and returns `true` if it is a node or
|
|
334
408
|
* `null`, and `false` otherwise.
|
|
335
409
|
*/
|
|
336
|
-
isRealNodeOrNull(
|
|
410
|
+
isRealNodeOrNull(
|
|
411
|
+
keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
|
|
412
|
+
): keyNodeOrEntry is BinaryTreeNode<K, V> | null {
|
|
337
413
|
return keyNodeOrEntry === null || this.isRealNode(keyNodeOrEntry);
|
|
338
414
|
}
|
|
339
415
|
|
|
@@ -342,12 +418,12 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
342
418
|
* Space Complexity: O(1)
|
|
343
419
|
*
|
|
344
420
|
* The function isNIL checks if a given key, node, entry, or raw value is equal to the _NIL value.
|
|
345
|
-
* @param {
|
|
421
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - BTNRep<K, V,
|
|
346
422
|
* BinaryTreeNode<K, V>>
|
|
347
423
|
* @returns The function is checking if the `keyNodeOrEntry` parameter is equal to the `_NIL`
|
|
348
424
|
* property of the current object and returning a boolean value based on that comparison.
|
|
349
425
|
*/
|
|
350
|
-
isNIL(keyNodeOrEntry:
|
|
426
|
+
isNIL(keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined): boolean {
|
|
351
427
|
return keyNodeOrEntry === this._NIL;
|
|
352
428
|
}
|
|
353
429
|
|
|
@@ -356,9 +432,9 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
356
432
|
* Space Complexity: O(1)
|
|
357
433
|
*
|
|
358
434
|
* The function `isRange` checks if the input parameter is an instance of the `Range` class.
|
|
359
|
-
* @param {
|
|
360
|
-
*
|
|
361
|
-
* of type `
|
|
435
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>> | Range<K>} keyNodeEntryOrPredicate
|
|
436
|
+
* - The `keyNodeEntryOrPredicate` parameter in the `isRange` function can be
|
|
437
|
+
* of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `, `NodePredicate<BinaryTreeNode<K, V>>`, or
|
|
362
438
|
* `Range<K>`. The function checks if the `keyNodeEntry
|
|
363
439
|
* @returns The `isRange` function is checking if the `keyNodeEntryOrPredicate` parameter is an
|
|
364
440
|
* instance of the `Range` class. If it is an instance of `Range`, the function will return `true`,
|
|
@@ -366,7 +442,14 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
366
442
|
* will return `false`.
|
|
367
443
|
*/
|
|
368
444
|
isRange(
|
|
369
|
-
keyNodeEntryOrPredicate:
|
|
445
|
+
keyNodeEntryOrPredicate:
|
|
446
|
+
| K
|
|
447
|
+
| BinaryTreeNode<K, V>
|
|
448
|
+
| [K | null | undefined, V | undefined]
|
|
449
|
+
| null
|
|
450
|
+
| undefined
|
|
451
|
+
| NodePredicate<BinaryTreeNode<K, V>>
|
|
452
|
+
| Range<K>
|
|
370
453
|
): keyNodeEntryOrPredicate is Range<K> {
|
|
371
454
|
return keyNodeEntryOrPredicate instanceof Range;
|
|
372
455
|
}
|
|
@@ -377,14 +460,14 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
377
460
|
*
|
|
378
461
|
* The function determines whether a given key, node, entry, or raw data is a leaf node in a binary
|
|
379
462
|
* tree.
|
|
380
|
-
* @param {
|
|
381
|
-
* `keyNodeOrEntry` can be of type `
|
|
463
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter
|
|
464
|
+
* `keyNodeOrEntry` can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. It represents a
|
|
382
465
|
* key, node, entry, or raw data in a binary tree structure. The function `isLeaf` checks whether the
|
|
383
466
|
* provided
|
|
384
467
|
* @returns The function `isLeaf` returns a boolean value indicating whether the input
|
|
385
468
|
* `keyNodeOrEntry` is a leaf node in a binary tree.
|
|
386
469
|
*/
|
|
387
|
-
isLeaf(keyNodeOrEntry:
|
|
470
|
+
isLeaf(keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined): boolean {
|
|
388
471
|
keyNodeOrEntry = this.ensureNode(keyNodeOrEntry);
|
|
389
472
|
if (keyNodeOrEntry === undefined) return false;
|
|
390
473
|
if (keyNodeOrEntry === null) return true;
|
|
@@ -397,14 +480,16 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
397
480
|
*
|
|
398
481
|
* The function `isEntry` checks if the input is a BTNEntry object by verifying if it is an array
|
|
399
482
|
* with a length of 2.
|
|
400
|
-
* @param {
|
|
401
|
-
* parameter in the `isEntry` function can be of type `
|
|
483
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `keyNodeOrEntry`
|
|
484
|
+
* parameter in the `isEntry` function can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or type `R`.
|
|
402
485
|
* The function checks if the provided `keyNodeOrEntry` is of type `BTN
|
|
403
486
|
* @returns The `isEntry` function is checking if the `keyNodeOrEntry` parameter is an array
|
|
404
487
|
* with a length of 2. If it is, then it returns `true`, indicating that the parameter is of type
|
|
405
488
|
* `BTNEntry<K, V>`. If the condition is not met, it returns `false`.
|
|
406
489
|
*/
|
|
407
|
-
isEntry(
|
|
490
|
+
isEntry(
|
|
491
|
+
keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
|
|
492
|
+
): keyNodeOrEntry is BTNEntry<K, V> {
|
|
408
493
|
return Array.isArray(keyNodeOrEntry) && keyNodeOrEntry.length === 2;
|
|
409
494
|
}
|
|
410
495
|
|
|
@@ -430,7 +515,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
430
515
|
*
|
|
431
516
|
* The `add` function in TypeScript adds a new node to a binary tree while handling duplicate keys
|
|
432
517
|
* and finding the correct insertion position.
|
|
433
|
-
* @param {
|
|
518
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `add` method you provided
|
|
434
519
|
* seems to be for adding a new node to a binary tree structure. The `keyNodeOrEntry`
|
|
435
520
|
* parameter in the method can accept different types of values:
|
|
436
521
|
* @param {V} [value] - The `value` parameter in the `add` method represents the value associated
|
|
@@ -441,7 +526,10 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
441
526
|
* node was successful, and `false` if the insertion position could not be found or if a duplicate
|
|
442
527
|
* key was found and the node was replaced instead of inserted.
|
|
443
528
|
*/
|
|
444
|
-
add(
|
|
529
|
+
add(
|
|
530
|
+
keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
|
|
531
|
+
value?: V
|
|
532
|
+
): boolean {
|
|
445
533
|
const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
|
|
446
534
|
if (newNode === undefined) return false;
|
|
447
535
|
|
|
@@ -461,11 +549,13 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
461
549
|
|
|
462
550
|
if (!cur) continue;
|
|
463
551
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
552
|
+
if (!this._isDuplicate) {
|
|
553
|
+
// Check for duplicate keys when newNode is not null
|
|
554
|
+
if (newNode !== null && cur.key === newNode.key) {
|
|
555
|
+
this._replaceNode(cur, newNode);
|
|
556
|
+
if (this._isMapMode) this._setValue(cur.key, newValue);
|
|
557
|
+
return true; // If duplicate keys are found, no insertion is performed
|
|
558
|
+
}
|
|
469
559
|
}
|
|
470
560
|
|
|
471
561
|
// Record the first possible insertion location found
|
|
@@ -506,7 +596,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
506
596
|
* each insertion was successful.
|
|
507
597
|
* @param keysNodesEntriesOrRaws - `keysNodesEntriesOrRaws` is an iterable that can contain a
|
|
508
598
|
* mix of keys, nodes, entries, or raw values. Each element in this iterable can be of type
|
|
509
|
-
* `
|
|
599
|
+
* `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`.
|
|
510
600
|
* @param [values] - The `values` parameter in the `addMany` function is an optional parameter that
|
|
511
601
|
* accepts an iterable of values. These values correspond to the keys or nodes being added in the
|
|
512
602
|
* `keysNodesEntriesOrRaws` parameter. If provided, the function will iterate over the values and
|
|
@@ -516,7 +606,9 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
516
606
|
* corresponds to the success of adding the corresponding key or value in the input iterable.
|
|
517
607
|
*/
|
|
518
608
|
addMany(
|
|
519
|
-
keysNodesEntriesOrRaws: Iterable<
|
|
609
|
+
keysNodesEntriesOrRaws: Iterable<
|
|
610
|
+
K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R
|
|
611
|
+
>,
|
|
520
612
|
values?: Iterable<V | undefined>
|
|
521
613
|
): boolean[] {
|
|
522
614
|
// TODO not sure addMany not be run multi times
|
|
@@ -562,13 +654,15 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
562
654
|
* The `refill` function clears the existing data structure and then adds new key-value pairs based
|
|
563
655
|
* on the provided input.
|
|
564
656
|
* @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the `refill`
|
|
565
|
-
* method can accept an iterable containing a mix of `
|
|
657
|
+
* method can accept an iterable containing a mix of `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` objects or `R`
|
|
566
658
|
* objects.
|
|
567
659
|
* @param [values] - The `values` parameter in the `refill` method is an optional parameter that
|
|
568
660
|
* accepts an iterable of values of type `V` or `undefined`.
|
|
569
661
|
*/
|
|
570
662
|
refill(
|
|
571
|
-
keysNodesEntriesOrRaws: Iterable<
|
|
663
|
+
keysNodesEntriesOrRaws: Iterable<
|
|
664
|
+
K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R
|
|
665
|
+
>,
|
|
572
666
|
values?: Iterable<V | undefined>
|
|
573
667
|
): void {
|
|
574
668
|
this.clear();
|
|
@@ -581,7 +675,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
581
675
|
*
|
|
582
676
|
* The function `delete` in TypeScript implements the deletion of a node in a binary tree and returns
|
|
583
677
|
* the deleted node along with information for tree balancing.
|
|
584
|
-
* @param {
|
|
678
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry
|
|
585
679
|
* - The `delete` method you provided is used to delete a node from a binary tree based on the key,
|
|
586
680
|
* node, entry or raw data. The method returns an array of
|
|
587
681
|
* `BinaryTreeDeleteResult` objects containing information about the deleted node and whether
|
|
@@ -590,7 +684,9 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
590
684
|
* the array contains information about the node that was deleted (`deleted`) and the node that may
|
|
591
685
|
* need to be balanced (`needBalanced`).
|
|
592
686
|
*/
|
|
593
|
-
delete(
|
|
687
|
+
delete(
|
|
688
|
+
keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
|
|
689
|
+
): BinaryTreeDeleteResult<BinaryTreeNode<K, V>>[] {
|
|
594
690
|
const deletedResult: BinaryTreeDeleteResult<BinaryTreeNode<K, V>>[] = [];
|
|
595
691
|
if (!this._root) return deletedResult;
|
|
596
692
|
|
|
@@ -641,15 +737,15 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
641
737
|
*
|
|
642
738
|
* The `search` function in TypeScript performs a depth-first or breadth-first search on a tree
|
|
643
739
|
* structure based on a given predicate or key, with options to return multiple results or just one.
|
|
644
|
-
* @param {
|
|
740
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate - The
|
|
645
741
|
* `keyNodeEntryOrPredicate` parameter in the `search` function can accept three types of values:
|
|
646
742
|
* @param [onlyOne=false] - The `onlyOne` parameter in the `search` function is a boolean flag that
|
|
647
743
|
* determines whether the search should stop after finding the first matching node. If `onlyOne` is
|
|
648
744
|
* set to `true`, the search will return as soon as a matching node is found. If `onlyOne` is
|
|
649
745
|
* @param {C} callback - The `callback` parameter in the `search` function is a callback function
|
|
650
746
|
* that will be called on each node that matches the search criteria. It is of type `C`, which
|
|
651
|
-
* extends `NodeCallback<BinaryTreeNode<K, V
|
|
652
|
-
* @param {
|
|
747
|
+
* extends `NodeCallback<BinaryTreeNode<K, V> | null>`. The default value for `callback` is `this._DEFAULT_NODE_CALLBACK` if
|
|
748
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `search` function is
|
|
653
749
|
* used to specify the node from which the search operation should begin. It represents the starting
|
|
654
750
|
* point in the binary tree where the search will be performed. If no specific `startNode` is
|
|
655
751
|
* provided, the search operation will start from the root
|
|
@@ -659,11 +755,17 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
659
755
|
* @returns The `search` function returns an array of values that match the provided criteria based
|
|
660
756
|
* on the search algorithm implemented within the function.
|
|
661
757
|
*/
|
|
662
|
-
search<C extends NodeCallback<BinaryTreeNode<K, V
|
|
663
|
-
keyNodeEntryOrPredicate:
|
|
758
|
+
search<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
|
|
759
|
+
keyNodeEntryOrPredicate:
|
|
760
|
+
| K
|
|
761
|
+
| BinaryTreeNode<K, V>
|
|
762
|
+
| [K | null | undefined, V | undefined]
|
|
763
|
+
| null
|
|
764
|
+
| undefined
|
|
765
|
+
| NodePredicate<BinaryTreeNode<K, V> | null>,
|
|
664
766
|
onlyOne = false,
|
|
665
767
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
666
|
-
startNode:
|
|
768
|
+
startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
|
|
667
769
|
iterationType: IterationType = this.iterationType
|
|
668
770
|
): ReturnType<C>[] {
|
|
669
771
|
if (keyNodeEntryOrPredicate === undefined) return [];
|
|
@@ -704,18 +806,31 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
704
806
|
return ans;
|
|
705
807
|
}
|
|
706
808
|
|
|
809
|
+
getNodes(
|
|
810
|
+
keyNodeEntryOrPredicate:
|
|
811
|
+
| K
|
|
812
|
+
| BinaryTreeNode<K, V>
|
|
813
|
+
| [K | null | undefined, V | undefined]
|
|
814
|
+
| null
|
|
815
|
+
| undefined
|
|
816
|
+
| NodePredicate<BinaryTreeNode<K, V>>,
|
|
817
|
+
onlyOne?: boolean,
|
|
818
|
+
startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
|
|
819
|
+
iterationType?: IterationType
|
|
820
|
+
): BinaryTreeNode<K, V>[];
|
|
821
|
+
|
|
707
822
|
/**
|
|
708
823
|
* Time Complexity: O(n)
|
|
709
824
|
* Space Complexity: O(k + log n)
|
|
710
825
|
*
|
|
711
826
|
* The function `getNodes` retrieves nodes from a binary tree based on a key, node, entry, raw data,
|
|
712
827
|
* or predicate, with options for recursive or iterative traversal.
|
|
713
|
-
* @param {
|
|
828
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate
|
|
714
829
|
* - The `getNodes` function you provided takes several parameters:
|
|
715
830
|
* @param [onlyOne=false] - The `onlyOne` parameter in the `getNodes` function is a boolean flag that
|
|
716
831
|
* determines whether to return only the first node that matches the criteria specified by the
|
|
717
832
|
* `keyNodeEntryOrPredicate` parameter. If `onlyOne` is set to `true`, the function will
|
|
718
|
-
* @param {
|
|
833
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
|
|
719
834
|
* `getNodes` function is used to specify the starting point for traversing the binary tree. It
|
|
720
835
|
* represents the root node of the binary tree or the node from which the traversal should begin. If
|
|
721
836
|
* not provided, the default value is set to `this._root
|
|
@@ -726,11 +841,17 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
726
841
|
* based on the input parameters and the iteration type specified.
|
|
727
842
|
*/
|
|
728
843
|
getNodes(
|
|
729
|
-
keyNodeEntryOrPredicate:
|
|
844
|
+
keyNodeEntryOrPredicate:
|
|
845
|
+
| K
|
|
846
|
+
| BinaryTreeNode<K, V>
|
|
847
|
+
| [K | null | undefined, V | undefined]
|
|
848
|
+
| null
|
|
849
|
+
| undefined
|
|
850
|
+
| NodePredicate<BinaryTreeNode<K, V> | null>,
|
|
730
851
|
onlyOne = false,
|
|
731
|
-
startNode:
|
|
852
|
+
startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
|
|
732
853
|
iterationType: IterationType = this.iterationType
|
|
733
|
-
): BinaryTreeNode<K, V>[] {
|
|
854
|
+
): (BinaryTreeNode<K, V> | null)[] {
|
|
734
855
|
return this.search(keyNodeEntryOrPredicate, onlyOne, node => node, startNode, iterationType);
|
|
735
856
|
}
|
|
736
857
|
|
|
@@ -740,10 +861,10 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
740
861
|
*
|
|
741
862
|
* The `getNode` function retrieves a node based on the provided key, node, entry, raw data, or
|
|
742
863
|
* predicate.
|
|
743
|
-
* @param {
|
|
864
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate
|
|
744
865
|
* - The `keyNodeEntryOrPredicate` parameter in the `getNode` function can accept a key,
|
|
745
866
|
* node, entry, raw data, or a predicate function.
|
|
746
|
-
* @param {
|
|
867
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
|
|
747
868
|
* `getNode` function is used to specify the starting point for searching for a node in a binary
|
|
748
869
|
* tree. If no specific starting point is provided, the default value is set to `this._root`, which
|
|
749
870
|
* is typically the root node of the binary tree.
|
|
@@ -755,10 +876,16 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
755
876
|
* or `null` if no matching node is found.
|
|
756
877
|
*/
|
|
757
878
|
getNode(
|
|
758
|
-
keyNodeEntryOrPredicate:
|
|
759
|
-
|
|
879
|
+
keyNodeEntryOrPredicate:
|
|
880
|
+
| K
|
|
881
|
+
| BinaryTreeNode<K, V>
|
|
882
|
+
| [K | null | undefined, V | undefined]
|
|
883
|
+
| null
|
|
884
|
+
| undefined
|
|
885
|
+
| NodePredicate<BinaryTreeNode<K, V> | null>,
|
|
886
|
+
startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
|
|
760
887
|
iterationType: IterationType = this.iterationType
|
|
761
|
-
):
|
|
888
|
+
): BinaryTreeNode<K, V> | null | undefined {
|
|
762
889
|
return this.search(keyNodeEntryOrPredicate, true, node => node, startNode, iterationType)[0];
|
|
763
890
|
}
|
|
764
891
|
|
|
@@ -768,10 +895,10 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
768
895
|
*
|
|
769
896
|
* This function overrides the `get` method to retrieve the value associated with a specified key,
|
|
770
897
|
* node, entry, raw data, or predicate in a data structure.
|
|
771
|
-
* @param {
|
|
898
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate
|
|
772
899
|
* - The `keyNodeEntryOrPredicate` parameter in the `get` method can accept one of the
|
|
773
900
|
* following types:
|
|
774
|
-
* @param {
|
|
901
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `get`
|
|
775
902
|
* method is used to specify the starting point for searching for a key or node in the binary tree.
|
|
776
903
|
* If no specific starting point is provided, the default starting point is the root of the binary
|
|
777
904
|
* tree (`this._root`).
|
|
@@ -785,8 +912,8 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
785
912
|
* `undefined`.
|
|
786
913
|
*/
|
|
787
914
|
override get(
|
|
788
|
-
keyNodeEntryOrPredicate:
|
|
789
|
-
startNode:
|
|
915
|
+
keyNodeEntryOrPredicate: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
|
|
916
|
+
startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
|
|
790
917
|
iterationType: IterationType = this.iterationType
|
|
791
918
|
): V | undefined {
|
|
792
919
|
if (this._isMapMode) {
|
|
@@ -797,16 +924,28 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
797
924
|
return this.getNode(keyNodeEntryOrPredicate, startNode, iterationType)?.value;
|
|
798
925
|
}
|
|
799
926
|
|
|
927
|
+
override has(
|
|
928
|
+
keyNodeEntryOrPredicate?:
|
|
929
|
+
| K
|
|
930
|
+
| BinaryTreeNode<K, V>
|
|
931
|
+
| [K | null | undefined, V | undefined]
|
|
932
|
+
| null
|
|
933
|
+
| undefined
|
|
934
|
+
| NodePredicate<BinaryTreeNode<K, V>>,
|
|
935
|
+
startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
|
|
936
|
+
iterationType?: IterationType
|
|
937
|
+
): boolean;
|
|
938
|
+
|
|
800
939
|
/**
|
|
801
940
|
* Time Complexity: O(n)
|
|
802
941
|
* Space Complexity: O(log n)
|
|
803
942
|
*
|
|
804
943
|
* The `has` function in TypeScript checks if a specified key, node, entry, raw data, or predicate
|
|
805
944
|
* exists in the data structure.
|
|
806
|
-
* @param {
|
|
945
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate
|
|
807
946
|
* - The `keyNodeEntryOrPredicate` parameter in the `override has` method can accept one of
|
|
808
947
|
* the following types:
|
|
809
|
-
* @param {
|
|
948
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
|
|
810
949
|
* `override` method is used to specify the starting point for the search operation within the data
|
|
811
950
|
* structure. It defaults to `this._root` if not provided explicitly.
|
|
812
951
|
* @param {IterationType} iterationType - The `iterationType` parameter in the `override has` method
|
|
@@ -819,8 +958,14 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
819
958
|
* Otherwise, it returns `false`.
|
|
820
959
|
*/
|
|
821
960
|
override has(
|
|
822
|
-
keyNodeEntryOrPredicate:
|
|
823
|
-
|
|
961
|
+
keyNodeEntryOrPredicate:
|
|
962
|
+
| K
|
|
963
|
+
| BinaryTreeNode<K, V>
|
|
964
|
+
| [K | null | undefined, V | undefined]
|
|
965
|
+
| null
|
|
966
|
+
| undefined
|
|
967
|
+
| NodePredicate<BinaryTreeNode<K, V> | null>,
|
|
968
|
+
startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
|
|
824
969
|
iterationType: IterationType = this.iterationType
|
|
825
970
|
): boolean {
|
|
826
971
|
return this.search(keyNodeEntryOrPredicate, true, node => node, startNode, iterationType).length > 0;
|
|
@@ -856,7 +1001,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
856
1001
|
*
|
|
857
1002
|
* The function checks if a binary tree is perfectly balanced by comparing its minimum height with
|
|
858
1003
|
* its height.
|
|
859
|
-
* @param {
|
|
1004
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter is the starting
|
|
860
1005
|
* point for checking if the binary tree is perfectly balanced. It represents the root node of the
|
|
861
1006
|
* binary tree or a specific node from which the balance check should begin.
|
|
862
1007
|
* @returns The method `isPerfectlyBalanced` is returning a boolean value, which indicates whether
|
|
@@ -865,7 +1010,9 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
865
1010
|
* height plus 1 is greater than or equal to the height of the tree, then it is considered perfectly
|
|
866
1011
|
* balanced and
|
|
867
1012
|
*/
|
|
868
|
-
isPerfectlyBalanced(
|
|
1013
|
+
isPerfectlyBalanced(
|
|
1014
|
+
startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root
|
|
1015
|
+
): boolean {
|
|
869
1016
|
return this.getMinHeight(startNode) + 1 >= this.getHeight(startNode);
|
|
870
1017
|
}
|
|
871
1018
|
|
|
@@ -875,7 +1022,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
875
1022
|
*
|
|
876
1023
|
* The function `isBST` in TypeScript checks if a binary search tree is valid using either recursive
|
|
877
1024
|
* or iterative methods.
|
|
878
|
-
* @param {
|
|
1025
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `isBST`
|
|
879
1026
|
* function represents the starting point for checking whether a binary search tree (BST) is valid.
|
|
880
1027
|
* It can be a node in the BST or a reference to the root of the BST. If no specific node is
|
|
881
1028
|
* provided, the function will default to
|
|
@@ -888,7 +1035,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
888
1035
|
* less than the node's key, and all nodes in its right subtree have keys greater than the node's
|
|
889
1036
|
*/
|
|
890
1037
|
isBST(
|
|
891
|
-
startNode:
|
|
1038
|
+
startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
|
|
892
1039
|
iterationType: IterationType = this.iterationType
|
|
893
1040
|
): boolean {
|
|
894
1041
|
// TODO there is a bug
|
|
@@ -896,7 +1043,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
896
1043
|
if (!startNode) return true;
|
|
897
1044
|
|
|
898
1045
|
if (iterationType === 'RECURSIVE') {
|
|
899
|
-
const dfs = (cur:
|
|
1046
|
+
const dfs = (cur: BinaryTreeNode<K, V> | null | undefined, min: number, max: number): boolean => {
|
|
900
1047
|
if (!this.isRealNode(cur)) return true;
|
|
901
1048
|
const numKey = Number(cur.key);
|
|
902
1049
|
if (numKey <= min || numKey >= max) return false;
|
|
@@ -911,7 +1058,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
911
1058
|
const stack = [];
|
|
912
1059
|
let prev = checkMax ? Number.MAX_SAFE_INTEGER : Number.MIN_SAFE_INTEGER;
|
|
913
1060
|
// @ts-ignore
|
|
914
|
-
let curr:
|
|
1061
|
+
let curr: BinaryTreeNode<K, V> | null | undefined = startNode;
|
|
915
1062
|
while (this.isRealNode(curr) || stack.length > 0) {
|
|
916
1063
|
while (this.isRealNode(curr)) {
|
|
917
1064
|
stack.push(curr);
|
|
@@ -936,10 +1083,10 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
936
1083
|
* Space Complexity: O(log n)
|
|
937
1084
|
*
|
|
938
1085
|
* The `getDepth` function calculates the depth between two nodes in a binary tree.
|
|
939
|
-
* @param {
|
|
1086
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } dist - The `dist` parameter in the `getDepth`
|
|
940
1087
|
* function represents the node or entry in a binary tree map, or a reference to a node in the tree.
|
|
941
1088
|
* It is the target node for which you want to calculate the depth from the `startNode` node.
|
|
942
|
-
* @param {
|
|
1089
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
|
|
943
1090
|
* `getDepth` function represents the starting point from which you want to calculate the depth of a
|
|
944
1091
|
* given node or entry in a binary tree. If no specific starting point is provided, the default value
|
|
945
1092
|
* for `startNode` is set to the root of the binary
|
|
@@ -948,8 +1095,8 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
948
1095
|
* node, it returns the depth of the `dist` node from the root of the tree.
|
|
949
1096
|
*/
|
|
950
1097
|
getDepth(
|
|
951
|
-
dist:
|
|
952
|
-
startNode:
|
|
1098
|
+
dist: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
|
|
1099
|
+
startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root
|
|
953
1100
|
): number {
|
|
954
1101
|
let distEnsured = this.ensureNode(dist);
|
|
955
1102
|
const beginRootEnsured = this.ensureNode(startNode);
|
|
@@ -970,7 +1117,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
970
1117
|
*
|
|
971
1118
|
* The `getHeight` function calculates the maximum height of a binary tree using either a recursive
|
|
972
1119
|
* or iterative approach in TypeScript.
|
|
973
|
-
* @param {
|
|
1120
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter is the starting
|
|
974
1121
|
* point from which the height of the binary tree will be calculated. It can be a node in the binary
|
|
975
1122
|
* tree or a reference to the root of the tree. If not provided, it defaults to the root of the
|
|
976
1123
|
* binary tree data structure.
|
|
@@ -982,14 +1129,14 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
982
1129
|
* recursive approach or an iterative approach depending on the `iterationType` parameter.
|
|
983
1130
|
*/
|
|
984
1131
|
getHeight(
|
|
985
|
-
startNode:
|
|
1132
|
+
startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
|
|
986
1133
|
iterationType: IterationType = this.iterationType
|
|
987
1134
|
): number {
|
|
988
1135
|
startNode = this.ensureNode(startNode);
|
|
989
1136
|
if (!this.isRealNode(startNode)) return -1;
|
|
990
1137
|
|
|
991
1138
|
if (iterationType === 'RECURSIVE') {
|
|
992
|
-
const _getMaxHeight = (cur:
|
|
1139
|
+
const _getMaxHeight = (cur: BinaryTreeNode<K, V> | null | undefined): number => {
|
|
993
1140
|
if (!this.isRealNode(cur)) return -1;
|
|
994
1141
|
const leftHeight = _getMaxHeight(cur.left);
|
|
995
1142
|
const rightHeight = _getMaxHeight(cur.right);
|
|
@@ -1020,7 +1167,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1020
1167
|
*
|
|
1021
1168
|
* The `getMinHeight` function calculates the minimum height of a binary tree using either a
|
|
1022
1169
|
* recursive or iterative approach in TypeScript.
|
|
1023
|
-
* @param {
|
|
1170
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
|
|
1024
1171
|
* `getMinHeight` function represents the starting node from which the minimum height of the binary
|
|
1025
1172
|
* tree will be calculated. It is either a node in the binary tree or a reference to the root of the
|
|
1026
1173
|
* tree. If not provided, the default value is the root
|
|
@@ -1033,14 +1180,14 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1033
1180
|
* a stack) based on the `iterationType` parameter.
|
|
1034
1181
|
*/
|
|
1035
1182
|
getMinHeight(
|
|
1036
|
-
startNode:
|
|
1183
|
+
startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
|
|
1037
1184
|
iterationType: IterationType = this.iterationType
|
|
1038
1185
|
): number {
|
|
1039
1186
|
startNode = this.ensureNode(startNode);
|
|
1040
1187
|
if (!startNode) return -1;
|
|
1041
1188
|
|
|
1042
1189
|
if (iterationType === 'RECURSIVE') {
|
|
1043
|
-
const _getMinHeight = (cur:
|
|
1190
|
+
const _getMinHeight = (cur: BinaryTreeNode<K, V> | null | undefined): number => {
|
|
1044
1191
|
if (!this.isRealNode(cur)) return 0;
|
|
1045
1192
|
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return 0;
|
|
1046
1193
|
const leftMinHeight = _getMinHeight(cur.left);
|
|
@@ -1051,8 +1198,8 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1051
1198
|
return _getMinHeight(startNode);
|
|
1052
1199
|
} else {
|
|
1053
1200
|
const stack: BinaryTreeNode<K, V>[] = [];
|
|
1054
|
-
let node:
|
|
1055
|
-
last:
|
|
1201
|
+
let node: BinaryTreeNode<K, V> | null | undefined = startNode,
|
|
1202
|
+
last: BinaryTreeNode<K, V> | null | undefined = null;
|
|
1056
1203
|
const depths: Map<BinaryTreeNode<K, V>, number> = new Map();
|
|
1057
1204
|
|
|
1058
1205
|
while (stack.length > 0 || node) {
|
|
@@ -1088,7 +1235,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1088
1235
|
* the path to the root. It is expected to be a function that takes a node as an argument and returns
|
|
1089
1236
|
* a value based on that node. The return type of the callback function is determined by the generic
|
|
1090
1237
|
* type `C
|
|
1091
|
-
* @param {
|
|
1238
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } beginNode - The `beginNode` parameter in the
|
|
1092
1239
|
* `getPathToRoot` function can be either a key, a node, an entry, or any other value of type `R`.
|
|
1093
1240
|
* @param [isReverse=true] - The `isReverse` parameter in the `getPathToRoot` function determines
|
|
1094
1241
|
* whether the resulting path from the given `beginNode` to the root should be in reverse order or
|
|
@@ -1099,7 +1246,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1099
1246
|
* parameter.
|
|
1100
1247
|
*/
|
|
1101
1248
|
getPathToRoot<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(
|
|
1102
|
-
beginNode:
|
|
1249
|
+
beginNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
|
|
1103
1250
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1104
1251
|
isReverse = false
|
|
1105
1252
|
): ReturnType<C>[] {
|
|
@@ -1126,7 +1273,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1126
1273
|
* @param {C} callback - The `callback` parameter is a function that will be called with the leftmost
|
|
1127
1274
|
* node of a binary tree or with `undefined` if the tree is empty. It is provided with a default
|
|
1128
1275
|
* value of `_DEFAULT_NODE_CALLBACK` if not specified.
|
|
1129
|
-
* @param {
|
|
1276
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
|
|
1130
1277
|
* `getLeftMost` function represents the starting point for finding the leftmost node in a binary
|
|
1131
1278
|
* tree. It can be either a key, a node, or an entry in the binary tree structure. If no specific
|
|
1132
1279
|
* starting point is provided, the function will default
|
|
@@ -1140,7 +1287,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1140
1287
|
*/
|
|
1141
1288
|
getLeftMost<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(
|
|
1142
1289
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1143
|
-
startNode:
|
|
1290
|
+
startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
|
|
1144
1291
|
iterationType: IterationType = this.iterationType
|
|
1145
1292
|
): ReturnType<C> {
|
|
1146
1293
|
if (this.isNIL(startNode)) return callback(undefined);
|
|
@@ -1176,7 +1323,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1176
1323
|
* of finding the rightmost node in a binary tree. It is of type `NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>`,
|
|
1177
1324
|
* which means it is a callback function that can accept either an optional binary tree node or null
|
|
1178
1325
|
* as
|
|
1179
|
-
* @param {
|
|
1326
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
|
|
1180
1327
|
* `getRightMost` function represents the starting point for finding the rightmost node in a binary
|
|
1181
1328
|
* tree. It can be either a key, a node, or an entry in the binary tree structure. If no specific
|
|
1182
1329
|
* starting point is provided, the function will default
|
|
@@ -1190,7 +1337,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1190
1337
|
*/
|
|
1191
1338
|
getRightMost<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(
|
|
1192
1339
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1193
|
-
startNode:
|
|
1340
|
+
startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
|
|
1194
1341
|
iterationType: IterationType = this.iterationType
|
|
1195
1342
|
): ReturnType<C> {
|
|
1196
1343
|
if (this.isNIL(startNode)) return callback(undefined);
|
|
@@ -1230,7 +1377,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1230
1377
|
*/
|
|
1231
1378
|
getPredecessor(node: BinaryTreeNode<K, V>): BinaryTreeNode<K, V> {
|
|
1232
1379
|
if (this.isRealNode(node.left)) {
|
|
1233
|
-
let predecessor:
|
|
1380
|
+
let predecessor: BinaryTreeNode<K, V> | null | undefined = node.left;
|
|
1234
1381
|
while (!this.isRealNode(predecessor) || (this.isRealNode(predecessor.right) && predecessor.right !== node)) {
|
|
1235
1382
|
if (this.isRealNode(predecessor)) {
|
|
1236
1383
|
predecessor = predecessor.right;
|
|
@@ -1255,7 +1402,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1255
1402
|
* have a right child, the function traverses up the parent nodes until it finds a node that is not
|
|
1256
1403
|
* the right child of its parent, and returns that node
|
|
1257
1404
|
*/
|
|
1258
|
-
getSuccessor(x?: K | BinaryTreeNode<K, V> | null):
|
|
1405
|
+
getSuccessor(x?: K | BinaryTreeNode<K, V> | null): BinaryTreeNode<K, V> | null | undefined {
|
|
1259
1406
|
x = this.ensureNode(x);
|
|
1260
1407
|
if (!this.isRealNode(x)) return undefined;
|
|
1261
1408
|
|
|
@@ -1263,7 +1410,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1263
1410
|
return this.getLeftMost(node => node, x.right);
|
|
1264
1411
|
}
|
|
1265
1412
|
|
|
1266
|
-
let y:
|
|
1413
|
+
let y: BinaryTreeNode<K, V> | null | undefined = x.parent;
|
|
1267
1414
|
while (this.isRealNode(y) && x === y.right) {
|
|
1268
1415
|
x = y;
|
|
1269
1416
|
y = y.parent;
|
|
@@ -1274,14 +1421,16 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1274
1421
|
dfs<C extends NodeCallback<BinaryTreeNode<K, V>>>(
|
|
1275
1422
|
callback?: C,
|
|
1276
1423
|
pattern?: DFSOrderPattern,
|
|
1277
|
-
|
|
1424
|
+
onlyOne?: boolean,
|
|
1425
|
+
startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
|
|
1278
1426
|
iterationType?: IterationType
|
|
1279
1427
|
): ReturnType<C>[];
|
|
1280
1428
|
|
|
1281
1429
|
dfs<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
|
|
1282
1430
|
callback?: C,
|
|
1283
1431
|
pattern?: DFSOrderPattern,
|
|
1284
|
-
|
|
1432
|
+
onlyOne?: boolean,
|
|
1433
|
+
startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
|
|
1285
1434
|
iterationType?: IterationType,
|
|
1286
1435
|
includeNull?: boolean
|
|
1287
1436
|
): ReturnType<C>[];
|
|
@@ -1290,50 +1439,53 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1290
1439
|
* Time complexity: O(n)
|
|
1291
1440
|
* Space complexity: O(n)
|
|
1292
1441
|
*
|
|
1293
|
-
* The function
|
|
1294
|
-
*
|
|
1295
|
-
* @param {C} callback - The `callback` parameter is a
|
|
1296
|
-
*
|
|
1297
|
-
*
|
|
1298
|
-
* @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `dfs`
|
|
1299
|
-
* order in which the
|
|
1300
|
-
*
|
|
1301
|
-
* @param {
|
|
1302
|
-
*
|
|
1303
|
-
*
|
|
1304
|
-
*
|
|
1305
|
-
* @param {
|
|
1306
|
-
*
|
|
1307
|
-
*
|
|
1308
|
-
*
|
|
1309
|
-
*
|
|
1310
|
-
*
|
|
1311
|
-
* `
|
|
1312
|
-
*
|
|
1313
|
-
*
|
|
1442
|
+
* The function performs a depth-first search on a binary tree structure based on the specified
|
|
1443
|
+
* parameters.
|
|
1444
|
+
* @param {C} callback - The `callback` parameter is a function that will be called for each node
|
|
1445
|
+
* visited during the depth-first search. It should accept a `BinaryTreeNode` as an argument and
|
|
1446
|
+
* return an optional node or null. The default value for this parameter is `_DEFAULT_NODE_CALLBACK`.
|
|
1447
|
+
* @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `dfs` function specifies
|
|
1448
|
+
* the order in which the nodes are visited during a depth-first search traversal. The possible
|
|
1449
|
+
* values for the `pattern` parameter are:
|
|
1450
|
+
* @param {boolean} [onlyOne=false] - The `onlyOne` parameter in the `dfs` function is a boolean flag
|
|
1451
|
+
* that determines whether the depth-first search should stop after finding the first matching node
|
|
1452
|
+
* or continue searching for all matching nodes. If `onlyOne` is set to `true`, the search will stop
|
|
1453
|
+
* after finding the first matching node
|
|
1454
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined}
|
|
1455
|
+
* startNode - The `startNode` parameter in the `dfs` function can be one of the following types:
|
|
1456
|
+
* @param {IterationType} iterationType - The `iterationType` parameter in the `dfs` function
|
|
1457
|
+
* specifies the type of iteration to be performed during the Depth-First Search traversal. It is
|
|
1458
|
+
* used to determine the order in which nodes are visited during the traversal. The possible values
|
|
1459
|
+
* for `iterationType` are typically defined as an enum or a
|
|
1460
|
+
* @param [includeNull=false] - The `includeNull` parameter in the `dfs` function determines whether
|
|
1461
|
+
* null nodes should be included in the depth-first search traversal. If `includeNull` is set to
|
|
1462
|
+
* `true`, null nodes will be included in the traversal process. If it is set to `false`, null nodes
|
|
1463
|
+
* will be skipped
|
|
1464
|
+
* @returns The `dfs` method is returning an array of the return type of the callback function `C`.
|
|
1314
1465
|
*/
|
|
1315
1466
|
dfs<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(
|
|
1316
1467
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1317
1468
|
pattern: DFSOrderPattern = 'IN',
|
|
1318
|
-
|
|
1469
|
+
onlyOne: boolean = false,
|
|
1470
|
+
startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
|
|
1319
1471
|
iterationType: IterationType = this.iterationType,
|
|
1320
1472
|
includeNull = false
|
|
1321
1473
|
): ReturnType<C>[] {
|
|
1322
1474
|
startNode = this.ensureNode(startNode);
|
|
1323
1475
|
if (!startNode) return [];
|
|
1324
|
-
return this._dfs(callback, pattern, startNode, iterationType, includeNull);
|
|
1476
|
+
return this._dfs(callback, pattern, onlyOne, startNode, iterationType, includeNull);
|
|
1325
1477
|
}
|
|
1326
1478
|
|
|
1327
1479
|
bfs<C extends NodeCallback<BinaryTreeNode<K, V>>>(
|
|
1328
1480
|
callback?: C,
|
|
1329
|
-
startNode?:
|
|
1481
|
+
startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
|
|
1330
1482
|
iterationType?: IterationType,
|
|
1331
1483
|
includeNull?: false
|
|
1332
1484
|
): ReturnType<C>[];
|
|
1333
1485
|
|
|
1334
1486
|
bfs<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
|
|
1335
1487
|
callback?: C,
|
|
1336
|
-
startNode?:
|
|
1488
|
+
startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
|
|
1337
1489
|
iterationType?: IterationType,
|
|
1338
1490
|
includeNull?: true
|
|
1339
1491
|
): ReturnType<C>[];
|
|
@@ -1347,7 +1499,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1347
1499
|
* @param {C} callback - The `callback` parameter in the `bfs` function is a function that will be
|
|
1348
1500
|
* called on each node visited during the breadth-first search traversal. It is a generic type `C`
|
|
1349
1501
|
* that extends the `NodeCallback` type, which takes a parameter of type `BinaryTreeNode<K, V>` or `null`.
|
|
1350
|
-
* @param {
|
|
1502
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `bfs`
|
|
1351
1503
|
* function represents the starting point for the breadth-first search traversal in a binary tree. It
|
|
1352
1504
|
* can be specified as a key, node, or entry in the binary tree structure. If not provided, the
|
|
1353
1505
|
* default value is the root node of the binary
|
|
@@ -1363,14 +1515,14 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1363
1515
|
*/
|
|
1364
1516
|
bfs<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
|
|
1365
1517
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1366
|
-
startNode:
|
|
1518
|
+
startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
|
|
1367
1519
|
iterationType: IterationType = this.iterationType,
|
|
1368
1520
|
includeNull = false
|
|
1369
1521
|
): ReturnType<C>[] {
|
|
1370
1522
|
startNode = this.ensureNode(startNode);
|
|
1371
1523
|
if (!startNode) return [];
|
|
1372
1524
|
|
|
1373
|
-
const ans: ReturnType<NodeCallback<BinaryTreeNode<K, V
|
|
1525
|
+
const ans: ReturnType<NodeCallback<BinaryTreeNode<K, V> | null>>[] = [];
|
|
1374
1526
|
|
|
1375
1527
|
if (iterationType === 'RECURSIVE') {
|
|
1376
1528
|
const queue: Queue<OptNodeOrNull<BinaryTreeNode<K, V>>> = new Queue<OptNodeOrNull<BinaryTreeNode<K, V>>>([
|
|
@@ -1425,7 +1577,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1425
1577
|
* structure based on a specified callback and iteration type.
|
|
1426
1578
|
* @param {C} callback - The `callback` parameter is a function that will be called on each leaf node
|
|
1427
1579
|
* in the binary tree. It is optional and defaults to a default callback function if not provided.
|
|
1428
|
-
* @param {
|
|
1580
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `leaves`
|
|
1429
1581
|
* method is used to specify the starting point for finding and processing the leaves of a binary
|
|
1430
1582
|
* tree. It can be provided as either a key, a node, or an entry in the binary tree structure. If not
|
|
1431
1583
|
* explicitly provided, the default value
|
|
@@ -1437,11 +1589,11 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1437
1589
|
*/
|
|
1438
1590
|
leaves<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
|
|
1439
1591
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1440
|
-
startNode:
|
|
1592
|
+
startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
|
|
1441
1593
|
iterationType: IterationType = this.iterationType
|
|
1442
1594
|
): ReturnType<C>[] {
|
|
1443
1595
|
startNode = this.ensureNode(startNode);
|
|
1444
|
-
const leaves: ReturnType<NodeCallback<BinaryTreeNode<K, V
|
|
1596
|
+
const leaves: ReturnType<NodeCallback<BinaryTreeNode<K, V> | null>>[] = [];
|
|
1445
1597
|
if (!this.isRealNode(startNode)) return [];
|
|
1446
1598
|
|
|
1447
1599
|
if (iterationType === 'RECURSIVE') {
|
|
@@ -1474,14 +1626,14 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1474
1626
|
|
|
1475
1627
|
listLevels<C extends NodeCallback<BinaryTreeNode<K, V>>>(
|
|
1476
1628
|
callback?: C,
|
|
1477
|
-
startNode?:
|
|
1629
|
+
startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
|
|
1478
1630
|
iterationType?: IterationType,
|
|
1479
1631
|
includeNull?: false
|
|
1480
1632
|
): ReturnType<C>[][];
|
|
1481
1633
|
|
|
1482
1634
|
listLevels<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
|
|
1483
1635
|
callback?: C,
|
|
1484
|
-
startNode?:
|
|
1636
|
+
startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
|
|
1485
1637
|
iterationType?: IterationType,
|
|
1486
1638
|
includeNull?: true
|
|
1487
1639
|
): ReturnType<C>[][];
|
|
@@ -1495,7 +1647,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1495
1647
|
* @param {C} callback - The `callback` parameter is a function that will be applied to each node in
|
|
1496
1648
|
* the binary tree during the traversal. It is used to process each node and determine what
|
|
1497
1649
|
* information to include in the output for each level of the tree.
|
|
1498
|
-
* @param {
|
|
1650
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
|
|
1499
1651
|
* `listLevels` function represents the starting point for traversing the binary tree. It can be
|
|
1500
1652
|
* either a key, a node, or an entry in the binary tree. If not provided, the default value is the
|
|
1501
1653
|
* root of the binary tree.
|
|
@@ -1512,7 +1664,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1512
1664
|
*/
|
|
1513
1665
|
listLevels<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
|
|
1514
1666
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1515
|
-
startNode:
|
|
1667
|
+
startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
|
|
1516
1668
|
iterationType: IterationType = this.iterationType,
|
|
1517
1669
|
includeNull = false
|
|
1518
1670
|
): ReturnType<C>[][] {
|
|
@@ -1557,6 +1709,12 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1557
1709
|
return levelsNodes;
|
|
1558
1710
|
}
|
|
1559
1711
|
|
|
1712
|
+
morris<C extends NodeCallback<BinaryTreeNode<K, V>>>(
|
|
1713
|
+
callback?: C,
|
|
1714
|
+
pattern?: DFSOrderPattern,
|
|
1715
|
+
startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
|
|
1716
|
+
): ReturnType<C>[];
|
|
1717
|
+
|
|
1560
1718
|
/**
|
|
1561
1719
|
* Time complexity: O(n)
|
|
1562
1720
|
* Space complexity: O(n)
|
|
@@ -1565,11 +1723,11 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1565
1723
|
* Morris Traversal algorithm with different order patterns.
|
|
1566
1724
|
* @param {C} callback - The `callback` parameter in the `morris` function is a function that will be
|
|
1567
1725
|
* called on each node in the binary tree during the traversal. It is of type `C`, which extends the
|
|
1568
|
-
* `NodeCallback<BinaryTreeNode<K, V
|
|
1726
|
+
* `NodeCallback<BinaryTreeNode<K, V> | null>` type. The default value for `callback` is `this._DEFAULT
|
|
1569
1727
|
* @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `morris` function specifies
|
|
1570
1728
|
* the type of Depth-First Search (DFS) order pattern to traverse the binary tree. The possible
|
|
1571
1729
|
* values for the `pattern` parameter are:
|
|
1572
|
-
* @param {
|
|
1730
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `morris`
|
|
1573
1731
|
* function is the starting point for the Morris traversal algorithm. It represents the root node of
|
|
1574
1732
|
* the binary tree or the node from which the traversal should begin. It can be provided as either a
|
|
1575
1733
|
* key, a node, an entry, or a reference
|
|
@@ -1577,19 +1735,19 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1577
1735
|
* provided callback function to each node in the binary tree in the specified order pattern (IN,
|
|
1578
1736
|
* PRE, or POST).
|
|
1579
1737
|
*/
|
|
1580
|
-
morris<C extends NodeCallback<BinaryTreeNode<K, V
|
|
1738
|
+
morris<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
|
|
1581
1739
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1582
1740
|
pattern: DFSOrderPattern = 'IN',
|
|
1583
|
-
startNode:
|
|
1741
|
+
startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root
|
|
1584
1742
|
): ReturnType<C>[] {
|
|
1585
1743
|
startNode = this.ensureNode(startNode);
|
|
1586
1744
|
if (!startNode) return [];
|
|
1587
|
-
const ans: ReturnType<NodeCallback<BinaryTreeNode<K, V
|
|
1745
|
+
const ans: ReturnType<NodeCallback<BinaryTreeNode<K, V> | null>>[] = [];
|
|
1588
1746
|
|
|
1589
|
-
let cur:
|
|
1590
|
-
const _reverseEdge = (node:
|
|
1591
|
-
let pre:
|
|
1592
|
-
let next:
|
|
1747
|
+
let cur: BinaryTreeNode<K, V> | null | undefined = startNode;
|
|
1748
|
+
const _reverseEdge = (node: BinaryTreeNode<K, V> | null | undefined) => {
|
|
1749
|
+
let pre: BinaryTreeNode<K, V> | null | undefined = null;
|
|
1750
|
+
let next: BinaryTreeNode<K, V> | null | undefined = null;
|
|
1593
1751
|
while (node) {
|
|
1594
1752
|
next = node.right;
|
|
1595
1753
|
node.right = pre;
|
|
@@ -1598,9 +1756,9 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1598
1756
|
}
|
|
1599
1757
|
return pre;
|
|
1600
1758
|
};
|
|
1601
|
-
const _printEdge = (node:
|
|
1602
|
-
const tail:
|
|
1603
|
-
let cur:
|
|
1759
|
+
const _printEdge = (node: BinaryTreeNode<K, V> | null | undefined) => {
|
|
1760
|
+
const tail: BinaryTreeNode<K, V> | null | undefined = _reverseEdge(node);
|
|
1761
|
+
let cur: BinaryTreeNode<K, V> | null | undefined = tail;
|
|
1604
1762
|
while (cur) {
|
|
1605
1763
|
ans.push(callback(cur));
|
|
1606
1764
|
cur = cur.right;
|
|
@@ -1680,22 +1838,6 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1680
1838
|
return cloned;
|
|
1681
1839
|
}
|
|
1682
1840
|
|
|
1683
|
-
protected _clone(cloned: BinaryTree<K, V, R, MK, MV, MR>) {
|
|
1684
|
-
this.bfs(
|
|
1685
|
-
node => {
|
|
1686
|
-
if (node === null) cloned.add(null);
|
|
1687
|
-
else {
|
|
1688
|
-
if (this._isMapMode) cloned.add([node.key, this._store.get(node.key)]);
|
|
1689
|
-
else cloned.add([node.key, node.value]);
|
|
1690
|
-
}
|
|
1691
|
-
},
|
|
1692
|
-
this._root,
|
|
1693
|
-
this.iterationType,
|
|
1694
|
-
true
|
|
1695
|
-
);
|
|
1696
|
-
if (this._isMapMode) cloned._store = this._store;
|
|
1697
|
-
}
|
|
1698
|
-
|
|
1699
1841
|
/**
|
|
1700
1842
|
* Time Complexity: O(n)
|
|
1701
1843
|
* Space Complexity: O(n)
|
|
@@ -1761,7 +1903,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1761
1903
|
*
|
|
1762
1904
|
* The function `toVisual` in TypeScript overrides the visual representation of a binary tree with
|
|
1763
1905
|
* customizable options for displaying undefined, null, and sentinel nodes.
|
|
1764
|
-
* @param {
|
|
1906
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
|
|
1765
1907
|
* `toVisual` method is used to specify the starting point for visualizing the binary tree structure.
|
|
1766
1908
|
* It can be a node, key, entry, or the root of the tree. If no specific starting point is provided,
|
|
1767
1909
|
* the default is set to the root
|
|
@@ -1774,7 +1916,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1774
1916
|
* binary tree with the specified options.
|
|
1775
1917
|
*/
|
|
1776
1918
|
override toVisual(
|
|
1777
|
-
startNode:
|
|
1919
|
+
startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
|
|
1778
1920
|
options?: BinaryTreePrintOptions
|
|
1779
1921
|
): string {
|
|
1780
1922
|
const opts = { isShowUndefined: false, isShowNull: true, isShowRedBlackNIL: false, ...options };
|
|
@@ -1786,7 +1928,7 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1786
1928
|
if (opts.isShowNull) output += `N for null\n`;
|
|
1787
1929
|
if (opts.isShowRedBlackNIL) output += `S for Sentinel Node(NIL)\n`;
|
|
1788
1930
|
|
|
1789
|
-
const display = (root:
|
|
1931
|
+
const display = (root: BinaryTreeNode<K, V> | null | undefined): void => {
|
|
1790
1932
|
const [lines] = this._displayAux(root, opts);
|
|
1791
1933
|
let paragraph = '';
|
|
1792
1934
|
for (const line of lines) {
|
|
@@ -1809,37 +1951,56 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1809
1951
|
* printing options for the binary tree. It is an optional parameter that allows you to customize how
|
|
1810
1952
|
* the binary tree is printed, such as choosing between different traversal orders or formatting
|
|
1811
1953
|
* options.
|
|
1812
|
-
* @param {
|
|
1954
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
|
|
1813
1955
|
* `override print` method is used to specify the starting point for printing the binary tree. It can
|
|
1814
1956
|
* be either a key, a node, an entry, or the root of the tree. If no specific starting point is
|
|
1815
1957
|
* provided, the default value is set to
|
|
1816
1958
|
*/
|
|
1817
|
-
override print(
|
|
1959
|
+
override print(
|
|
1960
|
+
options?: BinaryTreePrintOptions,
|
|
1961
|
+
startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root
|
|
1962
|
+
) {
|
|
1818
1963
|
console.log(this.toVisual(startNode, options));
|
|
1819
1964
|
}
|
|
1820
1965
|
|
|
1966
|
+
protected _clone(cloned: BinaryTree<K, V, R, MK, MV, MR>) {
|
|
1967
|
+
this.bfs(
|
|
1968
|
+
node => {
|
|
1969
|
+
if (node === null) cloned.add(null);
|
|
1970
|
+
else {
|
|
1971
|
+
if (this._isMapMode) cloned.add([node.key, this._store.get(node.key)]);
|
|
1972
|
+
else cloned.add([node.key, node.value]);
|
|
1973
|
+
}
|
|
1974
|
+
},
|
|
1975
|
+
this._root,
|
|
1976
|
+
this.iterationType,
|
|
1977
|
+
true
|
|
1978
|
+
);
|
|
1979
|
+
if (this._isMapMode) cloned._store = this._store;
|
|
1980
|
+
}
|
|
1981
|
+
|
|
1821
1982
|
/**
|
|
1822
1983
|
* Time Complexity: O(1)
|
|
1823
1984
|
* Space Complexity: O(1)
|
|
1824
1985
|
*
|
|
1825
1986
|
* The function `keyValueNodeEntryRawToNodeAndValue` converts various input types into a node object
|
|
1826
1987
|
* or returns null.
|
|
1827
|
-
* @param {
|
|
1988
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The
|
|
1828
1989
|
* `keyValueNodeEntryRawToNodeAndValue` function takes in a parameter `keyNodeOrEntry`, which
|
|
1829
|
-
* can be of type `
|
|
1990
|
+
* can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. This parameter represents either a key, a
|
|
1830
1991
|
* node, an entry
|
|
1831
1992
|
* @param {V} [value] - The `value` parameter in the `keyValueNodeEntryRawToNodeAndValue` function is
|
|
1832
1993
|
* an optional parameter of type `V`. It represents the value associated with the key in the node
|
|
1833
1994
|
* being created. If a `value` is provided, it will be used when creating the node. If
|
|
1834
1995
|
* @returns The `keyValueNodeEntryRawToNodeAndValue` function returns an optional node
|
|
1835
|
-
* (`
|
|
1996
|
+
* (`BinaryTreeNode<K, V> | null | undefined`) based on the input parameters provided. The function checks the type of the
|
|
1836
1997
|
* input parameter (`keyNodeOrEntry`) and processes it accordingly to return a node or null
|
|
1837
1998
|
* value.
|
|
1838
1999
|
*/
|
|
1839
2000
|
protected _keyValueNodeOrEntryToNodeAndValue(
|
|
1840
|
-
keyNodeOrEntry:
|
|
2001
|
+
keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
|
|
1841
2002
|
value?: V
|
|
1842
|
-
): [
|
|
2003
|
+
): [BinaryTreeNode<K, V> | null | undefined, V | undefined] {
|
|
1843
2004
|
if (keyNodeOrEntry === undefined) return [undefined, undefined];
|
|
1844
2005
|
if (keyNodeOrEntry === null) return [null, undefined];
|
|
1845
2006
|
|
|
@@ -1856,92 +2017,118 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1856
2017
|
return [this.createNode(keyNodeOrEntry, value), value];
|
|
1857
2018
|
}
|
|
1858
2019
|
|
|
2020
|
+
protected _dfs<C extends NodeCallback<BinaryTreeNode<K, V>>>(
|
|
2021
|
+
callback: C,
|
|
2022
|
+
pattern?: DFSOrderPattern,
|
|
2023
|
+
onlyOne?: boolean,
|
|
2024
|
+
startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
|
|
2025
|
+
iterationType?: IterationType,
|
|
2026
|
+
includeNull?: boolean,
|
|
2027
|
+
shouldVisitLeft?: (node: BinaryTreeNode<K, V> | null | undefined) => boolean,
|
|
2028
|
+
shouldVisitRight?: (node: BinaryTreeNode<K, V> | null | undefined) => boolean,
|
|
2029
|
+
shouldVisitRoot?: (node: BinaryTreeNode<K, V> | null | undefined) => boolean,
|
|
2030
|
+
shouldProcessRoot?: (node: BinaryTreeNode<K, V> | null | undefined) => boolean
|
|
2031
|
+
): ReturnType<C>[];
|
|
2032
|
+
|
|
1859
2033
|
/**
|
|
1860
2034
|
* Time complexity: O(n)
|
|
1861
2035
|
* Space complexity: O(n)
|
|
1862
2036
|
*
|
|
1863
|
-
* The `_dfs` function performs a depth-first search traversal on a binary tree
|
|
1864
|
-
*
|
|
2037
|
+
* The `_dfs` function performs a depth-first search traversal on a binary tree, with customizable
|
|
2038
|
+
* options for traversal order and node processing.
|
|
1865
2039
|
* @param {C} callback - The `callback` parameter in the `_dfs` method is a function that will be
|
|
1866
|
-
* called on each node visited during the depth-first search traversal. It is
|
|
1867
|
-
* extends `NodeCallback<
|
|
2040
|
+
* called on each node visited during the depth-first search traversal. It is a generic type `C` that
|
|
2041
|
+
* extends `NodeCallback<BinaryTreeNode<K, V> | null>`. The default value for `callback`
|
|
1868
2042
|
* @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `_dfs` method specifies the
|
|
1869
|
-
* order in which the nodes are visited during
|
|
1870
|
-
*
|
|
1871
|
-
* @param {
|
|
1872
|
-
*
|
|
1873
|
-
*
|
|
1874
|
-
*
|
|
2043
|
+
* order in which the nodes are visited during a depth-first search traversal. It can have one of the
|
|
2044
|
+
* following values:
|
|
2045
|
+
* @param {boolean} [onlyOne=false] - The `onlyOne` parameter in the `_dfs` method is a boolean flag
|
|
2046
|
+
* that determines whether the traversal should stop after processing a single node. If `onlyOne` is
|
|
2047
|
+
* set to `true`, the traversal will return as soon as a single node is processed. If it is set to
|
|
2048
|
+
* `false
|
|
2049
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined}
|
|
2050
|
+
* startNode - The `startNode` parameter in the `_dfs` method is used to specify the starting node
|
|
2051
|
+
* for the depth-first search traversal. It can be provided in different forms:
|
|
1875
2052
|
* @param {IterationType} iterationType - The `iterationType` parameter in the `_dfs` method
|
|
1876
|
-
* specifies the
|
|
1877
|
-
*
|
|
1878
|
-
* @param [includeNull=false] - The `includeNull` parameter in the `_dfs` method
|
|
1879
|
-
*
|
|
1880
|
-
*
|
|
1881
|
-
*
|
|
1882
|
-
* @param shouldVisitLeft - The `shouldVisitLeft` parameter
|
|
1883
|
-
*
|
|
1884
|
-
*
|
|
1885
|
-
*
|
|
1886
|
-
* @param shouldVisitRight - The `shouldVisitRight` parameter
|
|
1887
|
-
*
|
|
1888
|
-
*
|
|
1889
|
-
*
|
|
1890
|
-
* @param shouldVisitRoot - The `shouldVisitRoot` parameter
|
|
1891
|
-
*
|
|
1892
|
-
*
|
|
1893
|
-
*
|
|
1894
|
-
* @param shouldProcessRoot - The `shouldProcessRoot` parameter
|
|
1895
|
-
*
|
|
1896
|
-
*
|
|
1897
|
-
*
|
|
1898
|
-
* @returns The
|
|
1899
|
-
*
|
|
2053
|
+
* specifies whether the traversal should be done recursively or iteratively. It can have two
|
|
2054
|
+
* possible values:
|
|
2055
|
+
* @param [includeNull=false] - The `includeNull` parameter in the `_dfs` method determines whether
|
|
2056
|
+
* null nodes should be included in the traversal process. If `includeNull` is set to `true`, the
|
|
2057
|
+
* method will consider null nodes as valid nodes to visit or process. If `includeNull` is set to
|
|
2058
|
+
* `false`,
|
|
2059
|
+
* @param shouldVisitLeft - The `shouldVisitLeft` parameter in the `_dfs` method is a function that
|
|
2060
|
+
* determines whether the left child of a node should be visited during the Depth-First Search
|
|
2061
|
+
* traversal. By default, it checks if the node is not null or undefined before visiting the left
|
|
2062
|
+
* child. You can customize this behavior
|
|
2063
|
+
* @param shouldVisitRight - The `shouldVisitRight` parameter in the `_dfs` method is a function that
|
|
2064
|
+
* determines whether to visit the right child node of the current node during a depth-first search
|
|
2065
|
+
* traversal. The default implementation of this function checks if the node is not null or undefined
|
|
2066
|
+
* before deciding to visit it.
|
|
2067
|
+
* @param shouldVisitRoot - The `shouldVisitRoot` parameter in the `_dfs` method is a function that
|
|
2068
|
+
* determines whether a given node should be visited during the depth-first search traversal. The
|
|
2069
|
+
* function takes a node as an argument and returns a boolean value indicating whether the node
|
|
2070
|
+
* should be visited.
|
|
2071
|
+
* @param shouldProcessRoot - The `shouldProcessRoot` parameter in the `_dfs` method is a function
|
|
2072
|
+
* that determines whether the root node should be processed during the Depth-First Search traversal.
|
|
2073
|
+
* It takes a node (BinaryTreeNode<K, V> | null | undefined) as input and returns a boolean value. If
|
|
2074
|
+
* the function
|
|
2075
|
+
* @returns The `_dfs` method returns an array of the return type of the provided callback function
|
|
2076
|
+
* `C`.
|
|
1900
2077
|
*/
|
|
1901
|
-
protected _dfs<C extends NodeCallback<
|
|
2078
|
+
protected _dfs<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
|
|
1902
2079
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1903
2080
|
pattern: DFSOrderPattern = 'IN',
|
|
1904
|
-
|
|
2081
|
+
onlyOne: boolean = false,
|
|
2082
|
+
startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
|
|
1905
2083
|
iterationType: IterationType = this.iterationType,
|
|
1906
2084
|
includeNull = false,
|
|
1907
|
-
shouldVisitLeft: (node:
|
|
1908
|
-
shouldVisitRight: (node:
|
|
1909
|
-
shouldVisitRoot: (node:
|
|
2085
|
+
shouldVisitLeft: (node: BinaryTreeNode<K, V> | null | undefined) => boolean = node => !!node,
|
|
2086
|
+
shouldVisitRight: (node: BinaryTreeNode<K, V> | null | undefined) => boolean = node => !!node,
|
|
2087
|
+
shouldVisitRoot: (node: BinaryTreeNode<K, V> | null | undefined) => boolean = node => {
|
|
1910
2088
|
if (includeNull) return this.isRealNodeOrNull(node);
|
|
1911
2089
|
return this.isRealNode(node);
|
|
1912
2090
|
},
|
|
1913
|
-
shouldProcessRoot: (node:
|
|
2091
|
+
shouldProcessRoot: (node: BinaryTreeNode<K, V> | null | undefined) => boolean = node => this.isRealNodeOrNull(node)
|
|
1914
2092
|
): ReturnType<C>[] {
|
|
1915
2093
|
startNode = this.ensureNode(startNode);
|
|
1916
2094
|
if (!startNode) return [];
|
|
1917
2095
|
const ans: ReturnType<C>[] = [];
|
|
1918
2096
|
|
|
1919
2097
|
if (iterationType === 'RECURSIVE') {
|
|
1920
|
-
const dfs = (node:
|
|
2098
|
+
const dfs = (node: BinaryTreeNode<K, V> | null) => {
|
|
1921
2099
|
if (!shouldVisitRoot(node)) return;
|
|
1922
2100
|
|
|
1923
2101
|
const visitLeft = () => {
|
|
1924
|
-
if (shouldVisitLeft(node)) dfs(node?.left);
|
|
2102
|
+
if (shouldVisitLeft(node) && node?.left !== undefined) dfs(node?.left);
|
|
1925
2103
|
};
|
|
1926
2104
|
const visitRight = () => {
|
|
1927
|
-
if (shouldVisitRight(node)) dfs(node?.right);
|
|
2105
|
+
if (shouldVisitRight(node) && node?.right !== undefined) dfs(node?.right);
|
|
1928
2106
|
};
|
|
1929
2107
|
|
|
1930
2108
|
switch (pattern) {
|
|
1931
2109
|
case 'IN':
|
|
1932
2110
|
visitLeft();
|
|
1933
|
-
if (shouldProcessRoot(node))
|
|
2111
|
+
if (shouldProcessRoot(node)) {
|
|
2112
|
+
ans.push(callback(node));
|
|
2113
|
+
if (onlyOne) return;
|
|
2114
|
+
}
|
|
1934
2115
|
visitRight();
|
|
1935
2116
|
break;
|
|
1936
2117
|
case 'PRE':
|
|
1937
|
-
if (shouldProcessRoot(node))
|
|
2118
|
+
if (shouldProcessRoot(node)) {
|
|
2119
|
+
ans.push(callback(node));
|
|
2120
|
+
if (onlyOne) return;
|
|
2121
|
+
}
|
|
1938
2122
|
visitLeft();
|
|
1939
2123
|
visitRight();
|
|
1940
2124
|
break;
|
|
1941
2125
|
case 'POST':
|
|
1942
2126
|
visitLeft();
|
|
1943
2127
|
visitRight();
|
|
1944
|
-
if (shouldProcessRoot(node))
|
|
2128
|
+
if (shouldProcessRoot(node)) {
|
|
2129
|
+
ans.push(callback(node));
|
|
2130
|
+
if (onlyOne) return;
|
|
2131
|
+
}
|
|
1945
2132
|
break;
|
|
1946
2133
|
}
|
|
1947
2134
|
};
|
|
@@ -1965,7 +2152,10 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
1965
2152
|
if (cur === undefined) continue;
|
|
1966
2153
|
if (!shouldVisitRoot(cur.node)) continue;
|
|
1967
2154
|
if (cur.opt === DFSOperation.PROCESS) {
|
|
1968
|
-
if (shouldProcessRoot(cur.node)
|
|
2155
|
+
if (shouldProcessRoot(cur.node) && cur.node !== undefined) {
|
|
2156
|
+
ans.push(callback(cur.node));
|
|
2157
|
+
if (onlyOne) return ans;
|
|
2158
|
+
}
|
|
1969
2159
|
} else {
|
|
1970
2160
|
switch (pattern) {
|
|
1971
2161
|
case 'IN':
|
|
@@ -2010,8 +2200,8 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
2010
2200
|
if (!node) return;
|
|
2011
2201
|
|
|
2012
2202
|
if (this.iterationType === 'ITERATIVE') {
|
|
2013
|
-
const stack:
|
|
2014
|
-
let current:
|
|
2203
|
+
const stack: (BinaryTreeNode<K, V> | null | undefined)[] = [];
|
|
2204
|
+
let current: BinaryTreeNode<K, V> | null | undefined = node;
|
|
2015
2205
|
|
|
2016
2206
|
while (current || stack.length > 0) {
|
|
2017
2207
|
while (this.isRealNode(current)) {
|
|
@@ -2054,7 +2244,10 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
2054
2244
|
* information about how to display a node in a binary tree. The `NodeDisplayLayout` consists of four
|
|
2055
2245
|
* elements:
|
|
2056
2246
|
*/
|
|
2057
|
-
protected _displayAux(
|
|
2247
|
+
protected _displayAux(
|
|
2248
|
+
node: BinaryTreeNode<K, V> | null | undefined,
|
|
2249
|
+
options: BinaryTreePrintOptions
|
|
2250
|
+
): NodeDisplayLayout {
|
|
2058
2251
|
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
2059
2252
|
const emptyDisplayLayout = <NodeDisplayLayout>[['─'], 1, 0, 0];
|
|
2060
2253
|
|
|
@@ -2122,26 +2315,26 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
2122
2315
|
}
|
|
2123
2316
|
}
|
|
2124
2317
|
|
|
2125
|
-
protected _DEFAULT_NODE_CALLBACK = (node:
|
|
2318
|
+
protected _DEFAULT_NODE_CALLBACK = (node: BinaryTreeNode<K, V> | null | undefined) => (node ? node.key : undefined);
|
|
2126
2319
|
|
|
2127
2320
|
/**
|
|
2128
2321
|
* Time Complexity: O(1)
|
|
2129
2322
|
* Space Complexity: O(1)
|
|
2130
2323
|
*
|
|
2131
2324
|
* The _swapProperties function swaps key and value properties between two nodes in a binary tree.
|
|
2132
|
-
* @param {
|
|
2325
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } srcNode - The `srcNode` parameter in the
|
|
2133
2326
|
* `_swapProperties` method can be either a BTNRep object containing key and value
|
|
2134
2327
|
* properties, or it can be of type R.
|
|
2135
|
-
* @param {
|
|
2328
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } destNode - The `destNode` parameter in the
|
|
2136
2329
|
* `_swapProperties` method represents the node or entry where the properties will be swapped with
|
|
2137
|
-
* the `srcNode`. It can be of type `
|
|
2330
|
+
* the `srcNode`. It can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. The method ensures that
|
|
2138
2331
|
* both `srcNode
|
|
2139
2332
|
* @returns The `_swapProperties` method returns either the `destNode` with its key and value swapped
|
|
2140
2333
|
* with the `srcNode`, or `undefined` if either `srcNode` or `destNode` is falsy.
|
|
2141
2334
|
*/
|
|
2142
2335
|
protected _swapProperties(
|
|
2143
|
-
srcNode:
|
|
2144
|
-
destNode:
|
|
2336
|
+
srcNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
|
|
2337
|
+
destNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
|
|
2145
2338
|
): BinaryTreeNode<K, V> | undefined {
|
|
2146
2339
|
srcNode = this.ensureNode(srcNode);
|
|
2147
2340
|
destNode = this.ensureNode(destNode);
|
|
@@ -2201,45 +2394,67 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
2201
2394
|
*
|
|
2202
2395
|
* The function _setRoot sets the root node of a data structure while updating the parent reference
|
|
2203
2396
|
* of the previous root node.
|
|
2204
|
-
* @param v - The parameter `v` in the `_setRoot` method is of type `
|
|
2397
|
+
* @param v - The parameter `v` in the `_setRoot` method is of type `BinaryTreeNode<K, V> | null | undefined`, which means
|
|
2205
2398
|
* it can either be an optional `BinaryTreeNode<K, V>` type or `null`.
|
|
2206
2399
|
*/
|
|
2207
|
-
protected _setRoot(v:
|
|
2400
|
+
protected _setRoot(v: BinaryTreeNode<K, V> | null | undefined) {
|
|
2208
2401
|
if (v) {
|
|
2209
2402
|
v.parent = undefined;
|
|
2210
2403
|
}
|
|
2211
2404
|
this._root = v;
|
|
2212
2405
|
}
|
|
2213
2406
|
|
|
2407
|
+
protected _ensurePredicate(
|
|
2408
|
+
keyNodeEntryOrPredicate:
|
|
2409
|
+
| K
|
|
2410
|
+
| BinaryTreeNode<K, V>
|
|
2411
|
+
| [K | null | undefined, V | undefined]
|
|
2412
|
+
| null
|
|
2413
|
+
| undefined
|
|
2414
|
+
| NodePredicate<BinaryTreeNode<K, V>>
|
|
2415
|
+
): NodePredicate<BinaryTreeNode<K, V>>;
|
|
2416
|
+
|
|
2214
2417
|
/**
|
|
2215
2418
|
* Time Complexity: O(1)
|
|
2216
2419
|
* Space Complexity: O(1)
|
|
2217
2420
|
*
|
|
2218
2421
|
* The function `_ensurePredicate` in TypeScript ensures that the input is converted into a valid
|
|
2219
2422
|
* predicate function for a binary tree node.
|
|
2220
|
-
* @param {
|
|
2423
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate - The
|
|
2221
2424
|
* `_ensurePredicate` method in the provided code snippet is responsible for ensuring that the input
|
|
2222
2425
|
* parameter `keyNodeEntryOrPredicate` is transformed into a valid predicate function that can be
|
|
2223
2426
|
* used for filtering nodes in a binary tree.
|
|
2224
2427
|
* @returns A NodePredicate<BinaryTreeNode<K, V>> function is being returned.
|
|
2225
2428
|
*/
|
|
2226
2429
|
protected _ensurePredicate(
|
|
2227
|
-
keyNodeEntryOrPredicate:
|
|
2228
|
-
|
|
2430
|
+
keyNodeEntryOrPredicate:
|
|
2431
|
+
| K
|
|
2432
|
+
| BinaryTreeNode<K, V>
|
|
2433
|
+
| [K | null | undefined, V | undefined]
|
|
2434
|
+
| null
|
|
2435
|
+
| undefined
|
|
2436
|
+
| NodePredicate<BinaryTreeNode<K, V> | null>
|
|
2437
|
+
): NodePredicate<BinaryTreeNode<K, V> | null> {
|
|
2229
2438
|
if (keyNodeEntryOrPredicate === null || keyNodeEntryOrPredicate === undefined)
|
|
2230
|
-
return (node: BinaryTreeNode<K, V>) => (node ? false : false);
|
|
2439
|
+
return (node: BinaryTreeNode<K, V> | null | undefined) => (node ? false : false);
|
|
2231
2440
|
|
|
2232
2441
|
if (this._isPredicate(keyNodeEntryOrPredicate)) return keyNodeEntryOrPredicate;
|
|
2233
2442
|
|
|
2234
2443
|
if (this.isRealNode(keyNodeEntryOrPredicate))
|
|
2235
|
-
return (node: BinaryTreeNode<K, V>) => node === keyNodeEntryOrPredicate;
|
|
2444
|
+
return (node: BinaryTreeNode<K, V> | null) => node === keyNodeEntryOrPredicate;
|
|
2236
2445
|
|
|
2237
2446
|
if (this.isEntry(keyNodeEntryOrPredicate)) {
|
|
2238
2447
|
const [key] = keyNodeEntryOrPredicate;
|
|
2239
|
-
return (node: BinaryTreeNode<K, V>) =>
|
|
2448
|
+
return (node: BinaryTreeNode<K, V> | null) => {
|
|
2449
|
+
if (!node) return false;
|
|
2450
|
+
return node.key === key;
|
|
2451
|
+
};
|
|
2240
2452
|
}
|
|
2241
2453
|
|
|
2242
|
-
return (node: BinaryTreeNode<K, V>) =>
|
|
2454
|
+
return (node: BinaryTreeNode<K, V> | null) => {
|
|
2455
|
+
if (!node) return false;
|
|
2456
|
+
return node.key === keyNodeEntryOrPredicate;
|
|
2457
|
+
};
|
|
2243
2458
|
}
|
|
2244
2459
|
|
|
2245
2460
|
/**
|
|
@@ -2264,14 +2479,16 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|
|
2264
2479
|
*
|
|
2265
2480
|
* The function `_extractKey` in TypeScript returns the key from a given input, which can be a node,
|
|
2266
2481
|
* entry, raw data, or null/undefined.
|
|
2267
|
-
* @param {
|
|
2268
|
-
* TypeScript method that takes in a parameter `keyNodeOrEntry` of type `
|
|
2482
|
+
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `_extractKey` method you provided is a
|
|
2483
|
+
* TypeScript method that takes in a parameter `keyNodeOrEntry` of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `,
|
|
2269
2484
|
* where `BTNRep` is a generic type with keys `K`, `V`, and `BinaryTreeNode<K, V>`, and `
|
|
2270
2485
|
* @returns The `_extractKey` method returns the key value extracted from the `keyNodeOrEntry`
|
|
2271
2486
|
* parameter. The return value can be a key value of type `K`, `null`, or `undefined`, depending on
|
|
2272
2487
|
* the conditions checked in the method.
|
|
2273
2488
|
*/
|
|
2274
|
-
protected _extractKey(
|
|
2489
|
+
protected _extractKey(
|
|
2490
|
+
keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
|
|
2491
|
+
): K | null | undefined {
|
|
2275
2492
|
if (keyNodeOrEntry === null) return null;
|
|
2276
2493
|
if (keyNodeOrEntry === undefined) return;
|
|
2277
2494
|
if (keyNodeOrEntry === this._NIL) return;
|