From cef8b04a9f967f41160d1349de415cae9aa46760 Mon Sep 17 00:00:00 2001 From: Revone Date: Fri, 10 Nov 2023 11:01:49 +0800 Subject: [PATCH] chore: Add comments for the time and space complexity of all methods for the BinaryTree. --- CHANGELOG.md | 2 +- .../binary-tree/binary-tree.ts | 623 ++++++++++++------ test/integration/index.html | 26 +- .../binary-tree/binary-tree.test.ts | 21 +- .../linked-list/doubly-linked-list.test.ts | 1 - .../linked-list/singly-linked-list.test.ts | 1 - 6 files changed, 463 insertions(+), 211 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f390fd..d365a93 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.7](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming) +## [v1.42.8](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming) ### Changes diff --git a/src/data-structures/binary-tree/binary-tree.ts b/src/data-structures/binary-tree/binary-tree.ts index 2e95745..05e90ef 100644 --- a/src/data-structures/binary-tree/binary-tree.ts +++ b/src/data-structures/binary-tree/binary-tree.ts @@ -153,10 +153,23 @@ export class BinaryTree = BinaryTreeNode } /** - * Add a node with the given key and value to the binary tree. - * @param {BTNKey | N | null} keyOrNode - The key or node to add to the binary tree. - * @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. + * Time Complexity: O(n) + * Space Complexity: O(1) + * Comments: The time complexity for adding a node depends on the depth of the tree. In the best case (when the tree is empty), it's O(1). In the worst case (when the tree is a degenerate tree), it's O(n). The space complexity is constant. + */ + + /** + * Time Complexity: O(n) + * Space Complexity: O(1) + * + * The `add` function adds a new node with a key and value to a binary tree, or updates the value of + * an existing node with the same key. + * @param {BTNKey | N | null | undefined} keyOrNode - The `keyOrNode` parameter can be one of the + * following types: + * @param {V} [value] - The value to be associated with the key or node being added to the binary + * tree. + * @returns The function `add` returns a node (`N`) if it was successfully inserted into the binary + * tree, or `null` or `undefined` if the insertion was not successful. */ add(keyOrNode: BTNKey | N | null | undefined, value?: V): N | null | undefined { const _bfs = (root: N, newNode: N | null): N | undefined | null => { @@ -204,13 +217,22 @@ export class BinaryTree = BinaryTreeNode } /** - * The `addMany` function takes an array of binary tree node IDs or nodes, and optionally an array of corresponding data - * values, and adds them to the binary tree. - * @param {(BTNKey | null)[] | (N | null)[]} keysOrNodes - An array of BTNKey or BinaryTreeNode - * objects, or null values. - * @param {V[]} [values] - The `values` parameter is an optional array of values (`V[]`) that corresponds to - * the nodes or node IDs being added. It is used to set the value of each node being added. If `values` is not provided, - * the value of the nodes will be `undefined`. + * Time Complexity: O(n^2) + * Space Complexity: O(1) + */ + + /** + * Time Complexity: O(n^2) + * Space Complexity: O(1) + * + * The `addMany` function takes an array of keys or nodes and an optional array of values, and adds + * each key-value pair to a data structure. + * @param {(BTNKey | N |null | undefined)[]} keysOrNodes - An array of keys or nodes to be added to + * the binary search tree. Each element can be of type `BTNKey` (a key value), `N` (a node), `null`, + * or `undefined`. + * @param {(V | undefined)[]} [values] - The `values` parameter is an optional array of values that + * correspond to the keys or nodes being added. If provided, the values will be associated with the + * keys or nodes during the add operation. * @returns The function `addMany` returns an array of `N`, `null`, or `undefined` values. */ addMany(keysOrNodes: (BTNKey | N |null | undefined)[], values?: (V | undefined)[]): (N | null | undefined)[] { @@ -230,6 +252,14 @@ export class BinaryTree = BinaryTreeNode } /** + * Time Complexity: O(n^2) + * Space Complexity: O(1) + */ + + /** + * Time Complexity: O(n^2) + * Space Complexity: O(1) + * * The `refill` function clears the binary tree and adds multiple nodes with the given IDs or nodes and optional data. * @param {(BTNKey | N)[]} keysOrNodes - The `keysOrNodes` parameter is an array that can contain either * `BTNKey` or `N` values. @@ -250,18 +280,24 @@ export class BinaryTree = BinaryTreeNode delete>(identifier: ReturnType, callback: C): BiTreeDeleteResult[]; /** - * The `delete` function removes a node from a binary search tree and returns the deleted node along - * with the parent node that needs to be balanced. - * a key (`BTNKey`). If it is a key, the function will find the corresponding node in the - * binary tree. - * @returns an array of `BiTreeDeleteResult` objects. - * @param {ReturnType} identifier - The `identifier` parameter is either a - * `BTNKey` or a generic type `N`. It represents the property of the node that we are - * searching for. It can be a specific key value or any other property of the node. - * @param callback - The `callback` parameter is a function that takes a node as input and returns a - * value. This value is compared with the `identifier` parameter to determine if the node should be - * included in the result. The `callback` parameter has a default value of - * `this._defaultOneParamCallback`, which + * Time Complexity: O(n) + * Space Complexity: O(1) + */ + + /** + * Time Complexity: O(n) + * Space Complexity: O(1) + * + * The function deletes a node from a binary tree and returns an array of the deleted nodes along + * with the nodes that need to be balanced. + * @param {ReturnType | null | undefined} identifier - The identifier parameter is the value or + * object that you want to delete from the binary tree. It can be of any type that is compatible with + * the callback function's return type. It can also be null or undefined if you want to delete a + * specific node based on its value or object. + * @param {C} callback - The `callback` parameter is a function that is used to determine the + * identifier of the node to be deleted. It is optional and has a default value of + * `this._defaultOneParamCallback`. The `callback` function should return the identifier of the node. + * @returns an array of `BiTreeDeleteResult`. */ delete>( identifier: ReturnType | null | undefined, @@ -311,15 +347,21 @@ 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 | 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 | 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. + * Time Complexity: O(n) + * Space Complexity: O(1) + */ + + /** + * Time Complexity: O(n) + * Space Complexity: O(1) + * + * The function calculates the depth of a given node in a binary tree. + * @param {BTNKey | N | null | undefined} distNode - The `distNode` parameter represents the node in + * the binary tree whose depth we want to find. It can be of type `BTNKey`, `N`, `null`, or + * `undefined`. + * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node + * from which we want to calculate the depth. It can be either a `BTNKey` (binary tree node key) or + * `N` (binary tree node) or `null` or `undefined`. If no value is provided for `beginRoot * @returns the depth of the `distNode` relative to the `beginRoot`. */ getDepth(distNode: BTNKey | N | null | undefined, beginRoot: BTNKey | N | null | undefined = this.root): number { @@ -337,15 +379,24 @@ export class BinaryTree = BinaryTreeNode } /** - * The `getHeight` function calculates the maximum height of a binary tree using either recursive or - * iterative approach. + * Time Complexity: O(n) + * Space Complexity: O(log n) + * Best Case - O(log n) (when using recursive iterationType), Worst Case - O(n) (when using iterative iterationType) + */ + + + /** + * Time Complexity: O(n) + * Space Complexity: O(log n) + * + * The function `getHeight` calculates the maximum height of a binary tree using either recursive or + * iterative traversal. * @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 ` + * starting node of the binary tree from which we want to calculate the height. It can be of type + * `BTNKey`, `N`, `null`, or `undefined`. If not provided, it defaults to `this.root`. * @param iterationType - The `iterationType` parameter is used to determine whether to calculate the - * height of the binary tree using a recursive approach or an iterative approach. It can have two - * possible values: + * height of the tree using a recursive approach or an iterative approach. It can have two possible + * values: * @returns the height of the binary tree. */ getHeight(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.iterationType): number { @@ -383,11 +434,20 @@ export class BinaryTree = BinaryTreeNode } /** + * Time Complexity: O(n) + * Space Complexity: O(log n) + * Best Case - O(log n) (when using recursive iterationType), Worst Case - O(n) (when using iterative iterationType) + */ + + /** + * Time Complexity: O(n) + * Space Complexity: O(log n) + * * The `getMinHeight` function calculates the minimum height of a binary tree using either a * recursive or iterative approach. - * @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 {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the + * starting node of the binary tree from which we want to calculate the minimum height. It can be of + * type `BTNKey`, `N`, `null`, or `undefined`. If no value is provided, it defaults to `this.root`. * @param iterationType - The `iterationType` parameter is used to determine the method of iteration * to calculate the minimum height of a binary tree. It can have two possible values: * @returns The function `getMinHeight` returns the minimum height of a binary tree. @@ -436,11 +496,20 @@ export class BinaryTree = BinaryTreeNode } /** + * Time Complexity: O(n) + * Space Complexity: O(log n) + */ + + /** + * Time Complexity: O(n) + * Space Complexity: O(log n) + * * The function checks if a binary tree is perfectly balanced by comparing the minimum height and the * height of the tree. - * @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. + * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point + * for calculating the height and minimum height of a binary tree. It can be either a `BTNKey` (a key + * value of a binary tree node), `N` (a node of a binary tree), `null`, or `undefined`. If + * @returns a boolean value. */ isPerfectlyBalanced(beginRoot: BTNKey | N | null | undefined = this.root): boolean { return this.getMinHeight(beginRoot) + 1 >= this.getHeight(beginRoot); @@ -471,25 +540,35 @@ export class BinaryTree = BinaryTreeNode ): N[]; /** - * The function `getNodes` returns an array of nodes that match a given node property, using either - * recursive or iterative traversal. - * @param {ReturnType} identifier - The `identifier` parameter is either a - * `BTNKey` or a generic type `N`. It represents the property of the node that we are - * searching for. It can be a specific key value or any other property of the node. - * @param callback - The `callback` parameter is a function that takes a node as input and returns a - * value. This value is compared with the `identifier` parameter to determine if the node should be - * included in the result. The `callback` parameter has a default value of - * `this._defaultOneParamCallback`, which - * @param [onlyOne=false] - A boolean value indicating whether to stop searching after finding the - * 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 | 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. + * Time Complexity: O(n) + * Space Complexity: O(log n). + */ + + + /** + * Time Complexity: O(n) + * Space Complexity: O(log n). + * + * The function `getNodes` retrieves nodes from a binary tree based on a given identifier and + * callback function. + * @param {ReturnType | null | undefined} identifier - The `identifier` parameter is the value + * that you want to search for in the binary tree. It can be of any type that is returned by the + * callback function `C`. It can also be `null` or `undefined` if you don't want to search for a + * specific value. + * @param {C} callback - The `callback` parameter is a function that takes a node of type `N` as + * input and returns a value of type `C`. It is used to determine if a node matches the given + * identifier. If no callback is provided, the `_defaultOneParamCallback` function is used as the + * default + * @param [onlyOne=false] - A boolean value indicating whether to only return the first node that + * matches the identifier. If set to true, the function will stop iterating once it finds a matching + * node and return that node. If set to false (default), the function will continue iterating and + * return all nodes that match the identifier. + * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the + * starting node for the traversal. It can be either a key, a node object, or `null`/`undefined`. If + * it is `null` or `undefined`, an empty array will be returned. * @param iterationType - The `iterationType` parameter determines the type of iteration used to * traverse the binary tree. It can have two possible values: - * @returns The function `getNodes` returns an array of nodes (`N[]`). + * @returns an array of nodes of type `N`. */ getNodes>( identifier: ReturnType | null | undefined, @@ -557,20 +636,28 @@ export class BinaryTree = BinaryTreeNode ): boolean; /** - * The function checks if a binary tree has a node with a given property or key. - * @param {BTNKey | N} identifier - The `identifier` parameter is the key or value of - * the node that you want to find in the binary tree. It can be either a `BTNKey` or a - * generic type `N`. - * @param callback - The `callback` parameter is a function that is used to determine whether a node - * matches the desired criteria. It takes a node as input and returns a boolean value indicating - * whether the node matches the criteria or not. The default callback function - * `this._defaultOneParamCallback` is used if no callback function is - * @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies - * the node from which the search should begin. By default, it is set to `this.root`, which means the - * search will start from the root node of the binary tree. However, you can provide a different node - * as - * @param iterationType - The `iterationType` parameter specifies the type of iteration to be - * performed when searching for nodes in the binary tree. It can have one of the following values: + * Time Complexity: O(n) + * Space Complexity: O(log n). + */ + + /** + * Time Complexity: O(n) + * + * The function checks if a Binary Tree Node with a specific identifier exists in the tree. + * @param {ReturnType | null | undefined} identifier - The `identifier` parameter is the value + * that you want to search for in the binary tree. It can be of any type that is returned by the + * callback function `C`. It can also be `null` or `undefined` if you don't want to specify a + * specific identifier. + * @param {C} callback - The `callback` parameter is a function that will be called for each node in + * the binary tree. It is used to filter the nodes based on certain conditions. The `callback` + * function should return a boolean value indicating whether the node should be included in the + * result or not. + * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point + * for the search in the binary tree. It can be specified as a `BTNKey` (a unique identifier for a + * node in the binary tree), a node object (`N`), or `null`/`undefined` to start the search from + * @param iterationType - The `iterationType` parameter is a variable that determines the type of + * iteration to be performed on the binary tree. It is used to specify whether the iteration should + * be performed in a pre-order, in-order, or post-order manner. * @returns a boolean value. */ has>( @@ -606,19 +693,30 @@ export class BinaryTree = BinaryTreeNode ): N | null | undefined; /** - * The function `get` returns the first node in a binary tree that matches the given property or key. - * @param {BTNKey | N} identifier - The `identifier` parameter is the key or value of - * the node that you want to find in the binary tree. It can be either a `BTNKey` or `N` - * type. - * @param callback - The `callback` parameter is a function that is used to determine whether a node - * matches the desired criteria. It takes a node as input and returns a boolean value indicating - * whether the node matches the criteria or not. The default callback function - * (`this._defaultOneParamCallback`) is used if no callback function is - * @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies - * the root node from which the search should begin. - * @param iterationType - The `iterationType` parameter specifies the type of iteration to be - * performed when searching for a node in the binary tree. It can have one of the following values: - * @returns either the found node (of type N) or null if no node is found. + * Time Complexity: O(n) + * Space Complexity: O(log n) + */ + + /** + * Time Complexity: O(n) + * Space Complexity: O(log n) + * + * The function `getNode` returns the first node that matches the given identifier and callback + * function. + * @param {ReturnType | null | undefined} identifier - The `identifier` parameter is the value + * used to identify the node you want to retrieve. It can be of any type that is returned by the + * callback function `C`. It can also be `null` or `undefined` if you don't have a specific + * identifier. + * @param {C} callback - The `callback` parameter is a function that will be called for each node in + * the binary tree. It is used to determine if a node matches the given identifier. The `callback` + * function should take a single parameter of type `N` (the type of the nodes in the binary tree) and + * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point + * for searching the binary tree. It can be either a key value, a node object, or `null`/`undefined`. + * If `null` or `undefined` is passed, the search will start from the root of the binary tree. + * @param iterationType - The `iterationType` parameter is used to specify the type of iteration to + * be performed when searching for nodes in the binary tree. It determines the order in which the + * nodes are visited during the search. + * @returns a value of type `N | null | undefined`. */ getNode>( identifier: ReturnType | null | undefined, @@ -632,6 +730,14 @@ export class BinaryTree = BinaryTreeNode } /** + * Time Complexity: O(n) + * Space Complexity: O(log n) + */ + + /** + * Time Complexity: O(n) + * Space Complexity: O(log n) + * * The function `getNodeByKey` searches for a node in a binary tree by its key, using either * recursive or iterative iteration. * @param {BTNKey} key - The `key` parameter is the key value that we are searching for in the tree. @@ -666,7 +772,7 @@ export class BinaryTree = BinaryTreeNode } } } - + /** * The function `ensureNotKey` returns the node corresponding to the given key if it is a valid node * key, otherwise it returns the key itself. @@ -704,19 +810,31 @@ export class BinaryTree = BinaryTreeNode ): V | undefined; /** - * The function `get` returns the first node value in a binary tree that matches the given property or key. - * @param {BTNKey | N} identifier - The `identifier` parameter is the key or value of - * the node that you want to find in the binary tree. It can be either a `BTNKey` or `N` - * type. - * @param callback - The `callback` parameter is a function that is used to determine whether a node - * matches the desired criteria. It takes a node as input and returns a boolean value indicating - * whether the node matches the criteria or not. The default callback function - * (`this._defaultOneParamCallback`) is used if no callback function is - * @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies - * the root node from which the search should begin. - * @param iterationType - The `iterationType` parameter specifies the type of iteration to be - * performed when searching for a node in the binary tree. It can have one of the following values: - * @returns either the found value (of type V) or undefined if no node value is found. + * Time Complexity: O(n) + * Space Complexity: O(log n) + */ + + /** + * Time Complexity: O(n) + * Space Complexity: O(log n) + * + * The function `get` retrieves the value of a node in a binary tree based on the provided identifier + * and callback function. + * @param {ReturnType | null | undefined} identifier - The `identifier` parameter is the value + * used to identify the node in the binary tree. It can be of any type that is the return type of the + * callback function `C`. It can also be `null` or `undefined` if no identifier is provided. + * @param {C} callback - The `callback` parameter is a function that will be called with each node in + * the binary tree. It is used to determine whether a node matches the given identifier. The callback + * function should return a value that can be compared to the identifier to determine if it is a + * match. + * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point + * for the search in the binary tree. It can be specified as a `BTNKey` (a unique identifier for a + * node), a node object of type `N`, or `null`/`undefined` to start the search from the root of + * @param iterationType - The `iterationType` parameter is used to specify the type of iteration to + * be performed when searching for a node in the binary tree. It is an optional parameter with a + * default value specified by `this.iterationType`. + * @returns The value of the node with the given identifier is being returned. If the node is not + * found, `undefined` is returned. */ get>( identifier: ReturnType | null | undefined, @@ -744,16 +862,25 @@ export class BinaryTree = BinaryTreeNode isEmpty(): boolean { return this.size === 0; } - + /** - * The function `getPathToRoot` returns an array of nodes starting from a given node and traversing - * up to the root node, with the option to reverse the order of the nodes. - * @param {N} beginRoot - The `beginRoot` parameter represents the starting node from which you want - * to find the path to the root node. + * Time Complexity: O(log n) + * Space Complexity: O(log n) + */ + + /** + * Time Complexity: O(log n) + * Space Complexity: O(log n) + * + * The function `getPathToRoot` returns an array of nodes from a given node to the root of a tree + * structure, with the option to reverse the order of the nodes. + * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the + * starting node from which you want to find the path to the root. It can be of type `BTNKey`, `N`, + * `null`, or `undefined`. * @param [isReverse=true] - The `isReverse` parameter is a boolean flag that determines whether the * resulting path should be reversed or not. If `isReverse` is set to `true`, the path will be - * reversed before returning it. If `isReverse` is set to `false` or not provided, the path will - * @returns The function `getPathToRoot` returns an array of type `N[]`. + * reversed before returning it. If `isReverse` is set to `false`, the path will be returned as is + * @returns The function `getPathToRoot` returns an array of nodes (`N[]`). */ getPathToRoot(beginRoot: BTNKey | N | null | undefined, isReverse = true): N[] { // TODO to support get path through passing key @@ -773,15 +900,23 @@ export class BinaryTree = BinaryTreeNode } /** - * The function `getLeftMost` returns the leftmost node in a binary tree, either using recursive or - * iterative traversal. + * Time Complexity: O(log n) + * Space Complexity: O(1) + */ + + /** + * Time Complexity: O(log n) + * Space Complexity: O(1) + * + * The function `getLeftMost` returns the leftmost node in a binary tree, either recursively or + * iteratively. * @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. + * for finding the leftmost node in a binary tree. It can be either a `BTNKey` (a key value), `N` (a + * node), `null`, or `undefined`. If not provided, it defaults to `this.root`, * @param iterationType - The `iterationType` parameter is used to determine the type of iteration to * be performed when finding the leftmost node in a binary tree. It can have two possible values: - * @returns The function `getLeftMost` returns the leftmost node (`N`) in a binary tree. If there is - * no leftmost node, it returns `null`. + * @returns The function `getLeftMost` returns the leftmost node (`N`) in the binary tree. If there + * is no leftmost node, it returns `null` or `undefined` depending on the input. */ getLeftMost(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.iterationType): N | null | undefined { beginRoot = this.ensureNotKey(beginRoot); @@ -807,15 +942,24 @@ export class BinaryTree = BinaryTreeNode } /** + * Time Complexity: O(log n) + * Space Complexity: O(1) + */ + + /** + * Time Complexity: O(log n) + * Space Complexity: O(1) + * * The function `getRightMost` returns the rightmost node in a binary tree, either recursively or * iteratively. - * @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`. + * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the + * starting node from which we want to find the rightmost node. It can be of type `BTNKey`, `N`, + * `null`, or `undefined`. If not provided, it defaults to `this.root`, which is a property of the + * current object. + * @param iterationType - The `iterationType` parameter is an optional parameter that specifies the + * type of iteration to use when finding the rightmost node. It can have one of two values: + * @returns The function `getRightMost` returns the rightmost node (`N`) in a binary tree. If there + * is no rightmost node, it returns `null` or `undefined`, depending on the input. */ getRightMost(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.iterationType): N | null | undefined { // TODO support get right most by passing key in @@ -841,13 +985,21 @@ export class BinaryTree = BinaryTreeNode } /** + * Time Complexity: O(n) + * Space Complexity: O(1) + */ + + /** + * Time Complexity: O(n) + * Space Complexity: O(1) + * * The function `isSubtreeBST` checks if a given binary tree is a valid binary search tree. - * @param {N} beginRoot - The `beginRoot` parameter is the root node of the binary tree that you want - * to check if it is a binary search tree (BST) subtree. + * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the root + * node of the binary search tree (BST) that you want to check if it is a subtree of another BST. * @param iterationType - The `iterationType` parameter is an optional parameter that specifies the * type of iteration to use when checking if a subtree is a binary search tree (BST). It can have two * possible values: - * @returns The function `isSubtreeBST` returns a boolean value. + * @returns a boolean value. */ isSubtreeBST(beginRoot: BTNKey | N | null | undefined, iterationType = this.iterationType): boolean { // TODO there is a bug @@ -881,11 +1033,19 @@ export class BinaryTree = BinaryTreeNode } /** + * Time Complexity: O(n) + * Space Complexity: O(1) + */ + + /** + * Time Complexity: O(n) + * Space Complexity: O(1) + * * The function checks if a binary tree is a binary search tree. * @param iterationType - The parameter "iterationType" is used to specify the type of iteration to * be used when checking if the binary tree is a binary search tree (BST). It is an optional - * parameter with a default value of "this.iterationType". The value of "this.iterationType" is not - * provided in + * parameter with a default value of "this.iterationType". The value of "this.iterationType" is + * expected to be * @returns a boolean value. */ isBST(iterationType = this.iterationType): boolean { @@ -914,20 +1074,32 @@ export class BinaryTree = BinaryTreeNode includeNull?: true ): ReturnType[]; + /** + * Time complexity: O(n) + * Space complexity: O(log n) + */ + /** + * Time complexity: O(n) + * Space complexity: O(log n) + * * The function `subTreeTraverse` traverses a binary tree and applies a callback function to each * node, either recursively or iteratively. - * @param callback - The `callback` parameter is a function that will be called on each node in the - * 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 | 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 {C} callback - The `callback` parameter is a function that will be called for each node in + * the subtree traversal. It takes a single parameter, which is the current node being traversed, and + * returns a value of any type. + * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the + * starting node or key from which the subtree traversal should begin. It can be of type `BTNKey`, + * `N`, `null`, or `undefined`. If not provided, the `root` property of the current object is used as + * the default value. * @param iterationType - The `iterationType` parameter determines the type of traversal to be - * performed on the binary tree. It can have two possible values: - * @param includeNull - The choice to output null values during binary tree traversal should be provided. - * @returns The function `subTreeTraverse` returns an array of `ReturnType>`. + * performed on the subtree. It can have two possible values: + * @param [includeNull=false] - The `includeNull` parameter is a boolean value that determines + * whether or not to include null values in the traversal. If `includeNull` is set to `true`, the + * traversal will include null values, otherwise it will skip them. + * @returns The function `subTreeTraverse` returns an array of values that are the result of invoking + * the `callback` function on each node in the subtree. The type of the array elements is determined + * by the return type of the `callback` function. */ subTreeTraverse>( callback: C = this._defaultOneParamCallback as C, @@ -1038,20 +1210,32 @@ export class BinaryTree = BinaryTreeNode ): ReturnType[]; /** - * The `dfs` function performs a depth-first search traversal on a binary tree, executing a callback - * function on each node according to a specified order pattern. - * @param callback - The `callback` parameter is a function that will be called on each node during - * the depth-first search traversal. It takes a node as input and returns a value. The default value - * is `this._defaultOneParamCallback`, which is a callback function defined elsewhere in the code. + * Time complexity: O(n) + * Space complexity: O(n) + */ + + /** + * Time complexity: O(n) + * Space complexity: O(n) + * + * The `dfs` function performs a depth-first search traversal on a binary tree or graph, based on the + * specified pattern and iteration type, and returns an array of values obtained from applying a + * callback function to each visited node. + * @param {C} callback - The `callback` parameter is a function that will be called for each node in + * the tree during the depth-first search. It takes a single parameter, which can be of type `N`, + * `null`, or `undefined`, and returns a value of any type. The default value for this parameter is * @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 | 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. + * nodes are traversed during the depth-first search. It can have one of the following values: + * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node + * for the depth-first search traversal. It can be specified as a key, a node object, or + * `null`/`undefined`. If not provided, the `beginRoot` will default to the root node of the tree. * @param {IterationType} iterationType - The `iterationType` parameter determines the type of - * iteration used in the depth-first search algorithm. It can have two possible values: - * @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. + * iteration to use when traversing the tree. It can have one of the following values: + * @param [includeNull=false] - The `includeNull` parameter is a boolean value that determines + * whether null or undefined nodes should be included in the traversal. If `includeNull` is set to + * `true`, null or undefined nodes will be included in the traversal. If `includeNull` is set to + * `false`, null or undefined + * @returns an array of values that are the return values of the callback function. */ dfs>( callback: C = this._defaultOneParamCallback as C, @@ -1171,18 +1355,30 @@ export class BinaryTree = BinaryTreeNode ): ReturnType[]; /** - * The bfs function performs a breadth-first search traversal on a binary tree, executing a callback - * function on each node. - * @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 | 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 - * in the breadth-first search (BFS) algorithm. It can have two possible values: - * @param includeNull - The choice to output null values during binary tree traversal should be provided. - * @returns The function `bfs` returns an array of `ReturnType>[]`. + * Time complexity: O(n) + * Space complexity: O(n) + */ + + /** + * Time complexity: O(n) + * Space complexity: O(n) + * + * The `bfs` function performs a breadth-first search traversal on a binary tree, executing a + * callback function on each node. + * @param {C} callback - The `callback` parameter is a function that will be called for each node in + * the breadth-first search traversal. It takes a single parameter, which is the current node being + * visited, and returns a value of any type. + * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the + * starting node for the breadth-first search traversal. It can be specified as a key, a node object, + * or `null`/`undefined` to indicate the root of the tree. If not provided, the `root` property of + * the class is used as + * @param iterationType - The `iterationType` parameter determines the type of iteration to be + * performed during the breadth-first search (BFS). It can have two possible values: + * @param [includeNull=false] - The `includeNull` parameter is a boolean flag that determines whether + * or not to include null values in the breadth-first search traversal. If `includeNull` is set to + * `true`, null values will be included in the traversal, otherwise they will be skipped. + * @returns an array of values that are the result of invoking the callback function on each node in + * the breadth-first traversal of a binary tree. */ bfs>( callback: C = this._defaultOneParamCallback as C, @@ -1260,20 +1456,31 @@ export class BinaryTree = BinaryTreeNode ): ReturnType[][]; /** - * The `listLevels` function takes a binary tree node and a callback function, and returns an array - * of arrays representing the levels of the tree. - * @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 | 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 - * recursively or iteratively. It can have two possible values: - * @param includeNull - The choice to output null values during binary tree traversal should be provided. - * @returns The function `listLevels` returns an array of arrays, where each inner array represents a - * 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. + * Time complexity: O(n) + * Space complexity: O(n) + */ + + + /** + * Time complexity: O(n) + * Space complexity: O(n) + * + * The `listLevels` function returns an array of arrays, where each inner array represents a level in + * a binary tree and contains the values returned by a callback function applied to the nodes at that + * level. + * @param {C} callback - The `callback` parameter is a function that will be called for each node in + * the tree. It takes a single parameter, which can be of type `N`, `null`, or `undefined`, and + * returns a value of any type. + * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the + * starting node for traversing the tree. It can be either a node object (`N`), a key value + * (`BTNKey`), `null`, or `undefined`. If not provided, it defaults to the root node of the tree. + * @param iterationType - The `iterationType` parameter determines the type of iteration to be + * performed on the tree. It can have two possible values: + * @param [includeNull=false] - The `includeNull` parameter is a boolean value that determines + * whether or not to include null values in the resulting levels. If `includeNull` is set to `true`, + * null values will be included in the levels. If `includeNull` is set to `false`, null values will + * be excluded + * @returns The function `listLevels` returns a two-dimensional array of type `ReturnType[][]`. */ listLevels>( callback: C = this._defaultOneParamCallback as C, @@ -1324,10 +1531,12 @@ export class BinaryTree = BinaryTreeNode getPredecessor(node: N ): N + /** - * The function returns the predecessor node of a given node in a binary tree. - * @param {N} node - The parameter "node" represents a node in a binary tree. - * @returns The function `getPredecessor` returns the predecessor node of the given node `node`. + * The function `getPredecessor` returns the predecessor node of a given node in a binary tree. + * @param {BTNKey | N | null | undefined} node - The `node` parameter can be of type `BTNKey`, `N`, + * `null`, or `undefined`. + * @returns The function `getPredecessor` returns a value of type `N | undefined`. */ getPredecessor(node: BTNKey | N | null | undefined): N | undefined{ node = this.ensureNotKey(node); @@ -1346,12 +1555,12 @@ export class BinaryTree = BinaryTreeNode } } + /** - * The function `getSuccessor` returns the next node in a binary tree given a node `x`, or `null` if - * `x` is the last node. - * @param {N} x - N - a node in a binary tree - * @returns The function `getSuccessor` returns a value of type `N` (the successor node), or `null` - * if there is no successor, or `undefined` if the input `x` is `undefined`. + * The function `getSuccessor` returns the next node in a binary tree given a current node. + * @param {BTNKey | N | null} [x] - The parameter `x` can be of type `BTNKey`, `N`, or `null`. + * @returns the successor of the given node or key. The successor is the node that comes immediately + * after the given node in the inorder traversal of the binary tree. */ getSuccessor(x?: BTNKey | N | null): N | null | undefined { x = this.ensureNotKey(x); @@ -1370,18 +1579,27 @@ export class BinaryTree = BinaryTreeNode } /** - * The `morris` function performs a depth-first traversal of a binary tree using the Morris traversal - * algorithm and returns an array of values obtained by applying a callback function to each node. - * @param callback - The `callback` parameter is a function that will be called on each node in the - * tree. It takes a node of type `N` as input and returns a value of type `ReturnType>`. The - * default value for this parameter is `this._defaultOneParamCallback`. + * Time complexity: O(n) + * Space complexity: O(1) + */ + + /** + * Time complexity: O(n) + * Space complexity: O(1) + * The `morris` function performs a depth-first traversal on a binary tree using the Morris traversal + * algorithm. + * @param {C} callback - The `callback` parameter is a function that will be called for each node in + * the tree. It takes a single parameter of type `N` (the type of the nodes in the tree) and returns + * a value of any type. * @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 | 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. + * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node + * for the traversal. It can be specified as a key, a node object, or `null`/`undefined` to indicate + * the root of the tree. If no value is provided, the default value is the root of the tree. + * @returns The function `morris` returns an array of values that are the result of invoking the + * `callback` function on each node in the binary tree. The type of the array elements is determined + * by the return type of the `callback` function. */ morris>( callback: C = this._defaultOneParamCallback as C, @@ -1469,7 +1687,6 @@ export class BinaryTree = BinaryTreeNode return ans; } - // --- start additional methods --- /** * The above function is an iterator for a binary tree that can be used to traverse the tree in @@ -1502,12 +1719,10 @@ export class BinaryTree = BinaryTreeNode } } else { if (node.left) { - // @ts-ignore yield* this[Symbol.iterator](node.left); } yield node.key; if (node.right) { - // @ts-ignore yield* this[Symbol.iterator](node.right); } } @@ -1593,11 +1808,12 @@ export class BinaryTree = BinaryTreeNode this._root = v; } + /** * The `print` function is used to display a binary tree structure in a visually appealing way. - * @param {N | null | undefined} root - The `root` parameter in the `print` function represents the - * root node of a binary tree. It can have one of the following types: `BTNKey`, `N`, `null`, or - * `undefined`. The default value is `this.root`, which suggests that `this.root` is the + * @param {N | null | undefined} root - The `root` parameter is of type `BTNKey | N | null | + * undefined`. It represents the root node of a binary tree. The root node can have one of the + * following types: */ print(beginRoot: BTNKey | N | null | undefined = this.root): void { beginRoot = this.ensureNotKey(beginRoot); @@ -1611,11 +1827,11 @@ export class BinaryTree = BinaryTreeNode }; const _displayAux = (node: N | null | undefined): [string[], number, number, number] => { - if (node === undefined || node === null) { + if (!this.isRealNode(node)) { return [[], 0, 0, 0]; } - if (node && node.right === undefined && node.left === undefined) { + if (this.isRealNode(node) && !this.isRealNode(node.right) && !this.isRealNode(node.left)) { const line = `${node.key}`; const width = line.length; const height = 1; @@ -1623,7 +1839,7 @@ export class BinaryTree = BinaryTreeNode return [[line], width, height, middle]; } - if (node && node.right === undefined) { + if (this.isRealNode(node) && !this.isRealNode(node.right)) { const [lines, n, p, x] = _displayAux(node.left); const s = `${node.key}`; const u = s.length; @@ -1633,7 +1849,7 @@ export class BinaryTree = BinaryTreeNode return [[first_line, second_line, ...shifted_lines], n + u, p + 2, n + Math.floor(u / 2)]; } - if (node && node.left === undefined) { + if (this.isRealNode(node) && !this.isRealNode(node.left)) { const [lines, n, p, u] = _displayAux(node.right); const s = `${node.key}`; const x = s.length; @@ -1660,5 +1876,4 @@ export class BinaryTree = BinaryTreeNode display(beginRoot); } - // --- end additional methods --- } diff --git a/test/integration/index.html b/test/integration/index.html index 8c85112..c481f7e 100644 --- a/test/integration/index.html +++ b/test/integration/index.html @@ -28,13 +28,13 @@ const queue = new Queue(); - for (let i = 0; i < 1000000; i++) { + for (let i = 0; i < 100000; i++) { queue.enqueue(i); } let last = 0; const startTime = performance.now(); - for (let i = 0; i < 1000000; i++) { + for (let i = 0; i < 100000; i++) { last = queue.dequeue(); } @@ -44,6 +44,28 @@ console.error(e); } + try { + const {BinaryTree} = dataStructureTyped; + const tree = new BinaryTree(); + tree.add(3); + tree.add(12); + tree.addMany([1, 6, 9, 8,5,2,3,4,7]) + tree.add(10); + console.log(tree.isPerfectlyBalanced()); + tree.print(); + + const node3 = tree.getNode(3); + if (node3) node3.right = tree.createNode(1); + console.log(tree.isPerfectlyBalanced()); + tree.print(); + + tree.clear(); + tree.addMany([1, null, 2, null, 3, null, 4, null, 5, null, 6, null]); + console.log(tree.isPerfectlyBalanced()); + tree.print(); + } catch (e) { + console.error(e); + } 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 ae49e6b..32b04ae 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,5 @@ import {BinaryTree, BinaryTreeNode, IterationType} from '../../../../src'; +import {getRandomIntArray} from "../../../utils"; // import {isDebugTest} from '../../../config'; // const isDebug = isDebugTest; @@ -112,6 +113,24 @@ describe('BinaryTree', () => { expect(tree.has('3', node => node.value?.toString())).toBe(true); }); + + it('should be a balance tree after malicious manipulation', () => { + tree.add(3); + tree.add(12); + tree.addMany(getRandomIntArray(100, 1, 100)) + tree.add(10); + + expect(tree.isPerfectlyBalanced()).toBe(true); + const node3 = tree.getNode(3); + + if (node3) node3.right = tree.createNode(1); + expect(tree.isPerfectlyBalanced()).toBe(false); + + tree.clear(); + tree.addMany([1, null, 2, null, 3, null, 4, null, 5, null, 6, null]); + expect(tree.isPerfectlyBalanced()).toBe(false); + }); + it('should getDepth return correct depth', () => { tree.add(1); expect(tree.getDepth(1)).toBe(0); @@ -480,10 +499,8 @@ describe('BinaryTree', () => { tree.add(7, 'C'); tree.iterationType = IterationType.ITERATIVE; - // @ts-ignore expect([...tree]).toEqual([3, 5, 7]); tree.iterationType = IterationType.RECURSIVE; - // @ts-ignore expect([...tree]).toEqual([3, 5, 7]); tree.iterationType = IterationType.ITERATIVE; diff --git a/test/unit/data-structures/linked-list/doubly-linked-list.test.ts b/test/unit/data-structures/linked-list/doubly-linked-list.test.ts index d715f6c..7ca69fa 100644 --- a/test/unit/data-structures/linked-list/doubly-linked-list.test.ts +++ b/test/unit/data-structures/linked-list/doubly-linked-list.test.ts @@ -54,7 +54,6 @@ describe('DoublyLinkedList Operation Test', () => { }); it('should insertAfter tail', () => { - // @ts-ignore expect([...list]).toEqual([1, 2, 3, 4, 5]); }); }); diff --git a/test/unit/data-structures/linked-list/singly-linked-list.test.ts b/test/unit/data-structures/linked-list/singly-linked-list.test.ts index 008b16b..a80fb87 100644 --- a/test/unit/data-structures/linked-list/singly-linked-list.test.ts +++ b/test/unit/data-structures/linked-list/singly-linked-list.test.ts @@ -441,7 +441,6 @@ describe('SinglyLinkedList', () => { list.push(3); const array = list.toArray(); expect(array).toEqual([1, 2, 3]); - // @ts-ignore expect([...list]).toEqual([1, 2, 3]); });