min-heap-typed 1.42.2 → 1.42.4
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 +2 -2
- package/dist/data-structures/binary-tree/avl-tree.js +5 -3
- package/dist/data-structures/binary-tree/binary-tree.d.ts +57 -53
- package/dist/data-structures/binary-tree/binary-tree.js +116 -54
- package/dist/data-structures/binary-tree/bst.d.ts +42 -15
- package/dist/data-structures/binary-tree/bst.js +77 -21
- package/dist/data-structures/binary-tree/rb-tree.d.ts +28 -51
- package/dist/data-structures/binary-tree/rb-tree.js +148 -180
- package/dist/data-structures/binary-tree/tree-multiset.d.ts +10 -10
- package/dist/data-structures/binary-tree/tree-multiset.js +20 -17
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +1 -1
- package/dist/types/data-structures/binary-tree/rb-tree.d.ts +4 -0
- package/dist/types/data-structures/binary-tree/rb-tree.js +0 -5
- package/package.json +2 -2
- package/src/data-structures/binary-tree/avl-tree.ts +5 -4
- package/src/data-structures/binary-tree/binary-tree.ts +227 -158
- package/src/data-structures/binary-tree/bst.ts +100 -34
- package/src/data-structures/binary-tree/rb-tree.ts +227 -236
- package/src/data-structures/binary-tree/tree-multiset.ts +24 -23
- package/src/data-structures/graph/abstract-graph.ts +18 -14
- package/src/types/data-structures/binary-tree/binary-tree.ts +1 -1
- package/src/types/data-structures/binary-tree/rb-tree.ts +5 -5
|
@@ -108,7 +108,8 @@ export class BinaryTreeNode<V = any, N extends BinaryTreeNode<V, N> = BinaryTree
|
|
|
108
108
|
* @template N - The type of the binary tree's nodes.
|
|
109
109
|
*/
|
|
110
110
|
export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode<V, BinaryTreeNodeNested<V>>>
|
|
111
|
-
implements IBinaryTree<V, N>
|
|
111
|
+
implements IBinaryTree<V, N>
|
|
112
|
+
{
|
|
112
113
|
iterationType: IterationType = IterationType.ITERATIVE;
|
|
113
114
|
|
|
114
115
|
/**
|
|
@@ -122,12 +123,12 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
122
123
|
}
|
|
123
124
|
}
|
|
124
125
|
|
|
125
|
-
protected _root: N | null =
|
|
126
|
+
protected _root: N | null | undefined = undefined;
|
|
126
127
|
|
|
127
128
|
/**
|
|
128
129
|
* Get the root node of the binary tree.
|
|
129
130
|
*/
|
|
130
|
-
get root(): N | null {
|
|
131
|
+
get root(): N | null | undefined {
|
|
131
132
|
return this._root;
|
|
132
133
|
}
|
|
133
134
|
|
|
@@ -140,8 +141,6 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
140
141
|
return this._size;
|
|
141
142
|
}
|
|
142
143
|
|
|
143
|
-
protected defaultOneParamCallback = (node: N) => node.key;
|
|
144
|
-
|
|
145
144
|
/**
|
|
146
145
|
* Creates a new instance of BinaryTreeNode with the given key and value.
|
|
147
146
|
* @param {BTNKey} key - The key for the new node.
|
|
@@ -156,7 +155,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
156
155
|
* Clear the binary tree, removing all nodes.
|
|
157
156
|
*/
|
|
158
157
|
clear() {
|
|
159
|
-
this._setRoot(
|
|
158
|
+
this._setRoot(undefined);
|
|
160
159
|
this._size = 0;
|
|
161
160
|
}
|
|
162
161
|
|
|
@@ -174,7 +173,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
174
173
|
* @param {V} value - The value for the new node (optional).
|
|
175
174
|
* @returns {N | null | undefined} - The inserted node, or null if nothing was inserted, or undefined if the operation failed.
|
|
176
175
|
*/
|
|
177
|
-
add(keyOrNode: BTNKey | N | null, value?: V): N | null | undefined {
|
|
176
|
+
add(keyOrNode: BTNKey | N | null | undefined, value?: V): N | null | undefined {
|
|
178
177
|
const _bfs = (root: N, newNode: N | null): N | undefined | null => {
|
|
179
178
|
const queue = new Queue<N | null>([root]);
|
|
180
179
|
while (queue.size > 0) {
|
|
@@ -237,7 +236,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
237
236
|
* the value of the nodes will be `undefined`.
|
|
238
237
|
* @returns The function `addMany` returns an array of `N`, `null`, or `undefined` values.
|
|
239
238
|
*/
|
|
240
|
-
addMany(keysOrNodes: (BTNKey | null)[] | (N | null)[], values?: V[]): (N | null | undefined)[] {
|
|
239
|
+
addMany(keysOrNodes: (BTNKey | null | undefined)[] | (N | null | undefined)[], values?: V[]): (N | null | undefined)[] {
|
|
241
240
|
// TODO not sure addMany not be run multi times
|
|
242
241
|
return keysOrNodes.map((keyOrNode, i) => {
|
|
243
242
|
if (keyOrNode instanceof BinaryTreeNode) {
|
|
@@ -262,14 +261,14 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
262
261
|
* array. Each value in the `data` array will be assigned to the
|
|
263
262
|
* @returns The method is returning a boolean value.
|
|
264
263
|
*/
|
|
265
|
-
refill(keysOrNodes: (BTNKey | null)[] | (N | null)[], data?: Array<V>): boolean {
|
|
264
|
+
refill(keysOrNodes: (BTNKey | null | undefined)[] | (N | null | undefined)[], data?: Array<V>): boolean {
|
|
266
265
|
this.clear();
|
|
267
266
|
return keysOrNodes.length === this.addMany(keysOrNodes, data).length;
|
|
268
267
|
}
|
|
269
268
|
|
|
270
269
|
delete<C extends BTNCallback<N, BTNKey>>(identifier: BTNKey, callback?: C): BinaryTreeDeletedResult<N>[];
|
|
271
270
|
|
|
272
|
-
delete<C extends BTNCallback<N, N>>(identifier: N | null, callback?: C): BinaryTreeDeletedResult<N>[];
|
|
271
|
+
delete<C extends BTNCallback<N, N>>(identifier: N | null | undefined, callback?: C): BinaryTreeDeletedResult<N>[];
|
|
273
272
|
|
|
274
273
|
delete<C extends BTNCallback<N>>(identifier: ReturnType<C>, callback: C): BinaryTreeDeletedResult<N>[];
|
|
275
274
|
|
|
@@ -288,7 +287,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
288
287
|
* `this.defaultOneParamCallback`, which
|
|
289
288
|
*/
|
|
290
289
|
delete<C extends BTNCallback<N>>(
|
|
291
|
-
identifier: ReturnType<C> | null,
|
|
290
|
+
identifier: ReturnType<C> | null | undefined,
|
|
292
291
|
callback: C = this.defaultOneParamCallback as C
|
|
293
292
|
): BinaryTreeDeletedResult<N>[] {
|
|
294
293
|
const bstDeletedResult: BinaryTreeDeletedResult<N>[] = [];
|
|
@@ -298,8 +297,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
298
297
|
const curr = this.getNode(identifier, callback);
|
|
299
298
|
if (!curr) return bstDeletedResult;
|
|
300
299
|
|
|
301
|
-
const parent: N | null = curr?.parent ? curr.parent : null;
|
|
302
|
-
let needBalanced: N | null = null,
|
|
300
|
+
const parent: N | null | undefined = curr?.parent ? curr.parent : null;
|
|
301
|
+
let needBalanced: N | null | undefined = null,
|
|
303
302
|
orgCurrent = curr;
|
|
304
303
|
|
|
305
304
|
if (!curr.left) {
|
|
@@ -337,16 +336,16 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
337
336
|
/**
|
|
338
337
|
* The function `getDepth` calculates the depth of a given node in a binary tree relative to a
|
|
339
338
|
* specified root node.
|
|
340
|
-
* @param {BTNKey | N | null} distNode - The `distNode` parameter represents the node
|
|
339
|
+
* @param {BTNKey | N | null | undefined} distNode - The `distNode` parameter represents the node
|
|
341
340
|
* whose depth we want to find in the binary tree. It can be either a node object (`N`), a key value
|
|
342
341
|
* of the node (`BTNKey`), or `null`.
|
|
343
|
-
* @param {BTNKey | N | null} beginRoot - The `beginRoot` parameter represents the
|
|
342
|
+
* @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
|
|
344
343
|
* starting node from which we want to calculate the depth. It can be either a node object or the key
|
|
345
344
|
* of a node in the binary tree. If no value is provided for `beginRoot`, it defaults to the root
|
|
346
345
|
* node of the binary tree.
|
|
347
346
|
* @returns the depth of the `distNode` relative to the `beginRoot`.
|
|
348
347
|
*/
|
|
349
|
-
getDepth(distNode: BTNKey | N | null, beginRoot: BTNKey | N | null = this.root): number {
|
|
348
|
+
getDepth(distNode: BTNKey | N | null | undefined, beginRoot: BTNKey | N | null | undefined = this.root): number {
|
|
350
349
|
if (typeof distNode === 'number') distNode = this.getNode(distNode);
|
|
351
350
|
if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);
|
|
352
351
|
let depth = 0;
|
|
@@ -363,7 +362,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
363
362
|
/**
|
|
364
363
|
* The `getHeight` function calculates the maximum height of a binary tree using either recursive or
|
|
365
364
|
* iterative approach.
|
|
366
|
-
* @param {BTNKey | N | null} beginRoot - The `beginRoot` parameter represents the
|
|
365
|
+
* @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
|
|
367
366
|
* starting node from which the height of the binary tree is calculated. It can be either a node
|
|
368
367
|
* object (`N`), a key value of a node in the tree (`BTNKey`), or `null` if no starting
|
|
369
368
|
* node is specified. If `
|
|
@@ -372,7 +371,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
372
371
|
* possible values:
|
|
373
372
|
* @returns the height of the binary tree.
|
|
374
373
|
*/
|
|
375
|
-
getHeight(beginRoot: BTNKey | N | null = this.root, iterationType = this.iterationType): number {
|
|
374
|
+
getHeight(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.iterationType): number {
|
|
376
375
|
if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);
|
|
377
376
|
if (!beginRoot) return -1;
|
|
378
377
|
|
|
@@ -390,7 +389,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
390
389
|
return -1;
|
|
391
390
|
}
|
|
392
391
|
|
|
393
|
-
const stack: {
|
|
392
|
+
const stack: {node: N; depth: number}[] = [{node: beginRoot, depth: 0}];
|
|
394
393
|
let maxHeight = 0;
|
|
395
394
|
|
|
396
395
|
while (stack.length > 0) {
|
|
@@ -414,14 +413,14 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
414
413
|
/**
|
|
415
414
|
* The `getMinHeight` function calculates the minimum height of a binary tree using either a
|
|
416
415
|
* recursive or iterative approach.
|
|
417
|
-
* @param {N | null} beginRoot - The `beginRoot` parameter is the starting node from which we want to
|
|
416
|
+
* @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node from which we want to
|
|
418
417
|
* calculate the minimum height of the tree. It is optional and defaults to the root of the tree if
|
|
419
418
|
* not provided.
|
|
420
419
|
* @param iterationType - The `iterationType` parameter is used to determine the method of iteration
|
|
421
420
|
* to calculate the minimum height of a binary tree. It can have two possible values:
|
|
422
421
|
* @returns The function `getMinHeight` returns the minimum height of a binary tree.
|
|
423
422
|
*/
|
|
424
|
-
getMinHeight(beginRoot: N | null = this.root, iterationType = this.iterationType): number {
|
|
423
|
+
getMinHeight(beginRoot: N | null | undefined = this.root, iterationType = this.iterationType): number {
|
|
425
424
|
if (!beginRoot) return -1;
|
|
426
425
|
|
|
427
426
|
if (iterationType === IterationType.RECURSIVE) {
|
|
@@ -437,7 +436,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
437
436
|
} else {
|
|
438
437
|
const stack: N[] = [];
|
|
439
438
|
let node: N | null | undefined = beginRoot,
|
|
440
|
-
last: N | null = null;
|
|
439
|
+
last: N | null | undefined = null;
|
|
441
440
|
const depths: Map<N, number> = new Map();
|
|
442
441
|
|
|
443
442
|
while (stack.length > 0 || node) {
|
|
@@ -466,11 +465,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
466
465
|
/**
|
|
467
466
|
* The function checks if a binary tree is perfectly balanced by comparing the minimum height and the
|
|
468
467
|
* height of the tree.
|
|
469
|
-
* @param {N | null} beginRoot - The parameter `beginRoot` is of type `N | null`, which means it can
|
|
468
|
+
* @param {N | null | undefined} beginRoot - The parameter `beginRoot` is of type `N | null | undefined`, which means it can
|
|
470
469
|
* either be of type `N` (representing a node in a tree) or `null` (representing an empty tree).
|
|
471
470
|
* @returns The method is returning a boolean value.
|
|
472
471
|
*/
|
|
473
|
-
isPerfectlyBalanced(beginRoot: N | null = this.root): boolean {
|
|
472
|
+
isPerfectlyBalanced(beginRoot: N | null | undefined = this.root): boolean {
|
|
474
473
|
return this.getMinHeight(beginRoot) + 1 >= this.getHeight(beginRoot);
|
|
475
474
|
}
|
|
476
475
|
|
|
@@ -478,15 +477,15 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
478
477
|
identifier: BTNKey,
|
|
479
478
|
callback?: C,
|
|
480
479
|
onlyOne?: boolean,
|
|
481
|
-
beginRoot?: N | null,
|
|
480
|
+
beginRoot?: N | null | undefined,
|
|
482
481
|
iterationType?: IterationType
|
|
483
482
|
): N[];
|
|
484
483
|
|
|
485
484
|
getNodes<C extends BTNCallback<N, N>>(
|
|
486
|
-
identifier: N | null,
|
|
485
|
+
identifier: N | null | undefined,
|
|
487
486
|
callback?: C,
|
|
488
487
|
onlyOne?: boolean,
|
|
489
|
-
beginRoot?: N | null,
|
|
488
|
+
beginRoot?: N | null | undefined,
|
|
490
489
|
iterationType?: IterationType
|
|
491
490
|
): N[];
|
|
492
491
|
|
|
@@ -494,7 +493,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
494
493
|
identifier: ReturnType<C>,
|
|
495
494
|
callback: C,
|
|
496
495
|
onlyOne?: boolean,
|
|
497
|
-
beginRoot?: N | null,
|
|
496
|
+
beginRoot?: N | null | undefined,
|
|
498
497
|
iterationType?: IterationType
|
|
499
498
|
): N[];
|
|
500
499
|
|
|
@@ -512,7 +511,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
512
511
|
* first node that matches the identifier. If set to true, the function will return an array with
|
|
513
512
|
* only one element (or an empty array if no matching node is found). If set to false (default), the
|
|
514
513
|
* function will continue searching for all
|
|
515
|
-
* @param {N | null} beginRoot - The `beginRoot` parameter is the starting node from which the
|
|
514
|
+
* @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node from which the
|
|
516
515
|
* traversal of the binary tree will begin. It is optional and defaults to the root of the binary
|
|
517
516
|
* tree.
|
|
518
517
|
* @param iterationType - The `iterationType` parameter determines the type of iteration used to
|
|
@@ -520,10 +519,10 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
520
519
|
* @returns The function `getNodes` returns an array of nodes (`N[]`).
|
|
521
520
|
*/
|
|
522
521
|
getNodes<C extends BTNCallback<N>>(
|
|
523
|
-
identifier: ReturnType<C> | null,
|
|
522
|
+
identifier: ReturnType<C> | null | undefined,
|
|
524
523
|
callback: C = this.defaultOneParamCallback as C,
|
|
525
524
|
onlyOne = false,
|
|
526
|
-
beginRoot: N | null = this.root,
|
|
525
|
+
beginRoot: N | null | undefined = this.root,
|
|
527
526
|
iterationType = this.iterationType
|
|
528
527
|
): N[] {
|
|
529
528
|
if (!beginRoot) return [];
|
|
@@ -563,21 +562,21 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
563
562
|
has<C extends BTNCallback<N, BTNKey>>(
|
|
564
563
|
identifier: BTNKey,
|
|
565
564
|
callback?: C,
|
|
566
|
-
beginRoot?: N | null,
|
|
565
|
+
beginRoot?: N | null | undefined,
|
|
567
566
|
iterationType?: IterationType
|
|
568
567
|
): boolean;
|
|
569
568
|
|
|
570
569
|
has<C extends BTNCallback<N, N>>(
|
|
571
|
-
identifier: N | null,
|
|
570
|
+
identifier: N | null | undefined,
|
|
572
571
|
callback?: C,
|
|
573
|
-
beginRoot?: N | null,
|
|
572
|
+
beginRoot?: N | null | undefined,
|
|
574
573
|
iterationType?: IterationType
|
|
575
574
|
): boolean;
|
|
576
575
|
|
|
577
576
|
has<C extends BTNCallback<N>>(
|
|
578
|
-
identifier: ReturnType<C> | null,
|
|
577
|
+
identifier: ReturnType<C> | null | undefined,
|
|
579
578
|
callback: C,
|
|
580
|
-
beginRoot?: N | null,
|
|
579
|
+
beginRoot?: N | null | undefined,
|
|
581
580
|
iterationType?: IterationType
|
|
582
581
|
): boolean;
|
|
583
582
|
|
|
@@ -599,7 +598,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
599
598
|
* @returns a boolean value.
|
|
600
599
|
*/
|
|
601
600
|
has<C extends BTNCallback<N>>(
|
|
602
|
-
identifier: ReturnType<C> | null,
|
|
601
|
+
identifier: ReturnType<C> | null | undefined,
|
|
603
602
|
callback: C = this.defaultOneParamCallback as C,
|
|
604
603
|
beginRoot = this.root,
|
|
605
604
|
iterationType = this.iterationType
|
|
@@ -612,23 +611,23 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
612
611
|
getNode<C extends BTNCallback<N, BTNKey>>(
|
|
613
612
|
identifier: BTNKey,
|
|
614
613
|
callback?: C,
|
|
615
|
-
beginRoot?: N | null,
|
|
614
|
+
beginRoot?: N | null | undefined,
|
|
616
615
|
iterationType?: IterationType
|
|
617
|
-
): N | null;
|
|
616
|
+
): N | null | undefined;
|
|
618
617
|
|
|
619
618
|
getNode<C extends BTNCallback<N, N>>(
|
|
620
|
-
identifier: N | null,
|
|
619
|
+
identifier: N | null | undefined,
|
|
621
620
|
callback?: C,
|
|
622
|
-
beginRoot?: N | null,
|
|
621
|
+
beginRoot?: N | null | undefined,
|
|
623
622
|
iterationType?: IterationType
|
|
624
|
-
): N | null;
|
|
623
|
+
): N | null | undefined;
|
|
625
624
|
|
|
626
625
|
getNode<C extends BTNCallback<N>>(
|
|
627
626
|
identifier: ReturnType<C>,
|
|
628
627
|
callback: C,
|
|
629
|
-
beginRoot?: N | null,
|
|
628
|
+
beginRoot?: N | null | undefined,
|
|
630
629
|
iterationType?: IterationType
|
|
631
|
-
): N | null;
|
|
630
|
+
): N | null | undefined;
|
|
632
631
|
|
|
633
632
|
/**
|
|
634
633
|
* The function `get` returns the first node in a binary tree that matches the given property or key.
|
|
@@ -646,11 +645,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
646
645
|
* @returns either the found node (of type N) or null if no node is found.
|
|
647
646
|
*/
|
|
648
647
|
getNode<C extends BTNCallback<N>>(
|
|
649
|
-
identifier: ReturnType<C> | null,
|
|
648
|
+
identifier: ReturnType<C> | null | undefined,
|
|
650
649
|
callback: C = this.defaultOneParamCallback as C,
|
|
651
650
|
beginRoot = this.root,
|
|
652
651
|
iterationType = this.iterationType
|
|
653
|
-
): N | null {
|
|
652
|
+
): N | null | undefined {
|
|
654
653
|
if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;
|
|
655
654
|
|
|
656
655
|
return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? null;
|
|
@@ -659,21 +658,21 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
659
658
|
get<C extends BTNCallback<N, BTNKey>>(
|
|
660
659
|
identifier: BTNKey,
|
|
661
660
|
callback?: C,
|
|
662
|
-
beginRoot?: N | null,
|
|
661
|
+
beginRoot?: N | null | undefined,
|
|
663
662
|
iterationType?: IterationType
|
|
664
663
|
): V | undefined;
|
|
665
664
|
|
|
666
665
|
get<C extends BTNCallback<N, N>>(
|
|
667
|
-
identifier: N | null,
|
|
666
|
+
identifier: N | null | undefined,
|
|
668
667
|
callback?: C,
|
|
669
|
-
beginRoot?: N | null,
|
|
668
|
+
beginRoot?: N | null | undefined,
|
|
670
669
|
iterationType?: IterationType
|
|
671
670
|
): V | undefined;
|
|
672
671
|
|
|
673
672
|
get<C extends BTNCallback<N>>(
|
|
674
673
|
identifier: ReturnType<C>,
|
|
675
674
|
callback: C,
|
|
676
|
-
beginRoot?: N | null,
|
|
675
|
+
beginRoot?: N | null | undefined,
|
|
677
676
|
iterationType?: IterationType
|
|
678
677
|
): V | undefined;
|
|
679
678
|
|
|
@@ -693,7 +692,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
693
692
|
* @returns either the found value (of type V) or undefined if no node value is found.
|
|
694
693
|
*/
|
|
695
694
|
get<C extends BTNCallback<N>>(
|
|
696
|
-
identifier: ReturnType<C> | null,
|
|
695
|
+
identifier: ReturnType<C> | null | undefined,
|
|
697
696
|
callback: C = this.defaultOneParamCallback as C,
|
|
698
697
|
beginRoot = this.root,
|
|
699
698
|
iterationType = this.iterationType
|
|
@@ -729,7 +728,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
729
728
|
/**
|
|
730
729
|
* The function `getLeftMost` returns the leftmost node in a binary tree, either using recursive or
|
|
731
730
|
* iterative traversal.
|
|
732
|
-
* @param {BTNKey | N | null} beginRoot - The `beginRoot` parameter is the starting point
|
|
731
|
+
* @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
|
|
733
732
|
* for finding the leftmost node in a binary tree. It can be either a node object (`N`), a key value
|
|
734
733
|
* of a node (`BTNKey`), or `null` if the tree is empty.
|
|
735
734
|
* @param iterationType - The `iterationType` parameter is used to determine the type of iteration to
|
|
@@ -737,7 +736,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
737
736
|
* @returns The function `getLeftMost` returns the leftmost node (`N`) in a binary tree. If there is
|
|
738
737
|
* no leftmost node, it returns `null`.
|
|
739
738
|
*/
|
|
740
|
-
getLeftMost(beginRoot: BTNKey | N | null = this.root, iterationType = this.iterationType): N | null {
|
|
739
|
+
getLeftMost(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.iterationType): N | null | undefined {
|
|
741
740
|
if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);
|
|
742
741
|
|
|
743
742
|
if (!beginRoot) return beginRoot;
|
|
@@ -763,15 +762,15 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
763
762
|
/**
|
|
764
763
|
* The function `getRightMost` returns the rightmost node in a binary tree, either recursively or
|
|
765
764
|
* iteratively.
|
|
766
|
-
* @param {N | null} beginRoot - The `beginRoot` parameter is the starting node from which we want to
|
|
767
|
-
* find the rightmost node. It is of type `N | null`, which means it can either be a node of type `N`
|
|
765
|
+
* @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node from which we want to
|
|
766
|
+
* find the rightmost node. It is of type `N | null | undefined`, which means it can either be a node of type `N`
|
|
768
767
|
* or `null`. If it is `null`, it means there is no starting node
|
|
769
768
|
* @param iterationType - The `iterationType` parameter is used to determine the type of iteration to
|
|
770
769
|
* be performed when finding the rightmost node in a binary tree. It can have two possible values:
|
|
771
770
|
* @returns The function `getRightMost` returns the rightmost node (`N`) in a binary tree. If the
|
|
772
771
|
* `beginRoot` parameter is `null`, it returns `null`.
|
|
773
772
|
*/
|
|
774
|
-
getRightMost(beginRoot: N | null = this.root, iterationType = this.iterationType): N | null {
|
|
773
|
+
getRightMost(beginRoot: N | null | undefined = this.root, iterationType = this.iterationType): N | null | undefined {
|
|
775
774
|
// TODO support get right most by passing key in
|
|
776
775
|
if (!beginRoot) return beginRoot;
|
|
777
776
|
|
|
@@ -802,7 +801,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
802
801
|
* possible values:
|
|
803
802
|
* @returns The function `isSubtreeBST` returns a boolean value.
|
|
804
803
|
*/
|
|
805
|
-
isSubtreeBST(beginRoot: N | null, iterationType = this.iterationType): boolean {
|
|
804
|
+
isSubtreeBST(beginRoot: N | null | undefined, iterationType = this.iterationType): boolean {
|
|
806
805
|
// TODO there is a bug
|
|
807
806
|
if (!beginRoot) return true;
|
|
808
807
|
|
|
@@ -847,24 +846,24 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
847
846
|
|
|
848
847
|
subTreeTraverse<C extends BTNCallback<N>>(
|
|
849
848
|
callback?: C,
|
|
850
|
-
beginRoot?: BTNKey | N | null,
|
|
849
|
+
beginRoot?: BTNKey | N | null | undefined,
|
|
851
850
|
iterationType?: IterationType,
|
|
852
851
|
includeNull?: false
|
|
853
|
-
): ReturnType<C>[]
|
|
852
|
+
): ReturnType<C>[];
|
|
854
853
|
|
|
855
854
|
subTreeTraverse<C extends BTNCallback<N>>(
|
|
856
855
|
callback?: C,
|
|
857
|
-
beginRoot?: BTNKey | N | null,
|
|
856
|
+
beginRoot?: BTNKey | N | null | undefined,
|
|
858
857
|
iterationType?: IterationType,
|
|
859
858
|
includeNull?: undefined
|
|
860
|
-
): ReturnType<C>[]
|
|
859
|
+
): ReturnType<C>[];
|
|
861
860
|
|
|
862
|
-
subTreeTraverse<C extends BTNCallback<N | null>>(
|
|
861
|
+
subTreeTraverse<C extends BTNCallback<N | null | undefined>>(
|
|
863
862
|
callback?: C,
|
|
864
|
-
beginRoot?: BTNKey | N | null,
|
|
863
|
+
beginRoot?: BTNKey | N | null | undefined,
|
|
865
864
|
iterationType?: IterationType,
|
|
866
865
|
includeNull?: true
|
|
867
|
-
): ReturnType<C>[]
|
|
866
|
+
): ReturnType<C>[];
|
|
868
867
|
|
|
869
868
|
/**
|
|
870
869
|
* The function `subTreeTraverse` traverses a binary tree and applies a callback function to each
|
|
@@ -873,7 +872,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
873
872
|
* subtree traversal. It takes a single argument, which is the current node being traversed, and
|
|
874
873
|
* returns a value. The return values from each callback invocation will be collected and returned as
|
|
875
874
|
* an array.
|
|
876
|
-
* @param {BTNKey | N | null} beginRoot - The `beginRoot` parameter is the starting point
|
|
875
|
+
* @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
|
|
877
876
|
* for traversing the subtree. It can be either a node object, a key value of a node, or `null` to
|
|
878
877
|
* start from the root of the tree.
|
|
879
878
|
* @param iterationType - The `iterationType` parameter determines the type of traversal to be
|
|
@@ -881,75 +880,87 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
881
880
|
* @param includeNull - The choice to output null values during binary tree traversal should be provided.
|
|
882
881
|
* @returns The function `subTreeTraverse` returns an array of `ReturnType<BTNCallback<N>>`.
|
|
883
882
|
*/
|
|
884
|
-
subTreeTraverse<C extends BTNCallback<N | null>>(
|
|
883
|
+
subTreeTraverse<C extends BTNCallback<N | null | undefined>>(
|
|
885
884
|
callback: C = this.defaultOneParamCallback as C,
|
|
886
|
-
beginRoot: BTNKey | N | null = this.root,
|
|
885
|
+
beginRoot: BTNKey | N | null | undefined = this.root,
|
|
887
886
|
iterationType = this.iterationType,
|
|
888
887
|
includeNull = false
|
|
889
888
|
): ReturnType<C>[] {
|
|
890
889
|
if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);
|
|
891
890
|
|
|
892
|
-
const ans: (ReturnType<BTNCallback<N>> | null)[] = [];
|
|
891
|
+
const ans: (ReturnType<BTNCallback<N>> | null | undefined)[] = [];
|
|
893
892
|
if (!beginRoot) return ans;
|
|
894
893
|
|
|
895
894
|
if (iterationType === IterationType.RECURSIVE) {
|
|
896
|
-
const _traverse = (cur: N | null) => {
|
|
895
|
+
const _traverse = (cur: N | null | undefined) => {
|
|
897
896
|
if (cur !== undefined) {
|
|
898
897
|
ans.push(callback(cur));
|
|
899
898
|
if (includeNull) {
|
|
900
|
-
cur
|
|
901
|
-
cur
|
|
899
|
+
cur && this.isNodeOrNull(cur.left) && _traverse(cur.left);
|
|
900
|
+
cur && this.isNodeOrNull(cur.right) && _traverse(cur.right);
|
|
902
901
|
} else {
|
|
903
|
-
cur
|
|
904
|
-
cur
|
|
902
|
+
cur && cur.left && _traverse(cur.left);
|
|
903
|
+
cur && cur.right && _traverse(cur.right);
|
|
905
904
|
}
|
|
906
905
|
}
|
|
907
906
|
};
|
|
908
907
|
|
|
909
908
|
_traverse(beginRoot);
|
|
910
909
|
} else {
|
|
911
|
-
const stack: (N| null)[] = [beginRoot];
|
|
910
|
+
const stack: (N | null | undefined)[] = [beginRoot];
|
|
912
911
|
|
|
913
912
|
while (stack.length > 0) {
|
|
914
913
|
const cur = stack.pop();
|
|
915
914
|
if (cur !== undefined) {
|
|
916
915
|
ans.push(callback(cur));
|
|
917
916
|
if (includeNull) {
|
|
918
|
-
cur
|
|
919
|
-
cur
|
|
917
|
+
cur && this.isNodeOrNull(cur.right) && stack.push(cur.right);
|
|
918
|
+
cur && this.isNodeOrNull(cur.left) && stack.push(cur.left);
|
|
920
919
|
} else {
|
|
921
|
-
cur
|
|
922
|
-
cur
|
|
920
|
+
cur && cur.right && stack.push(cur.right);
|
|
921
|
+
cur && cur.left && stack.push(cur.left);
|
|
923
922
|
}
|
|
924
923
|
}
|
|
925
924
|
}
|
|
926
925
|
}
|
|
927
926
|
return ans;
|
|
928
927
|
}
|
|
928
|
+
|
|
929
|
+
isNode(node: any): node is N {
|
|
930
|
+
return node instanceof BinaryTreeNode && node.key.toString() !== 'NaN';
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
isNIL(node: any) {
|
|
934
|
+
return node instanceof BinaryTreeNode && node.key.toString() === 'NaN';
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
isNodeOrNull(node: any): node is (N | null){
|
|
938
|
+
return this.isNode(node) || node === null;
|
|
939
|
+
}
|
|
929
940
|
|
|
930
941
|
dfs<C extends BTNCallback<N>>(
|
|
931
942
|
callback?: C,
|
|
932
943
|
pattern?: DFSOrderPattern,
|
|
933
|
-
beginRoot?: N | null,
|
|
944
|
+
beginRoot?: N | null | undefined,
|
|
934
945
|
iterationType?: IterationType,
|
|
935
946
|
includeNull?: false
|
|
936
|
-
): ReturnType<C>[]
|
|
947
|
+
): ReturnType<C>[];
|
|
937
948
|
|
|
938
949
|
dfs<C extends BTNCallback<N>>(
|
|
939
950
|
callback?: C,
|
|
940
951
|
pattern?: DFSOrderPattern,
|
|
941
|
-
beginRoot?: N | null,
|
|
952
|
+
beginRoot?: N | null | undefined,
|
|
942
953
|
iterationType?: IterationType,
|
|
943
954
|
includeNull?: undefined
|
|
944
|
-
): ReturnType<C>[]
|
|
955
|
+
): ReturnType<C>[];
|
|
945
956
|
|
|
946
|
-
dfs<C extends BTNCallback<N | null>>(
|
|
957
|
+
dfs<C extends BTNCallback<N | null | undefined>>(
|
|
947
958
|
callback?: C,
|
|
948
959
|
pattern?: DFSOrderPattern,
|
|
949
|
-
beginRoot?: N | null,
|
|
960
|
+
beginRoot?: N | null | undefined,
|
|
950
961
|
iterationType?: IterationType,
|
|
951
962
|
includeNull?: true
|
|
952
|
-
): ReturnType<C>[]
|
|
963
|
+
): ReturnType<C>[];
|
|
953
964
|
|
|
954
965
|
/**
|
|
955
966
|
* The `dfs` function performs a depth-first search traversal on a binary tree, executing a callback
|
|
@@ -959,7 +970,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
959
970
|
* is `this.defaultOneParamCallback`, which is a callback function defined elsewhere in the code.
|
|
960
971
|
* @param {DFSOrderPattern} [pattern=in] - The `pattern` parameter determines the order in which the
|
|
961
972
|
* nodes are visited during the depth-first search. There are three possible values for `pattern`:
|
|
962
|
-
* @param {N | null} beginRoot - The `beginRoot` parameter is the starting node for the depth-first
|
|
973
|
+
* @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node for the depth-first
|
|
963
974
|
* search. It determines where the search will begin in the tree or graph structure. If `beginRoot`
|
|
964
975
|
* is `null`, an empty array will be returned.
|
|
965
976
|
* @param {IterationType} iterationType - The `iterationType` parameter determines the type of
|
|
@@ -967,49 +978,49 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
967
978
|
* @param includeNull - The choice to output null values during binary tree traversal should be provided.
|
|
968
979
|
* @returns The function `dfs` returns an array of `ReturnType<BTNCallback<N>>` values.
|
|
969
980
|
*/
|
|
970
|
-
dfs<C extends BTNCallback<N | null>>(
|
|
981
|
+
dfs<C extends BTNCallback<N | null | undefined>>(
|
|
971
982
|
callback: C = this.defaultOneParamCallback as C,
|
|
972
983
|
pattern: DFSOrderPattern = 'in',
|
|
973
|
-
beginRoot: N | null = this.root,
|
|
984
|
+
beginRoot: N | null | undefined = this.root,
|
|
974
985
|
iterationType: IterationType = IterationType.ITERATIVE,
|
|
975
986
|
includeNull = false
|
|
976
987
|
): ReturnType<C>[] {
|
|
977
988
|
if (!beginRoot) return [];
|
|
978
989
|
const ans: ReturnType<C>[] = [];
|
|
979
990
|
if (iterationType === IterationType.RECURSIVE) {
|
|
980
|
-
const _traverse = (node: N | null) => {
|
|
991
|
+
const _traverse = (node: N | null | undefined) => {
|
|
981
992
|
switch (pattern) {
|
|
982
993
|
case 'in':
|
|
983
994
|
if (includeNull) {
|
|
984
|
-
if (node
|
|
985
|
-
ans.push(callback(node));
|
|
986
|
-
if (node
|
|
995
|
+
if (node && this.isNodeOrNull(node.left)) _traverse(node.left);
|
|
996
|
+
this.isNodeOrNull(node) && ans.push(callback(node));
|
|
997
|
+
if (node && this.isNodeOrNull(node.right)) _traverse(node.right);
|
|
987
998
|
} else {
|
|
988
|
-
if (node
|
|
989
|
-
ans.push(callback(node));
|
|
990
|
-
if (node
|
|
999
|
+
if (node && node.left) _traverse(node.left);
|
|
1000
|
+
this.isNode(node) && ans.push(callback(node));
|
|
1001
|
+
if (node && node.right) _traverse(node.right);
|
|
991
1002
|
}
|
|
992
1003
|
break;
|
|
993
1004
|
case 'pre':
|
|
994
1005
|
if (includeNull) {
|
|
995
|
-
ans.push(callback(node));
|
|
996
|
-
if (node
|
|
997
|
-
if (node
|
|
1006
|
+
this.isNodeOrNull(node) && ans.push(callback(node));
|
|
1007
|
+
if (node && this.isNodeOrNull(node.left)) _traverse(node.left);
|
|
1008
|
+
if (node && this.isNodeOrNull(node.right)) _traverse(node.right);
|
|
998
1009
|
} else {
|
|
999
|
-
ans.push(callback(node));
|
|
1000
|
-
if (node
|
|
1001
|
-
if (node
|
|
1010
|
+
this.isNode(node) && ans.push(callback(node));
|
|
1011
|
+
if (node && node.left) _traverse(node.left);
|
|
1012
|
+
if (node && node.right) _traverse(node.right);
|
|
1002
1013
|
}
|
|
1003
1014
|
break;
|
|
1004
1015
|
case 'post':
|
|
1005
1016
|
if (includeNull) {
|
|
1006
|
-
if (node
|
|
1007
|
-
if (node
|
|
1008
|
-
ans.push(callback(node));
|
|
1017
|
+
if (node && this.isNodeOrNull(node.left)) _traverse(node.left);
|
|
1018
|
+
if (node && this.isNodeOrNull(node.right)) _traverse(node.right);
|
|
1019
|
+
this.isNodeOrNull(node) && ans.push(callback(node));
|
|
1009
1020
|
} else {
|
|
1010
|
-
if (node
|
|
1011
|
-
if (node
|
|
1012
|
-
ans.push(callback(node));
|
|
1021
|
+
if (node && node.left) _traverse(node.left);
|
|
1022
|
+
if (node && node.right) _traverse(node.right);
|
|
1023
|
+
this.isNode(node) && ans.push(callback(node));
|
|
1013
1024
|
}
|
|
1014
1025
|
|
|
1015
1026
|
break;
|
|
@@ -1019,11 +1030,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1019
1030
|
_traverse(beginRoot);
|
|
1020
1031
|
} else {
|
|
1021
1032
|
// 0: visit, 1: print
|
|
1022
|
-
const stack: {
|
|
1033
|
+
const stack: {opt: 0 | 1; node: N | null | undefined}[] = [{opt: 0, node: beginRoot}];
|
|
1023
1034
|
|
|
1024
1035
|
while (stack.length > 0) {
|
|
1025
1036
|
const cur = stack.pop();
|
|
1026
|
-
if (cur === undefined) continue;
|
|
1037
|
+
if (cur === undefined || this.isNIL(cur.node)) continue;
|
|
1027
1038
|
if (includeNull) {
|
|
1028
1039
|
if (cur.node === undefined) continue;
|
|
1029
1040
|
} else {
|
|
@@ -1063,24 +1074,24 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1063
1074
|
|
|
1064
1075
|
bfs<C extends BTNCallback<N>>(
|
|
1065
1076
|
callback?: C,
|
|
1066
|
-
beginRoot?: N | null,
|
|
1077
|
+
beginRoot?: N | null | undefined,
|
|
1067
1078
|
iterationType?: IterationType,
|
|
1068
1079
|
includeNull?: false
|
|
1069
|
-
): ReturnType<C>[]
|
|
1080
|
+
): ReturnType<C>[];
|
|
1070
1081
|
|
|
1071
1082
|
bfs<C extends BTNCallback<N>>(
|
|
1072
1083
|
callback?: C,
|
|
1073
|
-
beginRoot?: N | null,
|
|
1084
|
+
beginRoot?: N | null | undefined,
|
|
1074
1085
|
iterationType?: IterationType,
|
|
1075
1086
|
includeNull?: undefined
|
|
1076
|
-
): ReturnType<C>[]
|
|
1087
|
+
): ReturnType<C>[];
|
|
1077
1088
|
|
|
1078
|
-
bfs<C extends BTNCallback<N | null>>(
|
|
1089
|
+
bfs<C extends BTNCallback<N | null | undefined>>(
|
|
1079
1090
|
callback?: C,
|
|
1080
|
-
beginRoot?: N | null,
|
|
1091
|
+
beginRoot?: N | null | undefined,
|
|
1081
1092
|
iterationType?: IterationType,
|
|
1082
1093
|
includeNull?: true
|
|
1083
|
-
): ReturnType<C>[]
|
|
1094
|
+
): ReturnType<C>[];
|
|
1084
1095
|
|
|
1085
1096
|
/**
|
|
1086
1097
|
* The bfs function performs a breadth-first search traversal on a binary tree, executing a callback
|
|
@@ -1088,7 +1099,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1088
1099
|
* @param callback - The `callback` parameter is a function that will be called for each node in the
|
|
1089
1100
|
* breadth-first search. It takes a node of type `N` as its argument and returns a value of type
|
|
1090
1101
|
* `ReturnType<BTNCallback<N>>`. The default value for this parameter is `this.defaultOneParamCallback
|
|
1091
|
-
* @param {N | null} beginRoot - The `beginRoot` parameter is the starting node for the breadth-first
|
|
1102
|
+
* @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node for the breadth-first
|
|
1092
1103
|
* search. It determines from which node the search will begin. If `beginRoot` is `null`, the search
|
|
1093
1104
|
* will not be performed and an empty array will be returned.
|
|
1094
1105
|
* @param iterationType - The `iterationType` parameter determines the type of iteration to be used
|
|
@@ -1096,9 +1107,9 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1096
1107
|
* @param includeNull - The choice to output null values during binary tree traversal should be provided.
|
|
1097
1108
|
* @returns The function `bfs` returns an array of `ReturnType<BTNCallback<N>>[]`.
|
|
1098
1109
|
*/
|
|
1099
|
-
bfs<C extends BTNCallback<N | null>>(
|
|
1110
|
+
bfs<C extends BTNCallback<N | null | undefined>>(
|
|
1100
1111
|
callback: C = this.defaultOneParamCallback as C,
|
|
1101
|
-
beginRoot: N | null = this.root,
|
|
1112
|
+
beginRoot: N | null | undefined = this.root,
|
|
1102
1113
|
iterationType = this.iterationType,
|
|
1103
1114
|
includeNull = false
|
|
1104
1115
|
): ReturnType<C>[] {
|
|
@@ -1107,7 +1118,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1107
1118
|
const ans: ReturnType<BTNCallback<N>>[] = [];
|
|
1108
1119
|
|
|
1109
1120
|
if (iterationType === IterationType.RECURSIVE) {
|
|
1110
|
-
const queue: Queue<N | null> = new Queue<N | null>([beginRoot]);
|
|
1121
|
+
const queue: Queue<N | null | undefined> = new Queue<N | null | undefined>([beginRoot]);
|
|
1111
1122
|
|
|
1112
1123
|
const traverse = (level: number) => {
|
|
1113
1124
|
if (queue.size === 0) return;
|
|
@@ -1116,20 +1127,19 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1116
1127
|
ans.push(callback(current));
|
|
1117
1128
|
|
|
1118
1129
|
if (includeNull) {
|
|
1119
|
-
if (current && current.left
|
|
1120
|
-
if (current && current.right
|
|
1130
|
+
if (current && this.isNodeOrNull(current.left)) queue.push(current.left);
|
|
1131
|
+
if (current && this.isNodeOrNull(current.right)) queue.push(current.right);
|
|
1121
1132
|
} else {
|
|
1122
1133
|
if (current.left) queue.push(current.left);
|
|
1123
1134
|
if (current.right) queue.push(current.right);
|
|
1124
1135
|
}
|
|
1125
1136
|
|
|
1126
|
-
|
|
1127
1137
|
traverse(level + 1);
|
|
1128
1138
|
};
|
|
1129
1139
|
|
|
1130
1140
|
traverse(0);
|
|
1131
1141
|
} else {
|
|
1132
|
-
const queue = new Queue<N | null>([beginRoot]);
|
|
1142
|
+
const queue = new Queue<N | null | undefined>([beginRoot]);
|
|
1133
1143
|
while (queue.size > 0) {
|
|
1134
1144
|
const levelSize = queue.size;
|
|
1135
1145
|
|
|
@@ -1138,13 +1148,12 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1138
1148
|
ans.push(callback(current));
|
|
1139
1149
|
|
|
1140
1150
|
if (includeNull) {
|
|
1141
|
-
if (current
|
|
1142
|
-
if (current
|
|
1151
|
+
if (current && this.isNodeOrNull(current.left)) queue.push(current.left);
|
|
1152
|
+
if (current && this.isNodeOrNull(current.right)) queue.push(current.right);
|
|
1143
1153
|
} else {
|
|
1144
1154
|
if (current.left) queue.push(current.left);
|
|
1145
1155
|
if (current.right) queue.push(current.right);
|
|
1146
1156
|
}
|
|
1147
|
-
|
|
1148
1157
|
}
|
|
1149
1158
|
}
|
|
1150
1159
|
}
|
|
@@ -1152,25 +1161,25 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1152
1161
|
}
|
|
1153
1162
|
|
|
1154
1163
|
listLevels<C extends BTNCallback<N>>(
|
|
1155
|
-
callback?: C
|
|
1156
|
-
beginRoot?: N | null ,
|
|
1164
|
+
callback?: C,
|
|
1165
|
+
beginRoot?: N | null | undefined,
|
|
1157
1166
|
iterationType?: IterationType,
|
|
1158
1167
|
includeNull?: false
|
|
1159
|
-
): ReturnType<C>[][]
|
|
1168
|
+
): ReturnType<C>[][];
|
|
1160
1169
|
|
|
1161
1170
|
listLevels<C extends BTNCallback<N>>(
|
|
1162
|
-
callback?: C
|
|
1163
|
-
beginRoot?: N | null ,
|
|
1171
|
+
callback?: C,
|
|
1172
|
+
beginRoot?: N | null | undefined,
|
|
1164
1173
|
iterationType?: IterationType,
|
|
1165
1174
|
includeNull?: undefined
|
|
1166
|
-
): ReturnType<C>[][]
|
|
1175
|
+
): ReturnType<C>[][];
|
|
1167
1176
|
|
|
1168
|
-
listLevels<C extends BTNCallback<N | null>>(
|
|
1169
|
-
callback?: C
|
|
1170
|
-
beginRoot?: N | null ,
|
|
1177
|
+
listLevels<C extends BTNCallback<N | null | undefined>>(
|
|
1178
|
+
callback?: C,
|
|
1179
|
+
beginRoot?: N | null | undefined,
|
|
1171
1180
|
iterationType?: IterationType,
|
|
1172
1181
|
includeNull?: true
|
|
1173
|
-
): ReturnType<C>[][]
|
|
1182
|
+
): ReturnType<C>[][];
|
|
1174
1183
|
|
|
1175
1184
|
/**
|
|
1176
1185
|
* The `listLevels` function takes a binary tree node and a callback function, and returns an array
|
|
@@ -1178,7 +1187,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1178
1187
|
* @param {C} callback - The `callback` parameter is a function that will be called on each node in
|
|
1179
1188
|
* the tree. It takes a node as input and returns a value. The return type of the callback function
|
|
1180
1189
|
* is determined by the generic type `C`.
|
|
1181
|
-
* @param {N | null} beginRoot - The `beginRoot` parameter represents the starting node of the binary tree
|
|
1190
|
+
* @param {N | null | undefined} beginRoot - The `beginRoot` parameter represents the starting node of the binary tree
|
|
1182
1191
|
* traversal. It can be any node in the binary tree. If no node is provided, the traversal will start
|
|
1183
1192
|
* from the root node of the binary tree.
|
|
1184
1193
|
* @param iterationType - The `iterationType` parameter determines whether the tree traversal is done
|
|
@@ -1188,9 +1197,9 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1188
1197
|
* level in a binary tree. Each inner array contains the return type of the provided callback
|
|
1189
1198
|
* function `C` applied to the nodes at that level.
|
|
1190
1199
|
*/
|
|
1191
|
-
listLevels<C extends BTNCallback<N | null>>(
|
|
1200
|
+
listLevels<C extends BTNCallback<N | null | undefined>>(
|
|
1192
1201
|
callback: C = this.defaultOneParamCallback as C,
|
|
1193
|
-
beginRoot: N | null = this.root,
|
|
1202
|
+
beginRoot: N | null | undefined = this.root,
|
|
1194
1203
|
iterationType = this.iterationType,
|
|
1195
1204
|
includeNull = false
|
|
1196
1205
|
): ReturnType<C>[][] {
|
|
@@ -1198,13 +1207,13 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1198
1207
|
const levelsNodes: ReturnType<C>[][] = [];
|
|
1199
1208
|
|
|
1200
1209
|
if (iterationType === IterationType.RECURSIVE) {
|
|
1201
|
-
const _recursive = (node: N | null, level: number) => {
|
|
1210
|
+
const _recursive = (node: N | null | undefined, level: number) => {
|
|
1202
1211
|
if (!levelsNodes[level]) levelsNodes[level] = [];
|
|
1203
1212
|
levelsNodes[level].push(callback(node));
|
|
1204
1213
|
if (includeNull) {
|
|
1205
|
-
if (node && node.left
|
|
1206
|
-
if (node && node.right
|
|
1207
|
-
} else
|
|
1214
|
+
if (node && this.isNodeOrNull(node.left)) _recursive(node.left, level + 1);
|
|
1215
|
+
if (node && this.isNodeOrNull(node.right)) _recursive(node.right, level + 1);
|
|
1216
|
+
} else {
|
|
1208
1217
|
if (node && node.left) _recursive(node.left, level + 1);
|
|
1209
1218
|
if (node && node.right) _recursive(node.right, level + 1);
|
|
1210
1219
|
}
|
|
@@ -1212,7 +1221,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1212
1221
|
|
|
1213
1222
|
_recursive(beginRoot, 0);
|
|
1214
1223
|
} else {
|
|
1215
|
-
const stack: [N | null, number][] = [[beginRoot, 0]];
|
|
1224
|
+
const stack: [N | null | undefined, number][] = [[beginRoot, 0]];
|
|
1216
1225
|
|
|
1217
1226
|
while (stack.length > 0) {
|
|
1218
1227
|
const head = stack.pop()!;
|
|
@@ -1222,9 +1231,9 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1222
1231
|
levelsNodes[level].push(callback(node));
|
|
1223
1232
|
|
|
1224
1233
|
if (includeNull) {
|
|
1225
|
-
if (node && node.right
|
|
1226
|
-
if (node && node.left
|
|
1227
|
-
} else
|
|
1234
|
+
if (node && this.isNodeOrNull(node.right)) stack.push([node.right, level + 1]);
|
|
1235
|
+
if (node && this.isNodeOrNull(node.left)) stack.push([node.left, level + 1]);
|
|
1236
|
+
} else {
|
|
1228
1237
|
if (node && node.right) stack.push([node.right, level + 1]);
|
|
1229
1238
|
if (node && node.left) stack.push([node.left, level + 1]);
|
|
1230
1239
|
}
|
|
@@ -1273,8 +1282,6 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1273
1282
|
return y;
|
|
1274
1283
|
}
|
|
1275
1284
|
|
|
1276
|
-
// --- start additional methods ---
|
|
1277
|
-
|
|
1278
1285
|
/**
|
|
1279
1286
|
* The `morris` function performs a depth-first traversal of a binary tree using the Morris traversal
|
|
1280
1287
|
* algorithm and returns an array of values obtained by applying a callback function to each node.
|
|
@@ -1284,7 +1291,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1284
1291
|
* @param {DFSOrderPattern} [pattern=in] - The `pattern` parameter in the `morris` function
|
|
1285
1292
|
* determines the order in which the nodes of a binary tree are traversed. It can have one of the
|
|
1286
1293
|
* following values:
|
|
1287
|
-
* @param {N | null} beginRoot - The `beginRoot` parameter is the starting node for the Morris
|
|
1294
|
+
* @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node for the Morris
|
|
1288
1295
|
* traversal. It specifies the root node of the tree from which the traversal should begin. If
|
|
1289
1296
|
* `beginRoot` is `null`, an empty array will be returned.
|
|
1290
1297
|
* @returns The `morris` function returns an array of `ReturnType<BTNCallback<N>>` values.
|
|
@@ -1292,7 +1299,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1292
1299
|
morris<C extends BTNCallback<N>>(
|
|
1293
1300
|
callback: C = this.defaultOneParamCallback as C,
|
|
1294
1301
|
pattern: DFSOrderPattern = 'in',
|
|
1295
|
-
beginRoot: N | null = this.root
|
|
1302
|
+
beginRoot: N | null | undefined = this.root
|
|
1296
1303
|
): ReturnType<C>[] {
|
|
1297
1304
|
if (beginRoot === null) return [];
|
|
1298
1305
|
const ans: ReturnType<BTNCallback<N>>[] = [];
|
|
@@ -1309,7 +1316,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1309
1316
|
}
|
|
1310
1317
|
return pre;
|
|
1311
1318
|
};
|
|
1312
|
-
const _printEdge = (node: N | null) => {
|
|
1319
|
+
const _printEdge = (node: N | null | undefined) => {
|
|
1313
1320
|
const tail: N | null | undefined = _reverseEdge(node);
|
|
1314
1321
|
let cur: N | null | undefined = tail;
|
|
1315
1322
|
while (cur) {
|
|
@@ -1374,6 +1381,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1374
1381
|
return ans;
|
|
1375
1382
|
}
|
|
1376
1383
|
|
|
1384
|
+
// --- start additional methods ---
|
|
1385
|
+
|
|
1377
1386
|
/**
|
|
1378
1387
|
* The above function is an iterator for a binary tree that can be used to traverse the tree in
|
|
1379
1388
|
* either an iterative or recursive manner.
|
|
@@ -1383,7 +1392,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1383
1392
|
* @returns The `*[Symbol.iterator]` method returns a generator object that yields the keys of the
|
|
1384
1393
|
* binary tree nodes in a specific order.
|
|
1385
1394
|
*/
|
|
1386
|
-
*
|
|
1395
|
+
*[Symbol.iterator](node = this.root): Generator<BTNKey, void, undefined> {
|
|
1387
1396
|
if (!node) {
|
|
1388
1397
|
return;
|
|
1389
1398
|
}
|
|
@@ -1416,6 +1425,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1416
1425
|
}
|
|
1417
1426
|
}
|
|
1418
1427
|
|
|
1428
|
+
protected defaultOneParamCallback = (node: N) => node.key;
|
|
1429
|
+
|
|
1419
1430
|
/**
|
|
1420
1431
|
* Swap the data of two nodes in the binary tree.
|
|
1421
1432
|
* @param {N} srcNode - The source node to swap.
|
|
@@ -1439,7 +1450,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1439
1450
|
|
|
1440
1451
|
/**
|
|
1441
1452
|
* The function `_addTo` adds a new node to a binary tree if there is an available position.
|
|
1442
|
-
* @param {N | null} newNode - The `newNode` parameter represents the node that you want to add to
|
|
1453
|
+
* @param {N | null | undefined} newNode - The `newNode` parameter represents the node that you want to add to
|
|
1443
1454
|
* the binary tree. It can be either a node object or `null`.
|
|
1444
1455
|
* @param {N} parent - The `parent` parameter represents the parent node to which the new node will
|
|
1445
1456
|
* be added as a child.
|
|
@@ -1448,7 +1459,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1448
1459
|
* the binary tree. If neither the left nor right child is available, the function returns undefined.
|
|
1449
1460
|
* If the parent node is null, the function also returns undefined.
|
|
1450
1461
|
*/
|
|
1451
|
-
protected _addTo(newNode: N | null, parent: N): N | null | undefined {
|
|
1462
|
+
protected _addTo(newNode: N | null | undefined, parent: N): N | null | undefined {
|
|
1452
1463
|
if (parent) {
|
|
1453
1464
|
// When all leaf nodes are null, it will no longer be possible to add new entity nodes to this binary tree.
|
|
1454
1465
|
// In this scenario, null nodes serve as "sentinel nodes," "virtual nodes," or "placeholder nodes."
|
|
@@ -1475,15 +1486,73 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1475
1486
|
/**
|
|
1476
1487
|
* The function sets the root property of an object to a given value, and if the value is not null,
|
|
1477
1488
|
* it also sets the parent property of the value to undefined.
|
|
1478
|
-
* @param {N | null} v - The parameter `v` is of type `N | null`, which means it can either be of
|
|
1489
|
+
* @param {N | null | undefined} v - The parameter `v` is of type `N | null | undefined`, which means it can either be of
|
|
1479
1490
|
* type `N` or `null`.
|
|
1480
1491
|
*/
|
|
1481
|
-
protected _setRoot(v: N | null) {
|
|
1492
|
+
protected _setRoot(v: N | null | undefined) {
|
|
1482
1493
|
if (v) {
|
|
1483
1494
|
v.parent = undefined;
|
|
1484
1495
|
}
|
|
1485
1496
|
this._root = v;
|
|
1486
1497
|
}
|
|
1487
1498
|
|
|
1499
|
+
print(beginRoot: N | null | undefined = this.root) {
|
|
1500
|
+
const display = (root: N | null | undefined): void => {
|
|
1501
|
+
const [lines, , ,] = _displayAux(root);
|
|
1502
|
+
for (const line of lines) {
|
|
1503
|
+
console.log(line);
|
|
1504
|
+
}
|
|
1505
|
+
};
|
|
1506
|
+
|
|
1507
|
+
const _displayAux = (node: N | null | undefined): [string[], number, number, number] => {
|
|
1508
|
+
if (node === undefined || node === null) {
|
|
1509
|
+
return [[], 0, 0, 0];
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
if (node && node.right === undefined && node.left === undefined) {
|
|
1513
|
+
const line = `${node.key}`;
|
|
1514
|
+
const width = line.length;
|
|
1515
|
+
const height = 1;
|
|
1516
|
+
const middle = Math.floor(width / 2);
|
|
1517
|
+
return [[line], width, height, middle];
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
if (node && node.right === undefined) {
|
|
1521
|
+
const [lines, n, p, x] = _displayAux(node.left);
|
|
1522
|
+
const s = `${node.key}`;
|
|
1523
|
+
const u = s.length;
|
|
1524
|
+
const first_line = ' '.repeat(x + 1) + '_'.repeat(n - x - 1) + s;
|
|
1525
|
+
const second_line = ' '.repeat(x) + '/' + ' '.repeat(n - x - 1 + u);
|
|
1526
|
+
const shifted_lines = lines.map(line => line + ' '.repeat(u));
|
|
1527
|
+
return [[first_line, second_line, ...shifted_lines], n + u, p + 2, n + Math.floor(u / 2)];
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
if (node && node.left === undefined) {
|
|
1531
|
+
const [lines, n, p, u] = _displayAux(node.right);
|
|
1532
|
+
const s = `${node.key}`;
|
|
1533
|
+
const x = s.length;
|
|
1534
|
+
const first_line = s + '_'.repeat(x) + ' '.repeat(n - x);
|
|
1535
|
+
const second_line = ' '.repeat(u + x) + '\\' + ' '.repeat(n - x - 1);
|
|
1536
|
+
const shifted_lines = lines.map(line => ' '.repeat(u) + line);
|
|
1537
|
+
return [[first_line, second_line, ...shifted_lines], n + x, p + 2, Math.floor(u / 2)];
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
const [left, n, p, x] = _displayAux(node.left);
|
|
1541
|
+
const [right, m, q, y] = _displayAux(node.right);
|
|
1542
|
+
const s = `${node.key}`;
|
|
1543
|
+
const u = s.length;
|
|
1544
|
+
const first_line = ' '.repeat(x + 1) + '_'.repeat(n - x - 1) + s + '_'.repeat(y) + ' '.repeat(m - y);
|
|
1545
|
+
const second_line = ' '.repeat(x) + '/' + ' '.repeat(n - x - 1 + u + y) + '\\' + ' '.repeat(m - y - 1);
|
|
1546
|
+
if (p < q) {
|
|
1547
|
+
left.push(...new Array(q - p).fill(' '.repeat(n)));
|
|
1548
|
+
} else if (q < p) {
|
|
1549
|
+
right.push(...new Array(p - q).fill(' '.repeat(m)));
|
|
1550
|
+
}
|
|
1551
|
+
const zipped_lines = left.map((a, i) => a + ' '.repeat(u) + right[i]);
|
|
1552
|
+
return [[first_line, second_line, ...zipped_lines], n + m + u, Math.max(p, q) + 2, n + Math.floor(u / 2)];
|
|
1553
|
+
};
|
|
1554
|
+
|
|
1555
|
+
display(beginRoot);
|
|
1556
|
+
}
|
|
1488
1557
|
// --- end additional methods ---
|
|
1489
1558
|
}
|