+
+## Algorithms list only a few out, you can discover more in API docs
+
+DFS, DFSIterative, BFS, morris, Bellman-Ford Algorithm, Dijkstra's Algorithm, Floyd-Warshall Algorithm, Tarjan's Algorithm
# How
@@ -409,69 +599,6 @@ describe('DirectedGraph Test3', () => {
## API docs
-[//]: # ([api docs](https://data-structure-typed-docs.vercel.app/))
-
-
[//]: # ([Examples Repository](https://github.com/zrwusa/data-structure-typed-examples))
diff --git a/package.json b/package.json
index 954dfb4..642e724 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "data-structure-typed",
- "version": "1.18.0",
+ "version": "1.18.5",
"description": "Explore our comprehensive Javascript Data Structure / TypeScript Data Structure Library, meticulously crafted to empower developers with a versatile set of essential data structures. Our library includes a wide range of data structures, such as Binary Tree, AVL Tree, Binary Search Tree (BST), Tree Multiset, Segment Tree, Binary Indexed Tree, Graph, Directed Graph, Undirected Graph, Singly Linked List, Hash, CoordinateSet, CoordinateMap, Heap, Doubly Linked List, Priority Queue, Max Priority Queue, Min Priority Queue, Queue, ObjectDeque, ArrayDeque, Stack, and Trie. Each data structure is thoughtfully designed and implemented using TypeScript to provide efficient, reliable, and easy-to-use solutions for your programming needs. Whether you're optimizing algorithms, managing data, or enhancing performance, our TypeScript Data Structure Library is your go-to resource. Elevate your coding experience with these fundamental building blocks for software development.",
"main": "dist/index.js",
"scripts": {
@@ -38,7 +38,15 @@
"Priority Queue",
"Max Priority Queue",
"Min Priority Queue",
- "Trie"
+ "Trie",
+ "DFS",
+ "DFSIterative",
+ "BFS",
+ "morris",
+ "Bellman-Ford ",
+ "Dijkstra's Algorithm",
+ "Floyd-Warshall Algorithm",
+ "Tarjan's Algorithm"
],
"author": "Tyler Zeng zrwusa@gmail.com",
"license": "MIT",
diff --git a/src/data-structures/binary-tree/avl-tree.ts b/src/data-structures/binary-tree/avl-tree.ts
index d095a27..7c5953d 100644
--- a/src/data-structures/binary-tree/avl-tree.ts
+++ b/src/data-structures/binary-tree/avl-tree.ts
@@ -6,19 +6,19 @@
* @license MIT License
*/
import {BST, BSTNode} from './bst';
-import type {AVLTreeDeleted, BinaryTreeNodeId} from '../types';
+import type {AVLTreeDeleted, BinaryTreeNodeId, RecursiveAVLTreeNode} from '../types';
import {IBinaryTreeNode} from '../interfaces';
-export class AVLTreeNode extends BSTNode implements IBinaryTreeNode {
- override _createNode(id: BinaryTreeNodeId, val: T | null, count?: number): AVLTreeNode | null {
- return val !== null ? new AVLTreeNode(id, val, count) : null;
- }
+
+export class AVLTreeNode = RecursiveAVLTreeNode> extends BSTNode implements IBinaryTreeNode {
+
}
-export class AVLTree extends BST {
+export class AVLTree = AVLTreeNode> extends BST {
- override _createNode(id: BinaryTreeNodeId, val: T, count?: number): AVLTreeNode {
- return new AVLTreeNode(id, val, count);
+ override _createNode(id: BinaryTreeNodeId, val: N['val'], count?: number): N {
+ const node = new AVLTreeNode(id, val, count);
+ return node as N;
}
/**
@@ -26,14 +26,14 @@ export class AVLTree extends BST {
* balances the tree.
* @param {BinaryTreeNodeId} id - The `id` parameter is the identifier of the binary tree node that we want to add or
* update in the AVL tree.
- * @param {T | null} val - The `val` parameter represents the value that you want to assign to the node with the given
- * `id`. It can be of type `T` (the generic type) or `null`.
+ * @param {N | null} val - The `val` parameter represents the value that you want to assign to the node with the given
+ * `id`. It can be of type `N` (the generic type) or `null`.
* @param {number} [count] - The `count` parameter is an optional parameter of type `number`. It represents the number
* of times the value `val` should be inserted into the AVL tree. If the `count` parameter is not provided, it defaults
* to `1`, indicating that the value should be inserted once.
- * @returns The method is returning either an AVLTreeNode object or null.
+ * @returns The method is returning either an N object or null.
*/
- override add(id: BinaryTreeNodeId, val: T | null, count?: number): AVLTreeNode | null {
+ override add(id: BinaryTreeNodeId, val: N['val'] | null, count?: number): N | null {
const inserted = super.add(id, val, count);
if (inserted) this.balancePath(inserted);
return inserted;
@@ -47,9 +47,9 @@ export class AVLTree extends BST {
* @param {boolean} [isUpdateAllLeftSum] - The `isUpdateAllLeftSum` parameter is an optional boolean parameter that
* determines whether the left sum of all nodes in the AVL tree should be updated after removing a node. If
* `isUpdateAllLeftSum` is set to `true`, the left sum of all nodes will be recalculated.
- * @returns The method is returning an array of `AVLTreeDeleted` objects.
+ * @returns The method is returning an array of `AVLTreeDeleted` objects.
*/
- override remove(id: BinaryTreeNodeId, isUpdateAllLeftSum?: boolean): AVLTreeDeleted[] {
+ override remove(id: BinaryTreeNodeId, isUpdateAllLeftSum?: boolean): AVLTreeDeleted[] {
const deletedResults = super.remove(id, isUpdateAllLeftSum);
for (const {needBalanced} of deletedResults) {
if (needBalanced) {
@@ -62,10 +62,10 @@ export class AVLTree extends BST {
/**
* The balance factor of a given AVL tree node is calculated by subtracting the height of its left subtree from the
* height of its right subtree.
- * @param node - The parameter "node" is of type AVLTreeNode, which represents a node in an AVL tree.
+ * @param node - The parameter "node" is of type N, which represents a node in an AVL tree.
* @returns The balance factor of the given AVL tree node.
*/
- balanceFactor(node: AVLTreeNode): number {
+ balanceFactor(node: N): number {
if (!node.right) // node has no right subtree
return -node.height;
else if (!node.left) // node has no left subtree
@@ -78,7 +78,7 @@ export class AVLTree extends BST {
* The function updates the height of a node in an AVL tree based on the heights of its left and right subtrees.
* @param node - The parameter `node` is an AVLTreeNode object, which represents a node in an AVL tree.
*/
- updateHeight(node: AVLTreeNode): void {
+ updateHeight(node: N): void {
if (!node.left && !node.right) // node is a leaf
node.height = 0;
else if (!node.left) {
@@ -96,7 +96,7 @@ export class AVLTree extends BST {
* each node in the path from the given node to the root.
* @param node - The `node` parameter is an AVLTreeNode object, which represents a node in an AVL tree.
*/
- balancePath(node: AVLTreeNode): void {
+ balancePath(node: N): void {
const path = this.getPathToRoot(node);
for (let i = path.length - 1; i >= 0; i--) {
const A = path[i];
@@ -127,7 +127,7 @@ export class AVLTree extends BST {
* The `balanceLL` function performs a left-left rotation on an AVL tree to balance it.
* @param A - The parameter A is an AVLTreeNode object.
*/
- balanceLL(A: AVLTreeNode): void {
+ balanceLL(A: N): void {
const parentOfA = A.parent;
const B = A.left; // A is left-heavy and B is left-heavy
A.parent = B;
@@ -157,7 +157,7 @@ export class AVLTree extends BST {
* The `balanceLR` function performs a left-right rotation to balance an AVL tree.
* @param A - A is an AVLTreeNode object.
*/
- balanceLR(A: AVLTreeNode): void {
+ balanceLR(A: N): void {
const parentOfA = A.parent;
const B = A.left; // A is left-heavy
let C = null;
@@ -205,7 +205,7 @@ export class AVLTree extends BST {
* The `balanceRR` function performs a right-right rotation on an AVL tree to balance it.
* @param A - The parameter A is an AVLTreeNode object.
*/
- balanceRR(A: AVLTreeNode): void {
+ balanceRR(A: N): void {
const parentOfA = A.parent;
const B = A.right; // A is right-heavy and B is right-heavy
A.parent = B;
@@ -240,7 +240,7 @@ export class AVLTree extends BST {
* The `balanceRL` function performs a right-left rotation to balance an AVL tree.
* @param A - A is an AVLTreeNode object.
*/
- balanceRL(A: AVLTreeNode): void {
+ balanceRL(A: N): void {
const parentOfA = A.parent;
const B = A.right; // A is right-heavy
let C = null;
diff --git a/src/data-structures/binary-tree/binary-tree.ts b/src/data-structures/binary-tree/binary-tree.ts
index fb2faae..606a3c9 100644
--- a/src/data-structures/binary-tree/binary-tree.ts
+++ b/src/data-structures/binary-tree/binary-tree.ts
@@ -13,6 +13,7 @@ import type {
BinaryTreeNodePropertyName,
DFSOrderPattern,
NodeOrPropertyName,
+ RecursiveBinaryTreeNode,
ResultByProperty,
ResultsByProperty
} from '../types';
@@ -29,7 +30,7 @@ export enum FamilyPosition {root, left, right}
*/
export enum LoopType { iterative = 1, recursive = 2}
-export class BinaryTreeNode implements IBinaryTreeNode {
+export class BinaryTreeNode = RecursiveBinaryTreeNode> implements IBinaryTreeNode {
constructor(id: BinaryTreeNodeId, val: T, count?: number) {
this._id = id;
@@ -57,41 +58,41 @@ export class BinaryTreeNode implements IBinaryTreeNode {
this._val = v;
}
- private _left?: BinaryTreeNode | null;
+ private _left?: FAMILY | null;
- get left(): BinaryTreeNode | null | undefined {
+ get left(): FAMILY | null | undefined {
return this._left;
}
- set left(v: BinaryTreeNode | null | undefined) {
+ set left(v: FAMILY | null | undefined) {
if (v) {
- v.parent = this;
+ v.parent = this as unknown as FAMILY;
v.familyPosition = FamilyPosition.left;
}
this._left = v;
}
- private _right?: BinaryTreeNode | null;
+ private _right?: FAMILY | null;
- get right(): BinaryTreeNode | null | undefined {
+ get right(): FAMILY | null | undefined {
return this._right;
}
- set right(v: BinaryTreeNode | null | undefined) {
+ set right(v: FAMILY | null | undefined) {
if (v) {
- v.parent = this;
+ v.parent = this as unknown as FAMILY;
v.familyPosition = FamilyPosition.right;
}
this._right = v;
}
- private _parent: BinaryTreeNode | null | undefined;
+ private _parent: FAMILY | null | undefined;
- get parent(): BinaryTreeNode | null | undefined {
+ get parent(): FAMILY | null | undefined {
return this._parent;
}
- set parent(v: BinaryTreeNode | null | undefined) {
+ set parent(v: FAMILY | null | undefined) {
this._parent = v;
}
@@ -125,11 +126,11 @@ export class BinaryTreeNode implements IBinaryTreeNode {
this._height = v;
}
- _createNode(id: BinaryTreeNodeId, val: T | null, count?: number): BinaryTreeNode | null {
- return val !== null ? new BinaryTreeNode(id, val, count) : null;
+ _createNode(id: BinaryTreeNodeId, val: T | null, count?: number): FAMILY | null {
+ return val !== null ? new BinaryTreeNode(id, val, count) as FAMILY : null;
}
- swapLocation(swapNode: BinaryTreeNode): BinaryTreeNode {
+ swapLocation(swapNode: FAMILY): FAMILY {
const {val, count, height} = swapNode;
const tempNode = this._createNode(swapNode.id, val);
if (tempNode instanceof BinaryTreeNode) {
@@ -150,12 +151,12 @@ export class BinaryTreeNode implements IBinaryTreeNode {
return swapNode;
}
- clone(): BinaryTreeNode | null {
+ clone(): FAMILY | null {
return this._createNode(this.id, this.val, this.count);
}
}
-export class BinaryTree implements IBinaryTree {
+export class BinaryTree = BinaryTreeNode> implements IBinaryTree {
/**
* The constructor function accepts an optional options object and sets the values of loopType, autoIncrementId, and
@@ -190,15 +191,15 @@ export class BinaryTree implements IBinaryTree {
return this._visitedId;
}
- private _visitedVal: Array = [];
+ private _visitedVal: Array = [];
- get visitedVal(): Array {
+ get visitedVal(): Array {
return this._visitedVal;
}
- private _visitedNode: BinaryTreeNode[] = [];
+ private _visitedNode: N[] = [];
- get visitedNode(): BinaryTreeNode[] {
+ get visitedNode(): N[] {
return this._visitedNode;
}
@@ -232,9 +233,9 @@ export class BinaryTree implements IBinaryTree {
return this._isDuplicatedVal;
}
- private _root: BinaryTreeNode | null = null;
+ private _root: N | null = null;
- get root(): BinaryTreeNode | null {
+ get root(): N | null {
return this._root;
}
@@ -255,14 +256,15 @@ export class BinaryTree implements IBinaryTree {
* it returns null.
* @param {BinaryTreeNodeId} id - The `id` parameter is the identifier for the binary tree node. It is of type
* `BinaryTreeNodeId`.
- * @param {T | null} val - The `val` parameter represents the value of the node. It can be of type `T` (generic type)
+ * @param {N | null} val - The `val` parameter represents the value of the node. It can be of type `N` (generic type)
* or `null`.
* @param {number} [count] - The `count` parameter is an optional parameter of type `number`. It represents the number
* of occurrences of the value in the binary tree node. If not provided, the default value is `undefined`.
* @returns a BinaryTreeNode object if the value is not null, otherwise it returns null.
*/
- _createNode(id: BinaryTreeNodeId, val: T | null, count?: number): BinaryTreeNode | null {
- return val !== null ? new BinaryTreeNode(id, val, count) : null;
+ _createNode(id: BinaryTreeNodeId, val: N['val'] | null, count?: number): N | null {
+ const node = new BinaryTreeNode(id, val, count);
+ return node as N | null;
}
/**
@@ -288,17 +290,17 @@ export class BinaryTree implements IBinaryTree {
* already exists.
* @param {BinaryTreeNodeId} id - The id parameter is the identifier of the binary tree node. It is used to uniquely
* identify each node in the binary tree.
- * @param {T} val - The value to be inserted into the binary tree.
+ * @param {N} val - The value to be inserted into the binary tree.
* @param {number} [count] - The `count` parameter is an optional parameter that specifies the number of times the
* value should be inserted into the binary tree. If not provided, it defaults to 1.
- * @returns The function `add` returns a `BinaryTreeNode` object if a new node is inserted, or `null` if no new node
+ * @returns The function `add` returns a `N` object if a new node is inserted, or `null` if no new node
* is inserted, or `undefined` if the insertion fails.
*/
- add(id: BinaryTreeNodeId, val: T, count?: number): BinaryTreeNode | null | undefined {
+ add(id: BinaryTreeNodeId, val: N['val'], count?: number): N | null | undefined {
count = count ?? 1;
- const _bfs = (root: BinaryTreeNode, newNode: BinaryTreeNode | null): BinaryTreeNode | undefined | null => {
- const queue: Array | null> = [root];
+ const _bfs = (root: N, newNode: N | null): N | undefined | null => {
+ const queue: Array = [root];
while (queue.length > 0) {
const cur = queue.shift();
if (cur) {
@@ -311,7 +313,7 @@ export class BinaryTree implements IBinaryTree {
return;
};
- let inserted: BinaryTreeNode | null | undefined;
+ let inserted: N | null | undefined;
const needInsert = val !== null ? this._createNode(id, val, count) : null;
const existNode = val !== null ? this.get(id, 'id') : null;
if (this.root) {
@@ -338,13 +340,13 @@ export class BinaryTree implements IBinaryTree {
/**
* The function inserts a new node into a binary tree as the left or right child of a given parent node.
- * @param {BinaryTreeNode | null} newNode - The `newNode` parameter is an instance of the `BinaryTreeNode` class or
+ * @param {N | null} newNode - The `newNode` parameter is an instance of the `BinaryTreeNode` class or
* `null`. It represents the node that needs to be inserted into the binary tree.
* @param parent - The `parent` parameter is a BinaryTreeNode object representing the parent node to which the new node
* will be inserted as a child.
* @returns The method returns the newly inserted node, either as the left child or the right child of the parent node.
*/
- addTo(newNode: BinaryTreeNode | null, parent: BinaryTreeNode) {
+ addTo(newNode: N | null, parent: N) {
if (parent) {
if (parent.left === undefined) {
if (newNode) {
@@ -354,7 +356,7 @@ export class BinaryTree implements IBinaryTree {
parent.left = newNode;
if (newNode !== null) {
this._setSize(this.size + 1);
- this._setCount(this.count + newNode?.count ?? 0)
+ this._setCount(this.count + newNode.count ?? 0)
}
return parent.left;
@@ -366,7 +368,7 @@ export class BinaryTree implements IBinaryTree {
parent.right = newNode;
if (newNode !== null) {
this._setSize(this.size + 1);
- this._setCount(this.count + newNode?.count ?? 0);
+ this._setCount(this.count + newNode.count ?? 0);
}
return parent.right;
} else {
@@ -380,13 +382,13 @@ export class BinaryTree implements IBinaryTree {
/**
* The `addMany` function inserts multiple items into a binary tree and returns an array of the inserted nodes or
* null/undefined values.
- * @param {T[] | BinaryTreeNode[]} data - The `data` parameter can be either an array of elements of type `T` or an
- * array of `BinaryTreeNode` objects.
- * @returns The function `addMany` returns an array of `BinaryTreeNode`, `null`, or `undefined` values.
+ * @param {N[] | N[]} data - The `data` parameter can be either an array of elements of type `N` or an
+ * array of `N` objects.
+ * @returns The function `addMany` returns an array of `N`, `null`, or `undefined` values.
*/
- addMany(data: T[] | BinaryTreeNode[]): (BinaryTreeNode | null | undefined)[] {
- const inserted: (BinaryTreeNode | null | undefined)[] = [];
- const map: Map, number> = new Map();
+ addMany(data: N[] | Array): (N | null | undefined)[] {
+ const inserted: (N | null | undefined)[] = [];
+ const map: Map = new Map();
if (!this._isDuplicatedVal) {
for (const i of data) map.set(i, (map.get(i) ?? 0) + 1);
@@ -427,11 +429,11 @@ export class BinaryTree implements IBinaryTree {
/**
* The `fill` function clears the current data and inserts new data, returning a boolean indicating if the insertion
* was successful.
- * @param {T[] | BinaryTreeNode[]} data - The `data` parameter can be either an array of elements of type `T` or an
- * array of `BinaryTreeNode` objects.
+ * @param {N[] | N[]} data - The `data` parameter can be either an array of elements of type `N` or an
+ * array of `N` objects.
* @returns The method is returning a boolean value.
*/
- fill(data: T[] | BinaryTreeNode[]): boolean {
+ fill(data: N[] | Array): boolean {
this.clear();
return data.length === this.addMany(data).length;
}
@@ -447,9 +449,9 @@ export class BinaryTree implements IBinaryTree {
* "needBalanced". The "deleted" property contains the deleted node or undefined if no node was deleted. The
* "needBalanced" property is always null.
*/
- remove(id: BinaryTreeNodeId, ignoreCount?: boolean): BinaryTreeDeleted[] {
+ remove(id: BinaryTreeNodeId, ignoreCount?: boolean): BinaryTreeDeleted[] {
const nodes = this.getNodes(id, 'id', true);
- let node: BinaryTreeNode | null | undefined = nodes[0];
+ let node: N | null | undefined = nodes[0];
if (!node) node = undefined;
else if (node.count > 1 && !ignoreCount) {
@@ -485,11 +487,11 @@ export class BinaryTree implements IBinaryTree {
/**
* The function calculates the depth of a binary tree node by traversing its parent nodes.
- * @param node - BinaryTreeNode - This is the node for which we want to calculate the depth. It is a generic type,
+ * @param node - N - This is the node for which we want to calculate the depth. It is a generic type,
* meaning it can represent any type of data that we want to store in the node.
* @returns The depth of the given binary tree node.
*/
- getDepth(node: BinaryTreeNode): number {
+ getDepth(node: N): number {
let depth = 0;
while (node.parent) {
depth++;
@@ -501,17 +503,17 @@ export class BinaryTree implements IBinaryTree {
/**
* The `getHeight` function calculates the maximum height of a binary tree using either a recursive or iterative
* approach.
- * @param {BinaryTreeNode | null} [beginRoot] - The `beginRoot` parameter is an optional parameter of type
- * `BinaryTreeNode | null`. It represents the starting node from which to calculate the height of the binary tree.
+ * @param {N | null} [beginRoot] - The `beginRoot` parameter is an optional parameter of type
+ * `N | null`. It represents the starting node from which to calculate the height of the binary tree.
* If no value is provided for `beginRoot`, the function will use the `root` property of the class instance as
* @returns the height of the binary tree.
*/
- getHeight(beginRoot?: BinaryTreeNode | null): number {
+ getHeight(beginRoot?: N | null): number {
beginRoot = beginRoot ?? this.root;
if (!beginRoot) return -1;
if (this._loopType === LoopType.recursive) {
- const _getMaxHeight = (cur: BinaryTreeNode | null | undefined): number => {
+ const _getMaxHeight = (cur: N | null | undefined): number => {
if (!cur) return -1;
const leftHeight = _getMaxHeight(cur.left);
const rightHeight = _getMaxHeight(cur.right);
@@ -520,9 +522,9 @@ export class BinaryTree implements IBinaryTree {
return _getMaxHeight(beginRoot);
} else {
- const stack: BinaryTreeNode[] = [];
- let node: BinaryTreeNode | null | undefined = beginRoot, last: BinaryTreeNode | null = null;
- const depths: Map, number> = new Map();
+ const stack: N[] = [];
+ let node: N | null | undefined = beginRoot, last: N | null = null;
+ const depths: Map = new Map();
while (stack.length > 0 || node) {
if (node) {
@@ -550,17 +552,17 @@ export class BinaryTree implements IBinaryTree {
/**
* The `getMinHeight` function calculates the minimum height of a binary tree using either a recursive or iterative
* approach.
- * @param {BinaryTreeNode | null} [beginRoot] - The `beginRoot` parameter is an optional parameter of type
- * `BinaryTreeNode | null`. It represents the starting node from which to calculate the minimum height of the binary
+ * @param {N | null} [beginRoot] - The `beginRoot` parameter is an optional parameter of type
+ * `N | null`. It represents the starting node from which to calculate the minimum height of the binary
* tree. If no value is provided for `beginRoot`, the function will use the root node of the binary tree.
* @returns The function `getMinHeight` returns the minimum height of the binary tree.
*/
- getMinHeight(beginRoot?: BinaryTreeNode | null): number {
+ getMinHeight(beginRoot?: N | null): number {
beginRoot = beginRoot || this.root;
if (!beginRoot) return -1;
if (this._loopType === LoopType.recursive) {
- const _getMinHeight = (cur: BinaryTreeNode | null | undefined): number => {
+ const _getMinHeight = (cur: N | null | undefined): number => {
if (!cur) return 0;
if (!cur.left && !cur.right) return 0;
const leftMinHeight = _getMinHeight(cur.left);
@@ -570,9 +572,9 @@ export class BinaryTree implements IBinaryTree {
return _getMinHeight(beginRoot);
} else {
- const stack: BinaryTreeNode[] = [];
- let node: BinaryTreeNode | null | undefined = beginRoot, last: BinaryTreeNode | null = null;
- const depths: Map, number> = new Map();
+ const stack: N[] = [];
+ let node: N | null | undefined = beginRoot, last: N | null = null;
+ const depths: Map = new Map();
while (stack.length > 0 || node) {
if (node) {
@@ -599,34 +601,34 @@ export class BinaryTree implements IBinaryTree {
/**
* The function checks if a binary tree is balanced by comparing the minimum height and the maximum height of the tree.
- * @param {BinaryTreeNode | null} [beginRoot] - The `beginRoot` parameter is the root node of a binary tree. It is
- * of type `BinaryTreeNode | null`, which means it can either be a `BinaryTreeNode` object or `null`.
+ * @param {N | null} [beginRoot] - The `beginRoot` parameter is the root node of a binary tree. It is
+ * of type `N | null`, which means it can either be a `BinaryTreeNode` object or `null`.
* @returns The method is returning a boolean value.
*/
- isBalanced(beginRoot?: BinaryTreeNode | null): boolean {
+ isBalanced(beginRoot?: N | null): boolean {
return (this.getMinHeight(beginRoot) + 1 >= this.getHeight(beginRoot));
}
/**
* The function `getNodes` returns an array of binary tree nodes that match a given property value, with options for
* searching recursively or iteratively.
- * @param {BinaryTreeNodeId | T} nodeProperty - The `nodeProperty` parameter can be either a `BinaryTreeNodeId` or a
- * generic type `T`. It represents the property of the binary tree node that you want to search for.
+ * @param {BinaryTreeNodeId | N} nodeProperty - The `nodeProperty` parameter can be either a `BinaryTreeNodeId` or a
+ * generic type `N`. It represents the property of the binary tree node that you want to search for.
* @param {BinaryTreeNodePropertyName} [propertyName] - The `propertyName` parameter is an optional parameter that
* specifies the property name to use when searching for nodes. If not provided, it defaults to 'id'.
* @param {boolean} [onlyOne] - The `onlyOne` parameter is an optional boolean parameter that determines whether to
* return only one node that matches the `nodeProperty` or `propertyName` criteria. If `onlyOne` is set to `true`, the
* function will stop traversing the tree and return the first matching node. If `
- * @returns The function `getNodes` returns an array of `BinaryTreeNode | null | undefined` objects.
+ * @returns The function `getNodes` returns an array of `N | null | undefined` objects.
*/
- getNodes(nodeProperty: BinaryTreeNodeId | T, propertyName ?: BinaryTreeNodePropertyName, onlyOne ?: boolean) {
+ getNodes(nodeProperty: BinaryTreeNodeId | N, propertyName ?: BinaryTreeNodePropertyName, onlyOne ?: boolean) {
if (!this.root) return [] as null[];
propertyName = propertyName ?? 'id';
- const result: (BinaryTreeNode | null | undefined)[] = [];
+ const result: (N | null | undefined)[] = [];
if (this._loopType === LoopType.recursive) {
- const _traverse = (cur: BinaryTreeNode) => {
+ const _traverse = (cur: N) => {
if (this._pushByPropertyNameStopOrNot(cur, result, nodeProperty, propertyName, onlyOne)) return;
if (!cur.left && !cur.right) return;
cur.left && _traverse(cur.left);
@@ -635,7 +637,7 @@ export class BinaryTree implements IBinaryTree {
_traverse(this.root);
} else {
- const queue: BinaryTreeNode[] = [this.root];
+ const queue: N[] = [this.root];
while (queue.length > 0) {
const cur = queue.shift();
if (cur) {
@@ -652,26 +654,26 @@ export class BinaryTree implements IBinaryTree {
/**
* The function checks if a binary tree node has a specific property or if any node in the tree has a specific
* property.
- * @param {BinaryTreeNodeId | T} nodeProperty - The `nodeProperty` parameter can be either a `BinaryTreeNodeId` or a
- * generic type `T`. It represents the property of a binary tree node that you want to check.
+ * @param {BinaryTreeNodeId | N} nodeProperty - The `nodeProperty` parameter can be either a `BinaryTreeNodeId` or a
+ * generic type `N`. It represents the property of a binary tree node that you want to check.
* @param {BinaryTreeNodePropertyName} [propertyName] - The `propertyName` parameter is an optional parameter that
* specifies the name of the property to check for in the nodes.
* @returns a boolean value.
*/
- has(nodeProperty: BinaryTreeNodeId | T, propertyName ?: BinaryTreeNodePropertyName): boolean {
+ has(nodeProperty: BinaryTreeNodeId | N, propertyName ?: BinaryTreeNodePropertyName): boolean {
return this.getNodes(nodeProperty, propertyName).length > 0;
}
/**
* The function returns the first binary tree node that matches the given property name and value, or null if no match
* is found.
- * @param {BinaryTreeNodeId | T} nodeProperty - The `nodeProperty` parameter can be either a `BinaryTreeNodeId` or a
- * generic type `T`. It represents the property of the binary tree node that you want to search for.
+ * @param {BinaryTreeNodeId | N} nodeProperty - The `nodeProperty` parameter can be either a `BinaryTreeNodeId` or a
+ * generic type `N`. It represents the property of the binary tree node that you want to search for.
* @param {BinaryTreeNodePropertyName} [propertyName] - The `propertyName` parameter is an optional parameter that
* specifies the property of the binary tree node to search for. If not provided, it defaults to `'id'`.
* @returns a BinaryTreeNode object or null.
*/
- get(nodeProperty: BinaryTreeNodeId | T, propertyName ?: BinaryTreeNodePropertyName): BinaryTreeNode | null {
+ get(nodeProperty: BinaryTreeNodeId | N, propertyName ?: BinaryTreeNodePropertyName): N | null {
propertyName = propertyName ?? 'id';
return this.getNodes(nodeProperty, propertyName, true)[0] ?? null;
}
@@ -680,11 +682,11 @@ export class BinaryTree implements IBinaryTree {
* The function getPathToRoot returns an array of BinaryTreeNode objects representing the path from a given node to the
* root of a binary tree.
* @param node - The `node` parameter is a BinaryTreeNode object.
- * @returns The function `getPathToRoot` returns an array of `BinaryTreeNode` objects, representing the path from
+ * @returns The function `getPathToRoot` returns an array of `N` objects, representing the path from
* the given `node` to the root of the binary tree.
*/
- getPathToRoot(node: BinaryTreeNode): BinaryTreeNode[] {
- const result: BinaryTreeNode[] = [];
+ getPathToRoot(node: N): N[] {
+ const result: N[] = [];
while (node.parent) {
result.unshift(node);
node = node.parent;
@@ -693,25 +695,25 @@ export class BinaryTree implements IBinaryTree {
return result;
}
- getLeftMost(): BinaryTreeNode | null;
+ getLeftMost(): N | null;
- getLeftMost(node: BinaryTreeNode): BinaryTreeNode;
+ getLeftMost(node: N): N;
/**
* The `getLeftMost` function returns the leftmost node in a binary tree, either recursively or iteratively using tail
* recursion optimization.
- * @param {BinaryTreeNode | null} [node] - The `node` parameter is an optional parameter of type `BinaryTreeNode
+ * @param {N | null} [node] - The `node` parameter is an optional parameter of type `N
* | null`. It represents the starting node from which to find the leftmost node in a binary tree. If no node is
* provided, the function will use the root node of the binary tree.
* @returns The `getLeftMost` function returns the leftmost node in a binary tree.
*/
- getLeftMost(node?: BinaryTreeNode | null): BinaryTreeNode | null {
+ getLeftMost(node?: N | null): N | null {
node = node ?? this.root;
if (!node) return node;
if (this._loopType === LoopType.recursive) {
- const _traverse = (cur: BinaryTreeNode): BinaryTreeNode => {
+ const _traverse = (cur: N): N => {
if (!cur.left) return cur;
return _traverse(cur.left);
}
@@ -719,7 +721,7 @@ export class BinaryTree implements IBinaryTree {
return _traverse(node);
} else {
// Indirect implementation of iteration using tail recursion optimization
- const _traverse = trampoline((cur: BinaryTreeNode) => {
+ const _traverse = trampoline((cur: N) => {
if (!cur.left) return cur;
return _traverse.cont(cur.left);
});
@@ -728,24 +730,24 @@ export class BinaryTree implements IBinaryTree {
}
}
- getRightMost(): BinaryTreeNode | null;
+ getRightMost(): N | null;
- getRightMost(node: BinaryTreeNode): BinaryTreeNode;
+ getRightMost(node: N): N;
/**
* The `getRightMost` function returns the rightmost node in a binary tree, either recursively or iteratively using
* tail recursion optimization.
- * @param {BinaryTreeNode | null} [node] - The `node` parameter is an optional parameter of type `BinaryTreeNode
+ * @param {N | null} [node] - The `node` parameter is an optional parameter of type `N
* | null`. It represents the starting node from which to find the rightmost node in a binary tree. If no node is
* provided, the function will use the root node of the binary tree.
* @returns The `getRightMost` function returns the rightmost node in a binary tree.
*/
- getRightMost(node?: BinaryTreeNode | null): BinaryTreeNode | null {
+ getRightMost(node?: N | null): N | null {
node = node ?? this.root;
if (!node) return node;
if (this._loopType === LoopType.recursive) {
- const _traverse = (cur: BinaryTreeNode): BinaryTreeNode => {
+ const _traverse = (cur: N): N => {
if (!cur.right) return cur;
return _traverse(cur.right);
}
@@ -753,7 +755,7 @@ export class BinaryTree implements IBinaryTree {
return _traverse(node);
} else {
// Indirect implementation of iteration using tail recursion optimization
- const _traverse = trampoline((cur: BinaryTreeNode) => {
+ const _traverse = trampoline((cur: N) => {
if (!cur.right) return cur;
return _traverse.cont(cur.right);
});
@@ -764,18 +766,18 @@ export class BinaryTree implements IBinaryTree {
/**
* The `isBST` function checks if a binary tree is a binary search tree.
- * @param {BinaryTreeNode | null} [node] - The `node` parameter is an optional parameter of type `BinaryTreeNode
+ * @param {N | null} [node] - The `node` parameter is an optional parameter of type `N
* | null`. It represents the root node of the binary search tree (BST) that we want to check for validity. If no node
* is provided, the function will default to using the root node of the BST instance that
* @returns The `isBST` function returns a boolean value. It returns `true` if the binary tree is a valid binary search
* tree, and `false` otherwise.
*/
- isBST(node?: BinaryTreeNode | null): boolean {
+ isBST(node?: N | null): boolean {
node = node ?? this.root;
if (!node) return true;
if (this._loopType === LoopType.recursive) {
- const dfs = (cur: BinaryTreeNode | null | undefined, min: BinaryTreeNodeId, max: BinaryTreeNodeId): boolean => {
+ const dfs = (cur: N | null | undefined, min: BinaryTreeNodeId, max: BinaryTreeNodeId): boolean => {
if (!cur) return true;
if (cur.id <= min || cur.id >= max) return false;
return dfs(cur.left, min, cur.id) && dfs(cur.right, cur.id, max);
@@ -784,7 +786,7 @@ export class BinaryTree implements IBinaryTree {
return dfs(node, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);
} else {
const stack = [];
- let prev = Number.MIN_SAFE_INTEGER, curr: BinaryTreeNode | null | undefined = node;
+ let prev = Number.MIN_SAFE_INTEGER, curr: N | null | undefined = node;
while (curr || stack.length > 0) {
while (curr) {
stack.push(curr);
@@ -802,17 +804,17 @@ export class BinaryTree implements IBinaryTree {
/**
* The function calculates the size and count of a subtree in a binary tree using either recursive or iterative
* traversal.
- * @param {BinaryTreeNode | null | undefined} subTreeRoot - The `subTreeRoot` parameter is the root node of a binary
+ * @param {N | null | undefined} subTreeRoot - The `subTreeRoot` parameter is the root node of a binary
* tree.
* @returns The function `getSubTreeSizeAndCount` returns an array `[number, number]`. The first element of the array
* represents the size of the subtree, and the second element represents the count of the nodes in the subtree.
*/
- getSubTreeSizeAndCount(subTreeRoot: BinaryTreeNode | null | undefined) {
+ getSubTreeSizeAndCount(subTreeRoot: N | null | undefined) {
const res: [number, number] = [0, 0];
if (!subTreeRoot) return res;
if (this._loopType === LoopType.recursive) {
- const _traverse = (cur: BinaryTreeNode) => {
+ const _traverse = (cur: N) => {
res[0]++;
res[1] += cur.count;
cur.left && _traverse(cur.left);
@@ -822,7 +824,7 @@ export class BinaryTree implements IBinaryTree {
_traverse(subTreeRoot);
return res;
} else {
- const stack: BinaryTreeNode[] = [subTreeRoot];
+ const stack: N[] = [subTreeRoot];
while (stack.length > 0) {
const cur = stack.pop()!;
@@ -848,13 +850,13 @@ export class BinaryTree implements IBinaryTree {
* provided, it defaults to `'val'`.
* @returns a number, which is the sum of the values of the nodes in the subtree rooted at `subTreeRoot`.
*/
- subTreeSum(subTreeRoot: BinaryTreeNode, propertyName ?: BinaryTreeNodePropertyName): number {
+ subTreeSum(subTreeRoot: N, propertyName ?: BinaryTreeNodePropertyName): number {
propertyName = propertyName ?? 'val';
if (!subTreeRoot) return 0;
let sum = 0;
- const _sumByProperty = (cur: BinaryTreeNode) => {
+ const _sumByProperty = (cur: N) => {
let needSum: number;
switch (propertyName) {
case 'id':
@@ -874,7 +876,7 @@ export class BinaryTree implements IBinaryTree {
}
if (this._loopType === LoopType.recursive) {
- const _traverse = (cur: BinaryTreeNode): void => {
+ const _traverse = (cur: N): void => {
sum += _sumByProperty(cur);
cur.left && _traverse(cur.left);
cur.right && _traverse(cur.right);
@@ -882,7 +884,7 @@ export class BinaryTree implements IBinaryTree {
_traverse(subTreeRoot);
} else {
- const stack: BinaryTreeNode[] = [subTreeRoot];
+ const stack: N[] = [subTreeRoot];
while (stack.length > 0) {
const cur = stack.pop()!;
@@ -904,11 +906,11 @@ export class BinaryTree implements IBinaryTree {
* specifies the property of the `BinaryTreeNode` that should be modified. It defaults to `'id'` if not provided.
* @returns a boolean value, which is `true`.
*/
- subTreeAdd(subTreeRoot: BinaryTreeNode, delta: number, propertyName ?: BinaryTreeNodePropertyName): boolean {
+ subTreeAdd(subTreeRoot: N, delta: number, propertyName ?: BinaryTreeNodePropertyName): boolean {
propertyName = propertyName ?? 'id';
if (!subTreeRoot) return false;
- const _addByProperty = (cur: BinaryTreeNode) => {
+ const _addByProperty = (cur: N) => {
switch (propertyName) {
case 'id':
cur.id += delta;
@@ -924,7 +926,7 @@ export class BinaryTree implements IBinaryTree {
}
if (this._loopType === LoopType.recursive) {
- const _traverse = (cur: BinaryTreeNode) => {
+ const _traverse = (cur: N) => {
_addByProperty(cur);
cur.left && _traverse(cur.left);
cur.right && _traverse(cur.right);
@@ -932,7 +934,7 @@ export class BinaryTree implements IBinaryTree {
_traverse(subTreeRoot);
} else {
- const stack: BinaryTreeNode[] = [subTreeRoot];
+ const stack: N[] = [subTreeRoot];
while (stack.length > 0) {
const cur = stack.pop()!;
@@ -949,9 +951,9 @@ export class BinaryTree