diff --git a/README.md b/README.md
index a17da64..c6cbf31 100644
--- a/README.md
+++ b/README.md
@@ -939,43 +939,43 @@ We strictly adhere to computer science theory and software development standards
[//]: # (No deletion!!! Start of Replace Section)
avl-tree
-
test name | time taken (ms) | executions per sec | sample deviation |
---|
10,000 add randomly | 132.61 | 7.54 | 0.03 |
10,000 add & delete randomly | 179.82 | 5.56 | 0.00 |
10,000 addMany | 128.84 | 7.76 | 7.04e-4 |
10,000 get | 48.40 | 20.66 | 3.34e-4 |
+
test name | time taken (ms) | executions per sec | sample deviation |
---|
10,000 add randomly | 120.95 | 8.27 | 0.00 |
10,000 add & delete randomly | 180.36 | 5.54 | 0.00 |
10,000 addMany | 137.91 | 7.25 | 0.02 |
10,000 get | 49.52 | 20.19 | 0.00 |
binary-tree-overall
-
test name | time taken (ms) | executions per sec | sample deviation |
---|
10,000 RBTree add | 5.84 | 171.12 | 8.80e-5 |
10,000 RBTree add & delete randomly | 16.30 | 61.34 | 0.01 |
10,000 RBTree get | 19.80 | 50.50 | 0.00 |
10,000 AVLTree add | 122.94 | 8.13 | 0.00 |
10,000 AVLTree add & delete randomly | 185.43 | 5.39 | 0.00 |
10,000 AVLTree get | 0.96 | 1044.69 | 6.87e-6 |
+
test name | time taken (ms) | executions per sec | sample deviation |
---|
10,000 RBTree add | 6.17 | 162.12 | 8.39e-5 |
10,000 RBTree add & delete randomly | 16.24 | 61.59 | 7.03e-4 |
10,000 RBTree get | 21.72 | 46.05 | 0.01 |
10,000 AVLTree add | 126.30 | 7.92 | 0.01 |
10,000 AVLTree add & delete randomly | 187.04 | 5.35 | 0.00 |
10,000 AVLTree get | 0.91 | 1095.03 | 1.07e-5 |
rb-tree
-
test name | time taken (ms) | executions per sec | sample deviation |
---|
100,000 add | 79.39 | 12.60 | 0.00 |
100,000 add & delete randomly | 211.76 | 4.72 | 0.00 |
100,000 getNode | 169.34 | 5.91 | 6.62e-4 |
100,000 add & iterator | 112.02 | 8.93 | 0.01 |
+
test name | time taken (ms) | executions per sec | sample deviation |
---|
100,000 add | 89.08 | 11.23 | 0.01 |
100,000 add & delete randomly | 232.78 | 4.30 | 0.01 |
100,000 getNode | 190.64 | 5.25 | 0.00 |
100,000 add & iterator | 135.29 | 7.39 | 0.05 |
directed-graph
-
test name | time taken (ms) | executions per sec | sample deviation |
---|
1,000 addVertex | 0.10 | 9590.36 | 1.32e-6 |
1,000 addEdge | 6.19 | 161.68 | 4.32e-4 |
1,000 getVertex | 0.05 | 2.16e+4 | 3.75e-7 |
1,000 getEdge | 24.72 | 40.45 | 0.01 |
tarjan | 226.08 | 4.42 | 0.01 |
tarjan all | 6667.55 | 0.15 | 0.27 |
topologicalSort | 186.59 | 5.36 | 0.00 |
+
test name | time taken (ms) | executions per sec | sample deviation |
---|
1,000 addVertex | 0.11 | 9163.90 | 9.52e-6 |
1,000 addEdge | 6.11 | 163.62 | 1.43e-4 |
1,000 getVertex | 0.05 | 2.14e+4 | 5.12e-7 |
1,000 getEdge | 24.84 | 40.26 | 0.00 |
tarjan | 236.10 | 4.24 | 0.02 |
tarjan all | 6707.73 | 0.15 | 0.11 |
topologicalSort | 192.62 | 5.19 | 0.01 |
hash-map
-
test name | time taken (ms) | executions per sec | sample deviation |
---|
1,000,000 set | 137.00 | 7.30 | 0.08 |
Native Map 1,000,000 set | 236.58 | 4.23 | 0.05 |
Native Set 1,000,000 add | 187.78 | 5.33 | 0.05 |
1,000,000 set & get | 123.91 | 8.07 | 0.04 |
Native Map 1,000,000 set & get | 286.03 | 3.50 | 0.03 |
Native Set 1,000,000 add & has | 188.67 | 5.30 | 0.03 |
1,000,000 ObjKey set & get | 327.70 | 3.05 | 0.05 |
Native Map 1,000,000 ObjKey set & get | 285.22 | 3.51 | 0.05 |
Native Set 1,000,000 ObjKey add & has | 278.08 | 3.60 | 0.07 |
+
test name | time taken (ms) | executions per sec | sample deviation |
---|
1,000,000 set | 123.32 | 8.11 | 0.05 |
Native Map 1,000,000 set | 232.46 | 4.30 | 0.03 |
Native Set 1,000,000 add | 190.54 | 5.25 | 0.05 |
1,000,000 set & get | 118.71 | 8.42 | 0.03 |
Native Map 1,000,000 set & get | 294.15 | 3.40 | 0.04 |
Native Set 1,000,000 add & has | 182.79 | 5.47 | 0.02 |
1,000,000 ObjKey set & get | 331.70 | 3.01 | 0.06 |
Native Map 1,000,000 ObjKey set & get | 282.44 | 3.54 | 0.06 |
Native Set 1,000,000 ObjKey add & has | 290.19 | 3.45 | 0.07 |
heap
-
test name | time taken (ms) | executions per sec | sample deviation |
---|
100,000 add & poll | 23.99 | 41.68 | 0.00 |
100,000 add & dfs | 33.23 | 30.09 | 0.00 |
10,000 fib add & pop | 358.16 | 2.79 | 0.00 |
+
test name | time taken (ms) | executions per sec | sample deviation |
---|
100,000 add & poll | 24.36 | 41.06 | 0.00 |
100,000 add & dfs | 32.10 | 31.15 | 3.40e-4 |
10,000 fib add & pop | 354.32 | 2.82 | 0.00 |
doubly-linked-list
-
test name | time taken (ms) | executions per sec | sample deviation |
---|
1,000,000 push | 229.07 | 4.37 | 0.06 |
1,000,000 unshift | 217.64 | 4.59 | 0.08 |
1,000,000 unshift & shift | 175.13 | 5.71 | 0.04 |
1,000,000 addBefore | 342.22 | 2.92 | 0.08 |
+
test name | time taken (ms) | executions per sec | sample deviation |
---|
1,000,000 push | 215.49 | 4.64 | 0.02 |
1,000,000 unshift | 229.17 | 4.36 | 0.05 |
1,000,000 unshift & shift | 182.41 | 5.48 | 0.04 |
1,000,000 addBefore | 313.24 | 3.19 | 0.05 |
singly-linked-list
-
test name | time taken (ms) | executions per sec | sample deviation |
---|
1,000,000 push & shift | 210.65 | 4.75 | 0.06 |
10,000 push & pop | 214.54 | 4.66 | 0.01 |
10,000 addBefore | 248.45 | 4.02 | 0.01 |
+
test name | time taken (ms) | executions per sec | sample deviation |
---|
1,000,000 push & shift | 209.03 | 4.78 | 0.05 |
10,000 push & pop | 217.38 | 4.60 | 0.01 |
10,000 addBefore | 245.42 | 4.07 | 0.01 |
priority-queue
-
test name | time taken (ms) | executions per sec | sample deviation |
---|
100,000 add & poll | 75.67 | 13.22 | 0.00 |
+
test name | time taken (ms) | executions per sec | sample deviation |
---|
100,000 add & poll | 75.48 | 13.25 | 0.00 |
deque
-
test name | time taken (ms) | executions per sec | sample deviation |
---|
1,000,000 push | 13.14 | 76.13 | 1.36e-4 |
10,000 push & delete | 4716.79 | 0.21 | 0.13 |
1,000,000 push & pop | 22.38 | 44.68 | 0.00 |
100,000 push & shift | 2.15 | 464.20 | 1.98e-5 |
Native Array 100,000 push & shift | 2241.30 | 0.45 | 0.14 |
100,000 unshift & shift | 2.34 | 426.69 | 0.00 |
Native Array 100,000 unshift & shift | 3971.32 | 0.25 | 0.18 |
+
test name | time taken (ms) | executions per sec | sample deviation |
---|
1,000,000 push | 13.69 | 73.07 | 0.00 |
10,000 push & delete | 4928.03 | 0.20 | 0.41 |
1,000,000 push & pop | 25.16 | 39.74 | 0.01 |
100,000 push & shift | 3.12 | 320.28 | 0.00 |
Native Array 100,000 push & shift | 2216.18 | 0.45 | 0.08 |
100,000 unshift & shift | 2.17 | 461.58 | 4.01e-4 |
Native Array 100,000 unshift & shift | 4474.58 | 0.22 | 0.29 |
queue
-
test name | time taken (ms) | executions per sec | sample deviation |
---|
1,000,000 push | 44.80 | 22.32 | 0.01 |
100,000 push & shift | 4.91 | 203.64 | 1.15e-4 |
Native Array 100,000 push & shift | 2116.78 | 0.47 | 0.12 |
Native Array 100,000 push & pop | 4.30 | 232.29 | 9.32e-5 |
+
test name | time taken (ms) | executions per sec | sample deviation |
---|
1,000,000 push | 49.42 | 20.23 | 0.02 |
100,000 push & shift | 5.21 | 191.82 | 9.75e-4 |
Native Array 100,000 push & shift | 2328.85 | 0.43 | 0.25 |
Native Array 100,000 push & pop | 4.44 | 225.24 | 1.83e-4 |
stack
-
test name | time taken (ms) | executions per sec | sample deviation |
---|
1,000,000 push | 42.15 | 23.72 | 0.00 |
1,000,000 push & pop | 52.90 | 18.90 | 0.02 |
+
test name | time taken (ms) | executions per sec | sample deviation |
---|
1,000,000 push | 45.54 | 21.96 | 0.01 |
1,000,000 push & pop | 50.59 | 19.77 | 0.01 |
trie
-
test name | time taken (ms) | executions per sec | sample deviation |
---|
100,000 push | 44.55 | 22.45 | 8.46e-4 |
100,000 getWords | 87.48 | 11.43 | 0.00 |
+
test name | time taken (ms) | executions per sec | sample deviation |
---|
100,000 push | 47.74 | 20.95 | 0.00 |
100,000 getWords | 94.40 | 10.59 | 0.01 |
[//]: # (No deletion!!! End of Replace Section)
diff --git a/src/data-structures/base/iterable-base.ts b/src/data-structures/base/iterable-base.ts
index 968438a..35d6083 100644
--- a/src/data-structures/base/iterable-base.ts
+++ b/src/data-structures/base/iterable-base.ts
@@ -287,10 +287,14 @@ export abstract class IterableEntryBase {
console.log([...this]);
}
+ abstract isEmpty(): boolean;
+
+ abstract clone(): any;
+
protected abstract _getIterator(...args: any[]): IterableIterator<[K, V]>;
}
-export abstract class IterableElementBase {
+export abstract class IterableElementBase {
/**
* Time Complexity: O(n)
* Space Complexity: O(1)
@@ -491,5 +495,9 @@ export abstract class IterableElementBase {
console.log([...this]);
}
+ abstract isEmpty(): boolean;
+
+ abstract clone(): C;
+
protected abstract _getIterator(...args: any[]): IterableIterator;
}
diff --git a/src/data-structures/binary-tree/avl-tree.ts b/src/data-structures/binary-tree/avl-tree.ts
index 026b2ae..ef95641 100644
--- a/src/data-structures/binary-tree/avl-tree.ts
+++ b/src/data-structures/binary-tree/avl-tree.ts
@@ -17,11 +17,11 @@ import type {
} from '../../types';
import { IBinaryTree } from '../../interfaces';
-export class AVLTreeNode = AVLTreeNodeNested> extends BSTNode<
- K,
- V,
- N
-> {
+export class AVLTreeNode<
+ K = any,
+ V = any,
+ NODE extends AVLTreeNode = AVLTreeNodeNested
+> extends BSTNode {
height: number;
constructor(key: K, value?: V) {
@@ -42,21 +42,21 @@ export class AVLTreeNode = AVLT
export class AVLTree<
K = any,
V = any,
- N extends AVLTreeNode = AVLTreeNode>,
- TREE extends AVLTree = AVLTree>
+ NODE extends AVLTreeNode = AVLTreeNode>,
+ TREE extends AVLTree = AVLTree>
>
- extends BST
- implements IBinaryTree {
+ extends BST
+ implements IBinaryTree {
/**
* The constructor function initializes an AVLTree object with optional keysOrNodesOrEntries and options.
- * @param [keysOrNodesOrEntries] - The `keysOrNodesOrEntries` parameter is an optional iterable of `KeyOrNodeOrEntry`
+ * @param [keysOrNodesOrEntries] - The `keysOrNodesOrEntries` parameter is an optional iterable of `KeyOrNodeOrEntry`
* objects. It represents a collection of nodes that will be added to the AVL tree during
* initialization.
* @param [options] - The `options` parameter is an optional object that allows you to customize the
* behavior of the AVL tree. It is of type `Partial`, which means that you can
* provide only a subset of the properties defined in the `AVLTreeOptions` interface.
*/
- constructor(keysOrNodesOrEntries: Iterable> = [], options?: AVLTreeOptions) {
+ constructor(keysOrNodesOrEntries: Iterable> = [], options?: AVLTreeOptions) {
super([], options);
if (keysOrNodesOrEntries) super.addMany(keysOrNodesOrEntries);
}
@@ -67,11 +67,11 @@ export class AVLTree<
* the new node. It is used to determine the position of the node in the binary search tree.
* @param [value] - The parameter `value` is an optional value that can be assigned to the node. It is of
* type `V`, which means it can be any value that is assignable to the `value` property of the
- * node type `N`.
+ * node type `NODE`.
* @returns a new AVLTreeNode object with the specified key and value.
*/
- override createNode(key: K, value?: V): N {
- return new AVLTreeNode(key, value) as N;
+ override createNode(key: K, value?: V): NODE {
+ return new AVLTreeNode(key, value) as NODE;
}
/**
@@ -82,7 +82,7 @@ export class AVLTree<
* @returns a new AVLTree object.
*/
override createTree(options?: AVLTreeOptions): TREE {
- return new AVLTree([], {
+ return new AVLTree([], {
iterationType: this.iterationType,
variant: this.variant,
...options
@@ -91,10 +91,10 @@ export class AVLTree<
/**
* The function checks if an keyOrNodeOrEntry is an instance of AVLTreeNode.
- * @param keyOrNodeOrEntry - The `keyOrNodeOrEntry` parameter is of type `KeyOrNodeOrEntry`.
+ * @param keyOrNodeOrEntry - The `keyOrNodeOrEntry` parameter is of type `KeyOrNodeOrEntry`.
* @returns a boolean value indicating whether the keyOrNodeOrEntry is an instance of the AVLTreeNode class.
*/
- override isNode(keyOrNodeOrEntry: KeyOrNodeOrEntry): keyOrNodeOrEntry is N {
+ override isNode(keyOrNodeOrEntry: KeyOrNodeOrEntry): keyOrNodeOrEntry is NODE {
return keyOrNodeOrEntry instanceof AVLTreeNode;
}
@@ -116,7 +116,7 @@ export class AVLTree<
* being added to the binary tree.
* @returns The method is returning either the inserted node or undefined.
*/
- override add(keyOrNodeOrEntry: KeyOrNodeOrEntry, value?: V): boolean {
+ override add(keyOrNodeOrEntry: KeyOrNodeOrEntry, value?: V): boolean {
if (keyOrNodeOrEntry === null) return false;
const inserted = super.add(keyOrNodeOrEntry, value);
if (inserted) this._balancePath(keyOrNodeOrEntry);
@@ -140,13 +140,13 @@ export class AVLTree<
* @param {C} callback - The `callback` parameter is a function that will be called for each node
* that is deleted from the binary tree. It is an optional parameter and if not provided, it will
* default to the `_defaultOneParamCallback` function. The `callback` function should have a single
- * parameter of type `N
- * @returns The method is returning an array of `BinaryTreeDeleteResult`.
+ * parameter of type `NODE
+ * @returns The method is returning an array of `BinaryTreeDeleteResult`.
*/
- override delete>(
+ override delete>(
identifier: ReturnType,
callback: C = this._defaultOneParamCallback as C
- ): BinaryTreeDeleteResult[] {
+ ): BinaryTreeDeleteResult[] {
if ((identifier as any) instanceof AVLTreeNode) callback = (node => node) as C;
const deletedResults = super.delete(identifier, callback);
for (const { needBalanced } of deletedResults) {
@@ -160,14 +160,17 @@ export class AVLTree<
/**
* The `_swapProperties` function swaps the key, value, and height properties between two nodes in a binary
* tree.
- * @param {K | N | undefined} srcNode - The `srcNode` parameter represents the source node that
- * needs to be swapped with the destination node. It can be of type `K`, `N`, or `undefined`.
- * @param {K | N | undefined} destNode - The `destNode` parameter represents the destination
+ * @param {K | NODE | undefined} srcNode - The `srcNode` parameter represents the source node that
+ * needs to be swapped with the destination node. It can be of type `K`, `NODE`, or `undefined`.
+ * @param {K | NODE | undefined} destNode - The `destNode` parameter represents the destination
* node where the values from the source node will be swapped to.
* @returns either the `destNode` object if both `srcNode` and `destNode` are defined, or `undefined`
* if either `srcNode` or `destNode` is undefined.
*/
- protected override _swapProperties(srcNode: BSTNKeyOrNode, destNode: BSTNKeyOrNode): N | undefined {
+ protected override _swapProperties(
+ srcNode: BSTNKeyOrNode,
+ destNode: BSTNKeyOrNode
+ ): NODE | undefined {
srcNode = this.ensureNode(srcNode);
destNode = this.ensureNode(destNode);
@@ -203,11 +206,11 @@ export class AVLTree<
* Space Complexity: O(1)
*
* The function calculates the balance factor of a node in a binary tree.
- * @param {N} node - The parameter "node" represents a node in a binary tree data structure.
+ * @param {NODE} node - The parameter "node" represents a node in a binary tree data structure.
* @returns the balance factor of a given node. The balance factor is calculated by subtracting the
* height of the left subtree from the height of the right subtree.
*/
- protected _balanceFactor(node: N): number {
+ protected _balanceFactor(node: NODE): number {
if (!node.right)
// node has no right subtree
return -node.height;
@@ -229,9 +232,9 @@ export class AVLTree<
*
* The function updates the height of a node in a binary tree based on the heights of its left and
* right children.
- * @param {N} node - The parameter "node" represents a node in a binary tree data structure.
+ * @param {NODE} node - The parameter "node" represents a node in a binary tree data structure.
*/
- protected _updateHeight(node: N): void {
+ protected _updateHeight(node: NODE): void {
if (!node.left && !node.right) node.height = 0;
else if (!node.left) {
const rightHeight = node.right ? node.right.height : 0;
@@ -252,10 +255,10 @@ export class AVLTree<
*
* The `_balancePath` function is used to update the heights of nodes and perform rotation operations
* to restore balance in an AVL tree after inserting a node.
- * @param {N} node - The `node` parameter in the `_balancePath` function represents the node in the
+ * @param {NODE} node - The `node` parameter in the `_balancePath` function represents the node in the
* AVL tree that needs to be balanced.
*/
- protected _balancePath(node: KeyOrNodeOrEntry): void {
+ protected _balancePath(node: KeyOrNodeOrEntry): void {
node = this.ensureNode(node);
const path = this.getPathToRoot(node, false); // first O(log n) + O(log n)
for (let i = 0; i < path.length; i++) {
@@ -306,9 +309,9 @@ export class AVLTree<
* Space Complexity: O(1)
*
* The function `_balanceLL` performs a left-left rotation to balance a binary tree.
- * @param {N} A - A is a node in a binary tree.
+ * @param {NODE} A - A is a node in a binary tree.
*/
- protected _balanceLL(A: N): void {
+ protected _balanceLL(A: NODE): void {
const parentOfA = A.parent;
const B = A.left;
A.parent = B;
@@ -344,9 +347,9 @@ export class AVLTree<
* Space Complexity: O(1)
*
* The `_balanceLR` function performs a left-right rotation to balance a binary tree.
- * @param {N} A - A is a node in a binary tree.
+ * @param {NODE} A - A is a node in a binary tree.
*/
- protected _balanceLR(A: N): void {
+ protected _balanceLR(A: NODE): void {
const parentOfA = A.parent;
const B = A.left;
let C = undefined;
@@ -400,9 +403,9 @@ export class AVLTree<
* Space Complexity: O(1)
*
* The function `_balanceRR` performs a right-right rotation to balance a binary tree.
- * @param {N} A - A is a node in a binary tree.
+ * @param {NODE} A - A is a node in a binary tree.
*/
- protected _balanceRR(A: N): void {
+ protected _balanceRR(A: NODE): void {
const parentOfA = A.parent;
const B = A.right;
A.parent = B;
@@ -443,9 +446,9 @@ export class AVLTree<
* Space Complexity: O(1)
*
* The function `_balanceRL` performs a right-left rotation to balance a binary tree.
- * @param {N} A - A is a node in a binary tree.
+ * @param {NODE} A - A is a node in a binary tree.
*/
- protected _balanceRL(A: N): void {
+ protected _balanceRL(A: NODE): void {
const parentOfA = A.parent;
const B = A.right;
let C = undefined;
@@ -488,7 +491,7 @@ export class AVLTree<
C && this._updateHeight(C);
}
- protected _replaceNode(oldNode: N, newNode: N): N {
+ protected _replaceNode(oldNode: NODE, newNode: NODE): NODE {
newNode.height = oldNode.height;
return super._replaceNode(oldNode, newNode);
diff --git a/src/data-structures/binary-tree/binary-tree.ts b/src/data-structures/binary-tree/binary-tree.ts
index 72de2cd..852f1d8 100644
--- a/src/data-structures/binary-tree/binary-tree.ts
+++ b/src/data-structures/binary-tree/binary-tree.ts
@@ -28,46 +28,46 @@ import { IterableEntryBase } from '../base';
/**
* Represents a node in a binary tree.
* @template V - The type of data stored in the node.
- * @template N - The type of the family relationship in the binary tree.
+ * @template NODE - The type of the family relationship in the binary tree.
*/
export class BinaryTreeNode<
K = any,
V = any,
- N extends BinaryTreeNode = BinaryTreeNode>
+ NODE extends BinaryTreeNode = BinaryTreeNode>
> {
key: K;
value?: V;
- parent?: N;
+ parent?: NODE;
constructor(key: K, value?: V) {
this.key = key;
this.value = value;
}
- protected _left?: N | null;
+ protected _left?: NODE | null;
- get left(): N | null | undefined {
+ get left(): NODE | null | undefined {
return this._left;
}
- set left(v: N | null | undefined) {
+ set left(v: NODE | null | undefined) {
if (v) {
- v.parent = this as unknown as N;
+ v.parent = this as unknown as NODE;
}
this._left = v;
}
- protected _right?: N | null;
+ protected _right?: NODE | null;
- get right(): N | null | undefined {
+ get right(): NODE | null | undefined {
return this._right;
}
- set right(v: N | null | undefined) {
+ set right(v: NODE | null | undefined) {
if (v) {
- v.parent = this as unknown as N;
+ v.parent = this as unknown as NODE;
}
this._right = v;
}
@@ -77,7 +77,7 @@ export class BinaryTreeNode<
* @returns {FamilyPosition} - The family position of the node.
*/
get familyPosition(): FamilyPosition {
- const that = this as unknown as N;
+ const that = this as unknown as NODE;
if (!this.parent) {
return this.left || this.right ? FamilyPosition.ROOT : FamilyPosition.ISOLATED;
}
@@ -103,11 +103,11 @@ export class BinaryTreeNode<
export class BinaryTree<
K = any,
V = any,
- N extends BinaryTreeNode = BinaryTreeNode>,
- TREE extends BinaryTree = BinaryTree>
+ NODE extends BinaryTreeNode = BinaryTreeNode>,
+ TREE extends BinaryTree = BinaryTree>
>
extends IterableEntryBase
- implements IBinaryTree {
+ implements IBinaryTree {
iterationType = IterationType.ITERATIVE;
/**
@@ -119,7 +119,7 @@ export class BinaryTree<
* `Partial`, which means that not all properties of `BinaryTreeOptions` are
* required.
*/
- constructor(keysOrNodesOrEntries: Iterable> = [], options?: BinaryTreeOptions) {
+ constructor(keysOrNodesOrEntries: Iterable> = [], options?: BinaryTreeOptions) {
super();
if (options) {
const { iterationType, extractor } = options;
@@ -138,9 +138,9 @@ export class BinaryTree<
return this._extractor;
}
- protected _root?: N | null;
+ protected _root?: NODE | null;
- get root(): N | null | undefined {
+ get root(): NODE | null | undefined {
return this._root;
}
@@ -154,10 +154,10 @@ export class BinaryTree<
* Creates a new instance of BinaryTreeNode with the given key and value.
* @param {K} key - The key for the new node.
* @param {V} value - The value for the new node.
- * @returns {N} - The newly created BinaryTreeNode.
+ * @returns {NODE} - The newly created BinaryTreeNode.
*/
- createNode(key: K, value?: V): N {
- return new BinaryTreeNode(key, value) as N;
+ createNode(key: K, value?: V): NODE {
+ return new BinaryTreeNode(key, value) as NODE;
}
/**
@@ -168,21 +168,21 @@ export class BinaryTree<
* @returns a new instance of a binary tree.
*/
createTree(options?: Partial>): TREE {
- return new BinaryTree([], { iterationType: this.iterationType, ...options }) as TREE;
+ return new BinaryTree([], { iterationType: this.iterationType, ...options }) as TREE;
}
/**
* The function `keyValueOrEntryToNode` converts an keyOrNodeOrEntry object into a node object.
- * @param keyOrNodeOrEntry - The `keyOrNodeOrEntry` parameter is of type `KeyOrNodeOrEntry`.
+ * @param keyOrNodeOrEntry - The `keyOrNodeOrEntry` parameter is of type `KeyOrNodeOrEntry`.
* @param {V} [value] - The `value` parameter is an optional value that can be passed to the
* `keyValueOrEntryToNode` function. It represents the value associated with the keyOrNodeOrEntry node. If no value
* is provided, it will be `undefined`.
- * @returns a value of type N (node), or null, or undefined.
+ * @returns a value of type NODE (node), or null, or undefined.
*/
- keyValueOrEntryToNode(keyOrNodeOrEntry: KeyOrNodeOrEntry, value?: V): N | null | undefined {
+ keyValueOrEntryToNode(keyOrNodeOrEntry: KeyOrNodeOrEntry, value?: V): NODE | null | undefined {
if (keyOrNodeOrEntry === undefined) return;
- let node: N | null | undefined;
+ let node: NODE | null | undefined;
if (keyOrNodeOrEntry === null) {
node = null;
} else if (this.isEntry(keyOrNodeOrEntry)) {
@@ -215,7 +215,7 @@ export class BinaryTree<
*
* The function `ensureNode` returns the node corresponding to the given key if it is a valid node
* key, otherwise it returns the key itself.
- * @param {K | N | null | undefined} keyOrNodeOrEntry - The `key` parameter can be of type `K`, `N`,
+ * @param {K | NODE | null | undefined} keyOrNodeOrEntry - The `key` parameter can be of type `K`, `NODE`,
* `null`, or `undefined`. It represents a key used to identify a node in a binary tree.
* @param iterationType - The `iterationType` parameter is an optional parameter that specifies the
* type of iteration to be used when searching for a node by key. It has a default value of
@@ -224,10 +224,10 @@ export class BinaryTree<
* itself if it is not a valid node key.
*/
ensureNode(
- keyOrNodeOrEntry: KeyOrNodeOrEntry,
+ keyOrNodeOrEntry: KeyOrNodeOrEntry,
iterationType = IterationType.ITERATIVE
- ): N | null | undefined {
- let res: N | null | undefined;
+ ): NODE | null | undefined {
+ let res: NODE | null | undefined;
if (this.isRealNode(keyOrNodeOrEntry)) {
res = keyOrNodeOrEntry;
} else if (this.isEntry(keyOrNodeOrEntry)) {
@@ -242,20 +242,20 @@ export class BinaryTree<
/**
* The function "isNode" checks if an keyOrNodeOrEntry is an instance of the BinaryTreeNode class.
- * @param keyOrNodeOrEntry - The `keyOrNodeOrEntry` parameter is a variable of type `KeyOrNodeOrEntry`.
- * @returns a boolean value indicating whether the keyOrNodeOrEntry is an instance of the class N.
+ * @param keyOrNodeOrEntry - The `keyOrNodeOrEntry` parameter is a variable of type `KeyOrNodeOrEntry`.
+ * @returns a boolean value indicating whether the keyOrNodeOrEntry is an instance of the class NODE.
*/
- isNode(keyOrNodeOrEntry: KeyOrNodeOrEntry): keyOrNodeOrEntry is N {
+ isNode(keyOrNodeOrEntry: KeyOrNodeOrEntry): keyOrNodeOrEntry is NODE {
return keyOrNodeOrEntry instanceof BinaryTreeNode;
}
/**
* The function checks if a given value is an entry in a binary tree node.
- * @param keyOrNodeOrEntry - KeyOrNodeOrEntry - A generic type representing a node in a binary tree. It has
- * two type parameters V and N, representing the value and node type respectively.
+ * @param keyOrNodeOrEntry - KeyOrNodeOrEntry - A generic type representing a node in a binary tree. It has
+ * two type parameters V and NODE, representing the value and node type respectively.
* @returns a boolean value.
*/
- isEntry(keyOrNodeOrEntry: KeyOrNodeOrEntry): keyOrNodeOrEntry is BTNEntry {
+ isEntry(keyOrNodeOrEntry: KeyOrNodeOrEntry): keyOrNodeOrEntry is BTNEntry {
return Array.isArray(keyOrNodeOrEntry) && keyOrNodeOrEntry.length === 2;
}
@@ -270,7 +270,7 @@ export class BinaryTree<
* @param {any} node - The parameter `node` is of type `any`, which means it can be any data type.
* @returns a boolean value.
*/
- isRealNode(node: KeyOrNodeOrEntry): node is N {
+ isRealNode(node: KeyOrNodeOrEntry): node is NODE {
return node instanceof BinaryTreeNode && String(node.key) !== 'NaN';
}
@@ -279,7 +279,7 @@ export class BinaryTree<
* @param {any} node - The parameter `node` is of type `any`, which means it can be any data type.
* @returns a boolean value.
*/
- isNIL(node: KeyOrNodeOrEntry) {
+ isNIL(node: KeyOrNodeOrEntry) {
return node instanceof BinaryTreeNode && String(node.key) === 'NaN';
}
@@ -288,7 +288,7 @@ export class BinaryTree<
* @param {any} node - The parameter `node` is of type `any`, which means it can be any data type.
* @returns a boolean value.
*/
- isNodeOrNull(node: KeyOrNodeOrEntry): node is N | null {
+ isNodeOrNull(node: KeyOrNodeOrEntry): node is NODE | null {
return this.isRealNode(node) || node === null;
}
@@ -305,9 +305,9 @@ export class BinaryTree<
* existing node with the same key.
* @param keyOrNodeOrEntry - The `keyOrNodeOrEntry` parameter can be one of the following:
* @param {V} [value] - The value to be inserted into the binary tree.
- * @returns The function `add` returns either a node (`N`), `null`, or `undefined`.
+ * @returns The function `add` returns either a node (`NODE`), `null`, or `undefined`.
*/
- add(keyOrNodeOrEntry: KeyOrNodeOrEntry, value?: V): boolean {
+ add(keyOrNodeOrEntry: KeyOrNodeOrEntry, value?: V): boolean {
const newNode = this.keyValueOrEntryToNode(keyOrNodeOrEntry, value);
if (newNode === undefined) return false;
@@ -318,8 +318,8 @@ export class BinaryTree<
return true;
}
- const queue = new Queue([this.root]);
- let potentialParent: N | undefined; // Record the parent node of the potential insertion location
+ const queue = new Queue([this.root]);
+ let potentialParent: NODE | undefined; // Record the parent node of the potential insertion location
while (queue.size > 0) {
const cur = queue.shift();
@@ -374,9 +374,9 @@ export class BinaryTree<
* adds each node with its corresponding value to the data structure.
* @param keysOrNodesOrEntries - An iterable collection of KeyOrNodeOrEntry objects.
* @param [values] - An optional iterable of values that will be assigned to each node being added.
- * @returns The function `addMany` returns an array of `N`, `null`, or `undefined` values.
+ * @returns The function `addMany` returns an array of `NODE`, `null`, or `undefined` values.
*/
- addMany(keysOrNodesOrEntries: Iterable>, values?: Iterable): boolean[] {
+ addMany(keysOrNodesOrEntries: Iterable>, values?: Iterable): boolean[] {
// TODO not sure addMany not be run multi times
const inserted: boolean[] = [];
@@ -413,31 +413,28 @@ export class BinaryTree<
*
* The `refill` function clears the current data and adds new key-value pairs to the data structure.
* @param keysOrNodesOrEntries - An iterable containing keys, nodes, or entries. These can be of type
- * KeyOrNodeOrEntry.
+ * KeyOrNodeOrEntry.
* @param [values] - The `values` parameter is an optional iterable that contains the values to be
* associated with the keys or nodes or entries in the `keysOrNodesOrEntries` parameter. If provided,
* the values will be associated with the corresponding keys or nodes or entries in the
* `keysOrNodesOrEntries` iterable
*/
- refill(keysOrNodesOrEntries: Iterable>, values?: Iterable): void {
+ refill(keysOrNodesOrEntries: Iterable>, values?: Iterable): void {
this.clear();
this.addMany(keysOrNodesOrEntries, values);
}
- /**
- * Time Complexity: O(k * n)
- * Space Complexity: O(1)
- * "n" is the number of nodes in the tree, and "k" is the number of keys to be inserted.
- */
+ delete>(identifier: K, callback?: C): BinaryTreeDeleteResult[];
- delete>(identifier: K, callback?: C): BinaryTreeDeleteResult[];
+ delete>(
+ identifier: NODE | null | undefined,
+ callback?: C
+ ): BinaryTreeDeleteResult[];
- delete>(identifier: N | null | undefined, callback?: C): BinaryTreeDeleteResult[];
-
- delete>(identifier: ReturnType, callback: C): BinaryTreeDeleteResult[];
+ delete>(identifier: ReturnType, callback: C): BinaryTreeDeleteResult[];
/**
- * Time Complexity: O(n)
+ * Time Complexity: O(log n)
* Space Complexity: O(1)
*
* The function deletes a node from a binary tree and returns an array of the deleted nodes along
@@ -449,13 +446,13 @@ export class BinaryTree<
* @param {C} callback - The `callback` parameter is a function that is used to determine the
* identifier of the node to be deleted. It is optional and has a default value of
* `this._defaultOneParamCallback`. The `callback` function should return the identifier of the node.
- * @returns an array of `BinaryTreeDeleteResult`.
+ * @returns an array of `BinaryTreeDeleteResult`.
*/
- delete>(
+ delete>(
identifier: ReturnType | null | undefined,
callback: C = this._defaultOneParamCallback as C
- ): BinaryTreeDeleteResult[] {
- const deletedResult: BinaryTreeDeleteResult[] = [];
+ ): BinaryTreeDeleteResult[] {
+ const deletedResult: BinaryTreeDeleteResult[] = [];
if (!this.root) return deletedResult;
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
callback = (node => node) as C;
@@ -463,38 +460,37 @@ export class BinaryTree<
const curr = this.getNode(identifier, callback);
if (!curr) return deletedResult;
- const parent: N | null | undefined = curr?.parent ? curr.parent : null;
- let needBalanced: N | null | undefined = undefined;
- let orgCurrent: N | undefined = curr;
+ const parent: NODE | undefined = curr?.parent;
+ let needBalanced: NODE | undefined;
+ let orgCurrent: NODE | undefined = curr;
- if (!curr.left) {
- if (!parent) {
- // Handle the case when there's only one root node
- this._setRoot(null);
- } else {
- const { familyPosition: fp } = curr;
- if (fp === FamilyPosition.LEFT || fp === FamilyPosition.ROOT_LEFT) {
- parent.left = curr.right;
- } else if (fp === FamilyPosition.RIGHT || fp === FamilyPosition.ROOT_RIGHT) {
- parent.right = curr.right;
+ if (!curr.left && !curr.right && !parent) {
+ this._setRoot(undefined);
+ } else if (curr.left) {
+ const leftSubTreeRightMost = this.getRightMost(curr.left);
+ if (leftSubTreeRightMost) {
+ const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;
+ orgCurrent = this._swapProperties(curr, leftSubTreeRightMost);
+ if (parentOfLeftSubTreeMax) {
+ if (parentOfLeftSubTreeMax.right === leftSubTreeRightMost)
+ parentOfLeftSubTreeMax.right = leftSubTreeRightMost.left;
+ else parentOfLeftSubTreeMax.left = leftSubTreeRightMost.left;
+ needBalanced = parentOfLeftSubTreeMax;
}
- needBalanced = parent;
}
+ } else if (parent) {
+ const { familyPosition: fp } = curr;
+ if (fp === FamilyPosition.LEFT || fp === FamilyPosition.ROOT_LEFT) {
+ parent.left = curr.right;
+ } else if (fp === FamilyPosition.RIGHT || fp === FamilyPosition.ROOT_RIGHT) {
+ parent.right = curr.right;
+ }
+ needBalanced = parent;
} else {
- if (curr.left) {
- const leftSubTreeRightMost = this.getRightMost(curr.left);
- if (leftSubTreeRightMost) {
- const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;
- orgCurrent = this._swapProperties(curr, leftSubTreeRightMost);
- if (parentOfLeftSubTreeMax) {
- if (parentOfLeftSubTreeMax.right === leftSubTreeRightMost)
- parentOfLeftSubTreeMax.right = leftSubTreeRightMost.left;
- else parentOfLeftSubTreeMax.left = leftSubTreeRightMost.left;
- needBalanced = parentOfLeftSubTreeMax;
- }
- }
- }
+ this._setRoot(curr.right);
+ curr.right = undefined;
}
+
this._size = this.size - 1;
deletedResult.push({ deleted: orgCurrent, needBalanced });
@@ -511,15 +507,15 @@ export class BinaryTree<
* Space Complexity: O(1)
*
* The function calculates the depth of a given node in a binary tree.
- * @param {K | N | null | undefined} dist - The `dist` parameter represents the node in
- * the binary tree whose depth we want to find. It can be of type `K`, `N`, `null`, or
+ * @param {K | NODE | null | undefined} dist - The `dist` parameter represents the node in
+ * the binary tree whose depth we want to find. It can be of type `K`, `NODE`, `null`, or
* `undefined`.
- * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node
+ * @param {K | NODE | null | undefined} beginRoot - The `beginRoot` parameter is the starting node
* from which we want to calculate the depth. It can be either a `K` (binary tree node key) or
- * `N` (binary tree node) or `null` or `undefined`. If no value is provided for `beginRoot
+ * `NODE` (binary tree node) or `null` or `undefined`. If no value is provided for `beginRoot
* @returns the depth of the `dist` relative to the `beginRoot`.
*/
- getDepth(dist: KeyOrNodeOrEntry, beginRoot: KeyOrNodeOrEntry = this.root): number {
+ getDepth(dist: KeyOrNodeOrEntry, beginRoot: KeyOrNodeOrEntry = this.root): number {
dist = this.ensureNode(dist);
beginRoot = this.ensureNode(beginRoot);
let depth = 0;
@@ -544,20 +540,20 @@ export class BinaryTree<
*
* The function `getHeight` calculates the maximum height of a binary tree using either recursive or
* iterative traversal.
- * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
+ * @param {K | NODE | null | undefined} beginRoot - The `beginRoot` parameter represents the
* starting node of the binary tree from which we want to calculate the height. It can be of type
- * `K`, `N`, `null`, or `undefined`. If not provided, it defaults to `this.root`.
+ * `K`, `NODE`, `null`, or `undefined`. If not provided, it defaults to `this.root`.
* @param iterationType - The `iterationType` parameter is used to determine whether to calculate the
* height of the tree using a recursive approach or an iterative approach. It can have two possible
* values:
* @returns the height of the binary tree.
*/
- getHeight(beginRoot: KeyOrNodeOrEntry = this.root, iterationType = this.iterationType): number {
+ getHeight(beginRoot: KeyOrNodeOrEntry = this.root, iterationType = this.iterationType): number {
beginRoot = this.ensureNode(beginRoot);
if (!beginRoot) return -1;
if (iterationType === IterationType.RECURSIVE) {
- const _getMaxHeight = (cur: N | null | undefined): number => {
+ const _getMaxHeight = (cur: NODE | null | undefined): number => {
if (!cur) return -1;
const leftHeight = _getMaxHeight(cur.left);
const rightHeight = _getMaxHeight(cur.right);
@@ -566,7 +562,7 @@ export class BinaryTree<
return _getMaxHeight(beginRoot);
} else {
- const stack: { node: N; depth: number }[] = [{ node: beginRoot, depth: 0 }];
+ const stack: { node: NODE; depth: number }[] = [{ node: beginRoot, depth: 0 }];
let maxHeight = 0;
while (stack.length > 0) {
@@ -594,19 +590,19 @@ export class BinaryTree<
*
* The `getMinHeight` function calculates the minimum height of a binary tree using either a
* recursive or iterative approach.
- * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
+ * @param {K | NODE | null | undefined} beginRoot - The `beginRoot` parameter represents the
* starting node of the binary tree from which we want to calculate the minimum height. It can be of
- * type `K`, `N`, `null`, or `undefined`. If no value is provided, it defaults to `this.root`.
+ * type `K`, `NODE`, `null`, or `undefined`. If no value is provided, it defaults to `this.root`.
* @param iterationType - The `iterationType` parameter is used to determine the method of iteration
* to calculate the minimum height of a binary tree. It can have two possible values:
* @returns The function `getMinHeight` returns the minimum height of a binary tree.
*/
- getMinHeight(beginRoot: KeyOrNodeOrEntry = this.root, iterationType = this.iterationType): number {
+ getMinHeight(beginRoot: KeyOrNodeOrEntry = this.root, iterationType = this.iterationType): number {
beginRoot = this.ensureNode(beginRoot);
if (!beginRoot) return -1;
if (iterationType === IterationType.RECURSIVE) {
- const _getMinHeight = (cur: N | null | undefined): number => {
+ const _getMinHeight = (cur: NODE | null | undefined): number => {
if (!cur) return 0;
if (!cur.left && !cur.right) return 0;
const leftMinHeight = _getMinHeight(cur.left);
@@ -616,10 +612,10 @@ export class BinaryTree<
return _getMinHeight(beginRoot);
} else {
- const stack: N[] = [];
- let node: N | null | undefined = beginRoot,
- last: N | null | undefined = null;
- const depths: Map = new Map();
+ const stack: NODE[] = [];
+ let node: NODE | null | undefined = beginRoot,
+ last: NODE | null | undefined = null;
+ const depths: Map = new Map();
while (stack.length > 0 || node) {
if (node) {
@@ -656,12 +652,12 @@ export class BinaryTree<
*
* The function checks if a binary tree is perfectly balanced by comparing the minimum height and the
* height of the tree.
- * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
+ * @param {K | NODE | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
* for calculating the height and minimum height of a binary tree. It can be either a `K` (a key
- * value of a binary tree node), `N` (a node of a binary tree), `null`, or `undefined`. If
+ * value of a binary tree node), `NODE` (a node of a binary tree), `null`, or `undefined`. If
* @returns a boolean value.
*/
- isPerfectlyBalanced(beginRoot: KeyOrNodeOrEntry = this.root): boolean {
+ isPerfectlyBalanced(beginRoot: KeyOrNodeOrEntry = this.root): boolean {
return this.getMinHeight(beginRoot) + 1 >= this.getHeight(beginRoot);
}
@@ -670,29 +666,29 @@ export class BinaryTree<
* Space Complexity: O(log n)
*/
- getNodes>(
+ getNodes>(
identifier: K,
callback?: C,
onlyOne?: boolean,
- beginRoot?: KeyOrNodeOrEntry,
+ beginRoot?: KeyOrNodeOrEntry,
iterationType?: IterationType
- ): N[];
+ ): NODE[];
- getNodes>(
- identifier: N | null | undefined,
+ getNodes>(
+ identifier: NODE | null | undefined,
callback?: C,
onlyOne?: boolean,
- beginRoot?: KeyOrNodeOrEntry,
+ beginRoot?: KeyOrNodeOrEntry,
iterationType?: IterationType
- ): N[];
+ ): NODE[];
- getNodes>(
+ getNodes>(
identifier: ReturnType,
callback: C,
onlyOne?: boolean,
- beginRoot?: KeyOrNodeOrEntry,
+ beginRoot?: KeyOrNodeOrEntry,
iterationType?: IterationType
- ): N[];
+ ): NODE[];
/**
* Time Complexity: O(n)
@@ -704,7 +700,7 @@ export class BinaryTree<
* that you want to search for in the binary tree. It can be of any type that is returned by the
* callback function `C`. It can also be `null` or `undefined` if you don't want to search for a
* specific value.
- * @param {C} callback - The `callback` parameter is a function that takes a node of type `N` as
+ * @param {C} callback - The `callback` parameter is a function that takes a node of type `NODE` as
* input and returns a value of type `C`. It is used to determine if a node matches the given
* identifier. If no callback is provided, the `_defaultOneParamCallback` function is used as the
* default
@@ -712,29 +708,29 @@ export class BinaryTree<
* matches the identifier. If set to true, the function will stop iterating once it finds a matching
* node and return that node. If set to false (default), the function will continue iterating and
* return all nodes that match the identifier.
- * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
+ * @param {K | NODE | null | undefined} beginRoot - The `beginRoot` parameter represents the
* starting node for the traversal. It can be either a key, a node object, or `null`/`undefined`. If
* it is `null` or `undefined`, an empty array will be returned.
* @param iterationType - The `iterationType` parameter determines the type of iteration used to
* traverse the binary tree. It can have two possible values:
- * @returns an array of nodes of type `N`.
+ * @returns an array of nodes of type `NODE`.
*/
- getNodes>(
+ getNodes>(
identifier: ReturnType | null | undefined,
callback: C = this._defaultOneParamCallback as C,
onlyOne = false,
- beginRoot: KeyOrNodeOrEntry = this.root,
+ beginRoot: KeyOrNodeOrEntry = this.root,
iterationType = this.iterationType
- ): N[] {
+ ): NODE[] {
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
callback = (node => node) as C;
beginRoot = this.ensureNode(beginRoot);
if (!beginRoot) return [];
- const ans: N[] = [];
+ const ans: NODE[] = [];
if (iterationType === IterationType.RECURSIVE) {
- const _traverse = (cur: N) => {
+ const _traverse = (cur: NODE) => {
if (callback(cur) === identifier) {
ans.push(cur);
if (onlyOne) return;
@@ -746,7 +742,7 @@ export class BinaryTree<
_traverse(beginRoot);
} else {
- const queue = new Queue([beginRoot]);
+ const queue = new Queue([beginRoot]);
while (queue.size > 0) {
const cur = queue.shift();
if (cur) {
@@ -768,24 +764,24 @@ export class BinaryTree<
* Space Complexity: O(log n).
*/
- override has>(
+ override has>(
identifier: K,
callback?: C,
- beginRoot?: KeyOrNodeOrEntry,
+ beginRoot?: KeyOrNodeOrEntry,
iterationType?: IterationType
): boolean;
- override has>(
- identifier: N | null | undefined,
+ override has>(
+ identifier: NODE | null | undefined,
callback?: C,
- beginRoot?: KeyOrNodeOrEntry,
+ beginRoot?: KeyOrNodeOrEntry,
iterationType?: IterationType
): boolean;
- override has>(
+ override has>(
identifier: ReturnType | null | undefined,
callback: C,
- beginRoot?: KeyOrNodeOrEntry,
+ beginRoot?: KeyOrNodeOrEntry,
iterationType?: IterationType
): boolean;
@@ -802,18 +798,18 @@ export class BinaryTree<
* the binary tree. It is used to filter the nodes based on certain conditions. The `callback`
* function should return a boolean value indicating whether the node should be included in the
* result or not.
- * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
+ * @param {K | NODE | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
* for the search in the binary tree. It can be specified as a `K` (a unique identifier for a
- * node in the binary tree), a node object (`N`), or `null`/`undefined` to start the search from
+ * node in the binary tree), a node object (`NODE`), or `null`/`undefined` to start the search from
* @param iterationType - The `iterationType` parameter is a variable that determines the type of
* iteration to be performed on the binary tree. It is used to specify whether the iteration should
* be performed in a pre-order, in-order, or post-order manner.
* @returns a boolean value.
*/
- override has>(
+ override has>(
identifier: ReturnType | null | undefined,
callback: C = this._defaultOneParamCallback as C,
- beginRoot: KeyOrNodeOrEntry = this.root,
+ beginRoot: KeyOrNodeOrEntry = this.root,
iterationType = this.iterationType
): boolean {
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
@@ -827,26 +823,26 @@ export class BinaryTree<
* Space Complexity: O(log n).
*/
- getNode>(
+ getNode>(
identifier: K,
callback?: C,
- beginRoot?: KeyOrNodeOrEntry,
+ beginRoot?: KeyOrNodeOrEntry,
iterationType?: IterationType
- ): N | null | undefined;
+ ): NODE | null | undefined;
- getNode>(
- identifier: N | null | undefined,
+ getNode>(
+ identifier: NODE | null | undefined,
callback?: C,
- beginRoot?: KeyOrNodeOrEntry,
+ beginRoot?: KeyOrNodeOrEntry,
iterationType?: IterationType
- ): N | null | undefined;
+ ): NODE | null | undefined;
- getNode>(
+ getNode>(
identifier: ReturnType,
callback: C,
- beginRoot?: KeyOrNodeOrEntry,
+ beginRoot?: KeyOrNodeOrEntry,
iterationType?: IterationType
- ): N | null | undefined;
+ ): NODE | null | undefined;
/**
* Time Complexity: O(n)
@@ -860,21 +856,21 @@ export class BinaryTree<
* identifier.
* @param {C} callback - The `callback` parameter is a function that will be called for each node in
* the binary tree. It is used to determine if a node matches the given identifier. The `callback`
- * function should take a single parameter of type `N` (the type of the nodes in the binary tree) and
- * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
+ * function should take a single parameter of type `NODE` (the type of the nodes in the binary tree) and
+ * @param {K | NODE | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
* for searching the binary tree. It can be either a key value, a node object, or `null`/`undefined`.
* If `null` or `undefined` is passed, the search will start from the root of the binary tree.
* @param iterationType - The `iterationType` parameter is used to specify the type of iteration to
* be performed when searching for nodes in the binary tree. It determines the order in which the
* nodes are visited during the search.
- * @returns a value of type `N | null | undefined`.
+ * @returns a value of type `NODE | null | undefined`.
*/
- getNode>(
+ getNode>(
identifier: ReturnType | null | undefined,
callback: C = this._defaultOneParamCallback as C,
- beginRoot: KeyOrNodeOrEntry = this.root,
+ beginRoot: KeyOrNodeOrEntry = this.root,
iterationType = this.iterationType
- ): N | null | undefined {
+ ): NODE | null | undefined {
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
callback = (node => node) as C;
@@ -897,13 +893,13 @@ export class BinaryTree<
* @param iterationType - The `iterationType` parameter is used to determine whether the search for
* the node with the given key should be performed iteratively or recursively. It has two possible
* values:
- * @returns The function `getNodeByKey` returns a node (`N`) if a node with the specified key is
+ * @returns The function `getNodeByKey` returns a node (`NODE`) if a node with the specified key is
* found in the binary tree. If no node is found, it returns `undefined`.
*/
- getNodeByKey(key: K, iterationType = IterationType.ITERATIVE): N | undefined {
+ getNodeByKey(key: K, iterationType = IterationType.ITERATIVE): NODE | undefined {
if (!this.root) return undefined;
if (iterationType === IterationType.RECURSIVE) {
- const _dfs = (cur: N): N | undefined => {
+ const _dfs = (cur: NODE): NODE | undefined => {
if (cur.key === key) return cur;
if (!cur.left && !cur.right) return;
@@ -913,7 +909,7 @@ export class BinaryTree<
return _dfs(this.root);
} else {
- const queue = new Queue([this.root]);
+ const queue = new Queue([this.root]);
while (queue.size > 0) {
const cur = queue.shift();
if (cur) {
@@ -925,24 +921,24 @@ export class BinaryTree<
}
}
- override get>(
+ override get>(
identifier: K,
callback?: C,
- beginRoot?: KeyOrNodeOrEntry,
+ beginRoot?: KeyOrNodeOrEntry,
iterationType?: IterationType
): V | undefined;
- override get>(
- identifier: N | null | undefined,
+ override get>(
+ identifier: NODE | null | undefined,
callback?: C,
- beginRoot?: KeyOrNodeOrEntry,
+ beginRoot?: KeyOrNodeOrEntry,
iterationType?: IterationType
): V | undefined;
- override get>(
+ override get>(
identifier: ReturnType,
callback: C,
- beginRoot?: KeyOrNodeOrEntry,
+ beginRoot?: KeyOrNodeOrEntry,
iterationType?: IterationType
): V | undefined;
@@ -959,19 +955,19 @@ export class BinaryTree<
* the binary tree. It is used to determine whether a node matches the given identifier. The callback
* function should return a value that can be compared to the identifier to determine if it is a
* match.
- * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
+ * @param {K | NODE | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
* for the search in the binary tree. It can be specified as a `K` (a unique identifier for a
- * node), a node object of type `N`, or `null`/`undefined` to start the search from the root of
+ * node), a node object of type `NODE`, or `null`/`undefined` to start the search from the root of
* @param iterationType - The `iterationType` parameter is used to specify the type of iteration to
* be performed when searching for a node in the binary tree. It is an optional parameter with a
* default value specified by `this.iterationType`.
* @returns The value of the node with the given identifier is being returned. If the node is not
* found, `undefined` is returned.
*/
- override get>(
+ override get>(
identifier: ReturnType | null | undefined,
callback: C = this._defaultOneParamCallback as C,
- beginRoot: KeyOrNodeOrEntry = this.root,
+ beginRoot: KeyOrNodeOrEntry = this.root,
iterationType = this.iterationType
): V | undefined {
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
@@ -1018,17 +1014,17 @@ export class BinaryTree<
*
* The function `getPathToRoot` returns an array of nodes from a given node to the root of a tree
* structure, with the option to reverse the order of the nodes.
- * @param {K | N | null | undefined} beginNode - The `beginRoot` parameter represents the
- * starting node from which you want to find the path to the root. It can be of type `K`, `N`,
+ * @param {K | NODE | null | undefined} beginNode - The `beginRoot` parameter represents the
+ * starting node from which you want to find the path to the root. It can be of type `K`, `NODE`,
* `null`, or `undefined`.
* @param [isReverse=true] - The `isReverse` parameter is a boolean flag that determines whether the
* resulting path should be reversed or not. If `isReverse` is set to `true`, the path will be
* reversed before returning it. If `isReverse` is set to `false`, the path will be returned as is
- * @returns The function `getPathToRoot` returns an array of nodes (`N[]`).
+ * @returns The function `getPathToRoot` returns an array of nodes (`NODE[]`).
*/
- getPathToRoot(beginNode: KeyOrNodeOrEntry, isReverse = true): N[] {
+ getPathToRoot(beginNode: KeyOrNodeOrEntry, isReverse = true): NODE[] {
// TODO to support get path through passing key
- const result: N[] = [];
+ const result: NODE[] = [];
beginNode = this.ensureNode(beginNode);
if (!beginNode) return result;
@@ -1054,24 +1050,24 @@ export class BinaryTree<
*
* The function `getLeftMost` returns the leftmost node in a binary tree, either recursively or
* iteratively.
- * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
- * for finding the leftmost node in a binary tree. It can be either a `K` (a key value), `N` (a
+ * @param {K | NODE | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
+ * for finding the leftmost node in a binary tree. It can be either a `K` (a key value), `NODE` (a
* node), `null`, or `undefined`. If not provided, it defaults to `this.root`,
* @param iterationType - The `iterationType` parameter is used to determine the type of iteration to
* be performed when finding the leftmost node in a binary tree. It can have two possible values:
- * @returns The function `getLeftMost` returns the leftmost node (`N`) in the binary tree. If there
+ * @returns The function `getLeftMost` returns the leftmost node (`NODE`) in the binary tree. If there
* is no leftmost node, it returns `null` or `undefined` depending on the input.
*/
getLeftMost(
- beginRoot: KeyOrNodeOrEntry = this.root,
+ beginRoot: KeyOrNodeOrEntry = this.root,
iterationType = this.iterationType
- ): N | null | undefined {
+ ): NODE | null | undefined {
beginRoot = this.ensureNode(beginRoot);
if (!beginRoot) return beginRoot;
if (iterationType === IterationType.RECURSIVE) {
- const _traverse = (cur: N): N => {
+ const _traverse = (cur: NODE): NODE => {
if (!this.isRealNode(cur.left)) return cur;
return _traverse(cur.left);
};
@@ -1079,7 +1075,7 @@ export class BinaryTree<
return _traverse(beginRoot);
} else {
// Indirect implementation of iteration using tail recursion optimization
- const _traverse = trampoline((cur: N) => {
+ const _traverse = trampoline((cur: NODE) => {
if (!this.isRealNode(cur.left)) return cur;
return _traverse.cont(cur.left);
});
@@ -1099,25 +1095,25 @@ export class BinaryTree<
*
* The function `getRightMost` returns the rightmost node in a binary tree, either recursively or
* iteratively.
- * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
- * starting node from which we want to find the rightmost node. It can be of type `K`, `N`,
+ * @param {K | NODE | null | undefined} beginRoot - The `beginRoot` parameter represents the
+ * starting node from which we want to find the rightmost node. It can be of type `K`, `NODE`,
* `null`, or `undefined`. If not provided, it defaults to `this.root`, which is a property of the
* current object.
* @param iterationType - The `iterationType` parameter is an optional parameter that specifies the
* type of iteration to use when finding the rightmost node. It can have one of two values:
- * @returns The function `getRightMost` returns the rightmost node (`N`) in a binary tree. If there
+ * @returns The function `getRightMost` returns the rightmost node (`NODE`) in a binary tree. If there
* is no rightmost node, it returns `null` or `undefined`, depending on the input.
*/
getRightMost(
- beginRoot: KeyOrNodeOrEntry = this.root,
+ beginRoot: KeyOrNodeOrEntry = this.root,
iterationType = this.iterationType
- ): N | null | undefined {
+ ): NODE | null | undefined {
// TODO support get right most by passing key in
beginRoot = this.ensureNode(beginRoot);
if (!beginRoot) return beginRoot;
if (iterationType === IterationType.RECURSIVE) {
- const _traverse = (cur: N): N => {
+ const _traverse = (cur: NODE): NODE => {
if (!this.isRealNode(cur.right)) return cur;
return _traverse(cur.right);
};
@@ -1125,7 +1121,7 @@ export class BinaryTree<
return _traverse(beginRoot);
} else {
// Indirect implementation of iteration using tail recursion optimization
- const _traverse = trampoline((cur: N) => {
+ const _traverse = trampoline((cur: NODE) => {
if (!this.isRealNode(cur.right)) return cur;
return _traverse.cont(cur.right);
});
@@ -1144,20 +1140,20 @@ export class BinaryTree<
* Space Complexity: O(1)
*
* The function `isSubtreeBST` checks if a given binary tree is a valid binary search tree.
- * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the root
+ * @param {K | NODE | null | undefined} beginRoot - The `beginRoot` parameter represents the root
* node of the binary search tree (BST) that you want to check if it is a subtree of another BST.
* @param iterationType - The `iterationType` parameter is an optional parameter that specifies the
* type of iteration to use when checking if a subtree is a binary search tree (BST). It can have two
* possible values:
* @returns a boolean value.
*/
- isBST(beginRoot: KeyOrNodeOrEntry = this.root, iterationType = this.iterationType): boolean {
+ isBST(beginRoot: KeyOrNodeOrEntry = this.root, iterationType = this.iterationType): boolean {
// TODO there is a bug
beginRoot = this.ensureNode(beginRoot);
if (!beginRoot) return true;
if (iterationType === IterationType.RECURSIVE) {
- const dfs = (cur: N | null | undefined, min: number, max: number): boolean => {
+ const dfs = (cur: NODE | null | undefined, min: number, max: number): boolean => {
if (!cur) return true;
const numKey = this.extractor(cur.key);
if (numKey <= min || numKey >= max) return false;
@@ -1172,7 +1168,7 @@ export class BinaryTree<
const stack = [];
let prev = checkMax ? Number.MAX_SAFE_INTEGER : Number.MIN_SAFE_INTEGER;
// @ts-ignore
- let curr: N | null | undefined = beginRoot;
+ let curr: NODE | null | undefined = beginRoot;
while (curr || stack.length > 0) {
while (curr) {
stack.push(curr);
@@ -1197,16 +1193,16 @@ export class BinaryTree<
// * Space complexity: O(log n)
// */
//
- // subTreeTraverse>(
+ // subTreeTraverse>(
// callback?: C,
- // beginRoot?: KeyOrNodeOrEntry,
+ // beginRoot?: KeyOrNodeOrEntry,
// iterationType?: IterationType,
// includeNull?: false
// ): ReturnType[];
//
- // subTreeTraverse>(
+ // subTreeTraverse>(
// callback?: C,
- // beginRoot?: KeyOrNodeOrEntry,
+ // beginRoot?: KeyOrNodeOrEntry,
// iterationType?: IterationType,
// includeNull?: true
// ): ReturnType[];
@@ -1220,9 +1216,9 @@ export class BinaryTree<
// * @param {C} callback - The `callback` parameter is a function that will be called for each node in
// * the subtree traversal. It takes a single parameter, which is the current node being traversed, and
// * returns a value of any type.
- // * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
+ // * @param {K | NODE | null | undefined} beginRoot - The `beginRoot` parameter represents the
// * starting node or key from which the subtree traversal should begin. It can be of type `K`,
- // * `N`, `null`, or `undefined`. If not provided, the `root` property of the current object is used as
+ // * `NODE`, `null`, or `undefined`. If not provided, the `root` property of the current object is used as
// * the default value.
// * @param iterationType - The `iterationType` parameter determines the type of traversal to be
// * performed on the subtree. It can have two possible values:
@@ -1233,9 +1229,9 @@ export class BinaryTree<
// * the `callback` function on each node in the subtree. The type of the array nodes is determined
// * by the return type of the `callback` function.
// */
- // subTreeTraverse>(
+ // subTreeTraverse>(
// callback: C = this._defaultOneParamCallback as C,
- // beginRoot: KeyOrNodeOrEntry = this.root,
+ // beginRoot: KeyOrNodeOrEntry = this.root,
// iterationType = this.iterationType,
// includeNull = false
// ): ReturnType[] {
@@ -1243,11 +1239,11 @@ export class BinaryTree<
//
// beginRoot = this.ensureNode(beginRoot);
//
- // const ans: (ReturnType> | null | undefined)[] = [];
+ // const ans: (ReturnType> | null | undefined)[] = [];
// if (!beginRoot) return ans;
//
// if (iterationType === IterationType.RECURSIVE) {
- // const _traverse = (cur: N | null | undefined) => {
+ // const _traverse = (cur: NODE | null | undefined) => {
// if (cur !== undefined) {
// ans.push(callback(cur));
// if (includeNull) {
@@ -1262,7 +1258,7 @@ export class BinaryTree<
//
// _traverse(beginRoot);
// } else {
- // const stack: (N | null | undefined)[] = [beginRoot];
+ // const stack: (NODE | null | undefined)[] = [beginRoot];
//
// while (stack.length > 0) {
// const cur = stack.pop();
@@ -1281,18 +1277,18 @@ export class BinaryTree<
// return ans;
// }
- dfs>(
+ dfs>(
callback?: C,
pattern?: DFSOrderPattern,
- beginRoot?: KeyOrNodeOrEntry