diff --git a/CHANGELOG.md b/CHANGELOG.md
index b112baf..2ece9ac 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,7 +8,7 @@ All notable changes to this project will be documented in this file.
- [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
- [`auto-changelog`](https://github.com/CookPete/auto-changelog)
-## [v1.42.2](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming)
+## [v1.42.3](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming)
### Changes
diff --git a/README.md b/README.md
index 853d220..7a24af6 100644
--- a/README.md
+++ b/README.md
@@ -636,40 +636,40 @@ optimal approach to data structure design.
[//]: # (Start of Replace Section)
avl-tree
-
test name | time taken (ms) | executions per sec | sample deviation |
---|
10,000 add randomly | 31.93 | 31.32 | 2.30e-4 |
10,000 add & delete randomly | 69.12 | 14.47 | 0.00 |
10,000 addMany | 41.14 | 24.31 | 1.60e-4 |
10,000 get | 28.68 | 34.86 | 7.65e-4 |
+
test name | time taken (ms) | executions per sec | sample deviation |
---|
10,000 add randomly | 30.33 | 32.97 | 3.56e-4 |
10,000 add & delete randomly | 66.10 | 15.13 | 0.00 |
10,000 addMany | 39.44 | 25.35 | 3.62e-4 |
10,000 get | 27.06 | 36.96 | 2.52e-4 |
binary-tree
-
test name | time taken (ms) | executions per sec | sample deviation |
---|
1,000 add randomly | 13.12 | 76.21 | 3.40e-4 |
1,000 add & delete randomly | 16.33 | 61.22 | 4.17e-4 |
1,000 addMany | 10.96 | 91.22 | 3.99e-4 |
1,000 get | 18.65 | 53.63 | 4.20e-4 |
1,000 dfs | 71.82 | 13.92 | 0.00 |
1,000 bfs | 58.95 | 16.96 | 0.00 |
1,000 morris | 37.46 | 26.70 | 4.60e-4 |
+
test name | time taken (ms) | executions per sec | sample deviation |
---|
1,000 add randomly | 12.90 | 77.52 | 1.09e-4 |
1,000 add & delete randomly | 16.13 | 61.99 | 1.61e-4 |
1,000 addMany | 10.74 | 93.09 | 1.00e-4 |
1,000 get | 18.09 | 55.28 | 1.90e-4 |
1,000 dfs | 71.12 | 14.06 | 7.83e-4 |
1,000 bfs | 57.24 | 17.47 | 4.17e-4 |
1,000 morris | 37.29 | 26.81 | 3.77e-4 |
bst
-
test name | time taken (ms) | executions per sec | sample deviation |
---|
10,000 add randomly | 32.98 | 30.32 | 0.00 |
10,000 add & delete randomly | 74.47 | 13.43 | 0.00 |
10,000 addMany | 29.93 | 33.41 | 6.02e-4 |
10,000 get | 29.92 | 33.42 | 8.61e-4 |
+
test name | time taken (ms) | executions per sec | sample deviation |
---|
10,000 add randomly | 31.58 | 31.67 | 0.00 |
10,000 add & delete randomly | 71.09 | 14.07 | 8.99e-4 |
10,000 addMany | 29.68 | 33.69 | 0.00 |
10,000 get | 28.55 | 35.03 | 0.00 |
rb-tree
-
test name | time taken (ms) | executions per sec | sample deviation |
---|
100,000 add randomly | 80.49 | 12.42 | 0.01 |
100,000 add & 1000 delete randomly | 89.97 | 11.11 | 0.01 |
100,000 getNode | 68.63 | 14.57 | 0.01 |
+
test name | time taken (ms) | executions per sec | sample deviation |
---|
100,000 add randomly | 84.64 | 11.82 | 0.01 |
100,000 add & 1000 delete randomly | 81.32 | 12.30 | 0.01 |
100,000 getNode | 61.18 | 16.35 | 0.00 |
directed-graph
-
test name | time taken (ms) | executions per sec | sample deviation |
---|
1,000 addVertex | 0.10 | 9878.72 | 1.87e-6 |
1,000 addEdge | 6.34 | 157.78 | 2.53e-4 |
1,000 getVertex | 0.05 | 2.12e+4 | 1.05e-6 |
1,000 getEdge | 23.08 | 43.33 | 0.00 |
tarjan | 217.75 | 4.59 | 0.01 |
tarjan all | 219.23 | 4.56 | 0.01 |
topologicalSort | 175.73 | 5.69 | 0.02 |
+
test name | time taken (ms) | executions per sec | sample deviation |
---|
1,000 addVertex | 0.10 | 9637.47 | 3.79e-6 |
1,000 addEdge | 6.09 | 164.18 | 1.31e-4 |
1,000 getVertex | 0.05 | 2.14e+4 | 1.35e-6 |
1,000 getEdge | 23.91 | 41.82 | 0.01 |
tarjan | 218.65 | 4.57 | 0.01 |
tarjan all | 221.67 | 4.51 | 0.00 |
topologicalSort | 184.34 | 5.42 | 0.02 |
heap
-
test name | time taken (ms) | executions per sec | sample deviation |
---|
10,000 add & pop | 4.64 | 215.44 | 6.89e-5 |
10,000 fib add & pop | 357.37 | 2.80 | 0.01 |
+
test name | time taken (ms) | executions per sec | sample deviation |
---|
10,000 add & pop | 4.63 | 215.77 | 4.49e-5 |
10,000 fib add & pop | 355.19 | 2.82 | 0.00 |
doubly-linked-list
-
test name | time taken (ms) | executions per sec | sample deviation |
---|
1,000,000 unshift | 239.34 | 4.18 | 0.04 |
1,000,000 unshift & shift | 168.74 | 5.93 | 0.04 |
1,000,000 insertBefore | 324.74 | 3.08 | 0.06 |
+
test name | time taken (ms) | executions per sec | sample deviation |
---|
1,000,000 unshift | 213.53 | 4.68 | 0.02 |
1,000,000 unshift & shift | 162.97 | 6.14 | 0.02 |
1,000,000 insertBefore | 335.19 | 2.98 | 0.09 |
singly-linked-list
-
test name | time taken (ms) | executions per sec | sample deviation |
---|
10,000 push & pop | 213.86 | 4.68 | 0.01 |
10,000 insertBefore | 254.02 | 3.94 | 0.02 |
+
test name | time taken (ms) | executions per sec | sample deviation |
---|
10,000 push & pop | 231.35 | 4.32 | 0.02 |
10,000 insertBefore | 251.49 | 3.98 | 0.01 |
max-priority-queue
-
test name | time taken (ms) | executions per sec | sample deviation |
---|
10,000 refill & poll | 11.39 | 87.76 | 2.14e-4 |
+
test name | time taken (ms) | executions per sec | sample deviation |
---|
10,000 refill & poll | 11.48 | 87.14 | 1.91e-4 |
deque
-
test name | time taken (ms) | executions per sec | sample deviation |
---|
1,000,000 push | 233.91 | 4.28 | 0.05 |
1,000,000 shift | 25.61 | 39.05 | 0.00 |
+
test name | time taken (ms) | executions per sec | sample deviation |
---|
1,000,000 push | 215.14 | 4.65 | 0.05 |
1,000,000 shift | 25.15 | 39.76 | 0.00 |
queue
-
test name | time taken (ms) | executions per sec | sample deviation |
---|
1,000,000 push | 43.88 | 22.79 | 0.01 |
1,000,000 push & shift | 81.71 | 12.24 | 0.00 |
+
test name | time taken (ms) | executions per sec | sample deviation |
---|
1,000,000 push | 44.15 | 22.65 | 0.01 |
1,000,000 push & shift | 80.87 | 12.37 | 0.00 |
trie
-
test name | time taken (ms) | executions per sec | sample deviation |
---|
100,000 push | 59.93 | 16.69 | 0.01 |
100,000 getWords | 93.10 | 10.74 | 0.01 |
+
test name | time taken (ms) | executions per sec | sample deviation |
---|
100,000 push | 61.38 | 16.29 | 0.01 |
100,000 getWords | 104.27 | 9.59 | 0.02 |
[//]: # (End of Replace Section)
\ No newline at end of file
diff --git a/package.json b/package.json
index e13c156..f3b8678 100644
--- a/package.json
+++ b/package.json
@@ -41,7 +41,7 @@
"copy:to-subs": "sh scripts/copy_to_all_subs.sh",
"publish:subs": "npm run copy:to-subs && sh scripts/publish_all_subs.sh",
"publish:docs": "sh scripts/publish_docs.sh",
- "publish:all": "npm run ci && npm run benchmark && npm publish && npm run publish:docs && npm run publish:subs"
+ "publish:all": "npm run ci && npm publish && npm run publish:docs && npm run publish:subs"
},
"repository": {
"type": "git",
diff --git a/src/data-structures/binary-tree/avl-tree.ts b/src/data-structures/binary-tree/avl-tree.ts
index 47d99fd..8e72d8a 100644
--- a/src/data-structures/binary-tree/avl-tree.ts
+++ b/src/data-structures/binary-tree/avl-tree.ts
@@ -49,13 +49,14 @@ export class AVLTree = AVLTreeNode = AVLTreeNode = AVLTreeNode = BinaryTreeNode
}
}
- protected _root: N | null = null;
+ protected _root: N | null | undefined = undefined;
/**
* Get the root node of the binary tree.
*/
- get root(): N | null {
+ get root(): N | null | undefined {
return this._root;
}
@@ -155,7 +155,7 @@ export class BinaryTree = BinaryTreeNode
* Clear the binary tree, removing all nodes.
*/
clear() {
- this._setRoot(null);
+ this._setRoot(undefined);
this._size = 0;
}
@@ -173,7 +173,7 @@ export class BinaryTree = BinaryTreeNode
* @param {V} value - The value for the new node (optional).
* @returns {N | null | undefined} - The inserted node, or null if nothing was inserted, or undefined if the operation failed.
*/
- add(keyOrNode: BTNKey | N | null, value?: V): N | null | undefined {
+ add(keyOrNode: BTNKey | N | null | undefined, value?: V): N | null | undefined {
const _bfs = (root: N, newNode: N | null): N | undefined | null => {
const queue = new Queue([root]);
while (queue.size > 0) {
@@ -236,7 +236,7 @@ export class BinaryTree = BinaryTreeNode
* the value of the nodes will be `undefined`.
* @returns The function `addMany` returns an array of `N`, `null`, or `undefined` values.
*/
- addMany(keysOrNodes: (BTNKey | null)[] | (N | null)[], values?: V[]): (N | null | undefined)[] {
+ addMany(keysOrNodes: (BTNKey | null | undefined)[] | (N | null | undefined)[], values?: V[]): (N | null | undefined)[] {
// TODO not sure addMany not be run multi times
return keysOrNodes.map((keyOrNode, i) => {
if (keyOrNode instanceof BinaryTreeNode) {
@@ -261,14 +261,14 @@ export class BinaryTree = BinaryTreeNode
* array. Each value in the `data` array will be assigned to the
* @returns The method is returning a boolean value.
*/
- refill(keysOrNodes: (BTNKey | null)[] | (N | null)[], data?: Array): boolean {
+ refill(keysOrNodes: (BTNKey | null | undefined)[] | (N | null | undefined)[], data?: Array): boolean {
this.clear();
return keysOrNodes.length === this.addMany(keysOrNodes, data).length;
}
delete>(identifier: BTNKey, callback?: C): BinaryTreeDeletedResult[];
- delete>(identifier: N | null, callback?: C): BinaryTreeDeletedResult[];
+ delete>(identifier: N | null | undefined, callback?: C): BinaryTreeDeletedResult[];
delete>(identifier: ReturnType, callback: C): BinaryTreeDeletedResult[];
@@ -287,7 +287,7 @@ export class BinaryTree = BinaryTreeNode
* `this.defaultOneParamCallback`, which
*/
delete>(
- identifier: ReturnType | null,
+ identifier: ReturnType | null | undefined,
callback: C = this.defaultOneParamCallback as C
): BinaryTreeDeletedResult[] {
const bstDeletedResult: BinaryTreeDeletedResult[] = [];
@@ -297,8 +297,8 @@ export class BinaryTree = BinaryTreeNode
const curr = this.getNode(identifier, callback);
if (!curr) return bstDeletedResult;
- const parent: N | null = curr?.parent ? curr.parent : null;
- let needBalanced: N | null = null,
+ const parent: N | null | undefined = curr?.parent ? curr.parent : null;
+ let needBalanced: N | null | undefined = null,
orgCurrent = curr;
if (!curr.left) {
@@ -336,16 +336,16 @@ export class BinaryTree = BinaryTreeNode
/**
* The function `getDepth` calculates the depth of a given node in a binary tree relative to a
* specified root node.
- * @param {BTNKey | N | null} distNode - The `distNode` parameter represents the node
+ * @param {BTNKey | N | null | undefined} distNode - The `distNode` parameter represents the node
* whose depth we want to find in the binary tree. It can be either a node object (`N`), a key value
* of the node (`BTNKey`), or `null`.
- * @param {BTNKey | N | null} beginRoot - The `beginRoot` parameter represents the
+ * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
* starting node from which we want to calculate the depth. It can be either a node object or the key
* of a node in the binary tree. If no value is provided for `beginRoot`, it defaults to the root
* node of the binary tree.
* @returns the depth of the `distNode` relative to the `beginRoot`.
*/
- getDepth(distNode: BTNKey | N | null, beginRoot: BTNKey | N | null = this.root): number {
+ getDepth(distNode: BTNKey | N | null | undefined, beginRoot: BTNKey | N | null | undefined = this.root): number {
if (typeof distNode === 'number') distNode = this.getNode(distNode);
if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);
let depth = 0;
@@ -362,7 +362,7 @@ export class BinaryTree = BinaryTreeNode
/**
* The `getHeight` function calculates the maximum height of a binary tree using either recursive or
* iterative approach.
- * @param {BTNKey | N | null} beginRoot - The `beginRoot` parameter represents the
+ * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
* starting node from which the height of the binary tree is calculated. It can be either a node
* object (`N`), a key value of a node in the tree (`BTNKey`), or `null` if no starting
* node is specified. If `
@@ -371,7 +371,7 @@ export class BinaryTree = BinaryTreeNode
* possible values:
* @returns the height of the binary tree.
*/
- getHeight(beginRoot: BTNKey | N | null = this.root, iterationType = this.iterationType): number {
+ getHeight(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.iterationType): number {
if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);
if (!beginRoot) return -1;
@@ -413,14 +413,14 @@ export class BinaryTree = BinaryTreeNode
/**
* The `getMinHeight` function calculates the minimum height of a binary tree using either a
* recursive or iterative approach.
- * @param {N | null} beginRoot - The `beginRoot` parameter is the starting node from which we want to
+ * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node from which we want to
* calculate the minimum height of the tree. It is optional and defaults to the root of the tree if
* not provided.
* @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: N | null = this.root, iterationType = this.iterationType): number {
+ getMinHeight(beginRoot: N | null | undefined = this.root, iterationType = this.iterationType): number {
if (!beginRoot) return -1;
if (iterationType === IterationType.RECURSIVE) {
@@ -436,7 +436,7 @@ export class BinaryTree = BinaryTreeNode
} else {
const stack: N[] = [];
let node: N | null | undefined = beginRoot,
- last: N | null = null;
+ last: N | null | undefined = null;
const depths: Map = new Map();
while (stack.length > 0 || node) {
@@ -465,11 +465,11 @@ export class BinaryTree = BinaryTreeNode
/**
* The function checks if a binary tree is perfectly balanced by comparing the minimum height and the
* height of the tree.
- * @param {N | null} beginRoot - The parameter `beginRoot` is of type `N | null`, which means it can
+ * @param {N | null | undefined} beginRoot - The parameter `beginRoot` is of type `N | null | undefined`, which means it can
* either be of type `N` (representing a node in a tree) or `null` (representing an empty tree).
* @returns The method is returning a boolean value.
*/
- isPerfectlyBalanced(beginRoot: N | null = this.root): boolean {
+ isPerfectlyBalanced(beginRoot: N | null | undefined = this.root): boolean {
return this.getMinHeight(beginRoot) + 1 >= this.getHeight(beginRoot);
}
@@ -477,15 +477,15 @@ export class BinaryTree = BinaryTreeNode
identifier: BTNKey,
callback?: C,
onlyOne?: boolean,
- beginRoot?: N | null,
+ beginRoot?: N | null | undefined,
iterationType?: IterationType
): N[];
getNodes>(
- identifier: N | null,
+ identifier: N | null | undefined,
callback?: C,
onlyOne?: boolean,
- beginRoot?: N | null,
+ beginRoot?: N | null | undefined,
iterationType?: IterationType
): N[];
@@ -493,7 +493,7 @@ export class BinaryTree = BinaryTreeNode
identifier: ReturnType,
callback: C,
onlyOne?: boolean,
- beginRoot?: N | null,
+ beginRoot?: N | null | undefined,
iterationType?: IterationType
): N[];
@@ -511,7 +511,7 @@ export class BinaryTree = BinaryTreeNode
* first node that matches the identifier. If set to true, the function will return an array with
* only one element (or an empty array if no matching node is found). If set to false (default), the
* function will continue searching for all
- * @param {N | null} beginRoot - The `beginRoot` parameter is the starting node from which the
+ * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node from which the
* traversal of the binary tree will begin. It is optional and defaults to the root of the binary
* tree.
* @param iterationType - The `iterationType` parameter determines the type of iteration used to
@@ -519,10 +519,10 @@ export class BinaryTree = BinaryTreeNode
* @returns The function `getNodes` returns an array of nodes (`N[]`).
*/
getNodes>(
- identifier: ReturnType | null,
+ identifier: ReturnType | null | undefined,
callback: C = this.defaultOneParamCallback as C,
onlyOne = false,
- beginRoot: N | null = this.root,
+ beginRoot: N | null | undefined = this.root,
iterationType = this.iterationType
): N[] {
if (!beginRoot) return [];
@@ -562,21 +562,21 @@ export class BinaryTree = BinaryTreeNode
has>(
identifier: BTNKey,
callback?: C,
- beginRoot?: N | null,
+ beginRoot?: N | null | undefined,
iterationType?: IterationType
): boolean;
has>(
- identifier: N | null,
+ identifier: N | null | undefined,
callback?: C,
- beginRoot?: N | null,
+ beginRoot?: N | null | undefined,
iterationType?: IterationType
): boolean;
has>(
- identifier: ReturnType | null,
+ identifier: ReturnType | null | undefined,
callback: C,
- beginRoot?: N | null,
+ beginRoot?: N | null | undefined,
iterationType?: IterationType
): boolean;
@@ -598,7 +598,7 @@ export class BinaryTree = BinaryTreeNode
* @returns a boolean value.
*/
has>(
- identifier: ReturnType | null,
+ identifier: ReturnType | null | undefined,
callback: C = this.defaultOneParamCallback as C,
beginRoot = this.root,
iterationType = this.iterationType
@@ -611,23 +611,23 @@ export class BinaryTree = BinaryTreeNode
getNode>(
identifier: BTNKey,
callback?: C,
- beginRoot?: N | null,
+ beginRoot?: N | null | undefined,
iterationType?: IterationType
- ): N | null;
+ ): N | null | undefined;
getNode>(
- identifier: N | null,
+ identifier: N | null | undefined,
callback?: C,
- beginRoot?: N | null,
+ beginRoot?: N | null | undefined,
iterationType?: IterationType
- ): N | null;
+ ): N | null | undefined;
getNode>(
identifier: ReturnType,
callback: C,
- beginRoot?: N | null,
+ beginRoot?: N | null | undefined,
iterationType?: IterationType
- ): N | null;
+ ): N | null | undefined;
/**
* The function `get` returns the first node in a binary tree that matches the given property or key.
@@ -645,11 +645,11 @@ export class BinaryTree = BinaryTreeNode
* @returns either the found node (of type N) or null if no node is found.
*/
getNode>(
- identifier: ReturnType | null,
+ identifier: ReturnType | null | undefined,
callback: C = this.defaultOneParamCallback as C,
beginRoot = this.root,
iterationType = this.iterationType
- ): N | null {
+ ): N | null | undefined {
if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;
return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? null;
@@ -658,21 +658,21 @@ export class BinaryTree = BinaryTreeNode
get>(
identifier: BTNKey,
callback?: C,
- beginRoot?: N | null,
+ beginRoot?: N | null | undefined,
iterationType?: IterationType
): V | undefined;
get>(
- identifier: N | null,
+ identifier: N | null | undefined,
callback?: C,
- beginRoot?: N | null,
+ beginRoot?: N | null | undefined,
iterationType?: IterationType
): V | undefined;
get>(
identifier: ReturnType,
callback: C,
- beginRoot?: N | null,
+ beginRoot?: N | null | undefined,
iterationType?: IterationType
): V | undefined;
@@ -692,7 +692,7 @@ export class BinaryTree = BinaryTreeNode
* @returns either the found value (of type V) or undefined if no node value is found.
*/
get>(
- identifier: ReturnType | null,
+ identifier: ReturnType | null | undefined,
callback: C = this.defaultOneParamCallback as C,
beginRoot = this.root,
iterationType = this.iterationType
@@ -728,7 +728,7 @@ export class BinaryTree = BinaryTreeNode
/**
* The function `getLeftMost` returns the leftmost node in a binary tree, either using recursive or
* iterative traversal.
- * @param {BTNKey | N | null} beginRoot - The `beginRoot` parameter is the starting point
+ * @param {BTNKey | 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 node object (`N`), a key value
* of a node (`BTNKey`), or `null` if the tree is empty.
* @param iterationType - The `iterationType` parameter is used to determine the type of iteration to
@@ -736,7 +736,7 @@ export class BinaryTree = BinaryTreeNode
* @returns The function `getLeftMost` returns the leftmost node (`N`) in a binary tree. If there is
* no leftmost node, it returns `null`.
*/
- getLeftMost(beginRoot: BTNKey | N | null = this.root, iterationType = this.iterationType): N | null {
+ getLeftMost(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.iterationType): N | null | undefined {
if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);
if (!beginRoot) return beginRoot;
@@ -762,15 +762,15 @@ export class BinaryTree = BinaryTreeNode
/**
* The function `getRightMost` returns the rightmost node in a binary tree, either recursively or
* iteratively.
- * @param {N | null} beginRoot - The `beginRoot` parameter is the starting node from which we want to
- * find the rightmost node. It is of type `N | null`, which means it can either be a node of type `N`
+ * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node from which we want to
+ * find the rightmost node. It is of type `N | null | undefined`, which means it can either be a node of type `N`
* or `null`. If it is `null`, it means there is no starting node
* @param iterationType - The `iterationType` parameter is used to determine the type of iteration to
* be performed when finding the rightmost node in a binary tree. It can have two possible values:
* @returns The function `getRightMost` returns the rightmost node (`N`) in a binary tree. If the
* `beginRoot` parameter is `null`, it returns `null`.
*/
- getRightMost(beginRoot: N | null = this.root, iterationType = this.iterationType): N | null {
+ getRightMost(beginRoot: N | null | undefined = this.root, iterationType = this.iterationType): N | null | undefined {
// TODO support get right most by passing key in
if (!beginRoot) return beginRoot;
@@ -801,7 +801,7 @@ export class BinaryTree = BinaryTreeNode
* possible values:
* @returns The function `isSubtreeBST` returns a boolean value.
*/
- isSubtreeBST(beginRoot: N | null, iterationType = this.iterationType): boolean {
+ isSubtreeBST(beginRoot: N | null | undefined, iterationType = this.iterationType): boolean {
// TODO there is a bug
if (!beginRoot) return true;
@@ -846,21 +846,21 @@ export class BinaryTree = BinaryTreeNode
subTreeTraverse>(
callback?: C,
- beginRoot?: BTNKey | N | null,
+ beginRoot?: BTNKey | N | null | undefined,
iterationType?: IterationType,
includeNull?: false
): ReturnType[];
subTreeTraverse>(
callback?: C,
- beginRoot?: BTNKey | N | null,
+ beginRoot?: BTNKey | N | null | undefined,
iterationType?: IterationType,
includeNull?: undefined
): ReturnType[];
- subTreeTraverse>(
+ subTreeTraverse>(
callback?: C,
- beginRoot?: BTNKey | N | null,
+ beginRoot?: BTNKey | N | null | undefined,
iterationType?: IterationType,
includeNull?: true
): ReturnType[];
@@ -872,7 +872,7 @@ export class BinaryTree = BinaryTreeNode
* subtree traversal. It takes a single argument, which is the current node being traversed, and
* returns a value. The return values from each callback invocation will be collected and returned as
* an array.
- * @param {BTNKey | N | null} beginRoot - The `beginRoot` parameter is the starting point
+ * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
* for traversing the subtree. It can be either a node object, a key value of a node, or `null` to
* start from the root of the tree.
* @param iterationType - The `iterationType` parameter determines the type of traversal to be
@@ -880,19 +880,19 @@ export class BinaryTree = BinaryTreeNode
* @param includeNull - The choice to output null values during binary tree traversal should be provided.
* @returns The function `subTreeTraverse` returns an array of `ReturnType>`.
*/
- subTreeTraverse>(
+ subTreeTraverse>(
callback: C = this.defaultOneParamCallback as C,
- beginRoot: BTNKey | N | null = this.root,
+ beginRoot: BTNKey | N | null | undefined = this.root,
iterationType = this.iterationType,
includeNull = false
): ReturnType[] {
if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);
- const ans: (ReturnType> | null)[] = [];
+ const ans: (ReturnType> | null | undefined)[] = [];
if (!beginRoot) return ans;
if (iterationType === IterationType.RECURSIVE) {
- const _traverse = (cur: N | null) => {
+ const _traverse = (cur: N | null | undefined) => {
if (cur !== undefined) {
ans.push(callback(cur));
if (includeNull) {
@@ -907,7 +907,7 @@ export class BinaryTree = BinaryTreeNode
_traverse(beginRoot);
} else {
- const stack: (N | null)[] = [beginRoot];
+ const stack: (N | null | undefined)[] = [beginRoot];
while (stack.length > 0) {
const cur = stack.pop();
@@ -929,7 +929,7 @@ export class BinaryTree = BinaryTreeNode
dfs>(
callback?: C,
pattern?: DFSOrderPattern,
- beginRoot?: N | null,
+ beginRoot?: N | null | undefined,
iterationType?: IterationType,
includeNull?: false
): ReturnType[];
@@ -937,15 +937,15 @@ export class BinaryTree = BinaryTreeNode
dfs>(
callback?: C,
pattern?: DFSOrderPattern,
- beginRoot?: N | null,
+ beginRoot?: N | null | undefined,
iterationType?: IterationType,
includeNull?: undefined
): ReturnType[];
- dfs>(
+ dfs>(
callback?: C,
pattern?: DFSOrderPattern,
- beginRoot?: N | null,
+ beginRoot?: N | null | undefined,
iterationType?: IterationType,
includeNull?: true
): ReturnType[];
@@ -958,7 +958,7 @@ export class BinaryTree = BinaryTreeNode
* is `this.defaultOneParamCallback`, which is a callback function defined elsewhere in the code.
* @param {DFSOrderPattern} [pattern=in] - The `pattern` parameter determines the order in which the
* nodes are visited during the depth-first search. There are three possible values for `pattern`:
- * @param {N | null} beginRoot - The `beginRoot` parameter is the starting node for the depth-first
+ * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node for the depth-first
* search. It determines where the search will begin in the tree or graph structure. If `beginRoot`
* is `null`, an empty array will be returned.
* @param {IterationType} iterationType - The `iterationType` parameter determines the type of
@@ -966,48 +966,48 @@ export class BinaryTree = BinaryTreeNode
* @param includeNull - The choice to output null values during binary tree traversal should be provided.
* @returns The function `dfs` returns an array of `ReturnType>` values.
*/
- dfs>(
+ dfs>(
callback: C = this.defaultOneParamCallback as C,
pattern: DFSOrderPattern = 'in',
- beginRoot: N | null = this.root,
+ beginRoot: N | null | undefined = this.root,
iterationType: IterationType = IterationType.ITERATIVE,
includeNull = false
): ReturnType[] {
if (!beginRoot) return [];
const ans: ReturnType[] = [];
if (iterationType === IterationType.RECURSIVE) {
- const _traverse = (node: N | null) => {
+ const _traverse = (node: N | null | undefined) => {
switch (pattern) {
case 'in':
if (includeNull) {
- if (node !== null && node.left !== undefined) _traverse(node.left);
+ if (node && node.left !== undefined) _traverse(node.left);
ans.push(callback(node));
- if (node !== null && node.right !== undefined) _traverse(node.right);
+ if (node && node.right !== undefined) _traverse(node.right);
} else {
- if (node !== null && node.left) _traverse(node.left);
+ if (node && node.left) _traverse(node.left);
ans.push(callback(node));
- if (node !== null && node.right) _traverse(node.right);
+ if (node && node.right) _traverse(node.right);
}
break;
case 'pre':
if (includeNull) {
ans.push(callback(node));
- if (node !== null && node.left !== undefined) _traverse(node.left);
- if (node !== null && node.right !== undefined) _traverse(node.right);
+ if (node && node.left !== undefined) _traverse(node.left);
+ if (node && node.right !== undefined) _traverse(node.right);
} else {
ans.push(callback(node));
- if (node !== null && node.left) _traverse(node.left);
- if (node !== null && node.right) _traverse(node.right);
+ if (node && node.left) _traverse(node.left);
+ if (node && node.right) _traverse(node.right);
}
break;
case 'post':
if (includeNull) {
- if (node !== null && node.left !== undefined) _traverse(node.left);
- if (node !== null && node.right !== undefined) _traverse(node.right);
+ if (node && node.left !== undefined) _traverse(node.left);
+ if (node && node.right !== undefined) _traverse(node.right);
ans.push(callback(node));
} else {
- if (node !== null && node.left) _traverse(node.left);
- if (node !== null && node.right) _traverse(node.right);
+ if (node && node.left) _traverse(node.left);
+ if (node && node.right) _traverse(node.right);
ans.push(callback(node));
}
@@ -1062,21 +1062,21 @@ export class BinaryTree = BinaryTreeNode
bfs>(
callback?: C,
- beginRoot?: N | null,
+ beginRoot?: N | null | undefined,
iterationType?: IterationType,
includeNull?: false
): ReturnType[];
bfs>(
callback?: C,
- beginRoot?: N | null,
+ beginRoot?: N | null | undefined,
iterationType?: IterationType,
includeNull?: undefined
): ReturnType[];
- bfs>(
+ bfs>(
callback?: C,
- beginRoot?: N | null,
+ beginRoot?: N | null | undefined,
iterationType?: IterationType,
includeNull?: true
): ReturnType[];
@@ -1087,7 +1087,7 @@ export class BinaryTree = BinaryTreeNode
* @param callback - The `callback` parameter is a function that will be called for each node in the
* breadth-first search. It takes a node of type `N` as its argument and returns a value of type
* `ReturnType>`. The default value for this parameter is `this.defaultOneParamCallback
- * @param {N | null} beginRoot - The `beginRoot` parameter is the starting node for the breadth-first
+ * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node for the breadth-first
* search. It determines from which node the search will begin. If `beginRoot` is `null`, the search
* will not be performed and an empty array will be returned.
* @param iterationType - The `iterationType` parameter determines the type of iteration to be used
@@ -1095,9 +1095,9 @@ export class BinaryTree = BinaryTreeNode
* @param includeNull - The choice to output null values during binary tree traversal should be provided.
* @returns The function `bfs` returns an array of `ReturnType>[]`.
*/
- bfs>(
+ bfs>(
callback: C = this.defaultOneParamCallback as C,
- beginRoot: N | null = this.root,
+ beginRoot: N | null | undefined = this.root,
iterationType = this.iterationType,
includeNull = false
): ReturnType[] {
@@ -1106,7 +1106,7 @@ export class BinaryTree = BinaryTreeNode
const ans: ReturnType>[] = [];
if (iterationType === IterationType.RECURSIVE) {
- const queue: Queue = new Queue([beginRoot]);
+ const queue: Queue = new Queue([beginRoot]);
const traverse = (level: number) => {
if (queue.size === 0) return;
@@ -1127,7 +1127,7 @@ export class BinaryTree = BinaryTreeNode
traverse(0);
} else {
- const queue = new Queue([beginRoot]);
+ const queue = new Queue([beginRoot]);
while (queue.size > 0) {
const levelSize = queue.size;
@@ -1150,21 +1150,21 @@ export class BinaryTree = BinaryTreeNode
listLevels>(
callback?: C,
- beginRoot?: N | null,
+ beginRoot?: N | null | undefined,
iterationType?: IterationType,
includeNull?: false
): ReturnType[][];
listLevels>(
callback?: C,
- beginRoot?: N | null,
+ beginRoot?: N | null | undefined,
iterationType?: IterationType,
includeNull?: undefined
): ReturnType[][];
- listLevels>(
+ listLevels>(
callback?: C,
- beginRoot?: N | null,
+ beginRoot?: N | null | undefined,
iterationType?: IterationType,
includeNull?: true
): ReturnType[][];
@@ -1175,7 +1175,7 @@ export class BinaryTree = BinaryTreeNode
* @param {C} callback - The `callback` parameter is a function that will be called on each node in
* the tree. It takes a node as input and returns a value. The return type of the callback function
* is determined by the generic type `C`.
- * @param {N | null} beginRoot - The `beginRoot` parameter represents the starting node of the binary tree
+ * @param {N | null | undefined} beginRoot - The `beginRoot` parameter represents the starting node of the binary tree
* traversal. It can be any node in the binary tree. If no node is provided, the traversal will start
* from the root node of the binary tree.
* @param iterationType - The `iterationType` parameter determines whether the tree traversal is done
@@ -1185,9 +1185,9 @@ export class BinaryTree = BinaryTreeNode
* level in a binary tree. Each inner array contains the return type of the provided callback
* function `C` applied to the nodes at that level.
*/
- listLevels>(
+ listLevels>(
callback: C = this.defaultOneParamCallback as C,
- beginRoot: N | null = this.root,
+ beginRoot: N | null | undefined = this.root,
iterationType = this.iterationType,
includeNull = false
): ReturnType[][] {
@@ -1195,7 +1195,7 @@ export class BinaryTree = BinaryTreeNode
const levelsNodes: ReturnType[][] = [];
if (iterationType === IterationType.RECURSIVE) {
- const _recursive = (node: N | null, level: number) => {
+ const _recursive = (node: N | null | undefined, level: number) => {
if (!levelsNodes[level]) levelsNodes[level] = [];
levelsNodes[level].push(callback(node));
if (includeNull) {
@@ -1209,7 +1209,7 @@ export class BinaryTree = BinaryTreeNode
_recursive(beginRoot, 0);
} else {
- const stack: [N | null, number][] = [[beginRoot, 0]];
+ const stack: [N | null | undefined, number][] = [[beginRoot, 0]];
while (stack.length > 0) {
const head = stack.pop()!;
@@ -1279,7 +1279,7 @@ export class BinaryTree = BinaryTreeNode
* @param {DFSOrderPattern} [pattern=in] - The `pattern` parameter in the `morris` function
* determines the order in which the nodes of a binary tree are traversed. It can have one of the
* following values:
- * @param {N | null} beginRoot - The `beginRoot` parameter is the starting node for the Morris
+ * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node for the Morris
* traversal. It specifies the root node of the tree from which the traversal should begin. If
* `beginRoot` is `null`, an empty array will be returned.
* @returns The `morris` function returns an array of `ReturnType>` values.
@@ -1287,7 +1287,7 @@ export class BinaryTree = BinaryTreeNode
morris>(
callback: C = this.defaultOneParamCallback as C,
pattern: DFSOrderPattern = 'in',
- beginRoot: N | null = this.root
+ beginRoot: N | null | undefined = this.root
): ReturnType[] {
if (beginRoot === null) return [];
const ans: ReturnType>[] = [];
@@ -1304,7 +1304,7 @@ export class BinaryTree = BinaryTreeNode
}
return pre;
};
- const _printEdge = (node: N | null) => {
+ const _printEdge = (node: N | null | undefined) => {
const tail: N | null | undefined = _reverseEdge(node);
let cur: N | null | undefined = tail;
while (cur) {
@@ -1438,7 +1438,7 @@ export class BinaryTree = BinaryTreeNode
/**
* The function `_addTo` adds a new node to a binary tree if there is an available position.
- * @param {N | null} newNode - The `newNode` parameter represents the node that you want to add to
+ * @param {N | null | undefined} newNode - The `newNode` parameter represents the node that you want to add to
* the binary tree. It can be either a node object or `null`.
* @param {N} parent - The `parent` parameter represents the parent node to which the new node will
* be added as a child.
@@ -1447,7 +1447,7 @@ export class BinaryTree = BinaryTreeNode
* the binary tree. If neither the left nor right child is available, the function returns undefined.
* If the parent node is null, the function also returns undefined.
*/
- protected _addTo(newNode: N | null, parent: N): N | null | undefined {
+ protected _addTo(newNode: N | null | undefined, parent: N): N | null | undefined {
if (parent) {
// When all leaf nodes are null, it will no longer be possible to add new entity nodes to this binary tree.
// In this scenario, null nodes serve as "sentinel nodes," "virtual nodes," or "placeholder nodes."
@@ -1474,10 +1474,10 @@ export class BinaryTree = BinaryTreeNode
/**
* The function sets the root property of an object to a given value, and if the value is not null,
* it also sets the parent property of the value to undefined.
- * @param {N | null} v - The parameter `v` is of type `N | null`, which means it can either be of
+ * @param {N | null | undefined} v - The parameter `v` is of type `N | null | undefined`, which means it can either be of
* type `N` or `null`.
*/
- protected _setRoot(v: N | null) {
+ protected _setRoot(v: N | null | undefined) {
if (v) {
v.parent = undefined;
}
diff --git a/src/data-structures/binary-tree/bst.ts b/src/data-structures/binary-tree/bst.ts
index 21fdc07..d626560 100644
--- a/src/data-structures/binary-tree/bst.ts
+++ b/src/data-structures/binary-tree/bst.ts
@@ -12,8 +12,53 @@ import {IBinaryTree} from '../../interfaces';
import {Queue} from '../queue';
export class BSTNode = BSTNodeNested> extends BinaryTreeNode {
+ override parent: N | undefined;
constructor(key: BTNKey, value?: V) {
super(key, value);
+ this.parent = undefined;
+ this._left = undefined;
+ this._right = undefined;
+ }
+
+ protected override _left: N | undefined;
+
+ /**
+ * Get the left child node.
+ */
+ override get left(): N | undefined {
+ return this._left;
+ }
+
+ /**
+ * Set the left child node.
+ * @param {N | undefined} v - The left child node.
+ */
+ override set left(v: N | undefined) {
+ if (v) {
+ v.parent = this as unknown as N;
+ }
+ this._left = v;
+ }
+
+
+ protected override _right: N | undefined;
+
+ /**
+ * Get the right child node.
+ */
+ override get right(): N | undefined {
+ return this._right;
+ }
+
+ /**
+ * Set the right child node.
+ * @param {N | undefined} v - The right child node.
+ */
+ override set right(v: N | undefined) {
+ if (v) {
+ v.parent = this as unknown as N;
+ }
+ this._right = v;
}
}
@@ -29,6 +74,7 @@ export class BST = BSTNode>
*/
constructor(options?: BSTOptions) {
super(options);
+ this._root = undefined;
if (options !== undefined) {
const {comparator} = options;
if (comparator !== undefined) {
@@ -36,6 +82,14 @@ export class BST = BSTNode>
}
}
}
+ protected override _root: N | undefined = undefined;
+
+ /**
+ * Get the root node of the binary tree.
+ */
+ override get root(): N | undefined {
+ return this._root;
+ }
/**
* The function creates a new binary search tree node with the given key and value.
@@ -52,33 +106,37 @@ export class BST = BSTNode>
/**
* The `add` function in a binary search tree class inserts a new node with a given key and value
* into the tree.
- * @param {BTNKey | N | null} keyOrNode - The `keyOrNode` parameter can be either a
- * `BTNKey` (which can be a number or a string), a `BSTNode` object, or `null`.
+ * @param {BTNKey | N | undefined} keyOrNode - The `keyOrNode` parameter can be either a
+ * `BTNKey` (which can be a number or a string), a `BSTNode` object, or `undefined`.
* @param [value] - The `value` parameter is the value to be assigned to the new node being added to the
* binary search tree.
* @returns the inserted node (N) if it was successfully added to the binary search tree. If the node
- * was not added or if the parameters were invalid, it returns null or undefined.
+ * was not added or if the parameters were invalid, it returns undefined or undefined.
*/
- override add(keyOrNode: BTNKey | N | null, value?: V): N | null | undefined {
+ override add(keyOrNode: BTNKey | N | null | undefined, value?: V): N | undefined {
+ if (keyOrNode === 8) {
+ debugger
+ }
+ if (keyOrNode === null) return undefined;
// TODO support node as a parameter
- let inserted: N | null = null;
- let newNode: N | null = null;
+ let inserted:N | undefined = undefined;
+ let newNode:N | undefined = undefined;
if (keyOrNode instanceof BSTNode) {
newNode = keyOrNode;
} else if (typeof keyOrNode === 'number') {
newNode = this.createNode(keyOrNode, value);
- } else if (keyOrNode === null) {
- newNode = null;
+ } else {
+ newNode = undefined;
}
- if (this.root === null) {
- this._setRoot(newNode);
+ if (this.root === undefined) {
+ this._root = newNode;
this._size = this.size + 1;
inserted = this.root;
} else {
let cur = this.root;
let traversing = true;
while (traversing) {
- if (cur !== null && newNode !== null) {
+ if (cur !== undefined && newNode !== undefined) {
if (this._compare(cur.key, newNode.key) === CP.eq) {
if (newNode) {
cur.value = newNode.value;
@@ -131,29 +189,29 @@ export class BST = BSTNode>
* @param {[BTNKey | N, V][]} keysOrNodes - The `arr` parameter in the `addMany` function
* represents an array of keys or nodes that need to be added to the binary search tree. It can be an
* array of `BTNKey` or `N` (which represents the node type in the binary search tree) or
- * `null
+ * `undefined
* @param {V[]} data - The values of tree nodes
* @param {boolean} isBalanceAdd - If true the nodes will be balance inserted in binary search method.
* @param iterationType - The `iterationType` parameter determines the type of iteration to be used.
* It can have two possible values:
- * @returns The `addMany` function returns an array of `N`, `null`, or `undefined` values.
+ * @returns The `addMany` function returns an array of `N`, `undefined`, or `undefined` values.
*/
override addMany(
- keysOrNodes: (BTNKey | null)[] | (N | null)[],
+ keysOrNodes: (BTNKey | undefined)[] | (N | undefined)[],
data?: V[],
isBalanceAdd = true,
iterationType = this.iterationType
- ): (N | null | undefined)[] {
+ ): (N | undefined)[] {
// TODO this addMany function is inefficient, it should be optimized
- function hasNoNull(arr: (BTNKey | null)[] | (N | null)[]): arr is BTNKey[] | N[] {
- return arr.indexOf(null) === -1;
+ function hasNoNull(arr: (BTNKey | undefined)[] | (N | undefined)[]): arr is BTNKey[] | N[] {
+ return arr.indexOf(undefined) === -1;
}
if (!isBalanceAdd || !hasNoNull(keysOrNodes)) {
- return super.addMany(keysOrNodes, data);
+ return super.addMany(keysOrNodes, data).map(n => n ?? undefined);
}
- const inserted: (N | null | undefined)[] = [];
+ const inserted: (N | undefined)[] = [];
const combinedArr: [BTNKey | N, V][] = keysOrNodes.map(
(value: BTNKey | N, index) => [value, data?.[index]] as [BTNKey | N, V]
);
@@ -169,7 +227,7 @@ export class BST = BSTNode>
return false;
}
- let sortedKeysOrNodes: (number | N | null)[] = [],
+ let sortedKeysOrNodes: (number | N | undefined)[] = [],
sortedData: (V | undefined)[] | undefined = [];
if (isNodeOrNullTuple(combinedArr)) {
@@ -181,7 +239,7 @@ export class BST = BSTNode>
}
sortedKeysOrNodes = sorted.map(([keyOrNode]) => keyOrNode);
sortedData = sorted.map(([, value]) => value);
- const recursive = (arr: (BTNKey | null | N)[], data?: (V | undefined)[]) => {
+ const recursive = (arr: (BTNKey | undefined | N)[], data?: (V | undefined)[]) => {
if (arr.length === 0) return;
const mid = Math.floor((arr.length - 1) / 2);
@@ -220,7 +278,7 @@ export class BST = BSTNode>
* The function `lastKey` returns the key of the rightmost node if the comparison result is less
* than, the key of the leftmost node if the comparison result is greater than, and the key of the
* rightmost node otherwise.
- * @param {N | null} beginRoot - The `beginRoot` parameter is the starting point for finding the last
+ * @param {N | undefined} beginRoot - The `beginRoot` parameter is the starting point for finding the last
* key in a binary tree. It represents the root node of the subtree from which the search for the
* last key should begin. If no specific `beginRoot` is provided, the search will start from the root
* of the entire binary
@@ -231,7 +289,7 @@ export class BST = BSTNode>
* the key of the leftmost node if the comparison result is greater than, and the key of the
* rightmost node otherwise. If no node is found, it returns 0.
*/
- lastKey(beginRoot: N | null = this.root, iterationType = this.iterationType): BTNKey {
+ lastKey(beginRoot: N | undefined = this.root, iterationType = this.iterationType): BTNKey {
if (this._compare(0, 1) === CP.lt) return this.getRightMost(beginRoot, iterationType)?.key ?? 0;
else if (this._compare(0, 1) === CP.gt) return this.getLeftMost(beginRoot, iterationType)?.key ?? 0;
else return this.getRightMost(beginRoot, iterationType)?.key ?? 0;
@@ -251,18 +309,18 @@ export class BST = BSTNode>
* the first node that matches the nodeProperty. If set to true, the function will return an array
* containing only that node. If set to false (default), the function will continue the traversal and
* return an array containing all nodes that match the node
- * @param {N | null} beginRoot - The `beginRoot` parameter is the starting node for the traversal. It
+ * @param {N | undefined} beginRoot - The `beginRoot` parameter is the starting node for the traversal. It
* specifies the root node of the binary tree from which the traversal should begin. If `beginRoot`
- * is `null`, an empty array will be returned.
+ * is `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 one of the following values:
* @returns an array of nodes (N[]).
*/
override getNodes>(
- identifier: ReturnType | null,
+ identifier: ReturnType | undefined,
callback: C = this.defaultOneParamCallback as C,
onlyOne = false,
- beginRoot: N | null = this.root,
+ beginRoot: N | undefined = this.root,
iterationType = this.iterationType
): N[] {
if (!beginRoot) return [];
@@ -324,10 +382,10 @@ export class BST = BSTNode>
* @param {CP} lesserOrGreater - The `lesserOrGreater` parameter is used to determine whether to
* traverse nodes that are lesser than, greater than, or equal to the `targetNode`. It can take one
* of the following values:
- * @param {BTNKey | N | null} targetNode - The `targetNode` parameter in the
+ * @param {BTNKey | N | undefined} targetNode - The `targetNode` parameter in the
* `lesserOrGreaterTraverse` function is used to specify the node from which the traversal should
* start. It can be either a reference to a specific node (`N`), the key of a node
- * (`BTNKey`), or `null` to
+ * (`BTNKey`), or `undefined` to
* @param iterationType - The `iterationType` parameter determines whether the traversal should be
* done recursively or iteratively. It can have two possible values:
* @returns The function `lesserOrGreaterTraverse` returns an array of `ReturnType>`.
@@ -335,10 +393,10 @@ export class BST = BSTNode>
lesserOrGreaterTraverse>(
callback: C = this.defaultOneParamCallback as C,
lesserOrGreater: CP = CP.lt,
- targetNode: BTNKey | N | null = this.root,
+ targetNode: BTNKey | N | undefined = this.root,
iterationType = this.iterationType
): ReturnType[] {
- if (typeof targetNode === 'number') targetNode = this.getNode(targetNode);
+ if (typeof targetNode === 'number') targetNode = this.getNode(targetNode) ?? undefined;
const ans: ReturnType>[] = [];
if (!targetNode) return ans;
const targetKey = targetNode.key;
@@ -417,6 +475,7 @@ export class BST = BSTNode>
if (l <= r) {
const m = l + Math.floor((r - l) / 2);
const midNode = sorted[m];
+ debugger
this.add(midNode.key, midNode.value);
stack.push([m + 1, r]);
stack.push([l, m - 1]);
@@ -439,7 +498,7 @@ export class BST = BSTNode>
let balanced = true;
if (iterationType === IterationType.RECURSIVE) {
- const _height = (cur: N | null | undefined): number => {
+ const _height = (cur: N | undefined): number => {
if (!cur) return 0;
const leftHeight = _height(cur.left),
rightHeight = _height(cur.right);
@@ -449,8 +508,8 @@ export class BST = BSTNode>
_height(this.root);
} else {
const stack: N[] = [];
- let node: N | null | undefined = this.root,
- last: N | null = null;
+ let node: N | undefined = this.root,
+ last:N | undefined = undefined;
const depths: Map = new Map();
while (stack.length > 0 || node) {
@@ -467,7 +526,7 @@ export class BST = BSTNode>
if (Math.abs(left - right) > 1) return false;
depths.set(node, 1 + Math.max(left, right));
last = node;
- node = null;
+ node = undefined;
}
} else node = node.right;
}
diff --git a/src/data-structures/binary-tree/tree-multiset.ts b/src/data-structures/binary-tree/tree-multiset.ts
index 7be1720..bb0c505 100644
--- a/src/data-structures/binary-tree/tree-multiset.ts
+++ b/src/data-structures/binary-tree/tree-multiset.ts
@@ -71,23 +71,24 @@ export class TreeMultiset = TreeMultis
/**
* The `add` function adds a new node to a binary search tree, updating the count if the key already
* exists, and balancing the tree if necessary.
- * @param {BTNKey | N | null} keyOrNode - The `keyOrNode` parameter can be either a
+ * @param {BTNKey | N | undefined} keyOrNode - The `keyOrNode` parameter can be either a
* `BTNKey` (which represents the key of the node to be added), a `N` (which represents a
- * node to be added), or `null` (which represents a null node).
+ * node to be added), or `undefined` (which represents a undefined node).
* @param [value] - The `value` parameter represents the value associated with the key that is being
* added to the binary tree.
* @param [count=1] - The `count` parameter represents the number of occurrences of the key/value
* pair that will be added to the binary tree. It has a default value of 1, which means that if no
* count is specified, the default count will be 1.
- * @returns The function `add` returns a value of type `N | null | undefined`.
+ * @returns The function `add` returns a value of type `N | undefined | undefined`.
*/
- override add(keyOrNode: BTNKey | N | null, value?: V, count = 1): N | null | undefined {
- let inserted: N | null | undefined = undefined,
- newNode: N | null;
+ override add(keyOrNode: BTNKey | N | null | undefined, value?: V, count = 1): N | undefined {
+ if(keyOrNode === null) return undefined;
+ let inserted: N | undefined = undefined,
+ newNode: N | undefined;
if (keyOrNode instanceof TreeMultisetNode) {
newNode = this.createNode(keyOrNode.key, keyOrNode.value, keyOrNode.count);
- } else if (keyOrNode === null) {
- newNode = null;
+ } else if (keyOrNode === undefined) {
+ newNode = undefined;
} else {
newNode = this.createNode(keyOrNode, value, count);
}
@@ -138,7 +139,7 @@ export class TreeMultiset = TreeMultis
}
}
} else {
- // TODO may need to support null inserted
+ // TODO may need to support undefined inserted
}
} else {
traversing = false;
@@ -151,17 +152,17 @@ export class TreeMultiset = TreeMultis
/**
* The function adds a new node to a binary tree if there is an available slot in the parent node.
- * @param {N | null} newNode - The `newNode` parameter represents the node that needs to be added to
- * the tree. It can be either a node object (`N`) or `null`.
+ * @param {N | undefined} newNode - The `newNode` parameter represents the node that needs to be added to
+ * the tree. It can be either a node object (`N`) or `undefined`.
* @param {N} parent - The `parent` parameter represents the parent node to which the new node will
* be added as a child.
* @returns The method `_addTo` returns either the `parent.left`, `parent.right`, or `undefined`.
*/
- override _addTo(newNode: N | null, parent: N): N | null | undefined {
+ override _addTo(newNode: N | undefined, parent: N): N | undefined {
if (parent) {
if (parent.left === undefined) {
parent.left = newNode;
- if (newNode !== null) {
+ if (newNode !== undefined) {
this._size = this.size + 1;
this._setCount(this.count + newNode.count);
}
@@ -169,7 +170,7 @@ export class TreeMultiset = TreeMultis
return parent.left;
} else if (parent.right === undefined) {
parent.right = newNode;
- if (newNode !== null) {
+ if (newNode !== undefined) {
this._size = this.size + 1;
this._setCount(this.count + newNode.count);
}
@@ -185,15 +186,15 @@ export class TreeMultiset = TreeMultis
/**
* The `addMany` function adds multiple keys or nodes to a TreeMultiset and returns an array of the
* inserted nodes.
- * @param {(BTNKey | null)[] | (N | null)[]} keysOrNodes - An array of keys or nodes to be
+ * @param {(BTNKey | undefined)[] | (N | undefined)[]} keysOrNodes - An array of keys or nodes to be
* added to the multiset. Each element can be either a BTNKey or a TreeMultisetNode.
* @param {V[]} [data] - The `data` parameter is an optional array of values that correspond
* to the keys or nodes being added to the multiset. It is used to associate additional data with
* each key or node.
- * @returns The function `addMany` returns an array of `N`, `null`, or `undefined` values.
+ * @returns The function `addMany` returns an array of `N`, `undefined`, or `undefined` values.
*/
- override addMany(keysOrNodes: (BTNKey | null)[] | (N | null)[], data?: V[]): (N | null | undefined)[] {
- const inserted: (N | null | undefined)[] = [];
+ override addMany(keysOrNodes: (BTNKey | undefined)[] | (N | undefined)[], data?: V[]): (N | undefined)[] {
+ const inserted: (N | undefined | undefined)[] = [];
for (let i = 0; i < keysOrNodes.length; i++) {
const keyOrNode = keysOrNodes[i];
@@ -203,7 +204,7 @@ export class TreeMultiset = TreeMultis
continue;
}
- if (keyOrNode === null) {
+ if (keyOrNode === undefined) {
inserted.push(this.add(NaN, undefined, 0));
continue;
}
@@ -283,11 +284,11 @@ export class TreeMultiset = TreeMultis
const bstDeletedResult: BinaryTreeDeletedResult[] = [];
if (!this.root) return bstDeletedResult;
- const curr: N | null = this.getNode(identifier, callback);
+ const curr: N | undefined = this.getNode(identifier, callback) ?? undefined;
if (!curr) return bstDeletedResult;
- const parent: N | null = curr?.parent ? curr.parent : null;
- let needBalanced: N | null = null,
+ const parent: N | undefined = curr?.parent ? curr.parent : undefined;
+ let needBalanced: N | undefined = undefined,
orgCurrent = curr;
if (curr.count > 1 && !ignoreCount) {
@@ -307,7 +308,7 @@ export class TreeMultiset = TreeMultis
needBalanced = parent;
}
} else {
- const leftSubTreeRightMost = curr.left ? this.getRightMost(curr.left) : null;
+ const leftSubTreeRightMost = curr.left ? this.getRightMost(curr.left) : undefined;
if (leftSubTreeRightMost) {
const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;
orgCurrent = this._swap(curr, leftSubTreeRightMost);
diff --git a/src/types/data-structures/binary-tree/binary-tree.ts b/src/types/data-structures/binary-tree/binary-tree.ts
index c9da335..dc843c2 100644
--- a/src/types/data-structures/binary-tree/binary-tree.ts
+++ b/src/types/data-structures/binary-tree/binary-tree.ts
@@ -24,7 +24,7 @@ export enum FamilyPosition {
export type BTNKey = number;
-export type BinaryTreeDeletedResult = { deleted: N | null | undefined; needBalanced: N | null };
+export type BinaryTreeDeletedResult = { deleted: N | null | undefined; needBalanced: N | null | undefined };
export type BinaryTreeNodeNested = BinaryTreeNode>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
diff --git a/test/unit/data-structures/binary-tree/avl-tree.test.ts b/test/unit/data-structures/binary-tree/avl-tree.test.ts
index 7518a9b..1af0ce6 100644
--- a/test/unit/data-structures/binary-tree/avl-tree.test.ts
+++ b/test/unit/data-structures/binary-tree/avl-tree.test.ts
@@ -36,7 +36,6 @@ describe('AVL Tree Test', () => {
const dfs = tree.dfs(node => node, 'in');
expect(dfs[0].key).toBe(1);
expect(dfs[dfs.length - 1].key).toBe(16);
-
tree.perfectlyBalance();
const bfs = tree.bfs(node => node);
expect(tree.isPerfectlyBalanced()).toBe(true);
@@ -266,4 +265,24 @@ describe('AVLTree', () => {
// You can add more specific assertions to check the tree's balance and structure.
});
+
+ describe('BinaryTree APIs test', () => {
+ const avl = new AVLTree<{id: number; text: string}>();
+ beforeEach(() => {
+ avl.clear();
+ });
+
+ it('add', () => {
+ avl.add(1);
+ const node2 = new AVLTreeNode(2);
+ avl.add(node2);
+ const node3 = new AVLTreeNode(3, {id: 3, text: 'text3'});
+ avl.add(node3);
+ avl.add(node3, {id: 3, text: 'text33'});
+
+ const bfsRes = avl.bfs(node => node);
+ expect(bfsRes[0]?.key).toBe(2);
+ });
+ });
+
});
diff --git a/test/unit/data-structures/binary-tree/binary-tree.test.ts b/test/unit/data-structures/binary-tree/binary-tree.test.ts
index 5d8d7f0..ae49e6b 100644
--- a/test/unit/data-structures/binary-tree/binary-tree.test.ts
+++ b/test/unit/data-structures/binary-tree/binary-tree.test.ts
@@ -1,4 +1,4 @@
-import {AVLTree, AVLTreeNode, BinaryTree, BinaryTreeNode, IterationType} from '../../../../src';
+import {BinaryTree, BinaryTreeNode, IterationType} from '../../../../src';
// import {isDebugTest} from '../../../config';
// const isDebug = isDebugTest;
@@ -177,10 +177,10 @@ describe('BinaryTree', () => {
expect(tree.subTreeTraverse(node => node.key, tree.getNode(6), IterationType.ITERATIVE)).toEqual([6, 3, 7]);
expect(tree.subTreeTraverse(node => node.key, tree.getNode(6), IterationType.RECURSIVE)).toEqual([6, 3, 7]);
expect(
- tree.subTreeTraverse(node => (node === null ? null : node.key), tree.getNode(6), IterationType.ITERATIVE, true)
+ tree.subTreeTraverse(node => (node ? node.key : null ), tree.getNode(6), IterationType.ITERATIVE, true)
).toEqual([6, 3, 7, null]);
expect(
- tree.subTreeTraverse(node => (node === null ? null : node.key), tree.getNode(6), IterationType.RECURSIVE, true)
+ tree.subTreeTraverse(node => (node ? node.key : null ), tree.getNode(6), IterationType.RECURSIVE, true)
).toEqual([6, 3, 7, null]);
});
@@ -193,7 +193,7 @@ describe('BinaryTree', () => {
tree.clear();
expect(tree.size).toBe(0);
- expect(tree.root).toBeNull();
+ expect(tree.root).toBeUndefined();
});
});
@@ -248,35 +248,16 @@ describe('BinaryTree Morris Traversal', () => {
});
});
-describe('BinaryTree APIs test', () => {
- const avl = new AVLTree<{id: number; text: string}>();
- beforeEach(() => {
- avl.clear();
- });
-
- it('add', () => {
- avl.add(1);
- const node2 = new AVLTreeNode(2);
- avl.add(node2);
- const node3 = new AVLTreeNode(3, {id: 3, text: 'text3'});
- avl.add(node3);
- avl.add(node3, {id: 3, text: 'text33'});
-
- const bfsRes = avl.bfs(node => node);
- expect(bfsRes[0]?.key).toBe(2);
- });
-});
-
describe('BinaryTree traversals', () => {
const tree = new BinaryTree();
const arr = [35, 20, 40, 15, 29, null, 50, null, 16, 28, 30, 45, 55];
tree.refill(arr);
expect(
- tree.bfs(node => node, tree.root, IterationType.ITERATIVE, true).map(node => (node === null ? null : node.key))
+ tree.bfs(node => node, tree.root, IterationType.ITERATIVE, true).map(node => (node ? node.key : null ))
).toEqual([35, 20, 40, 15, 29, null, 50, null, 16, 28, 30, 45, 55]);
expect(
- tree.bfs(node => node, tree.root, IterationType.RECURSIVE, true).map(node => (node === null ? null : node.key))
+ tree.bfs(node => node, tree.root, IterationType.RECURSIVE, true).map(node => (node ? node.key : null ))
).toEqual([35, 20, 40, 15, 29, null, 50, null, 16, 28, 30, 45, 55]);
expect(
tree.bfs(node => node, tree.root, IterationType.ITERATIVE).map(node => (node === null ? null : node.key))
@@ -292,12 +273,12 @@ describe('BinaryTree traversals', () => {
expect(
tree
.dfs(node => node, 'pre', tree.root, IterationType.ITERATIVE, true)
- .map(node => (node === null ? null : node.key))
+ .map(node => (node ? node.key : null ))
).toEqual([35, 20, 15, null, 16, 29, 28, 30, 40, null, 50, 45, 55]);
expect(
tree
.dfs(node => node, 'pre', tree.root, IterationType.RECURSIVE, true)
- .map(node => (node === null ? null : node.key))
+ .map(node => (node ? node.key : null ))
).toEqual([35, 20, 15, null, 16, 29, 28, 30, 40, null, 50, 45, 55]);
expect(tree.dfs(node => node.key, 'in')).toEqual([15, 16, 20, 28, 29, 30, 35, 40, 45, 50, 55]);
@@ -320,13 +301,13 @@ describe('BinaryTree traversals', () => {
[15, 29, 50],
[16, 28, 30, 45, 55]
]);
- expect(tree.listLevels(node => (node === null ? null : node.key), tree.root, IterationType.ITERATIVE, true)).toEqual([
+ expect(tree.listLevels(node => (node ? node.key : null ), tree.root, IterationType.ITERATIVE, true)).toEqual([
[35],
[20, 40],
[15, 29, null, 50],
[null, 16, 28, 30, 45, 55]
]);
- expect(tree.listLevels(node => (node === null ? null : node.key), tree.root, IterationType.RECURSIVE, true)).toEqual([
+ expect(tree.listLevels(node => ( node ? node.key : null ), tree.root, IterationType.RECURSIVE, true)).toEqual([
[35],
[20, 40],
[15, 29, null, 50],
@@ -348,7 +329,7 @@ describe('BinaryTree', () => {
it('should create an empty BinaryTree', () => {
expect(tree.size).toBe(0);
expect(tree.isEmpty()).toBe(true);
- expect(tree.root).toBe(null);
+ expect(tree.root).toBe(undefined);
});
it('should add nodes to the tree', () => {
@@ -370,7 +351,7 @@ describe('BinaryTree', () => {
expect(tree.size).toBe(0);
expect(tree.isEmpty()).toBe(true);
- expect(tree.root).toBe(null);
+ expect(tree.root).toBe(undefined);
});
it('should get nodes by key', () => {
diff --git a/test/unit/data-structures/binary-tree/bst.test.ts b/test/unit/data-structures/binary-tree/bst.test.ts
index e82bf9c..ef80c31 100644
--- a/test/unit/data-structures/binary-tree/bst.test.ts
+++ b/test/unit/data-structures/binary-tree/bst.test.ts
@@ -840,14 +840,14 @@ describe('BST Performance test', function () {
it('should subTreeTraverse, null should be ignored', () => {
const bst = new BST();
- bst.addMany([4, 2, 6, null, 1, 3, null, 5, null, 7]);
+ bst.addMany([4, 2, 6, 1, 3, 5, 7]);
expect(bst.subTreeTraverse(node => node.key, bst.getNode(6), IterationType.ITERATIVE)).toEqual([6, 5, 7]);
expect(bst.subTreeTraverse(node => node.key, bst.getNode(6), IterationType.RECURSIVE)).toEqual([6, 5, 7]);
expect(
- bst.subTreeTraverse(node => (node === null ? null : node.key), bst.getNode(6), IterationType.ITERATIVE, true)
+ bst.subTreeTraverse(node => (node?.key ?? undefined), bst.getNode(6), IterationType.ITERATIVE, true)
).toEqual([6, 5, 7]);
expect(
- bst.subTreeTraverse(node => (node === null ? null : node.key), bst.getNode(6), IterationType.RECURSIVE, true)
+ bst.subTreeTraverse(node => (node?.key ?? undefined), bst.getNode(6), IterationType.RECURSIVE, true)
).toEqual([6, 5, 7]);
});
});