data-structure-typed 1.37.2 → 1.37.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3 -1
- package/dist/data-structures/binary-tree/avl-tree.d.ts +5 -7
- package/dist/data-structures/binary-tree/avl-tree.js +7 -9
- package/dist/data-structures/binary-tree/avl-tree.js.map +1 -1
- package/dist/data-structures/binary-tree/binary-tree.d.ts +36 -20
- package/dist/data-structures/binary-tree/binary-tree.js +66 -50
- package/dist/data-structures/binary-tree/binary-tree.js.map +1 -1
- package/dist/data-structures/binary-tree/bst.d.ts +15 -13
- package/dist/data-structures/binary-tree/bst.js +35 -33
- package/dist/data-structures/binary-tree/bst.js.map +1 -1
- package/dist/data-structures/binary-tree/tree-multiset.d.ts +2 -2
- package/dist/data-structures/binary-tree/tree-multiset.js +2 -2
- package/dist/data-structures/binary-tree/tree-multiset.js.map +1 -1
- package/dist/types/data-structures/binary-tree.d.ts +2 -2
- package/dist/types/data-structures/binary-tree.js +6 -6
- package/dist/types/data-structures/binary-tree.js.map +1 -1
- package/lib/data-structures/binary-tree/avl-tree.d.ts +5 -7
- package/lib/data-structures/binary-tree/avl-tree.js +7 -9
- package/lib/data-structures/binary-tree/binary-tree.d.ts +36 -20
- package/lib/data-structures/binary-tree/binary-tree.js +67 -51
- package/lib/data-structures/binary-tree/bst.d.ts +15 -13
- package/lib/data-structures/binary-tree/bst.js +36 -34
- package/lib/data-structures/binary-tree/tree-multiset.d.ts +2 -2
- package/lib/data-structures/binary-tree/tree-multiset.js +3 -3
- package/lib/types/data-structures/binary-tree.d.ts +2 -2
- package/lib/types/data-structures/binary-tree.js +5 -5
- package/package.json +6 -6
- package/src/data-structures/binary-tree/avl-tree.ts +7 -9
- package/src/data-structures/binary-tree/binary-tree.ts +79 -54
- package/src/data-structures/binary-tree/bst.ts +37 -32
- package/src/data-structures/binary-tree/tree-multiset.ts +3 -3
- package/src/types/data-structures/binary-tree.ts +2 -2
- package/test/config.ts +1 -0
- package/test/integration/avl-tree.test.ts +7 -8
- package/test/integration/bst.test.ts +17 -16
- package/test/unit/data-structures/binary-tree/binary-tree.test.ts +50 -0
- package/test/unit/data-structures/binary-tree/bst.test.ts +8 -1
- package/test/unit/data-structures/binary-tree/tree-multiset.test.ts +2 -1
- package/test/unit/data-structures/linked-list/linked-list.test.ts +1 -1
- package/test/utils/big-o.ts +2 -1
- package/umd/bundle.min.js +1 -1
- package/umd/bundle.min.js.map +1 -1
|
@@ -15,12 +15,7 @@ import type {
|
|
|
15
15
|
MapCallback,
|
|
16
16
|
MapCallbackReturn
|
|
17
17
|
} from '../../types';
|
|
18
|
-
import {
|
|
19
|
-
BinaryTreeDeletedResult,
|
|
20
|
-
DFSOrderPattern,
|
|
21
|
-
FamilyPosition,
|
|
22
|
-
LoopType
|
|
23
|
-
} from '../../types';
|
|
18
|
+
import {BinaryTreeDeletedResult, DFSOrderPattern, FamilyPosition, IterationType} from '../../types';
|
|
24
19
|
import {IBinaryTree} from '../../interfaces';
|
|
25
20
|
import {trampoline} from '../../utils';
|
|
26
21
|
import {Queue} from '../queue';
|
|
@@ -111,8 +106,8 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|
|
111
106
|
*/
|
|
112
107
|
constructor(options?: BinaryTreeOptions) {
|
|
113
108
|
if (options !== undefined) {
|
|
114
|
-
const {
|
|
115
|
-
this._loopType =
|
|
109
|
+
const {iterationType = IterationType.ITERATIVE} = options;
|
|
110
|
+
this._loopType = iterationType;
|
|
116
111
|
}
|
|
117
112
|
}
|
|
118
113
|
|
|
@@ -141,13 +136,13 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|
|
141
136
|
return this._size;
|
|
142
137
|
}
|
|
143
138
|
|
|
144
|
-
private _loopType:
|
|
139
|
+
private _loopType: IterationType = IterationType.ITERATIVE;
|
|
145
140
|
|
|
146
|
-
get
|
|
141
|
+
get iterationType(): IterationType {
|
|
147
142
|
return this._loopType;
|
|
148
143
|
}
|
|
149
144
|
|
|
150
|
-
set
|
|
145
|
+
set iterationType(v: IterationType) {
|
|
151
146
|
this._loopType = v;
|
|
152
147
|
}
|
|
153
148
|
|
|
@@ -372,13 +367,14 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|
|
372
367
|
* @param {N | BinaryTreeNodeKey | null} [beginRoot] - The `beginRoot` parameter is optional and can be of type `N` (a
|
|
373
368
|
* generic type representing a node in a binary tree), `BinaryTreeNodeKey` (a type representing the ID of a binary tree
|
|
374
369
|
* node), or `null`.
|
|
370
|
+
* @param iterationType - The `iterationType` parameter is an optional parameter of type `IterationType`. It represents the type of
|
|
375
371
|
* @returns the height of the binary tree.
|
|
376
372
|
*/
|
|
377
|
-
getHeight(beginRoot: N | BinaryTreeNodeKey | null = this.root): number {
|
|
373
|
+
getHeight(beginRoot: N | BinaryTreeNodeKey | null = this.root, iterationType = this.iterationType): number {
|
|
378
374
|
if (typeof beginRoot === 'number') beginRoot = this.get(beginRoot);
|
|
379
375
|
if (!beginRoot) return -1;
|
|
380
376
|
|
|
381
|
-
if (
|
|
377
|
+
if (iterationType === IterationType.RECURSIVE) {
|
|
382
378
|
const _getMaxHeight = (cur: N | null | undefined): number => {
|
|
383
379
|
if (!cur) return -1;
|
|
384
380
|
const leftHeight = _getMaxHeight(cur.left);
|
|
@@ -421,12 +417,13 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|
|
421
417
|
* @param {N | null} [beginRoot] - The `beginRoot` parameter is an optional parameter of type `N` or `null`. It
|
|
422
418
|
* represents the starting node from which to calculate the minimum height of a binary tree. If no value is provided
|
|
423
419
|
* for `beginRoot`, the `this.root` property is used as the default value.
|
|
420
|
+
* @param iterationType - The `iterationType` parameter is an optional parameter of type `IterationType`. It represents the type of loop
|
|
424
421
|
* @returns The function `getMinHeight` returns the minimum height of the binary tree.
|
|
425
422
|
*/
|
|
426
|
-
getMinHeight(beginRoot: N | null = this.root): number {
|
|
423
|
+
getMinHeight(beginRoot: N | null = this.root, iterationType = this.iterationType): number {
|
|
427
424
|
if (!beginRoot) return -1;
|
|
428
425
|
|
|
429
|
-
if (
|
|
426
|
+
if (iterationType === IterationType.RECURSIVE) {
|
|
430
427
|
const _getMinHeight = (cur: N | null | undefined): number => {
|
|
431
428
|
if (!cur) return 0;
|
|
432
429
|
if (!cur.left && !cur.right) return 0;
|
|
@@ -486,19 +483,21 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|
|
486
483
|
* return only one node that matches the given `nodeProperty` or `propertyName`. If `onlyOne` is set to `true`, the
|
|
487
484
|
* function will stop traversing the tree and return the first matching node. If `only
|
|
488
485
|
* @param beginRoot
|
|
486
|
+
* @param iterationType - The `iterationType` parameter is an optional parameter of type `IterationType`. It represents the type of loop
|
|
489
487
|
* @returns an array of nodes (type N).
|
|
490
488
|
*/
|
|
491
489
|
getNodes(
|
|
492
490
|
nodeProperty: BinaryTreeNodeKey | N,
|
|
493
491
|
callback: MapCallback<N> = this._defaultCallbackByKey,
|
|
494
492
|
onlyOne = false,
|
|
495
|
-
beginRoot: N | null = this.root
|
|
493
|
+
beginRoot: N | null = this.root,
|
|
494
|
+
iterationType = this.iterationType
|
|
496
495
|
): N[] {
|
|
497
496
|
if (!beginRoot) return [];
|
|
498
497
|
|
|
499
498
|
const ans: N[] = [];
|
|
500
499
|
|
|
501
|
-
if (
|
|
500
|
+
if (iterationType === IterationType.RECURSIVE) {
|
|
502
501
|
const _traverse = (cur: N) => {
|
|
503
502
|
if (callback(cur) === nodeProperty) {
|
|
504
503
|
ans.push(cur);
|
|
@@ -534,11 +533,18 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|
|
534
533
|
* @param {BinaryTreeNodeKey | N} nodeProperty - The `nodeProperty` parameter can be either a `BinaryTreeNodeKey` or `N`.
|
|
535
534
|
* It represents the property of the binary tree node that you want to check.
|
|
536
535
|
* specifies the name of the property to be checked in the nodes. If not provided, it defaults to 'key'.
|
|
536
|
+
* @param beginRoot - The `beginRoot` parameter is an optional parameter of type `N` or `null`. It represents the root node of a tree or null if the tree is empty.
|
|
537
|
+
* @param iterationType - The `iterationType` parameter is an optional parameter of type `IterationType`. It represents the type of loop
|
|
537
538
|
* @returns a boolean value.
|
|
538
539
|
*/
|
|
539
|
-
has(
|
|
540
|
+
has(
|
|
541
|
+
nodeProperty: BinaryTreeNodeKey | N,
|
|
542
|
+
callback: MapCallback<N> = this._defaultCallbackByKey,
|
|
543
|
+
beginRoot = this.root,
|
|
544
|
+
iterationType = this.iterationType
|
|
545
|
+
): boolean {
|
|
540
546
|
// TODO may support finding node by value equal
|
|
541
|
-
return this.getNodes(nodeProperty, callback, true).length > 0;
|
|
547
|
+
return this.getNodes(nodeProperty, callback, true, beginRoot, iterationType).length > 0;
|
|
542
548
|
}
|
|
543
549
|
|
|
544
550
|
/**
|
|
@@ -549,12 +555,19 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|
|
549
555
|
* It represents the property of the binary tree node that you want to search for.
|
|
550
556
|
* specifies the property name to be used for searching the binary tree nodes. If this parameter is not provided, the
|
|
551
557
|
* default value is set to `'key'`.
|
|
558
|
+
* @param beginRoot - The `beginRoot` parameter is an optional parameter of type `N` or `null`. It represents the root node of a tree or null if the tree is empty.
|
|
559
|
+
* @param iterationType - The `iterationType` parameter is an optional parameter of type `IterationType`. It represents the type of loop used to traverse the binary tree.
|
|
552
560
|
* @returns either the value of the specified property of the node, or the node itself if no property name is provided.
|
|
553
561
|
* If no matching node is found, it returns null.
|
|
554
562
|
*/
|
|
555
|
-
get(
|
|
563
|
+
get(
|
|
564
|
+
nodeProperty: BinaryTreeNodeKey | N,
|
|
565
|
+
callback: MapCallback<N> = this._defaultCallbackByKey,
|
|
566
|
+
beginRoot = this.root,
|
|
567
|
+
iterationType = this.iterationType
|
|
568
|
+
): N | null {
|
|
556
569
|
// TODO may support finding node by value equal
|
|
557
|
-
return this.getNodes(nodeProperty, callback, true)[0] ?? null;
|
|
570
|
+
return this.getNodes(nodeProperty, callback, true, beginRoot, iterationType)[0] ?? null;
|
|
558
571
|
}
|
|
559
572
|
|
|
560
573
|
/**
|
|
@@ -586,17 +599,18 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|
|
586
599
|
* @param {N | BinaryTreeNodeKey | null} [beginRoot] - The `beginRoot` parameter is optional and can be of type `N` (a
|
|
587
600
|
* generic type representing a node in a binary tree), `BinaryTreeNodeKey` (a type representing the ID of a binary tree
|
|
588
601
|
* node), or `null`.
|
|
602
|
+
* @param iterationType - The `iterationType` parameter is an optional parameter of type `IterationType`. It represents the type of loop used to traverse the binary tree.
|
|
589
603
|
* @returns The function `getLeftMost` returns the leftmost node in a binary tree. If the `beginRoot` parameter is
|
|
590
604
|
* provided, it starts the traversal from that node. If `beginRoot` is not provided or is `null`, it starts the traversal
|
|
591
605
|
* from the root of the binary tree. The function returns the leftmost node found during the traversal. If no leftmost
|
|
592
606
|
* node is found (
|
|
593
607
|
*/
|
|
594
|
-
getLeftMost(beginRoot: N | BinaryTreeNodeKey | null = this.root): N | null {
|
|
608
|
+
getLeftMost(beginRoot: N | BinaryTreeNodeKey | null = this.root, iterationType = this.iterationType): N | null {
|
|
595
609
|
if (typeof beginRoot === 'number') beginRoot = this.get(beginRoot);
|
|
596
610
|
|
|
597
611
|
if (!beginRoot) return beginRoot;
|
|
598
612
|
|
|
599
|
-
if (
|
|
613
|
+
if (iterationType === IterationType.RECURSIVE) {
|
|
600
614
|
const _traverse = (cur: N): N => {
|
|
601
615
|
if (!cur.left) return cur;
|
|
602
616
|
return _traverse(cur.left);
|
|
@@ -620,15 +634,16 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|
|
620
634
|
* @param {N | null} [beginRoot] - The `node` parameter is an optional parameter of type `N` or `null`. It represents the
|
|
621
635
|
* starting node from which we want to find the rightmost node. If no node is provided, the function will default to
|
|
622
636
|
* using the root node of the data structure.
|
|
637
|
+
* @param iterationType - The `iterationType` parameter is an optional parameter of type `IterationType`. It represents the type of loop
|
|
623
638
|
* @returns The `getRightMost` function returns the rightmost node in a binary tree. If the `node` parameter is provided,
|
|
624
639
|
* it returns the rightmost node starting from that node. If the `node` parameter is not provided, it returns the
|
|
625
640
|
* rightmost node starting from the root of the binary tree.
|
|
626
641
|
*/
|
|
627
|
-
getRightMost(beginRoot: N | null = this.root): N | null {
|
|
642
|
+
getRightMost(beginRoot: N | null = this.root, iterationType = this.iterationType): N | null {
|
|
628
643
|
// TODO support get right most by passing key in
|
|
629
644
|
if (!beginRoot) return beginRoot;
|
|
630
645
|
|
|
631
|
-
if (
|
|
646
|
+
if (iterationType === IterationType.RECURSIVE) {
|
|
632
647
|
const _traverse = (cur: N): N => {
|
|
633
648
|
if (!cur.right) return cur;
|
|
634
649
|
return _traverse(cur.right);
|
|
@@ -648,25 +663,26 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|
|
648
663
|
|
|
649
664
|
/**
|
|
650
665
|
* The function checks if a binary search tree is valid by traversing it either recursively or iteratively.
|
|
651
|
-
* @param {N | null}
|
|
666
|
+
* @param {N | null} beginRoot - The `node` parameter represents the root node of a binary search tree (BST).
|
|
667
|
+
* @param iterationType - The `iterationType` parameter is an optional parameter of type `IterationType`. It represents the type of loop
|
|
652
668
|
* @returns a boolean value.
|
|
653
669
|
*/
|
|
654
|
-
isSubtreeBST(
|
|
670
|
+
isSubtreeBST(beginRoot: N, iterationType = this.iterationType): boolean {
|
|
655
671
|
// TODO there is a bug
|
|
656
|
-
if (!
|
|
672
|
+
if (!beginRoot) return true;
|
|
657
673
|
|
|
658
|
-
if (
|
|
674
|
+
if (iterationType === IterationType.RECURSIVE) {
|
|
659
675
|
const dfs = (cur: N | null | undefined, min: BinaryTreeNodeKey, max: BinaryTreeNodeKey): boolean => {
|
|
660
676
|
if (!cur) return true;
|
|
661
677
|
if (cur.key <= min || cur.key >= max) return false;
|
|
662
678
|
return dfs(cur.left, min, cur.key) && dfs(cur.right, cur.key, max);
|
|
663
679
|
};
|
|
664
680
|
|
|
665
|
-
return dfs(
|
|
681
|
+
return dfs(beginRoot, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);
|
|
666
682
|
} else {
|
|
667
683
|
const stack = [];
|
|
668
684
|
let prev = Number.MIN_SAFE_INTEGER,
|
|
669
|
-
curr: N | null | undefined =
|
|
685
|
+
curr: N | null | undefined = beginRoot;
|
|
670
686
|
while (curr || stack.length > 0) {
|
|
671
687
|
while (curr) {
|
|
672
688
|
stack.push(curr);
|
|
@@ -685,37 +701,40 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|
|
685
701
|
* The function isBST checks if the binary tree is valid binary search tree.
|
|
686
702
|
* @returns The `isBST()` function is returning a boolean value.
|
|
687
703
|
*/
|
|
688
|
-
isBST(): boolean {
|
|
689
|
-
|
|
704
|
+
isBST(iterationType = this.iterationType): boolean {
|
|
705
|
+
if (this.root === null) return true;
|
|
706
|
+
return this.isSubtreeBST(this.root, iterationType);
|
|
690
707
|
}
|
|
691
708
|
|
|
692
709
|
/**
|
|
693
710
|
* The function `subTreeTraverse` adds a delta value to a specified property of each node in a subtree.
|
|
694
|
-
* @param {N | BinaryTreeNodeKey | null}
|
|
711
|
+
* @param {N | BinaryTreeNodeKey | null} beginRoot - The `beginRoot` parameter represents the root node of a binary
|
|
695
712
|
* tree or the ID of a node in the binary tree. It can also be `null` if there is no subtree to add to.
|
|
696
713
|
* @param callback - The `callback` parameter is a function that takes a node as a parameter and returns a value.
|
|
697
714
|
* specifies the property of the binary tree node that should be modified. If not provided, it defaults to 'key'.
|
|
715
|
+
* @param iterationType - The `iterationType` parameter is an optional parameter of type `IterationType`. It represents the type of loop
|
|
698
716
|
* @returns a boolean value.
|
|
699
717
|
*/
|
|
700
718
|
subTreeTraverse(
|
|
701
719
|
callback: MapCallback<N> = this._defaultCallbackByKey,
|
|
702
|
-
|
|
720
|
+
beginRoot: N | BinaryTreeNodeKey | null = this.root,
|
|
721
|
+
iterationType = this.iterationType
|
|
703
722
|
): MapCallbackReturn<N>[] {
|
|
704
|
-
if (typeof
|
|
723
|
+
if (typeof beginRoot === 'number') beginRoot = this.get(beginRoot);
|
|
705
724
|
|
|
706
725
|
const ans: MapCallbackReturn<N>[] = [];
|
|
707
|
-
if (!
|
|
726
|
+
if (!beginRoot) return ans;
|
|
708
727
|
|
|
709
|
-
if (
|
|
728
|
+
if (iterationType === IterationType.RECURSIVE) {
|
|
710
729
|
const _traverse = (cur: N) => {
|
|
711
730
|
ans.push(callback(cur));
|
|
712
731
|
cur.left && _traverse(cur.left);
|
|
713
732
|
cur.right && _traverse(cur.right);
|
|
714
733
|
};
|
|
715
734
|
|
|
716
|
-
_traverse(
|
|
735
|
+
_traverse(beginRoot);
|
|
717
736
|
} else {
|
|
718
|
-
const stack: N[] = [
|
|
737
|
+
const stack: N[] = [beginRoot];
|
|
719
738
|
|
|
720
739
|
while (stack.length > 0) {
|
|
721
740
|
const cur = stack.pop()!;
|
|
@@ -734,18 +753,18 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|
|
734
753
|
* @param callback
|
|
735
754
|
* @param beginRoot - The `beginRoot` parameter is an optional parameter of type `N` or `null`. It represents the
|
|
736
755
|
* @param {'in' | 'pre' | 'post'} [pattern] - The traversal pattern: 'in' (in-order), 'pre' (pre-order), or 'post' (post-order).
|
|
737
|
-
* @param
|
|
756
|
+
* @param iterationType - The type of loop to use for the depth-first search traversal. The default value is `IterationType.ITERATIVE`.
|
|
738
757
|
* @returns an instance of the BinaryTreeNodeProperties class, which contains the accumulated properties of the binary tree nodes based on the specified pattern and node or property name.
|
|
739
758
|
*/
|
|
740
759
|
dfs(
|
|
741
760
|
callback: MapCallback<N> = this._defaultCallbackByKey,
|
|
742
761
|
pattern: DFSOrderPattern = 'in',
|
|
743
762
|
beginRoot: N | null = this.root,
|
|
744
|
-
|
|
763
|
+
iterationType: IterationType = IterationType.ITERATIVE
|
|
745
764
|
): MapCallbackReturn<N>[] {
|
|
746
765
|
if (!beginRoot) return [];
|
|
747
766
|
const ans: MapCallbackReturn<N>[] = [];
|
|
748
|
-
if (
|
|
767
|
+
if (iterationType === IterationType.RECURSIVE) {
|
|
749
768
|
const _traverse = (node: N) => {
|
|
750
769
|
switch (pattern) {
|
|
751
770
|
case 'in':
|
|
@@ -812,30 +831,31 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|
|
812
831
|
|
|
813
832
|
/**
|
|
814
833
|
* The `listLevels` function collects nodes from a binary tree by a specified property and organizes them into levels.
|
|
815
|
-
* @param {N | null} node - The `node` parameter is a BinaryTreeNode object or null. It represents the root node of a binary tree. If it is null, the function will use the root node of the current binary tree instance.
|
|
816
834
|
* @param callback - The `callback` parameter is a function that takes a node and a level as parameters and returns a value.
|
|
817
835
|
* @param withLevel - The `withLevel` parameter is a boolean flag that determines whether to include the level of each node in the result. If `withLevel` is set to `true`, the function will include the level of each node in the result. If `withLevel` is set to `false` or not provided, the function will not include the level of each node in the result.
|
|
836
|
+
* @param beginRoot - The `beginRoot` parameter is an optional parameter of type `N` or `null`. It represents the root node of a tree or null if the tree is empty.
|
|
837
|
+
* @param iterationType
|
|
818
838
|
*/
|
|
819
839
|
bfs(
|
|
820
840
|
callback: BFSCallback<N> = this._defaultCallbackByKey,
|
|
821
841
|
withLevel: boolean = false,
|
|
822
|
-
|
|
842
|
+
beginRoot: N | null = this.root,
|
|
843
|
+
iterationType = this.iterationType
|
|
823
844
|
): BFSCallbackReturn<N>[] {
|
|
824
|
-
if (!
|
|
825
|
-
if (!node) return [];
|
|
845
|
+
if (!beginRoot) return [];
|
|
826
846
|
|
|
827
847
|
const ans: BFSCallbackReturn<N>[] = [];
|
|
828
848
|
|
|
829
|
-
if (
|
|
849
|
+
if (iterationType === IterationType.RECURSIVE) {
|
|
830
850
|
const _recursive = (node: N, level: number) => {
|
|
831
851
|
callback && ans.push(callback(node, withLevel ? level : undefined));
|
|
832
852
|
if (node.left) _recursive(node.left, level + 1);
|
|
833
853
|
if (node.right) _recursive(node.right, level + 1);
|
|
834
854
|
};
|
|
835
855
|
|
|
836
|
-
_recursive(
|
|
856
|
+
_recursive(beginRoot, 0);
|
|
837
857
|
} else {
|
|
838
|
-
const stack: [N, number][] = [[
|
|
858
|
+
const stack: [N, number][] = [[beginRoot, 0]];
|
|
839
859
|
|
|
840
860
|
while (stack.length > 0) {
|
|
841
861
|
const head = stack.pop()!;
|
|
@@ -875,18 +895,23 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|
|
875
895
|
|
|
876
896
|
/**
|
|
877
897
|
* The `morris` function performs an in-order, pre-order, or post-order traversal on a binary tree using the Morris traversal algorithm.
|
|
898
|
+
* The Morris algorithm only modifies the tree's structure during traversal; once the traversal is complete,
|
|
899
|
+
* the tree's structure should be restored to its original state to maintain the tree's integrity.
|
|
900
|
+
* This is because the purpose of the Morris algorithm is to save space rather than permanently alter the tree's shape.
|
|
878
901
|
* @param {'in' | 'pre' | 'post'} [pattern] - The traversal pattern: 'in' (in-order), 'pre' (pre-order), or 'post' (post-order).
|
|
879
902
|
* @param callback - The `callback` parameter is a function that takes a node as a parameter and returns a value.
|
|
903
|
+
* @param beginRoot - The `beginRoot` parameter is an optional parameter of type `N` or `null`. It represents the
|
|
880
904
|
* @returns An array of BinaryTreeNodeProperties<N> objects.
|
|
881
905
|
*/
|
|
882
906
|
morris(
|
|
883
907
|
callback: MapCallback<N> = this._defaultCallbackByKey,
|
|
884
|
-
pattern: DFSOrderPattern = 'in'
|
|
908
|
+
pattern: DFSOrderPattern = 'in',
|
|
909
|
+
beginRoot: N | null = this.root
|
|
885
910
|
): MapCallbackReturn<N>[] {
|
|
886
|
-
if (
|
|
911
|
+
if (beginRoot === null) return [];
|
|
887
912
|
const ans: MapCallbackReturn<N>[] = [];
|
|
888
913
|
|
|
889
|
-
let cur: N | null | undefined =
|
|
914
|
+
let cur: N | null | undefined = beginRoot;
|
|
890
915
|
const _reverseEdge = (node: N | null | undefined) => {
|
|
891
916
|
let pre: N | null | undefined = null;
|
|
892
917
|
let next: N | null | undefined = null;
|
|
@@ -957,7 +982,7 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|
|
957
982
|
}
|
|
958
983
|
cur = cur.right;
|
|
959
984
|
}
|
|
960
|
-
_printEdge(
|
|
985
|
+
_printEdge(beginRoot);
|
|
961
986
|
break;
|
|
962
987
|
}
|
|
963
988
|
return ans;
|
|
@@ -13,7 +13,7 @@ import type {
|
|
|
13
13
|
MapCallback,
|
|
14
14
|
MapCallbackReturn
|
|
15
15
|
} from '../../types';
|
|
16
|
-
import {CP,
|
|
16
|
+
import {CP, IterationType} from '../../types';
|
|
17
17
|
import {BinaryTree, BinaryTreeNode} from './binary-tree';
|
|
18
18
|
import {IBinaryTree} from '../../interfaces';
|
|
19
19
|
import {Queue} from '../queue';
|
|
@@ -134,12 +134,14 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|
|
134
134
|
* to the binary search tree.
|
|
135
135
|
* @param {N['val'][]} data - The values of tree nodes
|
|
136
136
|
* @param {boolean} isBalanceAdd - If true the nodes will be balance inserted in binary search method.
|
|
137
|
+
* @param iterationType - The `iterationType` parameter is an optional parameter that specifies whether to use a
|
|
137
138
|
* @returns The function `addMany` returns an array of `N`, `null`, or `undefined` values.
|
|
138
139
|
*/
|
|
139
140
|
override addMany(
|
|
140
141
|
keysOrNodes: (BinaryTreeNodeKey | null)[] | (N | null)[],
|
|
141
142
|
data?: N['val'][],
|
|
142
|
-
isBalanceAdd = true
|
|
143
|
+
isBalanceAdd = true,
|
|
144
|
+
iterationType = this.iterationType
|
|
143
145
|
): (N | null | undefined)[] {
|
|
144
146
|
// TODO this addMany function is inefficient, it should be optimized
|
|
145
147
|
function hasNoNull(arr: (BinaryTreeNodeKey | null)[] | (N | null)[]): arr is BinaryTreeNodeKey[] | N[] {
|
|
@@ -199,7 +201,7 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|
|
199
201
|
}
|
|
200
202
|
}
|
|
201
203
|
};
|
|
202
|
-
if (
|
|
204
|
+
if (iterationType === IterationType.RECURSIVE) {
|
|
203
205
|
recursive(sortedKeysOrNodes, sortedData);
|
|
204
206
|
} else {
|
|
205
207
|
iterative();
|
|
@@ -221,16 +223,15 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|
|
221
223
|
}
|
|
222
224
|
|
|
223
225
|
/**
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
* equal, it returns the key of the rightmost node. If there are no nodes in the tree, it returns 0.
|
|
226
|
+
* lastKey returns the last key in a binary tree. If the binary tree is empty, it returns 0.
|
|
227
|
+
* @param beginRoot - The `beginRoot` parameter is an optional parameter that specifies the root node from which to begin
|
|
228
|
+
* the search for the last key.
|
|
229
|
+
* @param iterationType - The `iterationType` parameter is an optional parameter that specifies whether to use a recursive or iterative approach to search for the last key.
|
|
229
230
|
*/
|
|
230
|
-
lastKey(): BinaryTreeNodeKey {
|
|
231
|
-
if (this._compare(0, 1) === CP.lt) return this.getRightMost()?.key ?? 0;
|
|
232
|
-
else if (this._compare(0, 1) === CP.gt) return this.getLeftMost()?.key ?? 0;
|
|
233
|
-
else return this.getRightMost()?.key ?? 0;
|
|
231
|
+
lastKey(beginRoot: N | null = this.root, iterationType = this.iterationType): BinaryTreeNodeKey {
|
|
232
|
+
if (this._compare(0, 1) === CP.lt) return this.getRightMost(beginRoot, iterationType)?.key ?? 0;
|
|
233
|
+
else if (this._compare(0, 1) === CP.gt) return this.getLeftMost(beginRoot, iterationType)?.key ?? 0;
|
|
234
|
+
else return this.getRightMost(beginRoot, iterationType)?.key ?? 0;
|
|
234
235
|
}
|
|
235
236
|
|
|
236
237
|
/**
|
|
@@ -243,18 +244,20 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|
|
243
244
|
* return only one node that matches the given `nodeProperty` or all nodes that match the `nodeProperty`. If `onlyOne`
|
|
244
245
|
* is set to `true`, the function will return an array with only one node (if
|
|
245
246
|
* @param beginRoot - The `beginRoot` parameter is an optional parameter that specifies the root node from which to
|
|
247
|
+
* @param iterationType
|
|
246
248
|
* @returns an array of nodes (type N).
|
|
247
249
|
*/
|
|
248
250
|
override getNodes(
|
|
249
251
|
nodeProperty: BinaryTreeNodeKey | N,
|
|
250
252
|
callback: MapCallback<N> = this._defaultCallbackByKey,
|
|
251
253
|
onlyOne = false,
|
|
252
|
-
beginRoot: N | null = this.root
|
|
254
|
+
beginRoot: N | null = this.root,
|
|
255
|
+
iterationType = this.iterationType
|
|
253
256
|
): N[] {
|
|
254
257
|
if (!beginRoot) return [];
|
|
255
258
|
const ans: N[] = [];
|
|
256
259
|
|
|
257
|
-
if (
|
|
260
|
+
if (iterationType === IterationType.RECURSIVE) {
|
|
258
261
|
const _traverse = (cur: N) => {
|
|
259
262
|
const callbackResult = callback(cur);
|
|
260
263
|
if (callbackResult === nodeProperty) {
|
|
@@ -305,43 +308,45 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|
|
305
308
|
* The `lesserOrGreaterTraverse` function adds a delta value to the specified property of all nodes in a binary tree that
|
|
306
309
|
* have a greater value than a given node.
|
|
307
310
|
* @param callback - The `callback` parameter is a function that takes a node as a parameter and returns a value.
|
|
308
|
-
* @param {N | BinaryTreeNodeKey | null} node - The `node` parameter can be either of type `N` (a generic type), `BinaryTreeNodeKey`, or `null`. It
|
|
309
311
|
* represents the node in the binary tree to which the delta value will be added.
|
|
310
312
|
* @param lesserOrGreater - The `lesserOrGreater` parameter is an optional parameter that specifies whether the delta
|
|
313
|
+
* @param targetNode - The `targetNode` parameter is an optional parameter that specifies the node in the binary tree
|
|
314
|
+
* @param iterationType - The `iterationType` parameter is an optional parameter that specifies whether to use a
|
|
311
315
|
*/
|
|
312
316
|
lesserOrGreaterTraverse(
|
|
313
317
|
callback: MapCallback<N> = this._defaultCallbackByKey,
|
|
314
318
|
lesserOrGreater: CP = CP.lt,
|
|
315
|
-
|
|
319
|
+
targetNode: N | BinaryTreeNodeKey | null = this.root,
|
|
320
|
+
iterationType = this.iterationType
|
|
316
321
|
): MapCallbackReturn<N> {
|
|
317
|
-
if (typeof
|
|
322
|
+
if (typeof targetNode === 'number') targetNode = this.get(targetNode);
|
|
318
323
|
const ans: MapCallbackReturn<N>[] = [];
|
|
319
|
-
if (!
|
|
320
|
-
const
|
|
321
|
-
if (!this.root) return
|
|
324
|
+
if (!targetNode) return ans;
|
|
325
|
+
const targetKey = targetNode.key;
|
|
326
|
+
if (!this.root) return ans;
|
|
322
327
|
|
|
323
|
-
if (
|
|
328
|
+
if (iterationType === IterationType.RECURSIVE) {
|
|
324
329
|
const _traverse = (cur: N) => {
|
|
325
|
-
const compared = this._compare(cur.key,
|
|
330
|
+
const compared = this._compare(cur.key, targetKey);
|
|
326
331
|
if (compared === lesserOrGreater) ans.push(callback(cur));
|
|
327
332
|
|
|
328
333
|
if (!cur.left && !cur.right) return;
|
|
329
|
-
if (cur.left && this._compare(cur.left.key,
|
|
330
|
-
if (cur.right && this._compare(cur.right.key,
|
|
334
|
+
if (cur.left && this._compare(cur.left.key, targetKey) === lesserOrGreater) _traverse(cur.left);
|
|
335
|
+
if (cur.right && this._compare(cur.right.key, targetKey) === lesserOrGreater) _traverse(cur.right);
|
|
331
336
|
};
|
|
332
337
|
|
|
333
338
|
_traverse(this.root);
|
|
334
|
-
return
|
|
339
|
+
return ans;
|
|
335
340
|
} else {
|
|
336
341
|
const queue = new Queue<N>([this.root]);
|
|
337
342
|
while (queue.size > 0) {
|
|
338
343
|
const cur = queue.shift();
|
|
339
344
|
if (cur) {
|
|
340
|
-
const compared = this._compare(cur.key,
|
|
345
|
+
const compared = this._compare(cur.key, targetKey);
|
|
341
346
|
if (compared === lesserOrGreater) ans.push(callback(cur));
|
|
342
347
|
|
|
343
|
-
if (cur.left && this._compare(cur.left.key,
|
|
344
|
-
if (cur.right && this._compare(cur.right.key,
|
|
348
|
+
if (cur.left && this._compare(cur.left.key, targetKey) === lesserOrGreater) queue.push(cur.left);
|
|
349
|
+
if (cur.right && this._compare(cur.right.key, targetKey) === lesserOrGreater) queue.push(cur.right);
|
|
345
350
|
}
|
|
346
351
|
}
|
|
347
352
|
return ans;
|
|
@@ -363,13 +368,13 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|
|
363
368
|
* constructs a balanced binary search tree using either a recursive or iterative approach.
|
|
364
369
|
* @returns The function `perfectlyBalance()` returns a boolean value.
|
|
365
370
|
*/
|
|
366
|
-
perfectlyBalance(): boolean {
|
|
371
|
+
perfectlyBalance(iterationType = this.iterationType): boolean {
|
|
367
372
|
const sorted = this.dfs(node => node, 'in'),
|
|
368
373
|
n = sorted.length;
|
|
369
374
|
this.clear();
|
|
370
375
|
|
|
371
376
|
if (sorted.length < 1) return false;
|
|
372
|
-
if (
|
|
377
|
+
if (iterationType === IterationType.RECURSIVE) {
|
|
373
378
|
const buildBalanceBST = (l: number, r: number) => {
|
|
374
379
|
if (l > r) return;
|
|
375
380
|
const m = l + Math.floor((r - l) / 2);
|
|
@@ -404,12 +409,12 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|
|
404
409
|
* The function `isAVLBalanced` checks if a binary tree is balanced according to the AVL tree property.
|
|
405
410
|
* @returns a boolean value.
|
|
406
411
|
*/
|
|
407
|
-
isAVLBalanced(): boolean {
|
|
412
|
+
isAVLBalanced(iterationType = this.iterationType): boolean {
|
|
408
413
|
if (!this.root) return true;
|
|
409
414
|
|
|
410
415
|
let balanced = true;
|
|
411
416
|
|
|
412
|
-
if (
|
|
417
|
+
if (iterationType === IterationType.RECURSIVE) {
|
|
413
418
|
const _height = (cur: N | null | undefined): number => {
|
|
414
419
|
if (!cur) return 0;
|
|
415
420
|
const leftHeight = _height(cur.left),
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* @license MIT License
|
|
7
7
|
*/
|
|
8
8
|
import type {BinaryTreeNodeKey, TreeMultisetNodeNested, TreeMultisetOptions} from '../../types';
|
|
9
|
-
import {BinaryTreeDeletedResult, CP, FamilyPosition,
|
|
9
|
+
import {BinaryTreeDeletedResult, CP, FamilyPosition, IterationType} from '../../types';
|
|
10
10
|
import {IBinaryTree} from '../../interfaces';
|
|
11
11
|
import {AVLTree, AVLTreeNode} from './avl-tree';
|
|
12
12
|
|
|
@@ -246,14 +246,14 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|
|
246
246
|
* constructs a balanced binary search tree using either a recursive or iterative approach.
|
|
247
247
|
* @returns The function `perfectlyBalance()` returns a boolean value.
|
|
248
248
|
*/
|
|
249
|
-
override perfectlyBalance(): boolean {
|
|
249
|
+
override perfectlyBalance(iterationType = this.iterationType): boolean {
|
|
250
250
|
const sorted = this.dfs(node => node, 'in'),
|
|
251
251
|
n = sorted.length;
|
|
252
252
|
if (sorted.length < 1) return false;
|
|
253
253
|
|
|
254
254
|
this.clear();
|
|
255
255
|
|
|
256
|
-
if (
|
|
256
|
+
if (iterationType === IterationType.RECURSIVE) {
|
|
257
257
|
const buildBalanceBST = (l: number, r: number) => {
|
|
258
258
|
if (l > r) return;
|
|
259
259
|
const m = l + Math.floor((r - l) / 2);
|
|
@@ -7,7 +7,7 @@ import {BinaryTreeNode} from '../../data-structures/binary-tree';
|
|
|
7
7
|
* - `recursive`: Indicates the recursive loop type (with loops that call themselves).
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
export enum
|
|
10
|
+
export enum IterationType {
|
|
11
11
|
ITERATIVE = 'ITERATIVE',
|
|
12
12
|
RECURSIVE = 'RECURSIVE'
|
|
13
13
|
}
|
|
@@ -44,4 +44,4 @@ export type BinaryTreeNodeProperties<N extends BinaryTreeNode<N['val'], N>> =
|
|
|
44
44
|
|
|
45
45
|
export type BinaryTreeNodeNested<T> = BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
|
46
46
|
|
|
47
|
-
export type BinaryTreeOptions = {
|
|
47
|
+
export type BinaryTreeOptions = { iterationType?: IterationType }
|
package/test/config.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const isDebugTest = true;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {AVLTree} from 'avl-tree-typed';
|
|
2
|
-
import {CP} from "data-structure-typed";
|
|
1
|
+
import {AVLTree, CP} from 'avl-tree-typed';
|
|
3
2
|
|
|
4
3
|
describe('AVL Tree Test', () => {
|
|
5
4
|
it('should perform various operations on a AVL Tree', () => {
|
|
@@ -13,7 +12,7 @@ describe('AVL Tree Test', () => {
|
|
|
13
12
|
expect(node6 && tree.getHeight(node6)).toBe(3);
|
|
14
13
|
expect(node6 && tree.getDepth(node6)).toBe(1);
|
|
15
14
|
|
|
16
|
-
const getNodeById = tree.get(10
|
|
15
|
+
const getNodeById = tree.get(10);
|
|
17
16
|
expect(getNodeById?.key).toBe(10);
|
|
18
17
|
|
|
19
18
|
const getMinNodeByRoot = tree.getLeftMost();
|
|
@@ -24,22 +23,22 @@ describe('AVL Tree Test', () => {
|
|
|
24
23
|
expect(getMinNodeBySpecificNode?.key).toBe(12);
|
|
25
24
|
|
|
26
25
|
let subTreeSum = 0;
|
|
27
|
-
node15 && tree.
|
|
26
|
+
node15 && tree.subTreeTraverse(node => (subTreeSum += node.key), 15);
|
|
28
27
|
expect(subTreeSum).toBe(70);
|
|
29
28
|
|
|
30
29
|
let lesserSum = 0;
|
|
31
|
-
tree.
|
|
30
|
+
tree.lesserOrGreaterTraverse(node => (lesserSum += node.key), CP.lt, 10);
|
|
32
31
|
expect(lesserSum).toBe(45);
|
|
33
32
|
|
|
34
33
|
// node15 has type problem. After the uniform design, the generics of containers (DirectedGraph, BST) are based on the type of value. However, this design has a drawback: when I attempt to inherit from the Vertex or BSTNode classes, the types of the results obtained by all methods are those of the parent class.
|
|
35
34
|
expect(node15?.val).toBe(15);
|
|
36
35
|
|
|
37
|
-
const dfs = tree.dfs(
|
|
36
|
+
const dfs = tree.dfs(node => node, 'in');
|
|
38
37
|
expect(dfs[0].key).toBe(1);
|
|
39
38
|
expect(dfs[dfs.length - 1].key).toBe(16);
|
|
40
39
|
|
|
41
40
|
tree.perfectlyBalance();
|
|
42
|
-
const bfs = tree.bfs(
|
|
41
|
+
const bfs = tree.bfs(node => node);
|
|
43
42
|
expect(tree.isPerfectlyBalanced()).toBe(true);
|
|
44
43
|
expect(bfs[0].key).toBe(8);
|
|
45
44
|
expect(bfs[bfs.length - 1].key).toBe(16);
|
|
@@ -103,7 +102,7 @@ describe('AVL Tree Test', () => {
|
|
|
103
102
|
expect(lastBFSIds[1]).toBe(2);
|
|
104
103
|
expect(lastBFSIds[2]).toBe(16);
|
|
105
104
|
|
|
106
|
-
const lastBFSNodes = tree.bfs(
|
|
105
|
+
const lastBFSNodes = tree.bfs(node => node);
|
|
107
106
|
expect(lastBFSNodes[0].key).toBe(12);
|
|
108
107
|
expect(lastBFSNodes[1].key).toBe(2);
|
|
109
108
|
expect(lastBFSNodes[2].key).toBe(16);
|