fix: #38 Removed includeNull parameter from traversal methods.

feat: Removed unnecessary methods isNotNodeInstance and subTreeTraverse.
refactor: Organized the overloads of traversal methods.
This commit is contained in:
Revone 2023-12-29 11:15:19 +08:00
parent 8fd35dd1f8
commit 34d4abd9e6
28 changed files with 410 additions and 369 deletions

View file

@ -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

View file

@ -15,7 +15,7 @@ export abstract class IterableEntryBase<K = any, V = any> {
* 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<K = any, V = any> {
* 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<K = any, V = any> {
*
* The function returns an iterator that yields the keys of a data structure.
*/
*keys(): IterableIterator<K> {
* keys(): IterableIterator<K> {
for (const item of this) {
yield item[0];
}
@ -62,7 +62,7 @@ export abstract class IterableEntryBase<K = any, V = any> {
*
* The function returns an iterator that yields the values of a collection.
*/
*values(): IterableIterator<V> {
* values(): IterableIterator<V> {
for (const item of this) {
yield item[1];
}
@ -212,7 +212,7 @@ export abstract class IterableElementBase<V> {
* 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<V> {
* [Symbol.iterator](...args: any[]): IterableIterator<V> {
yield* this._getIterator(...args);
}
@ -226,7 +226,7 @@ export abstract class IterableElementBase<V> {
*
* The function returns an iterator that yields all the values in the object.
*/
*values(): IterableIterator<V> {
* values(): IterableIterator<V> {
for (const item of this) {
yield item;
}

View file

@ -40,14 +40,13 @@ export class AVLTreeNode<K = any, V = any, N extends AVLTreeNode<K, V, N> = 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<K, V, N> = AVLTreeNode<K, V, AVLTreeNodeNested<K, V>>,
TREE extends AVLTree<K, V, N, TREE> = AVLTree<K, V, N, AVLTreeNested<K, V, N>>
>
K = any,
V = any,
N extends AVLTreeNode<K, V, N> = AVLTreeNode<K, V, AVLTreeNodeNested<K, V>>,
TREE extends AVLTree<K, V, N, TREE> = AVLTree<K, V, N, AVLTreeNested<K, V, N>>
>
extends BST<K, V, N, TREE>
implements IBinaryTree<K, V, N, TREE>
{
implements IBinaryTree<K, V, N, TREE> {
/**
* The constructor function initializes an AVLTree object with optional keysOrNodesOrEntries and options.
* @param [keysOrNodesOrEntries] - The `keysOrNodesOrEntries` parameter is an optional iterable of `KeyOrNodeOrEntry<K, V, N>`
@ -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<K, V, N>): 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) {

View file

@ -101,14 +101,13 @@ export class BinaryTreeNode<
*/
export class BinaryTree<
K = any,
V = any,
N extends BinaryTreeNode<K, V, N> = BinaryTreeNode<K, V, BinaryTreeNodeNested<K, V>>,
TREE extends BinaryTree<K, V, N, TREE> = BinaryTree<K, V, N, BinaryTreeNested<K, V, N>>
>
K = any,
V = any,
N extends BinaryTreeNode<K, V, N> = BinaryTreeNode<K, V, BinaryTreeNodeNested<K, V>>,
TREE extends BinaryTree<K, V, N, TREE> = BinaryTree<K, V, N, BinaryTreeNested<K, V, N>>
>
extends IterableEntryBase<K, V | undefined>
implements IBinaryTree<K, V, N, TREE>
{
implements IBinaryTree<K, V, N, TREE> {
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<K, V, N>): 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<K, V, N>, isReverse = true): N[] {
getPathToRoot(beginNode: KeyOrNodeOrEntry<K, V, N>, 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<C extends BTNCallback<N>>(
callback?: C,
beginRoot?: KeyOrNodeOrEntry<K, V, N>,
iterationType?: IterationType,
includeNull?: false
): ReturnType<C>[];
subTreeTraverse<C extends BTNCallback<N>>(
callback?: C,
beginRoot?: KeyOrNodeOrEntry<K, V, N>,
iterationType?: IterationType,
includeNull?: undefined
): ReturnType<C>[];
subTreeTraverse<C extends BTNCallback<N | null | undefined>>(
callback?: C,
beginRoot?: KeyOrNodeOrEntry<K, V, N>,
iterationType?: IterationType,
includeNull?: true
): ReturnType<C>[];
/**
* 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<C extends BTNCallback<N | null | undefined>>(
callback: C = this._defaultOneParamCallback as C,
beginRoot: KeyOrNodeOrEntry<K, V, N> = this.root,
iterationType = this.iterationType,
includeNull = false
): ReturnType<C>[] {
beginRoot = this.ensureNode(beginRoot);
const ans: (ReturnType<BTNCallback<N>> | 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<C extends BTNCallback<N>>(
// callback?: C,
// beginRoot?: KeyOrNodeOrEntry<K, V, N>,
// iterationType?: IterationType,
// includeNull?: false
// ): ReturnType<C>[];
//
// subTreeTraverse<C extends BTNCallback<N | null>>(
// callback?: C,
// beginRoot?: KeyOrNodeOrEntry<K, V, N>,
// iterationType?: IterationType,
// includeNull?: true
// ): ReturnType<C>[];
//
// /**
// * 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<C extends BTNCallback<N | null | undefined>>(
// callback: C = this._defaultOneParamCallback as C,
// beginRoot: KeyOrNodeOrEntry<K, V, N> = this.root,
// iterationType = this.iterationType,
// includeNull = false
// ): ReturnType<C>[] {
// console.warn('subTreeTraverse is unnecessary, since the dfs method can substitute it.');
//
// beginRoot = this.ensureNode(beginRoot);
//
// const ans: (ReturnType<BTNCallback<N>> | 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<C extends BTNCallback<N>>(
callback?: C,
@ -1305,15 +1289,7 @@ export class BinaryTree<
includeNull?: false
): ReturnType<C>[];
dfs<C extends BTNCallback<N>>(
callback?: C,
pattern?: DFSOrderPattern,
beginRoot?: KeyOrNodeOrEntry<K, V, N>,
iterationType?: IterationType,
includeNull?: undefined
): ReturnType<C>[];
dfs<C extends BTNCallback<N | null | undefined>>(
dfs<C extends BTNCallback<N | null>>(
callback?: C,
pattern?: DFSOrderPattern,
beginRoot?: KeyOrNodeOrEntry<K, V, N>,
@ -1451,14 +1427,7 @@ export class BinaryTree<
includeNull?: false
): ReturnType<C>[];
bfs<C extends BTNCallback<N>>(
callback?: C,
beginRoot?: KeyOrNodeOrEntry<K, V, N>,
iterationType?: IterationType,
includeNull?: undefined
): ReturnType<C>[];
bfs<C extends BTNCallback<N | null | undefined>>(
bfs<C extends BTNCallback<N | null>>(
callback?: C,
beginRoot?: KeyOrNodeOrEntry<K, V, N>,
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<C extends BTNCallback<N | null | undefined>>(
bfs<C extends BTNCallback<N | null>>(
callback: C = this._defaultOneParamCallback as C,
beginRoot: KeyOrNodeOrEntry<K, V, N> = this.root,
iterationType = this.iterationType,
@ -1552,14 +1521,7 @@ export class BinaryTree<
includeNull?: false
): ReturnType<C>[][];
listLevels<C extends BTNCallback<N>>(
callback?: C,
beginRoot?: KeyOrNodeOrEntry<K, V, N>,
iterationType?: IterationType,
includeNull?: undefined
): ReturnType<C>[][];
listLevels<C extends BTNCallback<N | null | undefined>>(
listLevels<C extends BTNCallback<N | null>>(
callback?: C,
beginRoot?: KeyOrNodeOrEntry<K, V, N>,
iterationType?: IterationType,
@ -1587,7 +1549,7 @@ export class BinaryTree<
* be excluded
* @returns The function `listLevels` returns a two-dimensional array of type `ReturnType<C>[][]`.
*/
listLevels<C extends BTNCallback<N | null | undefined>>(
listLevels<C extends BTNCallback<N | null>>(
callback: C = this._defaultOneParamCallback as C,
beginRoot: KeyOrNodeOrEntry<K, V, N> = 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) {

View file

@ -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<K = any, V = any, N extends BSTNode<K, V, N> = BSTNodeNeste
* 7. No Auto-Balancing: Standard BSTs don't automatically balance themselves.
*/
export class BST<
K = any,
V = any,
N extends BSTNode<K, V, N> = BSTNode<K, V, BSTNodeNested<K, V>>,
TREE extends BST<K, V, N, TREE> = BST<K, V, N, BSTNested<K, V, N>>
>
K = any,
V = any,
N extends BSTNode<K, V, N> = BSTNode<K, V, BSTNodeNested<K, V>>,
TREE extends BST<K, V, N, TREE> = BST<K, V, N, BSTNested<K, V, N>>
>
extends BinaryTree<K, V, N, TREE>
implements IBinaryTree<K, V, N, TREE>
{
implements IBinaryTree<K, V, N, TREE> {
/**
* 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<K, V, N>): 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<K, V, N>`.
@ -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<K, V, N> = 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<C extends BTNCallback<N>>(
// callback: C = this._defaultOneParamCallback as C,
// beginRoot: KeyOrNodeOrEntry<K, V, N> = this.root,
// iterationType = this.iterationType
// ): ReturnType<C>[] {
// 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<C extends BTNCallback<N>>(
callback: C = this._defaultOneParamCallback as C,
pattern: DFSOrderPattern = 'in',
beginRoot: KeyOrNodeOrEntry<K, V, N> = this.root,
iterationType: IterationType = IterationType.ITERATIVE
): ReturnType<C>[] {
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<C extends BTNCallback<N>>(
callback: C = this._defaultOneParamCallback as C,
beginRoot: KeyOrNodeOrEntry<K, V, N> = this.root,
iterationType = this.iterationType
): ReturnType<C>[] {
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<N>`. 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<C extends BTNCallback<N>>(
callback: C = this._defaultOneParamCallback as C,
beginRoot: KeyOrNodeOrEntry<K, V, N> = this.root,
iterationType = this.iterationType
): ReturnType<C>[][] {
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<K, V, N> = 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)

View file

@ -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<K, V, N> = RedBlackTreeNode<K, V, RedBlackTreeNodeNested<K, V>>,
TREE extends RedBlackTree<K, V, N, TREE> = RedBlackTree<K, V, N, RedBlackTreeNested<K, V, N>>
>
K = any,
V = any,
N extends RedBlackTreeNode<K, V, N> = RedBlackTreeNode<K, V, RedBlackTreeNodeNested<K, V>>,
TREE extends RedBlackTree<K, V, N, TREE> = RedBlackTree<K, V, N, RedBlackTreeNested<K, V, N>>
>
extends BST<K, V, N, TREE>
implements IBinaryTree<K, V, N, TREE>
{
implements IBinaryTree<K, V, N, TREE> {
Sentinel: N = new RedBlackTreeNode<K, V>(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<K, V, N>): potentialKey is K {
return !(potentialKey instanceof RedBlackTreeNode);
}
/**
* Time Complexity: O(log n)
* Space Complexity: O(1)

View file

@ -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<K, V, N> = TreeMultimapNode<K, V, TreeMultimapNodeNested<K, V>>,
TREE extends TreeMultimap<K, V, N, TREE> = TreeMultimap<K, V, N, TreeMultimapNested<K, V, N>>
>
K = any,
V = any,
N extends TreeMultimapNode<K, V, N> = TreeMultimapNode<K, V, TreeMultimapNodeNested<K, V>>,
TREE extends TreeMultimap<K, V, N, TREE> = TreeMultimap<K, V, N, TreeMultimapNested<K, V, N>>
>
extends AVLTree<K, V, N, TREE>
implements IBinaryTree<K, V, N, TREE>
{
implements IBinaryTree<K, V, N, TREE> {
constructor(keysOrNodesOrEntries: Iterable<KeyOrNodeOrEntry<K, V, N>> = [], options?: TreeMultimapOptions<K>) {
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<K, V, N>): potentialKey is K {
return !(potentialKey instanceof TreeMultimapNode);
}
/**
* Time Complexity: O(log n)
* Space Complexity: O(1)

View file

@ -61,14 +61,13 @@ export abstract class AbstractEdge<E = any> {
}
export abstract class AbstractGraph<
V = any,
E = any,
VO extends AbstractVertex<V> = AbstractVertex<V>,
EO extends AbstractEdge<E> = AbstractEdge<E>
>
V = any,
E = any,
VO extends AbstractVertex<V> = AbstractVertex<V>,
EO extends AbstractEdge<E> = AbstractEdge<E>
>
extends IterableEntryBase<VertexKey, V | undefined>
implements IGraph<V, E, VO, EO>
{
implements IGraph<V, E, VO, EO> {
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];
}

View file

@ -46,14 +46,13 @@ export class DirectedEdge<E = any> extends AbstractEdge<E> {
}
export class DirectedGraph<
V = any,
E = any,
VO extends DirectedVertex<V> = DirectedVertex<V>,
EO extends DirectedEdge<E> = DirectedEdge<E>
>
V = any,
E = any,
VO extends DirectedVertex<V> = DirectedVertex<V>,
EO extends DirectedEdge<E> = DirectedEdge<E>
>
extends AbstractGraph<V, E, VO, EO>
implements IGraph<V, E, VO, EO>
{
implements IGraph<V, E, VO, EO> {
/**
* The constructor function initializes an instance of a class.
*/

View file

@ -43,14 +43,13 @@ export class UndirectedEdge<E = number> extends AbstractEdge<E> {
}
export class UndirectedGraph<
V = any,
E = any,
VO extends UndirectedVertex<V> = UndirectedVertex<V>,
EO extends UndirectedEdge<E> = UndirectedEdge<E>
>
V = any,
E = any,
VO extends UndirectedVertex<V> = UndirectedVertex<V>,
EO extends UndirectedEdge<E> = UndirectedEdge<E>
>
extends AbstractGraph<V, E, VO, EO>
implements IGraph<V, E, VO, EO>
{
implements IGraph<V, E, VO, EO> {
/**
* The constructor initializes a new Map object to store edgeMap.
*/

View file

@ -24,24 +24,6 @@ import { isWeakKey, rangeCheck } from '../../utils';
export class HashMap<K = any, V = any, R = [K, V]> extends IterableEntryBase<K, V> {
protected _store: { [key: string]: HashMapStoreItem<K, V> } = {};
protected _objMap: Map<object, V> = 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<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
}
}
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;
}
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<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
* The function returns an iterator that yields key-value pairs from both an object store and an
* object map.
*/
protected *_getIterator(): IterableIterator<[K, V]> {
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<K = any, V = any> extends IterableEntryBase<K, V> {
/**
* 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<K = any, V = any> extends IterableEntryBase<K, V> {
* 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<K = any, V = any> extends IterableEntryBase<K, V> {
*
* 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];

View file

@ -391,7 +391,7 @@ export class Heap<E = any> extends IterableElementBase<E> {
return mappedHeap;
}
protected *_getIterator(): IterableIterator<E> {
protected* _getIterator(): IterableIterator<E> {
for (const element of this.elements) {
yield element;
}

View file

@ -808,7 +808,7 @@ export class DoublyLinkedList<E = any> extends IterableElementBase<E> {
/**
* The function returns an iterator that iterates over the values of a linked list.
*/
protected *_getIterator(): IterableIterator<E> {
protected* _getIterator(): IterableIterator<E> {
let current = this.head;
while (current) {

View file

@ -741,7 +741,7 @@ export class SinglyLinkedList<E = any> extends IterableElementBase<E> {
return mappedList;
}
protected *_getIterator(): IterableIterator<E> {
protected* _getIterator(): IterableIterator<E> {
let current = this.head;
while (current) {

View file

@ -232,7 +232,7 @@ export class Deque<E> extends IterableElementBase<E> {
/**
* The below function is a generator that yields elements from a collection one by one.
*/
*begin(): Generator<E> {
* begin(): Generator<E> {
let index = 0;
while (index < this.size) {
yield this.getAt(index);
@ -244,7 +244,7 @@ export class Deque<E> extends IterableElementBase<E> {
* The function `reverseBegin()` is a generator that yields elements in reverse order starting from
* the last element.
*/
*reverseBegin(): Generator<E> {
* reverseBegin(): Generator<E> {
let index = this.size - 1;
while (index >= 0) {
yield this.getAt(index);
@ -735,7 +735,7 @@ export class Deque<E> extends IterableElementBase<E> {
* 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<E> {
protected* _getIterator(): IterableIterator<E> {
for (let i = 0; i < this.size; ++i) {
yield this.getAt(i);
}

View file

@ -345,7 +345,7 @@ export class Queue<E = any> extends IterableElementBase<E> {
* Space Complexity: O(n)
*/
protected *_getIterator(): IterableIterator<E> {
protected* _getIterator(): IterableIterator<E> {
for (const item of this.elements) {
yield item;
}

View file

@ -229,7 +229,7 @@ export class Stack<E = any> extends IterableElementBase<E> {
* Custom iterator for the Stack class.
* @returns An iterator object.
*/
protected *_getIterator(): IterableIterator<E> {
protected* _getIterator(): IterableIterator<E> {
for (let i = 0; i < this.elements.length; i++) {
yield this.elements[i];
}

View file

@ -410,7 +410,7 @@ export class Trie extends IterableElementBase<string> {
return newTrie;
}
protected *_getIterator(): IterableIterator<string> {
protected* _getIterator(): IterableIterator<string> {
function* _dfs(node: TrieNode, path: string): IterableIterator<string> {
if (node.isEnd) {
yield path;

View file

@ -2,12 +2,12 @@ export type VertexKey = string | number;
export type DijkstraResult<V> =
| {
distMap: Map<V, number>;
distPaths?: Map<V, V[]>;
preMap: Map<V, V | undefined>;
seen: Set<V>;
paths: V[][];
minDist: number;
minPath: V[];
}
distMap: Map<V, number>;
distPaths?: Map<V, V[]>;
preMap: Map<V, V | undefined>;
seen: Set<V>;
paths: V[][];
minDist: number;
minPath: V[];
}
| undefined;

View file

@ -4,8 +4,8 @@
<meta charset='UTF-8'>
<title>CDN Test</title>
<!-- <script src="../../dist/umd/data-structure-typed.min.js"></script>-->
<script src="../../dist/umd/data-structure-typed.js"></script>
<!-- <script src='https://cdn.jsdelivr.net/npm/data-structure-typed/dist/umd/data-structure-typed.min.js'></script>-->
<script src="../../dist/umd/data-structure-typed.js"></script>
<!-- <script src='https://cdn.jsdelivr.net/npm/data-structure-typed/dist/umd/data-structure-typed.min.js'></script>-->
<!-- <script src='https://cdn.jsdelivr.net/npm/data-structure-typed@1.42.2/dist/umd/data-structure-typed.min.js'></script>-->
<!-- <script src='https://cdn.jsdelivr.net/npm/data-structure-typed@1.43.3/dist/umd/data-structure-typed.min.js'></script>-->
<!-- <script src='https://cdn.jsdelivr.net/npm/data-structure-typed@1.44.0/dist/umd/data-structure-typed.min.js'></script>-->

View file

@ -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<number>();
@ -20,6 +20,12 @@ if (isCompetitor) {
}
suite
.add(`${TEN_THOUSAND.toLocaleString()} push & delete`, () => {
const _deque = new Deque<number>();
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<number>();

View file

@ -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;

View file

@ -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', () => {

View file

@ -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]);
});
});

View file

@ -96,7 +96,7 @@ describe('TreeMultimap operations test1', () => {
expect(minNodeBySpecificNode?.key).toBe(15);
let subTreeSum = 0;
node15 && treeMultimap.subTreeTraverse((node: TreeMultimapNode<number>) => (subTreeSum += node.key), 15);
node15 && treeMultimap.dfs(node => (subTreeSum += node.key), 'pre', 15);
expect(subTreeSum).toBe(31);
let lesserSum = 0;
treeMultimap.lesserOrGreaterTraverse((node: TreeMultimapNode<number>) => (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<number>) => (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<number>) => (subTreeSum += node.key), 15);
node15 && treeMultimap.dfs(node => (subTreeSum += node.key), 'pre', 15);
expect(subTreeSum).toBe(31);
let lesserSum = 0;
treeMultimap.lesserOrGreaterTraverse((node: TreeMultimapNode<number>) => (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<number>) => (node.count += 1), 15);
const subTreeAdd = treeMultimap.dfs(node => (node.count += 1), 'pre', 15);
expect(subTreeAdd);
}
const node11 = treeMultimap.getNode(11);

View file

@ -85,7 +85,8 @@ class MyGraph<
describe('AbstractGraph Operation Test', () => {
const myGraph: MyGraph<number, string> = new MyGraph<number, string>();
beforeEach(() => {});
beforeEach(() => {
});
it('should edge cases', function () {
myGraph.addVertex('A', 1);
myGraph.addVertex('B', 2);

View file

@ -110,6 +110,8 @@ describe('HashMap Test2', () => {
test('Inheritability test', () => {
class ExtendedHashMap<K, V> extends HashMap<K, V> {
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;
}
}

View file

@ -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<number>;