min-heap-typed 1.42.5 → 1.42.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/data-structures/binary-tree/avl-tree.d.ts +5 -5
- package/dist/data-structures/binary-tree/avl-tree.js +19 -14
- package/dist/data-structures/binary-tree/binary-tree.d.ts +108 -60
- package/dist/data-structures/binary-tree/binary-tree.js +189 -89
- package/dist/data-structures/binary-tree/bst.d.ts +30 -8
- package/dist/data-structures/binary-tree/bst.js +77 -28
- package/dist/data-structures/binary-tree/rb-tree.d.ts +35 -28
- package/dist/data-structures/binary-tree/rb-tree.js +44 -45
- package/dist/data-structures/binary-tree/tree-multimap.d.ts +7 -12
- package/dist/data-structures/binary-tree/tree-multimap.js +38 -37
- package/dist/interfaces/binary-tree.d.ts +2 -2
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +1 -1
- package/dist/types/data-structures/binary-tree/binary-tree.js +6 -0
- package/dist/types/data-structures/binary-tree/rb-tree.d.ts +2 -2
- package/package.json +3 -3
- package/src/data-structures/binary-tree/avl-tree.ts +24 -18
- package/src/data-structures/binary-tree/binary-tree.ts +248 -142
- package/src/data-structures/binary-tree/bst.ts +88 -38
- package/src/data-structures/binary-tree/rb-tree.ts +52 -58
- package/src/data-structures/binary-tree/tree-multimap.ts +50 -54
- package/src/interfaces/binary-tree.ts +2 -2
- package/src/types/data-structures/binary-tree/binary-tree.ts +7 -1
- package/src/types/data-structures/binary-tree/rb-tree.ts +2 -2
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import type {BinaryTreeNodeNested, BinaryTreeOptions, BTNCallback, BTNKey} from '../../types';
|
|
10
|
-
import {
|
|
10
|
+
import {BiTreeDeleteResult, DFSOrderPattern, FamilyPosition, IterationType} from '../../types';
|
|
11
11
|
import {IBinaryTree} from '../../interfaces';
|
|
12
12
|
import {trampoline} from '../../utils';
|
|
13
13
|
import {Queue} from '../queue';
|
|
@@ -26,12 +26,12 @@ export class BinaryTreeNode<V = any, N extends BinaryTreeNode<V, N> = BinaryTree
|
|
|
26
26
|
/**
|
|
27
27
|
* The value stored in the node.
|
|
28
28
|
*/
|
|
29
|
-
value
|
|
29
|
+
value?: V;
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
32
|
* The parent node of the current node.
|
|
33
33
|
*/
|
|
34
|
-
parent
|
|
34
|
+
parent?: N | null;
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
37
|
* Creates a new instance of BinaryTreeNode.
|
|
@@ -43,7 +43,7 @@ export class BinaryTreeNode<V = any, N extends BinaryTreeNode<V, N> = BinaryTree
|
|
|
43
43
|
this.value = value;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
protected _left
|
|
46
|
+
protected _left?: N | null;
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
49
|
* Get the left child node.
|
|
@@ -63,7 +63,7 @@ export class BinaryTreeNode<V = any, N extends BinaryTreeNode<V, N> = BinaryTree
|
|
|
63
63
|
this._left = v;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
protected _right
|
|
66
|
+
protected _right?: N | null;
|
|
67
67
|
|
|
68
68
|
/**
|
|
69
69
|
* Get the right child node.
|
|
@@ -117,13 +117,14 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
117
117
|
* @param {BinaryTreeOptions} [options] - The options for the binary tree.
|
|
118
118
|
*/
|
|
119
119
|
constructor(options?: BinaryTreeOptions) {
|
|
120
|
-
if (options
|
|
120
|
+
if (options) {
|
|
121
121
|
const {iterationType = IterationType.ITERATIVE} = options;
|
|
122
122
|
this.iterationType = iterationType;
|
|
123
123
|
}
|
|
124
|
+
this._size = 0;
|
|
124
125
|
}
|
|
125
126
|
|
|
126
|
-
protected _root
|
|
127
|
+
protected _root?: N | null;
|
|
127
128
|
|
|
128
129
|
/**
|
|
129
130
|
* Get the root node of the binary tree.
|
|
@@ -132,7 +133,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
132
133
|
return this._root;
|
|
133
134
|
}
|
|
134
135
|
|
|
135
|
-
protected _size
|
|
136
|
+
protected _size: number;
|
|
136
137
|
|
|
137
138
|
/**
|
|
138
139
|
* Get the number of nodes in the binary tree.
|
|
@@ -151,22 +152,6 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
151
152
|
return new BinaryTreeNode<V, N>(key, value) as N;
|
|
152
153
|
}
|
|
153
154
|
|
|
154
|
-
/**
|
|
155
|
-
* Clear the binary tree, removing all nodes.
|
|
156
|
-
*/
|
|
157
|
-
clear() {
|
|
158
|
-
this._setRoot(undefined);
|
|
159
|
-
this._size = 0;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* Check if the binary tree is empty.
|
|
164
|
-
* @returns {boolean} - True if the binary tree is empty, false otherwise.
|
|
165
|
-
*/
|
|
166
|
-
isEmpty(): boolean {
|
|
167
|
-
return this.size === 0;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
155
|
/**
|
|
171
156
|
* Add a node with the given key and value to the binary tree.
|
|
172
157
|
* @param {BTNKey | N | null} keyOrNode - The key or node to add to the binary tree.
|
|
@@ -192,11 +177,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
192
177
|
return;
|
|
193
178
|
};
|
|
194
179
|
|
|
195
|
-
let inserted: N | null | undefined, needInsert: N | null;
|
|
180
|
+
let inserted: N | null | undefined, needInsert: N | null | undefined;
|
|
196
181
|
|
|
197
182
|
if (keyOrNode === null) {
|
|
198
183
|
needInsert = null;
|
|
199
|
-
} else if (
|
|
184
|
+
} else if (this.isNodeKey(keyOrNode)) {
|
|
200
185
|
needInsert = this.createNode(keyOrNode, value);
|
|
201
186
|
} else if (keyOrNode instanceof BinaryTreeNode) {
|
|
202
187
|
needInsert = keyOrNode;
|
|
@@ -204,19 +189,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
204
189
|
return;
|
|
205
190
|
}
|
|
206
191
|
|
|
207
|
-
// const key = typeof keyOrNode === 'number' ? keyOrNode : keyOrNode ? keyOrNode.key : undefined;
|
|
208
|
-
// const existNode = key !== undefined ? this.getNode(key, (node: N) => node.key) : undefined;
|
|
209
|
-
|
|
210
192
|
if (this.root) {
|
|
211
|
-
// if (existNode) {
|
|
212
|
-
// existNode.value = value;
|
|
213
|
-
// inserted = existNode;
|
|
214
|
-
// } else {
|
|
215
193
|
inserted = _bfs(this.root, needInsert);
|
|
216
|
-
// }
|
|
217
194
|
} else {
|
|
218
195
|
this._setRoot(needInsert);
|
|
219
|
-
if (needInsert
|
|
196
|
+
if (needInsert) {
|
|
220
197
|
this._size = 1;
|
|
221
198
|
} else {
|
|
222
199
|
this._size = 0;
|
|
@@ -236,7 +213,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
236
213
|
* the value of the nodes will be `undefined`.
|
|
237
214
|
* @returns The function `addMany` returns an array of `N`, `null`, or `undefined` values.
|
|
238
215
|
*/
|
|
239
|
-
addMany(keysOrNodes: (BTNKey |
|
|
216
|
+
addMany(keysOrNodes: (BTNKey | N |null | undefined)[], values?: (V | undefined)[]): (N | null | undefined)[] {
|
|
240
217
|
// TODO not sure addMany not be run multi times
|
|
241
218
|
return keysOrNodes.map((keyOrNode, i) => {
|
|
242
219
|
if (keyOrNode instanceof BinaryTreeNode) {
|
|
@@ -256,50 +233,50 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
256
233
|
* The `refill` function clears the binary tree and adds multiple nodes with the given IDs or nodes and optional data.
|
|
257
234
|
* @param {(BTNKey | N)[]} keysOrNodes - The `keysOrNodes` parameter is an array that can contain either
|
|
258
235
|
* `BTNKey` or `N` values.
|
|
259
|
-
* @param {N[] | Array<V>} [
|
|
236
|
+
* @param {N[] | Array<V>} [values] - The `data` parameter is an optional array of values that will be assigned to
|
|
260
237
|
* the nodes being added. If provided, the length of the `data` array should be equal to the length of the `keysOrNodes`
|
|
261
238
|
* array. Each value in the `data` array will be assigned to the
|
|
262
239
|
* @returns The method is returning a boolean value.
|
|
263
240
|
*/
|
|
264
|
-
refill(keysOrNodes: (BTNKey | null | undefined)[]
|
|
241
|
+
refill(keysOrNodes: (BTNKey | N | null | undefined)[], values?: (V | undefined)[]): boolean {
|
|
265
242
|
this.clear();
|
|
266
|
-
return keysOrNodes.length === this.addMany(keysOrNodes,
|
|
243
|
+
return keysOrNodes.length === this.addMany(keysOrNodes, values).length;
|
|
267
244
|
}
|
|
268
245
|
|
|
269
|
-
delete<C extends BTNCallback<N, BTNKey>>(identifier: BTNKey, callback?: C):
|
|
246
|
+
delete<C extends BTNCallback<N, BTNKey>>(identifier: BTNKey, callback?: C): BiTreeDeleteResult<N>[];
|
|
270
247
|
|
|
271
|
-
delete<C extends BTNCallback<N, N>>(identifier: N | null | undefined, callback?: C):
|
|
248
|
+
delete<C extends BTNCallback<N, N>>(identifier: N | null | undefined, callback?: C): BiTreeDeleteResult<N>[];
|
|
272
249
|
|
|
273
|
-
delete<C extends BTNCallback<N>>(identifier: ReturnType<C>, callback: C):
|
|
250
|
+
delete<C extends BTNCallback<N>>(identifier: ReturnType<C>, callback: C): BiTreeDeleteResult<N>[];
|
|
274
251
|
|
|
275
252
|
/**
|
|
276
253
|
* The `delete` function removes a node from a binary search tree and returns the deleted node along
|
|
277
254
|
* with the parent node that needs to be balanced.
|
|
278
255
|
* a key (`BTNKey`). If it is a key, the function will find the corresponding node in the
|
|
279
256
|
* binary tree.
|
|
280
|
-
* @returns an array of `
|
|
257
|
+
* @returns an array of `BiTreeDeleteResult<N>` objects.
|
|
281
258
|
* @param {ReturnType<C>} identifier - The `identifier` parameter is either a
|
|
282
259
|
* `BTNKey` or a generic type `N`. It represents the property of the node that we are
|
|
283
260
|
* searching for. It can be a specific key value or any other property of the node.
|
|
284
261
|
* @param callback - The `callback` parameter is a function that takes a node as input and returns a
|
|
285
262
|
* value. This value is compared with the `identifier` parameter to determine if the node should be
|
|
286
263
|
* included in the result. The `callback` parameter has a default value of
|
|
287
|
-
* `this.
|
|
264
|
+
* `this._defaultOneParamCallback`, which
|
|
288
265
|
*/
|
|
289
266
|
delete<C extends BTNCallback<N>>(
|
|
290
267
|
identifier: ReturnType<C> | null | undefined,
|
|
291
|
-
callback: C = this.
|
|
292
|
-
):
|
|
293
|
-
const
|
|
294
|
-
if (!this.root) return
|
|
268
|
+
callback: C = this._defaultOneParamCallback as C
|
|
269
|
+
): BiTreeDeleteResult<N>[] {
|
|
270
|
+
const deletedResult: BiTreeDeleteResult<N>[] = [];
|
|
271
|
+
if (!this.root) return deletedResult;
|
|
295
272
|
if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;
|
|
296
273
|
|
|
297
274
|
const curr = this.getNode(identifier, callback);
|
|
298
|
-
if (!curr) return
|
|
275
|
+
if (!curr) return deletedResult;
|
|
299
276
|
|
|
300
277
|
const parent: N | null | undefined = curr?.parent ? curr.parent : null;
|
|
301
|
-
let needBalanced: N | null | undefined =
|
|
302
|
-
|
|
278
|
+
let needBalanced: N | null | undefined = undefined;
|
|
279
|
+
let orgCurrent: N | undefined = curr;
|
|
303
280
|
|
|
304
281
|
if (!curr.left) {
|
|
305
282
|
if (!parent) {
|
|
@@ -329,8 +306,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
329
306
|
}
|
|
330
307
|
this._size = this.size - 1;
|
|
331
308
|
|
|
332
|
-
|
|
333
|
-
return
|
|
309
|
+
deletedResult.push({deleted: orgCurrent, needBalanced});
|
|
310
|
+
return deletedResult;
|
|
334
311
|
}
|
|
335
312
|
|
|
336
313
|
/**
|
|
@@ -346,8 +323,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
346
323
|
* @returns the depth of the `distNode` relative to the `beginRoot`.
|
|
347
324
|
*/
|
|
348
325
|
getDepth(distNode: BTNKey | N | null | undefined, beginRoot: BTNKey | N | null | undefined = this.root): number {
|
|
349
|
-
|
|
350
|
-
|
|
326
|
+
distNode = this.ensureNotKey(distNode);
|
|
327
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
351
328
|
let depth = 0;
|
|
352
329
|
while (distNode?.parent) {
|
|
353
330
|
if (distNode === beginRoot) {
|
|
@@ -372,7 +349,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
372
349
|
* @returns the height of the binary tree.
|
|
373
350
|
*/
|
|
374
351
|
getHeight(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.iterationType): number {
|
|
375
|
-
|
|
352
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
376
353
|
if (!beginRoot) return -1;
|
|
377
354
|
|
|
378
355
|
if (iterationType === IterationType.RECURSIVE) {
|
|
@@ -395,14 +372,9 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
395
372
|
while (stack.length > 0) {
|
|
396
373
|
const {node, depth} = stack.pop()!;
|
|
397
374
|
|
|
398
|
-
if (node.left) {
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
if (node.right) {
|
|
403
|
-
stack.push({node: node.right, depth: depth + 1});
|
|
404
|
-
}
|
|
405
|
-
|
|
375
|
+
if (node.left) stack.push({node: node.left, depth: depth + 1});
|
|
376
|
+
if (node.right) stack.push({node: node.right, depth: depth + 1});
|
|
377
|
+
|
|
406
378
|
maxHeight = Math.max(maxHeight, depth);
|
|
407
379
|
}
|
|
408
380
|
|
|
@@ -420,9 +392,10 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
420
392
|
* to calculate the minimum height of a binary tree. It can have two possible values:
|
|
421
393
|
* @returns The function `getMinHeight` returns the minimum height of a binary tree.
|
|
422
394
|
*/
|
|
423
|
-
getMinHeight(beginRoot: N | null | undefined = this.root, iterationType = this.iterationType): number {
|
|
395
|
+
getMinHeight(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.iterationType): number {
|
|
396
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
424
397
|
if (!beginRoot) return -1;
|
|
425
|
-
|
|
398
|
+
|
|
426
399
|
if (iterationType === IterationType.RECURSIVE) {
|
|
427
400
|
const _getMinHeight = (cur: N | null | undefined): number => {
|
|
428
401
|
if (!cur) return 0;
|
|
@@ -469,7 +442,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
469
442
|
* either be of type `N` (representing a node in a tree) or `null` (representing an empty tree).
|
|
470
443
|
* @returns The method is returning a boolean value.
|
|
471
444
|
*/
|
|
472
|
-
isPerfectlyBalanced(beginRoot: N | null | undefined = this.root): boolean {
|
|
445
|
+
isPerfectlyBalanced(beginRoot: BTNKey | N | null | undefined = this.root): boolean {
|
|
473
446
|
return this.getMinHeight(beginRoot) + 1 >= this.getHeight(beginRoot);
|
|
474
447
|
}
|
|
475
448
|
|
|
@@ -477,7 +450,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
477
450
|
identifier: BTNKey,
|
|
478
451
|
callback?: C,
|
|
479
452
|
onlyOne?: boolean,
|
|
480
|
-
beginRoot?: N | null | undefined,
|
|
453
|
+
beginRoot?: BTNKey | N | null | undefined,
|
|
481
454
|
iterationType?: IterationType
|
|
482
455
|
): N[];
|
|
483
456
|
|
|
@@ -485,7 +458,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
485
458
|
identifier: N | null | undefined,
|
|
486
459
|
callback?: C,
|
|
487
460
|
onlyOne?: boolean,
|
|
488
|
-
beginRoot?: N | null | undefined,
|
|
461
|
+
beginRoot?: BTNKey | N | null | undefined,
|
|
489
462
|
iterationType?: IterationType
|
|
490
463
|
): N[];
|
|
491
464
|
|
|
@@ -493,7 +466,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
493
466
|
identifier: ReturnType<C>,
|
|
494
467
|
callback: C,
|
|
495
468
|
onlyOne?: boolean,
|
|
496
|
-
beginRoot?: N | null | undefined,
|
|
469
|
+
beginRoot?: BTNKey | N | null | undefined,
|
|
497
470
|
iterationType?: IterationType
|
|
498
471
|
): N[];
|
|
499
472
|
|
|
@@ -506,7 +479,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
506
479
|
* @param callback - The `callback` parameter is a function that takes a node as input and returns a
|
|
507
480
|
* value. This value is compared with the `identifier` parameter to determine if the node should be
|
|
508
481
|
* included in the result. The `callback` parameter has a default value of
|
|
509
|
-
* `this.
|
|
482
|
+
* `this._defaultOneParamCallback`, which
|
|
510
483
|
* @param [onlyOne=false] - A boolean value indicating whether to stop searching after finding the
|
|
511
484
|
* first node that matches the identifier. If set to true, the function will return an array with
|
|
512
485
|
* only one element (or an empty array if no matching node is found). If set to false (default), the
|
|
@@ -520,13 +493,16 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
520
493
|
*/
|
|
521
494
|
getNodes<C extends BTNCallback<N>>(
|
|
522
495
|
identifier: ReturnType<C> | null | undefined,
|
|
523
|
-
callback: C = this.
|
|
496
|
+
callback: C = this._defaultOneParamCallback as C,
|
|
524
497
|
onlyOne = false,
|
|
525
|
-
beginRoot: N | null | undefined = this.root,
|
|
498
|
+
beginRoot: BTNKey | N | null | undefined = this.root,
|
|
526
499
|
iterationType = this.iterationType
|
|
527
500
|
): N[] {
|
|
528
501
|
if (!beginRoot) return [];
|
|
529
502
|
if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;
|
|
503
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
504
|
+
if (!beginRoot) return [];
|
|
505
|
+
|
|
530
506
|
const ans: N[] = [];
|
|
531
507
|
|
|
532
508
|
if (iterationType === IterationType.RECURSIVE) {
|
|
@@ -562,21 +538,21 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
562
538
|
has<C extends BTNCallback<N, BTNKey>>(
|
|
563
539
|
identifier: BTNKey,
|
|
564
540
|
callback?: C,
|
|
565
|
-
beginRoot?: N | null | undefined,
|
|
541
|
+
beginRoot?: BTNKey | N | null | undefined,
|
|
566
542
|
iterationType?: IterationType
|
|
567
543
|
): boolean;
|
|
568
544
|
|
|
569
545
|
has<C extends BTNCallback<N, N>>(
|
|
570
546
|
identifier: N | null | undefined,
|
|
571
547
|
callback?: C,
|
|
572
|
-
beginRoot?: N | null | undefined,
|
|
548
|
+
beginRoot?: BTNKey | N | null | undefined,
|
|
573
549
|
iterationType?: IterationType
|
|
574
550
|
): boolean;
|
|
575
551
|
|
|
576
552
|
has<C extends BTNCallback<N>>(
|
|
577
553
|
identifier: ReturnType<C> | null | undefined,
|
|
578
554
|
callback: C,
|
|
579
|
-
beginRoot?: N | null | undefined,
|
|
555
|
+
beginRoot?: BTNKey | N | null | undefined,
|
|
580
556
|
iterationType?: IterationType
|
|
581
557
|
): boolean;
|
|
582
558
|
|
|
@@ -588,7 +564,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
588
564
|
* @param callback - The `callback` parameter is a function that is used to determine whether a node
|
|
589
565
|
* matches the desired criteria. It takes a node as input and returns a boolean value indicating
|
|
590
566
|
* whether the node matches the criteria or not. The default callback function
|
|
591
|
-
* `this.
|
|
567
|
+
* `this._defaultOneParamCallback` is used if no callback function is
|
|
592
568
|
* @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies
|
|
593
569
|
* the node from which the search should begin. By default, it is set to `this.root`, which means the
|
|
594
570
|
* search will start from the root node of the binary tree. However, you can provide a different node
|
|
@@ -599,8 +575,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
599
575
|
*/
|
|
600
576
|
has<C extends BTNCallback<N>>(
|
|
601
577
|
identifier: ReturnType<C> | null | undefined,
|
|
602
|
-
callback: C = this.
|
|
603
|
-
beginRoot = this.root,
|
|
578
|
+
callback: C = this._defaultOneParamCallback as C,
|
|
579
|
+
beginRoot: BTNKey | N | null | undefined = this.root,
|
|
604
580
|
iterationType = this.iterationType
|
|
605
581
|
): boolean {
|
|
606
582
|
if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;
|
|
@@ -611,21 +587,21 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
611
587
|
getNode<C extends BTNCallback<N, BTNKey>>(
|
|
612
588
|
identifier: BTNKey,
|
|
613
589
|
callback?: C,
|
|
614
|
-
beginRoot?: N | null | undefined,
|
|
590
|
+
beginRoot?: BTNKey | N | null | undefined,
|
|
615
591
|
iterationType?: IterationType
|
|
616
592
|
): N | null | undefined;
|
|
617
593
|
|
|
618
594
|
getNode<C extends BTNCallback<N, N>>(
|
|
619
595
|
identifier: N | null | undefined,
|
|
620
596
|
callback?: C,
|
|
621
|
-
beginRoot?: N | null | undefined,
|
|
597
|
+
beginRoot?: BTNKey | N | null | undefined,
|
|
622
598
|
iterationType?: IterationType
|
|
623
599
|
): N | null | undefined;
|
|
624
600
|
|
|
625
601
|
getNode<C extends BTNCallback<N>>(
|
|
626
602
|
identifier: ReturnType<C>,
|
|
627
603
|
callback: C,
|
|
628
|
-
beginRoot?: N | null | undefined,
|
|
604
|
+
beginRoot?: BTNKey | N | null | undefined,
|
|
629
605
|
iterationType?: IterationType
|
|
630
606
|
): N | null | undefined;
|
|
631
607
|
|
|
@@ -637,7 +613,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
637
613
|
* @param callback - The `callback` parameter is a function that is used to determine whether a node
|
|
638
614
|
* matches the desired criteria. It takes a node as input and returns a boolean value indicating
|
|
639
615
|
* whether the node matches the criteria or not. The default callback function
|
|
640
|
-
* (`this.
|
|
616
|
+
* (`this._defaultOneParamCallback`) is used if no callback function is
|
|
641
617
|
* @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies
|
|
642
618
|
* the root node from which the search should begin.
|
|
643
619
|
* @param iterationType - The `iterationType` parameter specifies the type of iteration to be
|
|
@@ -646,8 +622,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
646
622
|
*/
|
|
647
623
|
getNode<C extends BTNCallback<N>>(
|
|
648
624
|
identifier: ReturnType<C> | null | undefined,
|
|
649
|
-
callback: C = this.
|
|
650
|
-
beginRoot = this.root,
|
|
625
|
+
callback: C = this._defaultOneParamCallback as C,
|
|
626
|
+
beginRoot: BTNKey | N | null | undefined = this.root,
|
|
651
627
|
iterationType = this.iterationType
|
|
652
628
|
): N | null | undefined {
|
|
653
629
|
if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;
|
|
@@ -655,24 +631,75 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
655
631
|
return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? null;
|
|
656
632
|
}
|
|
657
633
|
|
|
634
|
+
/**
|
|
635
|
+
* The function `getNodeByKey` searches for a node in a binary tree by its key, using either
|
|
636
|
+
* recursive or iterative iteration.
|
|
637
|
+
* @param {BTNKey} key - The `key` parameter is the key value that we are searching for in the tree.
|
|
638
|
+
* It is used to find the node with the matching key value.
|
|
639
|
+
* @param iterationType - The `iterationType` parameter is used to determine whether the search for
|
|
640
|
+
* the node with the given key should be performed iteratively or recursively. It has two possible
|
|
641
|
+
* values:
|
|
642
|
+
* @returns The function `getNodeByKey` returns a node (`N`) if a node with the specified key is
|
|
643
|
+
* found in the binary tree. If no node is found, it returns `undefined`.
|
|
644
|
+
*/
|
|
645
|
+
getNodeByKey(key: BTNKey, iterationType = IterationType.ITERATIVE): N | undefined {
|
|
646
|
+
if (!this.root) return undefined;
|
|
647
|
+
if (iterationType === IterationType.RECURSIVE) {
|
|
648
|
+
const _dfs = (cur: N): N | undefined => {
|
|
649
|
+
if (cur.key === key) return cur;
|
|
650
|
+
|
|
651
|
+
if (!cur.left && !cur.right) return;
|
|
652
|
+
if (cur.left) return _dfs(cur.left);
|
|
653
|
+
if (cur.right) return _dfs(cur.right);
|
|
654
|
+
};
|
|
655
|
+
|
|
656
|
+
return _dfs(this.root);
|
|
657
|
+
} else {
|
|
658
|
+
const queue = new Queue<N>([this.root]);
|
|
659
|
+
while (queue.size > 0) {
|
|
660
|
+
const cur = queue.shift();
|
|
661
|
+
if (cur) {
|
|
662
|
+
if (cur.key === key) return cur;
|
|
663
|
+
cur.left && queue.push(cur.left);
|
|
664
|
+
cur.right && queue.push(cur.right);
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
/**
|
|
671
|
+
* The function `ensureNotKey` returns the node corresponding to the given key if it is a valid node
|
|
672
|
+
* key, otherwise it returns the key itself.
|
|
673
|
+
* @param {BTNKey | N | null | undefined} key - The `key` parameter can be of type `BTNKey`, `N`,
|
|
674
|
+
* `null`, or `undefined`. It represents a key used to identify a node in a binary tree.
|
|
675
|
+
* @param iterationType - The `iterationType` parameter is an optional parameter that specifies the
|
|
676
|
+
* type of iteration to be used when searching for a node by key. It has a default value of
|
|
677
|
+
* `IterationType.ITERATIVE`.
|
|
678
|
+
* @returns either the node corresponding to the given key if it is a valid node key, or the key
|
|
679
|
+
* itself if it is not a valid node key.
|
|
680
|
+
*/
|
|
681
|
+
ensureNotKey(key: BTNKey | N | null | undefined, iterationType = IterationType.ITERATIVE): N | null | undefined {
|
|
682
|
+
return this.isNodeKey(key) ? this.getNodeByKey(key, iterationType) : key;
|
|
683
|
+
}
|
|
684
|
+
|
|
658
685
|
get<C extends BTNCallback<N, BTNKey>>(
|
|
659
686
|
identifier: BTNKey,
|
|
660
687
|
callback?: C,
|
|
661
|
-
beginRoot?: N | null | undefined,
|
|
688
|
+
beginRoot?: BTNKey | N | null | undefined,
|
|
662
689
|
iterationType?: IterationType
|
|
663
690
|
): V | undefined;
|
|
664
691
|
|
|
665
692
|
get<C extends BTNCallback<N, N>>(
|
|
666
693
|
identifier: N | null | undefined,
|
|
667
694
|
callback?: C,
|
|
668
|
-
beginRoot?: N | null | undefined,
|
|
695
|
+
beginRoot?: BTNKey | N | null | undefined,
|
|
669
696
|
iterationType?: IterationType
|
|
670
697
|
): V | undefined;
|
|
671
698
|
|
|
672
699
|
get<C extends BTNCallback<N>>(
|
|
673
700
|
identifier: ReturnType<C>,
|
|
674
701
|
callback: C,
|
|
675
|
-
beginRoot?: N | null | undefined,
|
|
702
|
+
beginRoot?: BTNKey | N | null | undefined,
|
|
676
703
|
iterationType?: IterationType
|
|
677
704
|
): V | undefined;
|
|
678
705
|
|
|
@@ -684,7 +711,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
684
711
|
* @param callback - The `callback` parameter is a function that is used to determine whether a node
|
|
685
712
|
* matches the desired criteria. It takes a node as input and returns a boolean value indicating
|
|
686
713
|
* whether the node matches the criteria or not. The default callback function
|
|
687
|
-
* (`this.
|
|
714
|
+
* (`this._defaultOneParamCallback`) is used if no callback function is
|
|
688
715
|
* @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies
|
|
689
716
|
* the root node from which the search should begin.
|
|
690
717
|
* @param iterationType - The `iterationType` parameter specifies the type of iteration to be
|
|
@@ -693,15 +720,31 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
693
720
|
*/
|
|
694
721
|
get<C extends BTNCallback<N>>(
|
|
695
722
|
identifier: ReturnType<C> | null | undefined,
|
|
696
|
-
callback: C = this.
|
|
697
|
-
beginRoot = this.root,
|
|
723
|
+
callback: C = this._defaultOneParamCallback as C,
|
|
724
|
+
beginRoot:BTNKey | N | null | undefined = this.root,
|
|
698
725
|
iterationType = this.iterationType
|
|
699
726
|
): V | undefined {
|
|
700
727
|
if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;
|
|
701
728
|
|
|
702
729
|
return this.getNode(identifier, callback, beginRoot, iterationType)?.value ?? undefined;
|
|
703
730
|
}
|
|
731
|
+
|
|
732
|
+
/**
|
|
733
|
+
* Clear the binary tree, removing all nodes.
|
|
734
|
+
*/
|
|
735
|
+
clear() {
|
|
736
|
+
this._setRoot(undefined);
|
|
737
|
+
this._size = 0;
|
|
738
|
+
}
|
|
704
739
|
|
|
740
|
+
/**
|
|
741
|
+
* Check if the binary tree is empty.
|
|
742
|
+
* @returns {boolean} - True if the binary tree is empty, false otherwise.
|
|
743
|
+
*/
|
|
744
|
+
isEmpty(): boolean {
|
|
745
|
+
return this.size === 0;
|
|
746
|
+
}
|
|
747
|
+
|
|
705
748
|
/**
|
|
706
749
|
* The function `getPathToRoot` returns an array of nodes starting from a given node and traversing
|
|
707
750
|
* up to the root node, with the option to reverse the order of the nodes.
|
|
@@ -712,9 +755,13 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
712
755
|
* reversed before returning it. If `isReverse` is set to `false` or not provided, the path will
|
|
713
756
|
* @returns The function `getPathToRoot` returns an array of type `N[]`.
|
|
714
757
|
*/
|
|
715
|
-
getPathToRoot(beginRoot: N, isReverse = true): N[] {
|
|
758
|
+
getPathToRoot(beginRoot: BTNKey | N | null | undefined, isReverse = true): N[] {
|
|
716
759
|
// TODO to support get path through passing key
|
|
717
760
|
const result: N[] = [];
|
|
761
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
762
|
+
|
|
763
|
+
if (!beginRoot) return result;
|
|
764
|
+
|
|
718
765
|
while (beginRoot.parent) {
|
|
719
766
|
// Array.push + Array.reverse is more efficient than Array.unshift
|
|
720
767
|
// TODO may consider using Deque, so far this is not the performance bottleneck
|
|
@@ -737,13 +784,13 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
737
784
|
* no leftmost node, it returns `null`.
|
|
738
785
|
*/
|
|
739
786
|
getLeftMost(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.iterationType): N | null | undefined {
|
|
740
|
-
|
|
787
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
741
788
|
|
|
742
789
|
if (!beginRoot) return beginRoot;
|
|
743
790
|
|
|
744
791
|
if (iterationType === IterationType.RECURSIVE) {
|
|
745
792
|
const _traverse = (cur: N): N => {
|
|
746
|
-
if (!cur.left) return cur;
|
|
793
|
+
if (!this.isRealNode(cur.left)) return cur;
|
|
747
794
|
return _traverse(cur.left);
|
|
748
795
|
};
|
|
749
796
|
|
|
@@ -751,7 +798,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
751
798
|
} else {
|
|
752
799
|
// Indirect implementation of iteration using tail recursion optimization
|
|
753
800
|
const _traverse = trampoline((cur: N) => {
|
|
754
|
-
if (!cur.left) return cur;
|
|
801
|
+
if (!this.isRealNode(cur.left)) return cur;
|
|
755
802
|
return _traverse.cont(cur.left);
|
|
756
803
|
});
|
|
757
804
|
|
|
@@ -770,13 +817,14 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
770
817
|
* @returns The function `getRightMost` returns the rightmost node (`N`) in a binary tree. If the
|
|
771
818
|
* `beginRoot` parameter is `null`, it returns `null`.
|
|
772
819
|
*/
|
|
773
|
-
getRightMost(beginRoot: N | null | undefined = this.root, iterationType = this.iterationType): N | null | undefined {
|
|
820
|
+
getRightMost(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.iterationType): N | null | undefined {
|
|
774
821
|
// TODO support get right most by passing key in
|
|
822
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
775
823
|
if (!beginRoot) return beginRoot;
|
|
776
824
|
|
|
777
825
|
if (iterationType === IterationType.RECURSIVE) {
|
|
778
826
|
const _traverse = (cur: N): N => {
|
|
779
|
-
if (!cur.right) return cur;
|
|
827
|
+
if (!this.isRealNode(cur.right)) return cur;
|
|
780
828
|
return _traverse(cur.right);
|
|
781
829
|
};
|
|
782
830
|
|
|
@@ -784,7 +832,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
784
832
|
} else {
|
|
785
833
|
// Indirect implementation of iteration using tail recursion optimization
|
|
786
834
|
const _traverse = trampoline((cur: N) => {
|
|
787
|
-
if (!cur.right) return cur;
|
|
835
|
+
if (!this.isRealNode(cur.right)) return cur;
|
|
788
836
|
return _traverse.cont(cur.right);
|
|
789
837
|
});
|
|
790
838
|
|
|
@@ -801,8 +849,9 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
801
849
|
* possible values:
|
|
802
850
|
* @returns The function `isSubtreeBST` returns a boolean value.
|
|
803
851
|
*/
|
|
804
|
-
isSubtreeBST(beginRoot: N | null | undefined, iterationType = this.iterationType): boolean {
|
|
852
|
+
isSubtreeBST(beginRoot: BTNKey | N | null | undefined, iterationType = this.iterationType): boolean {
|
|
805
853
|
// TODO there is a bug
|
|
854
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
806
855
|
if (!beginRoot) return true;
|
|
807
856
|
|
|
808
857
|
if (iterationType === IterationType.RECURSIVE) {
|
|
@@ -881,12 +930,12 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
881
930
|
* @returns The function `subTreeTraverse` returns an array of `ReturnType<BTNCallback<N>>`.
|
|
882
931
|
*/
|
|
883
932
|
subTreeTraverse<C extends BTNCallback<N | null | undefined>>(
|
|
884
|
-
callback: C = this.
|
|
933
|
+
callback: C = this._defaultOneParamCallback as C,
|
|
885
934
|
beginRoot: BTNKey | N | null | undefined = this.root,
|
|
886
935
|
iterationType = this.iterationType,
|
|
887
936
|
includeNull = false
|
|
888
937
|
): ReturnType<C>[] {
|
|
889
|
-
|
|
938
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
890
939
|
|
|
891
940
|
const ans: (ReturnType<BTNCallback<N>> | null | undefined)[] = [];
|
|
892
941
|
if (!beginRoot) return ans;
|
|
@@ -926,22 +975,48 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
926
975
|
return ans;
|
|
927
976
|
}
|
|
928
977
|
|
|
929
|
-
|
|
978
|
+
/**
|
|
979
|
+
* The function checks if a given node is a real node by verifying if it is an instance of
|
|
980
|
+
* BinaryTreeNode and its key is not NaN.
|
|
981
|
+
* @param {any} node - The parameter `node` is of type `any`, which means it can be any data type.
|
|
982
|
+
* @returns a boolean value.
|
|
983
|
+
*/
|
|
984
|
+
isRealNode(node: any): node is N {
|
|
930
985
|
return node instanceof BinaryTreeNode && node.key.toString() !== 'NaN';
|
|
931
986
|
}
|
|
932
987
|
|
|
988
|
+
/**
|
|
989
|
+
* The function checks if a given node is a BinaryTreeNode instance and has a key value of NaN.
|
|
990
|
+
* @param {any} node - The parameter `node` is of type `any`, which means it can be any data type.
|
|
991
|
+
* @returns a boolean value.
|
|
992
|
+
*/
|
|
933
993
|
isNIL(node: any) {
|
|
934
994
|
return node instanceof BinaryTreeNode && node.key.toString() === 'NaN';
|
|
935
995
|
}
|
|
936
996
|
|
|
997
|
+
/**
|
|
998
|
+
* The function checks if a given node is a real node or null.
|
|
999
|
+
* @param {any} node - The parameter `node` is of type `any`, which means it can be any data type.
|
|
1000
|
+
* @returns a boolean value.
|
|
1001
|
+
*/
|
|
937
1002
|
isNodeOrNull(node: any): node is (N | null){
|
|
938
|
-
return this.
|
|
1003
|
+
return this.isRealNode(node) || node === null;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
/**
|
|
1007
|
+
* The function "isNodeKey" checks if a potential key is a number.
|
|
1008
|
+
* @param {any} potentialKey - The potentialKey parameter is of type any, which means it can be any
|
|
1009
|
+
* data type.
|
|
1010
|
+
* @returns a boolean value indicating whether the potentialKey is of type number or not.
|
|
1011
|
+
*/
|
|
1012
|
+
isNodeKey(potentialKey: any) : potentialKey is number {
|
|
1013
|
+
return typeof potentialKey === 'number';
|
|
939
1014
|
}
|
|
940
1015
|
|
|
941
1016
|
dfs<C extends BTNCallback<N>>(
|
|
942
1017
|
callback?: C,
|
|
943
1018
|
pattern?: DFSOrderPattern,
|
|
944
|
-
beginRoot?: N | null | undefined,
|
|
1019
|
+
beginRoot?: BTNKey | N | null | undefined,
|
|
945
1020
|
iterationType?: IterationType,
|
|
946
1021
|
includeNull?: false
|
|
947
1022
|
): ReturnType<C>[];
|
|
@@ -949,7 +1024,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
949
1024
|
dfs<C extends BTNCallback<N>>(
|
|
950
1025
|
callback?: C,
|
|
951
1026
|
pattern?: DFSOrderPattern,
|
|
952
|
-
beginRoot?: N | null | undefined,
|
|
1027
|
+
beginRoot?: BTNKey | N | null | undefined,
|
|
953
1028
|
iterationType?: IterationType,
|
|
954
1029
|
includeNull?: undefined
|
|
955
1030
|
): ReturnType<C>[];
|
|
@@ -957,7 +1032,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
957
1032
|
dfs<C extends BTNCallback<N | null | undefined>>(
|
|
958
1033
|
callback?: C,
|
|
959
1034
|
pattern?: DFSOrderPattern,
|
|
960
|
-
beginRoot?: N | null | undefined,
|
|
1035
|
+
beginRoot?: BTNKey | N | null | undefined,
|
|
961
1036
|
iterationType?: IterationType,
|
|
962
1037
|
includeNull?: true
|
|
963
1038
|
): ReturnType<C>[];
|
|
@@ -967,7 +1042,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
967
1042
|
* function on each node according to a specified order pattern.
|
|
968
1043
|
* @param callback - The `callback` parameter is a function that will be called on each node during
|
|
969
1044
|
* the depth-first search traversal. It takes a node as input and returns a value. The default value
|
|
970
|
-
* is `this.
|
|
1045
|
+
* is `this._defaultOneParamCallback`, which is a callback function defined elsewhere in the code.
|
|
971
1046
|
* @param {DFSOrderPattern} [pattern=in] - The `pattern` parameter determines the order in which the
|
|
972
1047
|
* nodes are visited during the depth-first search. There are three possible values for `pattern`:
|
|
973
1048
|
* @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node for the depth-first
|
|
@@ -979,12 +1054,14 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
979
1054
|
* @returns The function `dfs` returns an array of `ReturnType<BTNCallback<N>>` values.
|
|
980
1055
|
*/
|
|
981
1056
|
dfs<C extends BTNCallback<N | null | undefined>>(
|
|
982
|
-
callback: C = this.
|
|
1057
|
+
callback: C = this._defaultOneParamCallback as C,
|
|
983
1058
|
pattern: DFSOrderPattern = 'in',
|
|
984
|
-
beginRoot: N | null | undefined = this.root,
|
|
1059
|
+
beginRoot: BTNKey | N | null | undefined = this.root,
|
|
985
1060
|
iterationType: IterationType = IterationType.ITERATIVE,
|
|
986
1061
|
includeNull = false
|
|
987
1062
|
): ReturnType<C>[] {
|
|
1063
|
+
|
|
1064
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
988
1065
|
if (!beginRoot) return [];
|
|
989
1066
|
const ans: ReturnType<C>[] = [];
|
|
990
1067
|
if (iterationType === IterationType.RECURSIVE) {
|
|
@@ -997,7 +1074,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
997
1074
|
if (node && this.isNodeOrNull(node.right)) _traverse(node.right);
|
|
998
1075
|
} else {
|
|
999
1076
|
if (node && node.left) _traverse(node.left);
|
|
1000
|
-
this.
|
|
1077
|
+
this.isRealNode(node) && ans.push(callback(node));
|
|
1001
1078
|
if (node && node.right) _traverse(node.right);
|
|
1002
1079
|
}
|
|
1003
1080
|
break;
|
|
@@ -1007,7 +1084,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1007
1084
|
if (node && this.isNodeOrNull(node.left)) _traverse(node.left);
|
|
1008
1085
|
if (node && this.isNodeOrNull(node.right)) _traverse(node.right);
|
|
1009
1086
|
} else {
|
|
1010
|
-
this.
|
|
1087
|
+
this.isRealNode(node) && ans.push(callback(node));
|
|
1011
1088
|
if (node && node.left) _traverse(node.left);
|
|
1012
1089
|
if (node && node.right) _traverse(node.right);
|
|
1013
1090
|
}
|
|
@@ -1020,7 +1097,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1020
1097
|
} else {
|
|
1021
1098
|
if (node && node.left) _traverse(node.left);
|
|
1022
1099
|
if (node && node.right) _traverse(node.right);
|
|
1023
|
-
this.
|
|
1100
|
+
this.isRealNode(node) && ans.push(callback(node));
|
|
1024
1101
|
}
|
|
1025
1102
|
|
|
1026
1103
|
break;
|
|
@@ -1074,21 +1151,21 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1074
1151
|
|
|
1075
1152
|
bfs<C extends BTNCallback<N>>(
|
|
1076
1153
|
callback?: C,
|
|
1077
|
-
beginRoot?: N | null | undefined,
|
|
1154
|
+
beginRoot?: BTNKey | N | null | undefined,
|
|
1078
1155
|
iterationType?: IterationType,
|
|
1079
1156
|
includeNull?: false
|
|
1080
1157
|
): ReturnType<C>[];
|
|
1081
1158
|
|
|
1082
1159
|
bfs<C extends BTNCallback<N>>(
|
|
1083
1160
|
callback?: C,
|
|
1084
|
-
beginRoot?: N | null | undefined,
|
|
1161
|
+
beginRoot?: BTNKey | N | null | undefined,
|
|
1085
1162
|
iterationType?: IterationType,
|
|
1086
1163
|
includeNull?: undefined
|
|
1087
1164
|
): ReturnType<C>[];
|
|
1088
1165
|
|
|
1089
1166
|
bfs<C extends BTNCallback<N | null | undefined>>(
|
|
1090
1167
|
callback?: C,
|
|
1091
|
-
beginRoot?: N | null | undefined,
|
|
1168
|
+
beginRoot?: BTNKey | N | null | undefined,
|
|
1092
1169
|
iterationType?: IterationType,
|
|
1093
1170
|
includeNull?: true
|
|
1094
1171
|
): ReturnType<C>[];
|
|
@@ -1098,7 +1175,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1098
1175
|
* function on each node.
|
|
1099
1176
|
* @param callback - The `callback` parameter is a function that will be called for each node in the
|
|
1100
1177
|
* breadth-first search. It takes a node of type `N` as its argument and returns a value of type
|
|
1101
|
-
* `ReturnType<BTNCallback<N>>`. The default value for this parameter is `this.
|
|
1178
|
+
* `ReturnType<BTNCallback<N>>`. The default value for this parameter is `this._defaultOneParamCallback
|
|
1102
1179
|
* @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node for the breadth-first
|
|
1103
1180
|
* search. It determines from which node the search will begin. If `beginRoot` is `null`, the search
|
|
1104
1181
|
* will not be performed and an empty array will be returned.
|
|
@@ -1108,11 +1185,12 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1108
1185
|
* @returns The function `bfs` returns an array of `ReturnType<BTNCallback<N>>[]`.
|
|
1109
1186
|
*/
|
|
1110
1187
|
bfs<C extends BTNCallback<N | null | undefined>>(
|
|
1111
|
-
callback: C = this.
|
|
1112
|
-
beginRoot: N | null | undefined = this.root,
|
|
1188
|
+
callback: C = this._defaultOneParamCallback as C,
|
|
1189
|
+
beginRoot: BTNKey | N | null | undefined = this.root,
|
|
1113
1190
|
iterationType = this.iterationType,
|
|
1114
1191
|
includeNull = false
|
|
1115
1192
|
): ReturnType<C>[] {
|
|
1193
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
1116
1194
|
if (!beginRoot) return [];
|
|
1117
1195
|
|
|
1118
1196
|
const ans: ReturnType<BTNCallback<N>>[] = [];
|
|
@@ -1162,21 +1240,21 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1162
1240
|
|
|
1163
1241
|
listLevels<C extends BTNCallback<N>>(
|
|
1164
1242
|
callback?: C,
|
|
1165
|
-
beginRoot?: N | null | undefined,
|
|
1243
|
+
beginRoot?: BTNKey | N | null | undefined,
|
|
1166
1244
|
iterationType?: IterationType,
|
|
1167
1245
|
includeNull?: false
|
|
1168
1246
|
): ReturnType<C>[][];
|
|
1169
1247
|
|
|
1170
1248
|
listLevels<C extends BTNCallback<N>>(
|
|
1171
1249
|
callback?: C,
|
|
1172
|
-
beginRoot?: N | null | undefined,
|
|
1250
|
+
beginRoot?: BTNKey | N | null | undefined,
|
|
1173
1251
|
iterationType?: IterationType,
|
|
1174
1252
|
includeNull?: undefined
|
|
1175
1253
|
): ReturnType<C>[][];
|
|
1176
1254
|
|
|
1177
1255
|
listLevels<C extends BTNCallback<N | null | undefined>>(
|
|
1178
1256
|
callback?: C,
|
|
1179
|
-
beginRoot?: N | null | undefined,
|
|
1257
|
+
beginRoot?: BTNKey | N | null | undefined,
|
|
1180
1258
|
iterationType?: IterationType,
|
|
1181
1259
|
includeNull?: true
|
|
1182
1260
|
): ReturnType<C>[][];
|
|
@@ -1198,13 +1276,14 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1198
1276
|
* function `C` applied to the nodes at that level.
|
|
1199
1277
|
*/
|
|
1200
1278
|
listLevels<C extends BTNCallback<N | null | undefined>>(
|
|
1201
|
-
callback: C = this.
|
|
1202
|
-
beginRoot: N | null | undefined = this.root,
|
|
1279
|
+
callback: C = this._defaultOneParamCallback as C,
|
|
1280
|
+
beginRoot: BTNKey | N | null | undefined = this.root,
|
|
1203
1281
|
iterationType = this.iterationType,
|
|
1204
1282
|
includeNull = false
|
|
1205
1283
|
): ReturnType<C>[][] {
|
|
1206
|
-
|
|
1284
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
1207
1285
|
const levelsNodes: ReturnType<C>[][] = [];
|
|
1286
|
+
if (!beginRoot) return levelsNodes;
|
|
1208
1287
|
|
|
1209
1288
|
if (iterationType === IterationType.RECURSIVE) {
|
|
1210
1289
|
const _recursive = (node: N | null | undefined, level: number) => {
|
|
@@ -1243,15 +1322,20 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1243
1322
|
return levelsNodes;
|
|
1244
1323
|
}
|
|
1245
1324
|
|
|
1325
|
+
getPredecessor(node: N ): N
|
|
1326
|
+
|
|
1246
1327
|
/**
|
|
1247
1328
|
* The function returns the predecessor node of a given node in a binary tree.
|
|
1248
1329
|
* @param {N} node - The parameter "node" represents a node in a binary tree.
|
|
1249
1330
|
* @returns The function `getPredecessor` returns the predecessor node of the given node `node`.
|
|
1250
1331
|
*/
|
|
1251
|
-
getPredecessor(node: N): N {
|
|
1332
|
+
getPredecessor(node: BTNKey | N | null | undefined): N | undefined{
|
|
1333
|
+
node = this.ensureNotKey(node);
|
|
1334
|
+
if (!this.isRealNode(node)) return undefined;
|
|
1335
|
+
|
|
1252
1336
|
if (node.left) {
|
|
1253
1337
|
let predecessor: N | null | undefined = node.left;
|
|
1254
|
-
while (!predecessor || (predecessor.right && predecessor.right !== node)) {
|
|
1338
|
+
while (!this.isRealNode(predecessor) || (this.isRealNode(predecessor.right) && predecessor.right !== node)) {
|
|
1255
1339
|
if (predecessor) {
|
|
1256
1340
|
predecessor = predecessor.right;
|
|
1257
1341
|
}
|
|
@@ -1269,7 +1353,10 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1269
1353
|
* @returns The function `getSuccessor` returns a value of type `N` (the successor node), or `null`
|
|
1270
1354
|
* if there is no successor, or `undefined` if the input `x` is `undefined`.
|
|
1271
1355
|
*/
|
|
1272
|
-
getSuccessor(x
|
|
1356
|
+
getSuccessor(x?: BTNKey | N | null): N | null | undefined {
|
|
1357
|
+
x = this.ensureNotKey(x);
|
|
1358
|
+
if (!x) return undefined;
|
|
1359
|
+
|
|
1273
1360
|
if (x.right) {
|
|
1274
1361
|
return this.getLeftMost(x.right);
|
|
1275
1362
|
}
|
|
@@ -1287,7 +1374,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1287
1374
|
* algorithm and returns an array of values obtained by applying a callback function to each node.
|
|
1288
1375
|
* @param callback - The `callback` parameter is a function that will be called on each node in the
|
|
1289
1376
|
* tree. It takes a node of type `N` as input and returns a value of type `ReturnType<BTNCallback<N>>`. The
|
|
1290
|
-
* default value for this parameter is `this.
|
|
1377
|
+
* default value for this parameter is `this._defaultOneParamCallback`.
|
|
1291
1378
|
* @param {DFSOrderPattern} [pattern=in] - The `pattern` parameter in the `morris` function
|
|
1292
1379
|
* determines the order in which the nodes of a binary tree are traversed. It can have one of the
|
|
1293
1380
|
* following values:
|
|
@@ -1297,10 +1384,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1297
1384
|
* @returns The `morris` function returns an array of `ReturnType<BTNCallback<N>>` values.
|
|
1298
1385
|
*/
|
|
1299
1386
|
morris<C extends BTNCallback<N>>(
|
|
1300
|
-
callback: C = this.
|
|
1387
|
+
callback: C = this._defaultOneParamCallback as C,
|
|
1301
1388
|
pattern: DFSOrderPattern = 'in',
|
|
1302
|
-
beginRoot: N | null | undefined = this.root
|
|
1389
|
+
beginRoot: BTNKey | N | null | undefined = this.root
|
|
1303
1390
|
): ReturnType<C>[] {
|
|
1391
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
1304
1392
|
if (beginRoot === null) return [];
|
|
1305
1393
|
const ans: ReturnType<BTNCallback<N>>[] = [];
|
|
1306
1394
|
|
|
@@ -1425,7 +1513,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1425
1513
|
}
|
|
1426
1514
|
}
|
|
1427
1515
|
|
|
1428
|
-
protected
|
|
1516
|
+
protected _defaultOneParamCallback = (node: N) => node.key;
|
|
1429
1517
|
|
|
1430
1518
|
/**
|
|
1431
1519
|
* Swap the data of two nodes in the binary tree.
|
|
@@ -1433,19 +1521,26 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1433
1521
|
* @param {N} destNode - The destination node to swap.
|
|
1434
1522
|
* @returns {N} - The destination node after the swap.
|
|
1435
1523
|
*/
|
|
1436
|
-
protected _swap(srcNode: N, destNode: N): N {
|
|
1437
|
-
|
|
1438
|
-
|
|
1524
|
+
protected _swap(srcNode: BTNKey | N | null | undefined, destNode:BTNKey | N | null | undefined): N | undefined{
|
|
1525
|
+
srcNode = this.ensureNotKey(srcNode);
|
|
1526
|
+
destNode = this.ensureNotKey(destNode);
|
|
1439
1527
|
|
|
1440
|
-
if (
|
|
1441
|
-
|
|
1442
|
-
|
|
1528
|
+
if (srcNode && destNode) {
|
|
1529
|
+
const {key, value} = destNode;
|
|
1530
|
+
const tempNode = this.createNode(key, value);
|
|
1443
1531
|
|
|
1444
|
-
|
|
1445
|
-
|
|
1532
|
+
if (tempNode) {
|
|
1533
|
+
destNode.key = srcNode.key;
|
|
1534
|
+
destNode.value = srcNode.value;
|
|
1535
|
+
|
|
1536
|
+
srcNode.key = tempNode.key;
|
|
1537
|
+
srcNode.value = tempNode.value;
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
return destNode;
|
|
1446
1541
|
}
|
|
1542
|
+
return undefined;
|
|
1447
1543
|
|
|
1448
|
-
return destNode;
|
|
1449
1544
|
}
|
|
1450
1545
|
|
|
1451
1546
|
/**
|
|
@@ -1459,7 +1554,9 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1459
1554
|
* the binary tree. If neither the left nor right child is available, the function returns undefined.
|
|
1460
1555
|
* If the parent node is null, the function also returns undefined.
|
|
1461
1556
|
*/
|
|
1462
|
-
protected _addTo(newNode: N | null | undefined, parent: N): N | null | undefined {
|
|
1557
|
+
protected _addTo(newNode: N | null | undefined, parent: BTNKey | N | null | undefined): N | null | undefined {
|
|
1558
|
+
if (this.isNodeKey(parent)) parent = this.getNode(parent);
|
|
1559
|
+
|
|
1463
1560
|
if (parent) {
|
|
1464
1561
|
// When all leaf nodes are null, it will no longer be possible to add new entity nodes to this binary tree.
|
|
1465
1562
|
// In this scenario, null nodes serve as "sentinel nodes," "virtual nodes," or "placeholder nodes."
|
|
@@ -1496,7 +1593,16 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1496
1593
|
this._root = v;
|
|
1497
1594
|
}
|
|
1498
1595
|
|
|
1499
|
-
|
|
1596
|
+
/**
|
|
1597
|
+
* The `print` function is used to display a binary tree structure in a visually appealing way.
|
|
1598
|
+
* @param {N | null | undefined} root - The `root` parameter in the `print` function represents the
|
|
1599
|
+
* root node of a binary tree. It can have one of the following types: `BTNKey`, `N`, `null`, or
|
|
1600
|
+
* `undefined`. The default value is `this.root`, which suggests that `this.root` is the
|
|
1601
|
+
*/
|
|
1602
|
+
print(beginRoot: BTNKey | N | null | undefined = this.root): void {
|
|
1603
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
1604
|
+
if (!beginRoot) return;
|
|
1605
|
+
|
|
1500
1606
|
const display = (root: N | null | undefined): void => {
|
|
1501
1607
|
const [lines, , ,] = _displayAux(root);
|
|
1502
1608
|
for (const line of lines) {
|