From 34d4abd9e678f07ffbd30e19ddff806fcacb5f51 Mon Sep 17 00:00:00 2001 From: Revone Date: Fri, 29 Dec 2023 11:15:19 +0800 Subject: [PATCH] fix: #38 Removed includeNull parameter from traversal methods. feat: Removed unnecessary methods isNotNodeInstance and subTreeTraverse. refactor: Organized the overloads of traversal methods. --- CHANGELOG.md | 2 +- src/data-structures/base/iterable-base.ts | 12 +- src/data-structures/binary-tree/avl-tree.ts | 25 +- .../binary-tree/binary-tree.ts | 260 ++++++++---------- src/data-structures/binary-tree/bst.ts | 191 +++++++++---- src/data-structures/binary-tree/rb-tree.ts | 25 +- .../binary-tree/tree-multimap.ts | 27 +- src/data-structures/graph/abstract-graph.ts | 29 +- src/data-structures/graph/directed-graph.ts | 13 +- src/data-structures/graph/undirected-graph.ts | 13 +- src/data-structures/hash/hash-map.ts | 45 +-- src/data-structures/heap/heap.ts | 2 +- .../linked-list/doubly-linked-list.ts | 2 +- .../linked-list/singly-linked-list.ts | 2 +- src/data-structures/queue/deque.ts | 6 +- src/data-structures/queue/queue.ts | 2 +- src/data-structures/stack/stack.ts | 2 +- src/data-structures/trie/trie.ts | 2 +- .../data-structures/graph/abstract-graph.ts | 16 +- test/integration/index.html | 4 +- .../data-structures/queue/deque.test.ts | 10 +- .../binary-tree/avl-tree.test.ts | 4 +- .../binary-tree/binary-tree.test.ts | 47 +++- .../data-structures/binary-tree/bst.test.ts | 20 +- .../binary-tree/tree-multimap.test.ts | 8 +- .../graph/abstract-graph.test.ts | 3 +- .../data-structures/hash/hash-map.test.ts | 4 +- test/unit/data-structures/queue/deque.test.ts | 3 +- 28 files changed, 410 insertions(+), 369 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7eb556..6721045 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.49.8](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming) +## [v1.49.9](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming) ### Changes diff --git a/src/data-structures/base/iterable-base.ts b/src/data-structures/base/iterable-base.ts index cf015bc..b9333e0 100644 --- a/src/data-structures/base/iterable-base.ts +++ b/src/data-structures/base/iterable-base.ts @@ -15,7 +15,7 @@ export abstract class IterableEntryBase { * allows the function to accept any number of arguments as an array. In this case, the `args` * parameter is used to pass any additional arguments to the `_getIterator` method. */ - *[Symbol.iterator](...args: any[]): IterableIterator<[K, V]> { + * [Symbol.iterator](...args: any[]): IterableIterator<[K, V]> { yield* this._getIterator(...args); } @@ -30,7 +30,7 @@ export abstract class IterableEntryBase { * The function returns an iterator that yields key-value pairs from the object, where the value can * be undefined. */ - *entries(): IterableIterator<[K, V | undefined]> { + * entries(): IterableIterator<[K, V | undefined]> { for (const item of this) { yield item; } @@ -46,7 +46,7 @@ export abstract class IterableEntryBase { * * The function returns an iterator that yields the keys of a data structure. */ - *keys(): IterableIterator { + * keys(): IterableIterator { for (const item of this) { yield item[0]; } @@ -62,7 +62,7 @@ export abstract class IterableEntryBase { * * The function returns an iterator that yields the values of a collection. */ - *values(): IterableIterator { + * values(): IterableIterator { for (const item of this) { yield item[1]; } @@ -212,7 +212,7 @@ export abstract class IterableElementBase { * allows the function to accept any number of arguments as an array. In this case, the `args` * parameter is used to pass any number of arguments to the `_getIterator` method. */ - *[Symbol.iterator](...args: any[]): IterableIterator { + * [Symbol.iterator](...args: any[]): IterableIterator { yield* this._getIterator(...args); } @@ -226,7 +226,7 @@ export abstract class IterableElementBase { * * The function returns an iterator that yields all the values in the object. */ - *values(): IterableIterator { + * values(): IterableIterator { for (const item of this) { yield item; } diff --git a/src/data-structures/binary-tree/avl-tree.ts b/src/data-structures/binary-tree/avl-tree.ts index 647a671..026b2ae 100644 --- a/src/data-structures/binary-tree/avl-tree.ts +++ b/src/data-structures/binary-tree/avl-tree.ts @@ -40,14 +40,13 @@ export class AVLTreeNode = AVLT * 7. Path Length: The path length from the root to any leaf is longer compared to an unbalanced BST, but shorter than a linear chain of nodes. */ export class AVLTree< - K = any, - V = any, - N extends AVLTreeNode = AVLTreeNode>, - TREE extends AVLTree = AVLTree> - > + K = any, + V = any, + N extends AVLTreeNode = AVLTreeNode>, + TREE extends AVLTree = AVLTree> +> extends BST - implements IBinaryTree -{ + implements IBinaryTree { /** * The constructor function initializes an AVLTree object with optional keysOrNodesOrEntries and options. * @param [keysOrNodesOrEntries] - The `keysOrNodesOrEntries` parameter is an optional iterable of `KeyOrNodeOrEntry` @@ -99,16 +98,6 @@ export class AVLTree< return keyOrNodeOrEntry instanceof AVLTreeNode; } - /** - * The function "isNotNodeInstance" checks if a potential key is a K. - * @param {any} potentialKey - The potentialKey parameter is of type any, which means it can be any - * data type. - * @returns a boolean value indicating whether the potentialKey is of type number or not. - */ - override isNotNodeInstance(potentialKey: KeyOrNodeOrEntry): potentialKey is K { - return !(potentialKey instanceof AVLTreeNode); - } - /** * Time Complexity: O(log n) * Space Complexity: O(1) @@ -278,7 +267,7 @@ export class AVLTree< // Balance Restoration: If a balance issue is discovered after inserting a node, it requires balance restoration operations. Balance restoration includes four basic cases where rotation operations need to be performed to fix the balance: switch ( this._balanceFactor(A) // second O(1) - ) { + ) { case -2: if (A && A.left) { if (this._balanceFactor(A.left) <= 0) { diff --git a/src/data-structures/binary-tree/binary-tree.ts b/src/data-structures/binary-tree/binary-tree.ts index 939bb00..88c3a89 100644 --- a/src/data-structures/binary-tree/binary-tree.ts +++ b/src/data-structures/binary-tree/binary-tree.ts @@ -101,14 +101,13 @@ export class BinaryTreeNode< */ export class BinaryTree< - K = any, - V = any, - N extends BinaryTreeNode = BinaryTreeNode>, - TREE extends BinaryTree = BinaryTree> - > + K = any, + V = any, + N extends BinaryTreeNode = BinaryTreeNode>, + TREE extends BinaryTree = BinaryTree> +> extends IterableEntryBase - implements IBinaryTree -{ + implements IBinaryTree { iterationType = IterationType.ITERATIVE; /** @@ -197,7 +196,7 @@ export class BinaryTree< } } else if (this.isNode(keyOrNodeOrEntry)) { node = keyOrNodeOrEntry; - } else if (this.isNotNodeInstance(keyOrNodeOrEntry)) { + } else if (!this.isNode(keyOrNodeOrEntry)) { node = this.createNode(keyOrNodeOrEntry, value); } else { return; @@ -293,16 +292,6 @@ export class BinaryTree< return this.isRealNode(node) || node === null; } - /** - * The function "isNotNodeInstance" checks if a potential key is a K. - * @param {any} potentialKey - The potentialKey parameter is of type any, which means it can be any - * data type. - * @returns a boolean value indicating whether the potentialKey is of type number or not. - */ - isNotNodeInstance(potentialKey: KeyOrNodeOrEntry): potentialKey is K { - return !(potentialKey instanceof BinaryTreeNode); - } - /** * Time Complexity O(log n) - O(n) * Space Complexity O(1) @@ -1029,7 +1018,7 @@ export class BinaryTree< * * The function `getPathToRoot` returns an array of nodes from a given node to the root of a tree * structure, with the option to reverse the order of the nodes. - * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the + * @param {K | N | null | undefined} beginNode - The `beginRoot` parameter represents the * starting node from which you want to find the path to the root. It can be of type `K`, `N`, * `null`, or `undefined`. * @param [isReverse=true] - The `isReverse` parameter is a boolean flag that determines whether the @@ -1037,20 +1026,20 @@ export class BinaryTree< * 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: KeyOrNodeOrEntry, isReverse = true): N[] { + getPathToRoot(beginNode: KeyOrNodeOrEntry, isReverse = true): N[] { // TODO to support get path through passing key const result: N[] = []; - beginRoot = this.ensureNode(beginRoot); + beginNode = this.ensureNode(beginNode); - if (!beginRoot) return result; + if (!beginNode) return result; - while (beginRoot.parent) { + while (beginNode.parent) { // Array.push + Array.reverse is more efficient than Array.unshift // TODO may consider using Deque, so far this is not the performance bottleneck - result.push(beginRoot); - beginRoot = beginRoot.parent; + result.push(beginNode); + beginNode = beginNode.parent; } - result.push(beginRoot); + result.push(beginNode); return isReverse ? result.reverse() : result; } @@ -1203,99 +1192,94 @@ export class BinaryTree< } } - /** - * Time complexity: O(n) - * Space complexity: O(log n) - */ - - subTreeTraverse>( - callback?: C, - beginRoot?: KeyOrNodeOrEntry, - iterationType?: IterationType, - includeNull?: false - ): ReturnType[]; - - subTreeTraverse>( - callback?: C, - beginRoot?: KeyOrNodeOrEntry, - iterationType?: IterationType, - includeNull?: undefined - ): ReturnType[]; - - subTreeTraverse>( - callback?: C, - beginRoot?: KeyOrNodeOrEntry, - iterationType?: IterationType, - includeNull?: true - ): ReturnType[]; - - /** - * 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 {C} callback - The `callback` parameter is a function that will be called for each node in - * the subtree traversal. It takes a single parameter, which is the current node being traversed, and - * returns a value of any type. - * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the - * starting node or key from which the subtree traversal should begin. It can be of type `K`, - * `N`, `null`, or `undefined`. If not provided, the `root` property of the current object is used as - * the default value. - * @param iterationType - The `iterationType` parameter determines the type of traversal to be - * performed on the subtree. It can have two possible values: - * @param [includeNull=false] - The `includeNull` parameter is a boolean value that determines - * whether 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 nodes is determined - * by the return type of the `callback` function. - */ - subTreeTraverse>( - callback: C = this._defaultOneParamCallback as C, - beginRoot: KeyOrNodeOrEntry = this.root, - iterationType = this.iterationType, - includeNull = false - ): ReturnType[] { - beginRoot = this.ensureNode(beginRoot); - - const ans: (ReturnType> | null | undefined)[] = []; - if (!beginRoot) return ans; - - if (iterationType === IterationType.RECURSIVE) { - const _traverse = (cur: N | null | undefined) => { - if (cur !== undefined) { - ans.push(callback(cur)); - if (includeNull) { - cur && this.isNodeOrNull(cur.left) && _traverse(cur.left); - cur && this.isNodeOrNull(cur.right) && _traverse(cur.right); - } else { - cur && cur.left && _traverse(cur.left); - cur && cur.right && _traverse(cur.right); - } - } - }; - - _traverse(beginRoot); - } else { - const stack: (N | null | undefined)[] = [beginRoot]; - - while (stack.length > 0) { - const cur = stack.pop(); - if (cur !== undefined) { - ans.push(callback(cur)); - if (includeNull) { - cur && this.isNodeOrNull(cur.right) && stack.push(cur.right); - cur && this.isNodeOrNull(cur.left) && stack.push(cur.left); - } else { - cur && cur.right && stack.push(cur.right); - cur && cur.left && stack.push(cur.left); - } - } - } - } - return ans; - } + // /** + // * Time complexity: O(n) + // * Space complexity: O(log n) + // */ + // + // subTreeTraverse>( + // callback?: C, + // beginRoot?: KeyOrNodeOrEntry, + // iterationType?: IterationType, + // includeNull?: false + // ): ReturnType[]; + // + // subTreeTraverse>( + // callback?: C, + // beginRoot?: KeyOrNodeOrEntry, + // iterationType?: IterationType, + // includeNull?: true + // ): ReturnType[]; + // + // /** + // * 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 {C} callback - The `callback` parameter is a function that will be called for each node in + // * the subtree traversal. It takes a single parameter, which is the current node being traversed, and + // * returns a value of any type. + // * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the + // * starting node or key from which the subtree traversal should begin. It can be of type `K`, + // * `N`, `null`, or `undefined`. If not provided, the `root` property of the current object is used as + // * the default value. + // * @param iterationType - The `iterationType` parameter determines the type of traversal to be + // * performed on the subtree. It can have two possible values: + // * @param [includeNull=false] - The `includeNull` parameter is a boolean value that determines + // * whether 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 nodes is determined + // * by the return type of the `callback` function. + // */ + // subTreeTraverse>( + // callback: C = this._defaultOneParamCallback as C, + // beginRoot: KeyOrNodeOrEntry = this.root, + // iterationType = this.iterationType, + // includeNull = false + // ): ReturnType[] { + // console.warn('subTreeTraverse is unnecessary, since the dfs method can substitute it.'); + // + // beginRoot = this.ensureNode(beginRoot); + // + // const ans: (ReturnType> | null | undefined)[] = []; + // if (!beginRoot) return ans; + // + // if (iterationType === IterationType.RECURSIVE) { + // const _traverse = (cur: N | null | undefined) => { + // if (cur !== undefined) { + // ans.push(callback(cur)); + // if (includeNull) { + // cur && this.isNodeOrNull(cur.left) && _traverse(cur.left); + // cur && this.isNodeOrNull(cur.right) && _traverse(cur.right); + // } else { + // cur && cur.left && _traverse(cur.left); + // cur && cur.right && _traverse(cur.right); + // } + // } + // }; + // + // _traverse(beginRoot); + // } else { + // const stack: (N | null | undefined)[] = [beginRoot]; + // + // while (stack.length > 0) { + // const cur = stack.pop(); + // if (cur !== undefined) { + // ans.push(callback(cur)); + // if (includeNull) { + // cur && this.isNodeOrNull(cur.right) && stack.push(cur.right); + // cur && this.isNodeOrNull(cur.left) && stack.push(cur.left); + // } else { + // cur && cur.right && stack.push(cur.right); + // cur && cur.left && stack.push(cur.left); + // } + // } + // } + // } + // return ans; + // } dfs>( callback?: C, @@ -1305,15 +1289,7 @@ export class BinaryTree< includeNull?: false ): ReturnType[]; - dfs>( - callback?: C, - pattern?: DFSOrderPattern, - beginRoot?: KeyOrNodeOrEntry, - iterationType?: IterationType, - includeNull?: undefined - ): ReturnType[]; - - dfs>( + dfs>( callback?: C, pattern?: DFSOrderPattern, beginRoot?: KeyOrNodeOrEntry, @@ -1451,14 +1427,7 @@ export class BinaryTree< includeNull?: false ): ReturnType[]; - bfs>( - callback?: C, - beginRoot?: KeyOrNodeOrEntry, - iterationType?: IterationType, - includeNull?: undefined - ): ReturnType[]; - - bfs>( + bfs>( callback?: C, beginRoot?: KeyOrNodeOrEntry, iterationType?: IterationType, @@ -1486,7 +1455,7 @@ export class BinaryTree< * @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>( + bfs>( callback: C = this._defaultOneParamCallback as C, beginRoot: KeyOrNodeOrEntry = this.root, iterationType = this.iterationType, @@ -1552,14 +1521,7 @@ export class BinaryTree< includeNull?: false ): ReturnType[][]; - listLevels>( - callback?: C, - beginRoot?: KeyOrNodeOrEntry, - iterationType?: IterationType, - includeNull?: undefined - ): ReturnType[][]; - - listLevels>( + listLevels>( callback?: C, beginRoot?: KeyOrNodeOrEntry, iterationType?: IterationType, @@ -1587,7 +1549,7 @@ export class BinaryTree< * be excluded * @returns The function `listLevels` returns a two-dimensional array of type `ReturnType[][]`. */ - listLevels>( + listLevels>( callback: C = this._defaultOneParamCallback as C, beginRoot: KeyOrNodeOrEntry = this.root, iterationType = this.iterationType, @@ -1598,7 +1560,7 @@ export class BinaryTree< if (!beginRoot) return levelsNodes; if (iterationType === IterationType.RECURSIVE) { - const _recursive = (node: N | null | undefined, level: number) => { + const _recursive = (node: N | null, level: number) => { if (!levelsNodes[level]) levelsNodes[level] = []; levelsNodes[level].push(callback(node)); if (includeNull) { @@ -1612,7 +1574,7 @@ export class BinaryTree< _recursive(beginRoot, 0); } else { - const stack: [N | null | undefined, number][] = [[beginRoot, 0]]; + const stack: [N | null, number][] = [[beginRoot, 0]]; while (stack.length > 0) { const head = stack.pop()!; @@ -1923,7 +1885,7 @@ export class BinaryTree< display(beginRoot); } - protected *_getIterator(node = this.root): IterableIterator<[K, V | undefined]> { + protected* _getIterator(node = this.root): IterableIterator<[K, V | undefined]> { if (!node) return; if (this.iterationType === IterationType.ITERATIVE) { diff --git a/src/data-structures/binary-tree/bst.ts b/src/data-structures/binary-tree/bst.ts index 35f881d..27be108 100644 --- a/src/data-structures/binary-tree/bst.ts +++ b/src/data-structures/binary-tree/bst.ts @@ -13,7 +13,7 @@ import type { BTNodePureExemplar, KeyOrNodeOrEntry } from '../../types'; -import { BSTVariant, CP, IterationType } from '../../types'; +import { BSTVariant, CP, DFSOrderPattern, IterationType } from '../../types'; import { BinaryTree, BinaryTreeNode } from './binary-tree'; import { IBinaryTree } from '../../interfaces'; import { Queue } from '../queue'; @@ -83,14 +83,13 @@ export class BSTNode = BSTNodeNeste * 7. No Auto-Balancing: Standard BSTs don't automatically balance themselves. */ export class BST< - K = any, - V = any, - N extends BSTNode = BSTNode>, - TREE extends BST = BST> - > + K = any, + V = any, + N extends BSTNode = BSTNode>, + TREE extends BST = BST> +> extends BinaryTree - implements IBinaryTree -{ + implements IBinaryTree { /** * This is the constructor function for a binary search tree class in TypeScript, which initializes * the tree with optional keysOrNodesOrEntries and options. @@ -172,7 +171,7 @@ export class BST< } else { node = this.createNode(key, value); } - } else if (this.isNotNodeInstance(keyOrNodeOrEntry)) { + } else if (!this.isNode(keyOrNodeOrEntry)) { node = this.createNode(keyOrNodeOrEntry, value); } else { return; @@ -213,16 +212,6 @@ export class BST< return res; } - /** - * The function "isNotNodeInstance" checks if a potential key is a K. - * @param {any} potentialKey - The potentialKey parameter is of type any, which means it can be any - * data type. - * @returns a boolean value indicating whether the potentialKey is of type number or not. - */ - override isNotNodeInstance(potentialKey: KeyOrNodeOrEntry): potentialKey is K { - return !(potentialKey instanceof BSTNode); - } - /** * The function checks if an keyOrNodeOrEntry is an instance of BSTNode. * @param keyOrNodeOrEntry - The `keyOrNodeOrEntry` parameter is a variable of type `KeyOrNodeOrEntry`. @@ -408,43 +397,6 @@ export class BST< return inserted; } - /** - * Time Complexity: O(n log n) - * Space Complexity: O(n) - * Adding each element individually in a balanced tree. Additional space is required for the sorted array. - */ - - /** - * Time Complexity: O(n log n) - * Space Complexity: O(n) - * - * The `lastKey` function returns the key of the rightmost node in a binary tree, or the key of the - * leftmost node if the comparison result is greater than. - * @param {K | N | undefined} beginRoot - The `beginRoot` parameter is optional and can be of - * type `K`, `N`, or `undefined`. It represents the starting point for finding the last key in - * the binary tree. If not provided, it defaults to the root of the binary tree (`this.root`). - * @returns the key of the rightmost node in the binary tree 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. If no node is found, it returns 0. - */ - lastKey(beginRoot: KeyOrNodeOrEntry = this.root): K | undefined { - let current = this.ensureNode(beginRoot); - if (!current) return undefined; - - if (this._variant === BSTVariant.STANDARD) { - // For BSTVariant.MIN, find the rightmost node - while (current.right !== undefined) { - current = current.right; - } - } else { - // For BSTVariant.MAX, find the leftmost node - while (current.left !== undefined) { - current = current.left; - } - } - return current.key; - } - /** * Time Complexity: O(log n) * Space Complexity: O(1) @@ -574,6 +526,133 @@ export class BST< return ans; } + // /** + // * The function overrides the subTreeTraverse method and returns the result of calling the super + // * method with the provided arguments. + // * @param {C} callback - The `callback` parameter is a function that will be called for each node in + // * the subtree traversal. It should accept a single parameter of type `N`, which represents a node in + // * the tree. The return type of the callback function can be any type. + // * @param beginRoot - The `beginRoot` parameter is the starting point for traversing the subtree. It + // * can be either a key, a node, or an entry. + // * @param iterationType - The `iterationType` parameter is used to specify the type of iteration to + // * be performed during the traversal of the subtree. It can have one of the following values: + // * @returns The method is returning an array of the return type of the callback function. + // */ + // override subTreeTraverse>( + // callback: C = this._defaultOneParamCallback as C, + // beginRoot: KeyOrNodeOrEntry = this.root, + // iterationType = this.iterationType + // ): ReturnType[] { + // return super.subTreeTraverse(callback, beginRoot, iterationType, false); + // } + + /** + * The function overrides the depth-first search method and returns an array of the return types of + * the callback function. + * @param {C} callback - The `callback` parameter is a function that will be called for each node + * during the depth-first search traversal. It is an optional parameter and if not provided, a + * default callback function will be used. + * @param {DFSOrderPattern} [pattern=in] - The `pattern` parameter specifies the order in which the + * nodes are visited during the depth-first search. It can have one of the following values: + * @param beginRoot - The `beginRoot` parameter is used to specify the starting point for the + * Depth-First Search (DFS) traversal. It can be either a key, a node, or an entry in the tree. If no + * value is provided, the DFS traversal will start from the root of the tree. + * @param {IterationType} iterationType - The `iterationType` parameter specifies the type of + * iteration to be used during the Depth-First Search (DFS) traversal. It can have one of the + * following values: + * @returns The method is returning an array of the return type of the callback function. + */ + override dfs>( + callback: C = this._defaultOneParamCallback as C, + pattern: DFSOrderPattern = 'in', + beginRoot: KeyOrNodeOrEntry = this.root, + iterationType: IterationType = IterationType.ITERATIVE + ): ReturnType[] { + return super.dfs(callback, pattern, beginRoot, iterationType, false); + } + + /** + * The function overrides the breadth-first search method and returns an array of the return types of + * the callback function. + * @param {C} callback - The `callback` parameter is a function that will be called for each node + * visited during the breadth-first search traversal. It is an optional parameter and if not + * provided, a default callback function will be used. + * @param beginRoot - The `beginRoot` parameter is the starting point for the breadth-first search + * traversal. It can be either a key, a node, or an entry in the tree. If not specified, the root of + * the tree is used as the starting point. + * @param iterationType - The `iterationType` parameter is used to specify the type of iteration to + * be performed during the breadth-first search (BFS) traversal. It determines the order in which the + * nodes are visited. + * @returns The method is returning an array of the return type of the callback function. + */ + override bfs>( + callback: C = this._defaultOneParamCallback as C, + beginRoot: KeyOrNodeOrEntry = this.root, + iterationType = this.iterationType + ): ReturnType[] { + return super.bfs(callback, beginRoot, iterationType, false); + } + + /** + * The function overrides the listLevels method and returns an array of arrays containing the return + * type of the callback function for each level of the tree. + * @param {C} callback - The `callback` parameter is a generic type `C` that extends + * `BTNCallback`. It represents a callback function that will be called for each node in the tree + * during the level listing process. + * @param beginRoot - The `beginRoot` parameter is used to specify the starting point for listing the + * levels of a binary tree. It can be either a key, a node, or an entry in the binary tree. If not + * provided, the root of the binary tree is used as the starting point. + * @param iterationType - The `iterationType` parameter is used to specify the type of iteration to + * be performed on the tree. It determines the order in which the nodes are visited during the + * iteration. + * @returns The method is returning a two-dimensional array of the return type of the callback + * function. + */ + override listLevels>( + callback: C = this._defaultOneParamCallback as C, + beginRoot: KeyOrNodeOrEntry = this.root, + iterationType = this.iterationType + ): ReturnType[][] { + return super.listLevels(callback, beginRoot, iterationType, false); + } + + /** + * Time Complexity: O(n log n) + * Space Complexity: O(n) + * Adding each element individually in a balanced tree. Additional space is required for the sorted array. + */ + + /** + * Time Complexity: O(n log n) + * Space Complexity: O(n) + * + * The `lastKey` function returns the key of the rightmost node in a binary tree, or the key of the + * leftmost node if the comparison result is greater than. + * @param {K | N | undefined} beginRoot - The `beginRoot` parameter is optional and can be of + * type `K`, `N`, or `undefined`. It represents the starting point for finding the last key in + * the binary tree. If not provided, it defaults to the root of the binary tree (`this.root`). + * @returns the key of the rightmost node in the binary tree 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. If no node is found, it returns 0. + */ + lastKey(beginRoot: KeyOrNodeOrEntry = this.root): K | undefined { + let current = this.ensureNode(beginRoot); + if (!current) return undefined; + + if (this._variant === BSTVariant.STANDARD) { + // For BSTVariant.MIN, find the rightmost node + while (current.right !== undefined) { + current = current.right; + } + } else { + // For BSTVariant.MAX, find the leftmost node + while (current.left !== undefined) { + current = current.left; + } + } + return current.key; + } + /** * Time Complexity: O(log n) * Space Complexity: O(log n) diff --git a/src/data-structures/binary-tree/rb-tree.ts b/src/data-structures/binary-tree/rb-tree.ts index 2e311c5..2ba0ee9 100644 --- a/src/data-structures/binary-tree/rb-tree.ts +++ b/src/data-structures/binary-tree/rb-tree.ts @@ -41,14 +41,13 @@ export class RedBlackTreeNode< * 5. Black balance: Every path from any node to each of its leaf nodes contains the same number of black nodes. */ export class RedBlackTree< - K = any, - V = any, - N extends RedBlackTreeNode = RedBlackTreeNode>, - TREE extends RedBlackTree = RedBlackTree> - > + K = any, + V = any, + N extends RedBlackTreeNode = RedBlackTreeNode>, + TREE extends RedBlackTree = RedBlackTree> +> extends BST - implements IBinaryTree -{ + implements IBinaryTree { Sentinel: N = new RedBlackTreeNode(NaN as K) as unknown as N; /** @@ -133,7 +132,7 @@ export class RedBlackTree< } else { node = this.createNode(key, value, RBTNColor.RED); } - } else if (this.isNotNodeInstance(keyOrNodeOrEntry)) { + } else if (!this.isNode(keyOrNodeOrEntry)) { node = this.createNode(keyOrNodeOrEntry, value, RBTNColor.RED); } else { return; @@ -161,16 +160,6 @@ export class RedBlackTree< return node instanceof RedBlackTreeNode; } - /** - * The function "isNotNodeInstance" checks if a potential key is a K. - * @param {any} potentialKey - The potentialKey parameter is of type any, which means it can be any - * data type. - * @returns a boolean value indicating whether the potentialKey is of type number or not. - */ - override isNotNodeInstance(potentialKey: KeyOrNodeOrEntry): potentialKey is K { - return !(potentialKey instanceof RedBlackTreeNode); - } - /** * Time Complexity: O(log n) * Space Complexity: O(1) diff --git a/src/data-structures/binary-tree/tree-multimap.ts b/src/data-structures/binary-tree/tree-multimap.ts index 61e444d..f7dea55 100644 --- a/src/data-structures/binary-tree/tree-multimap.ts +++ b/src/data-structures/binary-tree/tree-multimap.ts @@ -45,14 +45,13 @@ export class TreeMultimapNode< * The only distinction between a TreeMultimap and a AVLTree lies in the ability of the former to store duplicate nodes through the utilization of counters. */ export class TreeMultimap< - K = any, - V = any, - N extends TreeMultimapNode = TreeMultimapNode>, - TREE extends TreeMultimap = TreeMultimap> - > + K = any, + V = any, + N extends TreeMultimapNode = TreeMultimapNode>, + TREE extends TreeMultimap = TreeMultimap> +> extends AVLTree - implements IBinaryTree -{ + implements IBinaryTree { constructor(keysOrNodesOrEntries: Iterable> = [], options?: TreeMultimapOptions) { super([], options); if (keysOrNodesOrEntries) this.addMany(keysOrNodesOrEntries); @@ -63,7 +62,7 @@ export class TreeMultimap< // TODO the _count is not accurate after nodes count modified get count(): number { let sum = 0; - this.subTreeTraverse(node => (sum += node.count)); + this.dfs(node => (sum += node.count)); return sum; } @@ -112,7 +111,7 @@ export class TreeMultimap< } else { node = this.createNode(key, value, count); } - } else if (this.isNotNodeInstance(keyOrNodeOrEntry)) { + } else if (!this.isNode(keyOrNodeOrEntry)) { node = this.createNode(keyOrNodeOrEntry, value, count); } else { return; @@ -130,16 +129,6 @@ export class TreeMultimap< return keyOrNodeOrEntry instanceof TreeMultimapNode; } - /** - * The function "isNotNodeInstance" checks if a potential key is a K. - * @param {any} potentialKey - The potentialKey parameter is of type any, which means it can be any - * data type. - * @returns a boolean value indicating whether the potentialKey is of type number or not. - */ - override isNotNodeInstance(potentialKey: KeyOrNodeOrEntry): potentialKey is K { - return !(potentialKey instanceof TreeMultimapNode); - } - /** * Time Complexity: O(log n) * Space Complexity: O(1) diff --git a/src/data-structures/graph/abstract-graph.ts b/src/data-structures/graph/abstract-graph.ts index 25b192a..cb70033 100644 --- a/src/data-structures/graph/abstract-graph.ts +++ b/src/data-structures/graph/abstract-graph.ts @@ -61,14 +61,13 @@ export abstract class AbstractEdge { } export abstract class AbstractGraph< - V = any, - E = any, - VO extends AbstractVertex = AbstractVertex, - EO extends AbstractEdge = AbstractEdge - > + V = any, + E = any, + VO extends AbstractVertex = AbstractVertex, + EO extends AbstractEdge = AbstractEdge +> extends IterableEntryBase - implements IGraph -{ + implements IGraph { constructor() { super(); } @@ -611,14 +610,14 @@ export abstract class AbstractGraph< } getMinDist && - distMap.forEach((d, v) => { - if (v !== srcVertex) { - if (d < minDist) { - minDist = d; - if (genPaths) minDest = v; - } + distMap.forEach((d, v) => { + if (v !== srcVertex) { + if (d < minDist) { + minDist = d; + if (genPaths) minDest = v; } - }); + } + }); genPaths && getPaths(minDest); @@ -1273,7 +1272,7 @@ export abstract class AbstractGraph< return mapped; } - protected *_getIterator(): IterableIterator<[VertexKey, V | undefined]> { + protected* _getIterator(): IterableIterator<[VertexKey, V | undefined]> { for (const vertex of this._vertexMap.values()) { yield [vertex.key, vertex.value]; } diff --git a/src/data-structures/graph/directed-graph.ts b/src/data-structures/graph/directed-graph.ts index 71ecd98..f9c2ff0 100644 --- a/src/data-structures/graph/directed-graph.ts +++ b/src/data-structures/graph/directed-graph.ts @@ -46,14 +46,13 @@ export class DirectedEdge extends AbstractEdge { } export class DirectedGraph< - V = any, - E = any, - VO extends DirectedVertex = DirectedVertex, - EO extends DirectedEdge = DirectedEdge - > + V = any, + E = any, + VO extends DirectedVertex = DirectedVertex, + EO extends DirectedEdge = DirectedEdge +> extends AbstractGraph - implements IGraph -{ + implements IGraph { /** * The constructor function initializes an instance of a class. */ diff --git a/src/data-structures/graph/undirected-graph.ts b/src/data-structures/graph/undirected-graph.ts index acfa125..20cba16 100644 --- a/src/data-structures/graph/undirected-graph.ts +++ b/src/data-structures/graph/undirected-graph.ts @@ -43,14 +43,13 @@ export class UndirectedEdge extends AbstractEdge { } export class UndirectedGraph< - V = any, - E = any, - VO extends UndirectedVertex = UndirectedVertex, - EO extends UndirectedEdge = UndirectedEdge - > + V = any, + E = any, + VO extends UndirectedVertex = UndirectedVertex, + EO extends UndirectedEdge = UndirectedEdge +> extends AbstractGraph - implements IGraph -{ + implements IGraph { /** * The constructor initializes a new Map object to store edgeMap. */ diff --git a/src/data-structures/hash/hash-map.ts b/src/data-structures/hash/hash-map.ts index f0cedf1..dca1144 100644 --- a/src/data-structures/hash/hash-map.ts +++ b/src/data-structures/hash/hash-map.ts @@ -24,24 +24,6 @@ import { isWeakKey, rangeCheck } from '../../utils'; export class HashMap extends IterableEntryBase { protected _store: { [key: string]: HashMapStoreItem } = {}; protected _objMap: Map = new Map(); - protected _toEntryFn: (rawElement: R) => [K, V] = (rawElement: R) => { - if (this.isEntry(rawElement)) { - // TODO, For performance optimization, it may be necessary to only inspect the first element traversed. - return rawElement; - } else { - throw new Error( - "If the provided rawCollection does not adhere to the [key, value] type format, the toEntryFn in the constructor's options parameter needs to specified." - ); - } - }; - - get toEntryFn() { - return this._toEntryFn; - } - - isEntry(rawElement: any): rawElement is [K, V] { - return Array.isArray(rawElement) && rawElement.length === 2; - } /** * The constructor function initializes a HashMap object with an optional initial collection and @@ -66,12 +48,31 @@ export class HashMap extends IterableEntryBase [K, V] = (rawElement: R) => { + if (this.isEntry(rawElement)) { + // TODO, For performance optimization, it may be necessary to only inspect the first element traversed. + return rawElement; + } else { + throw new Error( + "If the provided rawCollection does not adhere to the [key, value] type format, the toEntryFn in the constructor's options parameter needs to specified." + ); + } + }; + + get toEntryFn() { + return this._toEntryFn; + } + protected _size = 0; get size(): number { return this._size; } + isEntry(rawElement: any): rawElement is [K, V] { + return Array.isArray(rawElement) && rawElement.length === 2; + } + isEmpty(): boolean { return this.size === 0; } @@ -248,7 +249,7 @@ export class HashMap extends IterableEntryBase { + protected* _getIterator(): IterableIterator<[K, V]> { for (const node of Object.values(this._store)) { yield [node.key, node.value] as [K, V]; } @@ -347,7 +348,7 @@ export class LinkedHashMap extends IterableEntryBase { /** * The `begin()` function in TypeScript iterates over a linked list and yields key-value pairs. */ - *begin() { + * begin() { let node = this._head; while (node !== this._sentinel) { yield [node.key, node.value]; @@ -359,7 +360,7 @@ export class LinkedHashMap extends IterableEntryBase { * The function `reverseBegin()` iterates over a linked list in reverse order, yielding each node's * key and value. */ - *reverseBegin() { + * reverseBegin() { let node = this._tail; while (node !== this._sentinel) { yield [node.key, node.value]; @@ -660,7 +661,7 @@ export class LinkedHashMap extends IterableEntryBase { * * The above function is an iterator that yields key-value pairs from a linked list. */ - protected *_getIterator() { + protected* _getIterator() { let node = this._head; while (node !== this._sentinel) { yield [node.key, node.value] as [K, V]; diff --git a/src/data-structures/heap/heap.ts b/src/data-structures/heap/heap.ts index d5391a3..8e2d9fe 100644 --- a/src/data-structures/heap/heap.ts +++ b/src/data-structures/heap/heap.ts @@ -391,7 +391,7 @@ export class Heap extends IterableElementBase { return mappedHeap; } - protected *_getIterator(): IterableIterator { + protected* _getIterator(): IterableIterator { for (const element of this.elements) { yield element; } diff --git a/src/data-structures/linked-list/doubly-linked-list.ts b/src/data-structures/linked-list/doubly-linked-list.ts index 757f41e..caaffc9 100644 --- a/src/data-structures/linked-list/doubly-linked-list.ts +++ b/src/data-structures/linked-list/doubly-linked-list.ts @@ -808,7 +808,7 @@ export class DoublyLinkedList extends IterableElementBase { /** * The function returns an iterator that iterates over the values of a linked list. */ - protected *_getIterator(): IterableIterator { + protected* _getIterator(): IterableIterator { let current = this.head; while (current) { diff --git a/src/data-structures/linked-list/singly-linked-list.ts b/src/data-structures/linked-list/singly-linked-list.ts index 13ec341..aa32809 100644 --- a/src/data-structures/linked-list/singly-linked-list.ts +++ b/src/data-structures/linked-list/singly-linked-list.ts @@ -741,7 +741,7 @@ export class SinglyLinkedList extends IterableElementBase { return mappedList; } - protected *_getIterator(): IterableIterator { + protected* _getIterator(): IterableIterator { let current = this.head; while (current) { diff --git a/src/data-structures/queue/deque.ts b/src/data-structures/queue/deque.ts index 744bb65..02aa162 100644 --- a/src/data-structures/queue/deque.ts +++ b/src/data-structures/queue/deque.ts @@ -232,7 +232,7 @@ export class Deque extends IterableElementBase { /** * The below function is a generator that yields elements from a collection one by one. */ - *begin(): Generator { + * begin(): Generator { let index = 0; while (index < this.size) { yield this.getAt(index); @@ -244,7 +244,7 @@ export class Deque extends IterableElementBase { * The function `reverseBegin()` is a generator that yields elements in reverse order starting from * the last element. */ - *reverseBegin(): Generator { + * reverseBegin(): Generator { let index = this.size - 1; while (index >= 0) { yield this.getAt(index); @@ -735,7 +735,7 @@ export class Deque extends IterableElementBase { * The above function is an implementation of the iterator protocol in TypeScript, allowing the * object to be iterated over using a for...of loop. */ - protected *_getIterator(): IterableIterator { + protected* _getIterator(): IterableIterator { for (let i = 0; i < this.size; ++i) { yield this.getAt(i); } diff --git a/src/data-structures/queue/queue.ts b/src/data-structures/queue/queue.ts index 3bcd1c6..1c2d4e7 100644 --- a/src/data-structures/queue/queue.ts +++ b/src/data-structures/queue/queue.ts @@ -345,7 +345,7 @@ export class Queue extends IterableElementBase { * Space Complexity: O(n) */ - protected *_getIterator(): IterableIterator { + protected* _getIterator(): IterableIterator { for (const item of this.elements) { yield item; } diff --git a/src/data-structures/stack/stack.ts b/src/data-structures/stack/stack.ts index c1775c7..63cabfa 100644 --- a/src/data-structures/stack/stack.ts +++ b/src/data-structures/stack/stack.ts @@ -229,7 +229,7 @@ export class Stack extends IterableElementBase { * Custom iterator for the Stack class. * @returns An iterator object. */ - protected *_getIterator(): IterableIterator { + protected* _getIterator(): IterableIterator { for (let i = 0; i < this.elements.length; i++) { yield this.elements[i]; } diff --git a/src/data-structures/trie/trie.ts b/src/data-structures/trie/trie.ts index cb4c0a3..d4a1eb9 100644 --- a/src/data-structures/trie/trie.ts +++ b/src/data-structures/trie/trie.ts @@ -410,7 +410,7 @@ export class Trie extends IterableElementBase { return newTrie; } - protected *_getIterator(): IterableIterator { + protected* _getIterator(): IterableIterator { function* _dfs(node: TrieNode, path: string): IterableIterator { if (node.isEnd) { yield path; diff --git a/src/types/data-structures/graph/abstract-graph.ts b/src/types/data-structures/graph/abstract-graph.ts index 32b6564..e799019 100644 --- a/src/types/data-structures/graph/abstract-graph.ts +++ b/src/types/data-structures/graph/abstract-graph.ts @@ -2,12 +2,12 @@ export type VertexKey = string | number; export type DijkstraResult = | { - distMap: Map; - distPaths?: Map; - preMap: Map; - seen: Set; - paths: V[][]; - minDist: number; - minPath: V[]; - } + distMap: Map; + distPaths?: Map; + preMap: Map; + seen: Set; + paths: V[][]; + minDist: number; + minPath: V[]; +} | undefined; diff --git a/test/integration/index.html b/test/integration/index.html index 4683997..ae19e7f 100644 --- a/test/integration/index.html +++ b/test/integration/index.html @@ -4,8 +4,8 @@ CDN Test - - + + diff --git a/test/performance/data-structures/queue/deque.test.ts b/test/performance/data-structures/queue/deque.test.ts index 31380d5..f1fda9c 100644 --- a/test/performance/data-structures/queue/deque.test.ts +++ b/test/performance/data-structures/queue/deque.test.ts @@ -1,11 +1,11 @@ import { Deque } from '../../../../src'; import { Deque as CDeque } from 'js-sdsl'; import * as Benchmark from 'benchmark'; -import { magnitude } from '../../../utils'; +import { getRandomInt, magnitude } from '../../../utils'; import { isCompetitor } from '../../../config'; export const suite = new Benchmark.Suite(); -const { MILLION, HUNDRED_THOUSAND } = magnitude; +const { MILLION, HUNDRED_THOUSAND, TEN_THOUSAND } = magnitude; suite.add(`${MILLION.toLocaleString()} push`, () => { const deque = new Deque(); @@ -20,6 +20,12 @@ if (isCompetitor) { } suite + .add(`${TEN_THOUSAND.toLocaleString()} push & delete`, () => { + const _deque = new Deque(); + + for (let i = 0; i < TEN_THOUSAND; i++) _deque.push(i); + for (let i = 0; i < TEN_THOUSAND; i++) _deque.delete(getRandomInt(0, TEN_THOUSAND - 1)); + }) .add(`${MILLION.toLocaleString()} push & pop`, () => { const _deque = new Deque(); 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 621d330..90f6921 100644 --- a/test/unit/data-structures/binary-tree/avl-tree.test.ts +++ b/test/unit/data-structures/binary-tree/avl-tree.test.ts @@ -24,7 +24,7 @@ describe('AVL Tree Test', () => { expect(getMinNodeBySpecificNode?.key).toBe(12); let subTreeSum = 0; - node15 && tree.subTreeTraverse(node => (subTreeSum += node.key), node15); + node15 && tree.dfs(node => (subTreeSum += node.key), 'pre', node15); expect(subTreeSum).toBe(70); let lesserSum = 0; @@ -132,7 +132,7 @@ describe('AVL Tree Test recursively', () => { expect(getMinNodeBySpecificNode?.key).toBe(12); let subTreeSum = 0; - node15 && tree.subTreeTraverse(node => (subTreeSum += node.key), node15); + node15 && tree.dfs(node => (subTreeSum += node.key), 'pre', node15); expect(subTreeSum).toBe(70); let lesserSum = 0; 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 e56ad69..dbbd02a 100644 --- a/test/unit/data-structures/binary-tree/binary-tree.test.ts +++ b/test/unit/data-structures/binary-tree/binary-tree.test.ts @@ -238,16 +238,45 @@ describe('BinaryTree', () => { expect(tree.getNodes(tree.getNodeByKey(2), undefined, false, tree.root)).toEqual([tree.getNodeByKey(2)]); }); - it('should subTreeTraverse', () => { + // it('should subTreeTraverse', () => { + // tree.addMany([4, 2, 6, null, 1, 3, null, 5, null, 7]); + // 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.ITERATIVE, false)).toEqual([6, 3, 7]); + // expect(tree.subTreeTraverse(node => node.key, tree.getNode(6), IterationType.RECURSIVE)).toEqual([6, 3, 7]); + // expect( + // tree.subTreeTraverse(node => (node ? node.key : null), tree.getNode(6), IterationType.ITERATIVE, true) + // ).toEqual([6, 3, 7, null]); + // expect( + // tree.subTreeTraverse(node => (node ? node.key : node), tree.getNode(6), IterationType.ITERATIVE, true) + // ).toEqual([6, 3, 7, null]); + // expect( + // tree.subTreeTraverse(node => (node ? node.key : null), tree.getNode(6), IterationType.RECURSIVE, true) + // ).toEqual([6, 3, 7, null]); + // }); + + it('should sub tree traverse', () => { tree.addMany([4, 2, 6, null, 1, 3, null, 5, null, 7]); - 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 ? node.key : null), tree.getNode(6), IterationType.ITERATIVE, true) - ).toEqual([6, 3, 7, null]); - expect( - tree.subTreeTraverse(node => (node ? node.key : null), tree.getNode(6), IterationType.RECURSIVE, true) - ).toEqual([6, 3, 7, null]); + expect(tree.dfs(node => node.key, 'pre', tree.getNode(6), IterationType.ITERATIVE)).toEqual([6, 3, 7]); + expect(tree.dfs(node => node.key, 'pre', tree.getNode(6), IterationType.ITERATIVE, false)).toEqual([6, 3, 7]); + expect(tree.dfs(node => node.key, 'pre', tree.getNode(6), IterationType.RECURSIVE)).toEqual([6, 3, 7]); + expect(tree.dfs(node => (node ? node.key : null), 'pre', tree.getNode(6), IterationType.ITERATIVE, true)).toEqual([ + 6, + 3, + 7, + null + ]); + expect(tree.dfs(node => (node ? node.key : node), 'pre', tree.getNode(6), IterationType.ITERATIVE, true)).toEqual([ + 6, + 3, + 7, + null + ]); + expect(tree.dfs(node => (node ? node.key : null), 'pre', tree.getNode(6), IterationType.RECURSIVE, true)).toEqual([ + 6, + 3, + 7, + null + ]); }); it('should clear the tree', () => { diff --git a/test/unit/data-structures/binary-tree/bst.test.ts b/test/unit/data-structures/binary-tree/bst.test.ts index 32a69ba..0680666 100644 --- a/test/unit/data-structures/binary-tree/bst.test.ts +++ b/test/unit/data-structures/binary-tree/bst.test.ts @@ -54,7 +54,7 @@ describe('BST operations test', () => { expect(minNodeBySpecificNode?.key).toBe(12); let subTreeSum = 0; - node15 && bst.subTreeTraverse(node => (subTreeSum += node.key), 15); + node15 && bst.dfs(node => (subTreeSum += node.key), 'pre', 15); expect(subTreeSum).toBe(70); let lesserSum = 0; @@ -257,7 +257,7 @@ describe('BST operations test', () => { expect(minNodeBySpecificNode?.key).toBe(12); let subTreeSum = 0; - node15 && objBST.subTreeTraverse(node => (subTreeSum += node.key), node15); + node15 && objBST.dfs(node => (subTreeSum += node.key), 'pre', node15); expect(subTreeSum).toBe(70); let lesserSum = 0; @@ -444,7 +444,7 @@ describe('BST operations test recursively', () => { expect(minNodeBySpecificNode?.key).toBe(12); let subTreeSum = 0; - node15 && bst.subTreeTraverse(node => (subTreeSum += node.key), 15); + node15 && bst.dfs(node => (subTreeSum += node.key), 'pre', 15); expect(subTreeSum).toBe(70); let lesserSum = 0; @@ -645,7 +645,7 @@ describe('BST operations test recursively', () => { expect(minNodeBySpecificNode?.key).toBe(12); let subTreeSum = 0; - node15 && objBST.subTreeTraverse(node => (subTreeSum += node.key), node15); + node15 && objBST.dfs(node => (subTreeSum += node.key), 'pre', node15); expect(subTreeSum).toBe(70); let lesserSum = 0; @@ -868,14 +868,10 @@ describe('BST Performance test', function () { it('should subTreeTraverse, null should be ignored', () => { const bst = new BST(); 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?.key ?? undefined, bst.getNode(6), IterationType.ITERATIVE, true)).toEqual([ - 6, 5, 7 - ]); - expect(bst.subTreeTraverse(node => node?.key ?? undefined, bst.getNode(6), IterationType.RECURSIVE, true)).toEqual([ - 6, 5, 7 - ]); + expect(bst.dfs(node => node.key, 'pre', bst.getNode(6), IterationType.ITERATIVE)).toEqual([6, 5, 7]); + expect(bst.dfs(node => node.key, 'pre', bst.getNode(6), IterationType.RECURSIVE)).toEqual([6, 5, 7]); + expect(bst.dfs(node => node?.key ?? undefined, 'pre', bst.getNode(6), IterationType.ITERATIVE)).toEqual([6, 5, 7]); + expect(bst.dfs(node => node?.key ?? undefined, 'pre', bst.getNode(6), IterationType.RECURSIVE)).toEqual([6, 5, 7]); }); }); diff --git a/test/unit/data-structures/binary-tree/tree-multimap.test.ts b/test/unit/data-structures/binary-tree/tree-multimap.test.ts index 1d35031..02c314b 100644 --- a/test/unit/data-structures/binary-tree/tree-multimap.test.ts +++ b/test/unit/data-structures/binary-tree/tree-multimap.test.ts @@ -96,7 +96,7 @@ describe('TreeMultimap operations test1', () => { expect(minNodeBySpecificNode?.key).toBe(15); let subTreeSum = 0; - node15 && treeMultimap.subTreeTraverse((node: TreeMultimapNode) => (subTreeSum += node.key), 15); + node15 && treeMultimap.dfs(node => (subTreeSum += node.key), 'pre', 15); expect(subTreeSum).toBe(31); let lesserSum = 0; treeMultimap.lesserOrGreaterTraverse((node: TreeMultimapNode) => (lesserSum += node.key), CP.lt, 10); @@ -104,7 +104,7 @@ describe('TreeMultimap operations test1', () => { expect(node15 instanceof TreeMultimapNode); if (node15 instanceof TreeMultimapNode) { - const subTreeAdd = treeMultimap.subTreeTraverse((node: TreeMultimapNode) => (node.count += 1), 15); + const subTreeAdd = treeMultimap.dfs(node => (node.count += 1), 'pre', 15); expect(subTreeAdd); } const node11 = treeMultimap.getNode(11); @@ -350,7 +350,7 @@ describe('TreeMultimap operations test recursively1', () => { expect(minNodeBySpecificNode?.key).toBe(15); let subTreeSum = 0; - node15 && treeMultimap.subTreeTraverse((node: TreeMultimapNode) => (subTreeSum += node.key), 15); + node15 && treeMultimap.dfs(node => (subTreeSum += node.key), 'pre', 15); expect(subTreeSum).toBe(31); let lesserSum = 0; treeMultimap.lesserOrGreaterTraverse((node: TreeMultimapNode) => (lesserSum += node.key), CP.lt, 10); @@ -358,7 +358,7 @@ describe('TreeMultimap operations test recursively1', () => { expect(node15 instanceof TreeMultimapNode); if (node15 instanceof TreeMultimapNode) { - const subTreeAdd = treeMultimap.subTreeTraverse((node: TreeMultimapNode) => (node.count += 1), 15); + const subTreeAdd = treeMultimap.dfs(node => (node.count += 1), 'pre', 15); expect(subTreeAdd); } const node11 = treeMultimap.getNode(11); diff --git a/test/unit/data-structures/graph/abstract-graph.test.ts b/test/unit/data-structures/graph/abstract-graph.test.ts index 7f54d21..6c634b6 100644 --- a/test/unit/data-structures/graph/abstract-graph.test.ts +++ b/test/unit/data-structures/graph/abstract-graph.test.ts @@ -85,7 +85,8 @@ class MyGraph< describe('AbstractGraph Operation Test', () => { const myGraph: MyGraph = new MyGraph(); - beforeEach(() => {}); + beforeEach(() => { + }); it('should edge cases', function () { myGraph.addVertex('A', 1); myGraph.addVertex('B', 2); diff --git a/test/unit/data-structures/hash/hash-map.test.ts b/test/unit/data-structures/hash/hash-map.test.ts index edad1ca..5e492f0 100644 --- a/test/unit/data-structures/hash/hash-map.test.ts +++ b/test/unit/data-structures/hash/hash-map.test.ts @@ -110,6 +110,8 @@ describe('HashMap Test2', () => { test('Inheritability test', () => { class ExtendedHashMap extends HashMap { + someOtherParam?: string; + constructor( elements: Iterable<[K, V]> = [], options?: { @@ -118,8 +120,8 @@ describe('HashMap Test2', () => { } ) { const { someOtherParam, ...restOptions } = options || {}; - // do something with someOtherParam super(elements, restOptions); + this.someOtherParam = someOtherParam; } } diff --git a/test/unit/data-structures/queue/deque.test.ts b/test/unit/data-structures/queue/deque.test.ts index e08d4f1..b5830bb 100644 --- a/test/unit/data-structures/queue/deque.test.ts +++ b/test/unit/data-structures/queue/deque.test.ts @@ -114,7 +114,8 @@ describe('Deque - Complex Operations', () => { expect([...deque]).toEqual([1, 2, 3]); }); - test('shrinkToFit should reduce the memory footprint', () => {}); + test('shrinkToFit should reduce the memory footprint', () => { + }); }); describe('Deque - Utility Operations', () => { let deque: Deque;