mirror of
https://github.com/zrwusa/data-structure-typed.git
synced 2024-11-23 12:54:04 +00:00
1. No need for dfsIterative; integrate it directly into the dfs method. 2. Allow for public configuration of setLoopType. 3. Replace subTreeAdd with subTreeForeach for improved clarity and flexibility; provide a callback for enhanced versatility. 4. Standardize the naming of certain methods and parameters.
This commit is contained in:
parent
cb56b04af5
commit
a6329163f7
|
@ -641,6 +641,14 @@ Array.from(dijkstraResult?.seen ?? []).map(vertex => vertex.id) // ['A', 'B', 'D
|
|||
|
||||
## Code design
|
||||
|
||||
### Adhere to ES6 standard naming conventions for APIs.
|
||||
|
||||
Standardize API conventions by using 'add' and 'delete' for element manipulation methods in all data structures.
|
||||
|
||||
Opt for concise and clear method names, avoiding excessive length while ensuring explicit intent.
|
||||
|
||||
### Object-oriented programming(OOP)
|
||||
|
||||
By strictly adhering to object-oriented design (BinaryTree -> BST -> AVLTree -> TreeMultiset), you can seamlessly
|
||||
inherit the existing data structures to implement the customized ones you need. Object-oriented design stands as the
|
||||
optimal approach to data structure design.
|
||||
|
|
|
@ -33,13 +33,13 @@ export class AVLTree<N extends AVLTreeNode<N['val'], N> = AVLTreeNode> extends B
|
|||
}
|
||||
|
||||
/**
|
||||
* The `swapLocation` function swaps the location of two nodes in a binary tree.
|
||||
* @param {N} srcNode - The source node that you want to swap with the destination node.
|
||||
* The `_swap` function swaps the location of two nodes in a binary tree.
|
||||
* @param {N} srcNode - The source node that you want to _swap with the destination node.
|
||||
* @param {N} destNode - The `destNode` parameter represents the destination node where the values from `srcNode` will
|
||||
* be swapped to.
|
||||
* @returns The `destNode` is being returned.
|
||||
*/
|
||||
override swapLocation(srcNode: N, destNode: N): N {
|
||||
protected override _swap(srcNode: N, destNode: N): N {
|
||||
const {key, val, height} = destNode;
|
||||
const tempNode = this.createNode(key, val);
|
||||
|
||||
|
@ -85,14 +85,14 @@ export class AVLTree<N extends AVLTreeNode<N['val'], N> = AVLTreeNode> extends B
|
|||
}
|
||||
|
||||
/**
|
||||
* The function overrides the remove method of a binary tree and performs additional operations to balance the tree after
|
||||
* The function overrides the delete method of a binary tree and performs additional operations to balance the tree after
|
||||
* deletion.
|
||||
* @param {BinaryTreeNodeKey} key - The `key` parameter represents the identifier of the binary tree node that needs to be
|
||||
* removed.
|
||||
* @returns The method is returning an array of `BinaryTreeDeletedResult<N>` objects.
|
||||
*/
|
||||
override remove(key: BinaryTreeNodeKey): BinaryTreeDeletedResult<N>[] {
|
||||
const deletedResults = super.remove(key);
|
||||
override delete(key: BinaryTreeNodeKey): BinaryTreeDeletedResult<N>[] {
|
||||
const deletedResults = super.delete(key);
|
||||
for (const {needBalanced} of deletedResults) {
|
||||
if (needBalanced) {
|
||||
this._balancePath(needBalanced);
|
||||
|
|
|
@ -145,6 +145,10 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|||
return this._loopType;
|
||||
}
|
||||
|
||||
set loopType(v: LoopType) {
|
||||
this._loopType = v;
|
||||
}
|
||||
|
||||
visitedKey: BinaryTreeNodeKey[] = [];
|
||||
|
||||
visitedVal: N['val'][] = [];
|
||||
|
@ -152,13 +156,13 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|||
visitedNode: N[] = [];
|
||||
|
||||
/**
|
||||
* The `swapLocation` function swaps the location of two nodes in a binary tree.
|
||||
* @param {N} srcNode - The source node that you want to swap with the destination node.
|
||||
* The `_swap` function swaps the location of two nodes in a binary tree.
|
||||
* @param {N} srcNode - The source node that you want to _swap with the destination node.
|
||||
* @param {N} destNode - The `destNode` parameter represents the destination node where the values from `srcNode` will
|
||||
* be swapped to.
|
||||
* @returns The `destNode` is being returned.
|
||||
*/
|
||||
swapLocation(srcNode: N, destNode: N): N {
|
||||
protected _swap(srcNode: N, destNode: N): N {
|
||||
const {key, val} = destNode;
|
||||
const tempNode = this.createNode(key, val);
|
||||
|
||||
|
@ -300,13 +304,13 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|||
}
|
||||
|
||||
/**
|
||||
* The `remove` function in TypeScript is used to delete a node from a binary search tree and returns an array of objects
|
||||
* The `delete` function in TypeScript is used to delete a node from a binary search tree and returns an array of objects
|
||||
* containing the deleted node and the node that needs to be balanced.
|
||||
* @param {N | BinaryTreeNodeKey} nodeOrKey - The `nodeOrKey` parameter can be either a node object (`N`) or a binary tree
|
||||
* node ID (`BinaryTreeNodeKey`).
|
||||
* @returns The function `remove` returns an array of `BinaryTreeDeletedResult<N>` objects.
|
||||
* @returns The function `delete` returns an array of `BinaryTreeDeletedResult<N>` objects.
|
||||
*/
|
||||
remove(nodeOrKey: N | BinaryTreeNodeKey): BinaryTreeDeletedResult<N>[] {
|
||||
delete(nodeOrKey: N | BinaryTreeNodeKey): BinaryTreeDeletedResult<N>[] {
|
||||
const bstDeletedResult: BinaryTreeDeletedResult<N>[] = [];
|
||||
if (!this.root) return bstDeletedResult;
|
||||
|
||||
|
@ -333,7 +337,7 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|||
const leftSubTreeRightMost = curr.left ? this.getRightMost(curr.left) : null;
|
||||
if (leftSubTreeRightMost) {
|
||||
const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;
|
||||
orgCurrent = this.swapLocation(curr, leftSubTreeRightMost);
|
||||
orgCurrent = this._swap(curr, leftSubTreeRightMost);
|
||||
if (parentOfLeftSubTreeMax) {
|
||||
if (parentOfLeftSubTreeMax.right === leftSubTreeRightMost)
|
||||
parentOfLeftSubTreeMax.right = leftSubTreeRightMost.left;
|
||||
|
@ -683,12 +687,12 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|||
|
||||
/**
|
||||
* The function checks if a binary search tree is valid by traversing it either recursively or iteratively.
|
||||
* @param {N | null} node - The `node` parameter represents the root node of a binary search tree (BST).
|
||||
* @param {N | null} subTreeRoot - The `node` parameter represents the root node of a binary search tree (BST).
|
||||
* @returns a boolean value.
|
||||
*/
|
||||
isSubtreeBST(node: N | null): boolean {
|
||||
isSubtreeBST(subTreeRoot: N | null): boolean {
|
||||
// TODO there is a bug
|
||||
if (!node) return true;
|
||||
if (!subTreeRoot) return true;
|
||||
|
||||
if (this._loopType === LoopType.RECURSIVE) {
|
||||
const dfs = (cur: N | null | undefined, min: BinaryTreeNodeKey, max: BinaryTreeNodeKey): boolean => {
|
||||
|
@ -697,11 +701,11 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|||
return dfs(cur.left, min, cur.key) && dfs(cur.right, cur.key, max);
|
||||
};
|
||||
|
||||
return dfs(node, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);
|
||||
return dfs(subTreeRoot, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);
|
||||
} else {
|
||||
const stack = [];
|
||||
let prev = Number.MIN_SAFE_INTEGER,
|
||||
curr: N | null | undefined = node;
|
||||
curr: N | null | undefined = subTreeRoot;
|
||||
while (curr || stack.length > 0) {
|
||||
while (curr) {
|
||||
stack.push(curr);
|
||||
|
@ -813,38 +817,21 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|||
}
|
||||
|
||||
/**
|
||||
* The function `subTreeAdd` adds a delta value to a specified property of each node in a subtree.
|
||||
* The function `subTreeForeach` adds a delta value to a specified property of each node in a subtree.
|
||||
* @param {N | BinaryTreeNodeKey | null} subTreeRoot - The `subTreeRoot` parameter represents the root node of a binary
|
||||
* tree or the ID of a node in the binary tree. It can also be `null` if there is no subtree to add to.
|
||||
* @param {number} delta - The `delta` parameter is a number that represents the amount by which the property value of
|
||||
* each node in the subtree should be incremented.
|
||||
* @param {BinaryTreeNodePropertyName} [propertyName] - The `propertyName` parameter is an optional parameter that
|
||||
* @param callBack - The `callBack` parameter is a function that takes a node as a parameter and returns a number.
|
||||
* specifies the property of the binary tree node that should be modified. If not provided, it defaults to 'key'.
|
||||
* @returns a boolean value.
|
||||
*/
|
||||
subTreeAdd(
|
||||
subTreeRoot: N | BinaryTreeNodeKey | null,
|
||||
delta: number,
|
||||
propertyName: BinaryTreeNodePropertyName = 'key'
|
||||
): boolean {
|
||||
subTreeForeach(subTreeRoot: N | BinaryTreeNodeKey | null, callback: (node: N) => any): boolean {
|
||||
if (typeof subTreeRoot === 'number') subTreeRoot = this.get(subTreeRoot, 'key');
|
||||
|
||||
if (!subTreeRoot) return false;
|
||||
|
||||
const _addByProperty = (cur: N) => {
|
||||
switch (propertyName) {
|
||||
case 'key':
|
||||
cur.key += delta;
|
||||
break;
|
||||
default:
|
||||
cur.key += delta;
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
if (this._loopType === LoopType.RECURSIVE) {
|
||||
const _traverse = (cur: N) => {
|
||||
_addByProperty(cur);
|
||||
callback(cur);
|
||||
cur.left && _traverse(cur.left);
|
||||
cur.right && _traverse(cur.right);
|
||||
};
|
||||
|
@ -856,7 +843,7 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|||
while (stack.length > 0) {
|
||||
const cur = stack.pop()!;
|
||||
|
||||
_addByProperty(cur);
|
||||
callback(cur);
|
||||
cur.right && stack.push(cur.right);
|
||||
cur.left && stack.push(cur.left);
|
||||
}
|
||||
|
@ -903,6 +890,7 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|||
const queue: Array<N | null | undefined> = [this.root];
|
||||
|
||||
while (queue.length !== 0) {
|
||||
// TODO Array.shift is not efficient, consider using Deque
|
||||
const cur = queue.shift();
|
||||
if (cur) {
|
||||
this._accumulatedByPropertyName(cur, nodeOrPropertyName);
|
||||
|
@ -931,222 +919,107 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|||
* Performs a depth-first search (dfs) traversal on a binary tree and accumulates properties of each node based on the specified property name.
|
||||
* @param {'in' | 'pre' | 'post'} [pattern] - The traversal pattern: 'in' (in-order), 'pre' (pre-order), or 'post' (post-order).
|
||||
* @param {string} nodeOrPropertyName - The name of the property to accumulate.
|
||||
* @param loopType - The type of loop to use for the depth-first search traversal. The default value is `LoopType.ITERATIVE`.
|
||||
* @returns An array of values corresponding to the specified property.
|
||||
*/
|
||||
dfs(pattern: DFSOrderPattern, nodeOrPropertyName: 'key'): BinaryTreeNodeKey[];
|
||||
dfs(pattern: DFSOrderPattern, nodeOrPropertyName: 'key', loopType?: LoopType): BinaryTreeNodeKey[];
|
||||
|
||||
/**
|
||||
* Performs a depth-first search (dfs) traversal on a binary tree and accumulates the 'val' property of each node.
|
||||
* @param {'in' | 'pre' | 'post'} [pattern] - The traversal pattern: 'in' (in-order), 'pre' (pre-order), or 'post' (post-order).
|
||||
* @param {'val'} nodeOrPropertyName - The name of the property to accumulate.
|
||||
* @param loopType - The type of loop to use for the depth-first search traversal. The default value is `LoopType.ITERATIVE`.
|
||||
* @returns An array of 'val' properties from each node.
|
||||
*/
|
||||
dfs(pattern: DFSOrderPattern, nodeOrPropertyName: 'val'): N[];
|
||||
dfs(pattern: DFSOrderPattern, nodeOrPropertyName: 'val', loopType?: LoopType): N[];
|
||||
|
||||
/**
|
||||
* Performs a depth-first search (dfs) traversal on a binary tree and accumulates nodes themselves.
|
||||
* @param {'in' | 'pre' | 'post'} [pattern] - The traversal pattern: 'in' (in-order), 'pre' (pre-order), or 'post' (post-order).
|
||||
* @param {'node'} nodeOrPropertyName - The name of the property to accumulate.
|
||||
* @param loopType - The type of loop to use for the depth-first search traversal. The default value is `LoopType.ITERATIVE`.
|
||||
* @returns An array of binary tree nodes.
|
||||
*/
|
||||
dfs(pattern: DFSOrderPattern, nodeOrPropertyName: 'node'): N[];
|
||||
dfs(pattern: DFSOrderPattern, nodeOrPropertyName: 'node', loopType?: LoopType): N[];
|
||||
|
||||
/**
|
||||
* The dfs function performs a depth-first search traversal on a binary tree and returns the accumulated properties of
|
||||
* each node based on the specified pattern and property name.
|
||||
* @param {'in' | 'pre' | 'post'} [pattern] - The traversal pattern: 'in' (in-order), 'pre' (pre-order), or 'post' (post-order).
|
||||
* @param {NodeOrPropertyName} [nodeOrPropertyName] - The name of a property of the nodes in the binary tree. This property will be used to accumulate values during the depth-first search traversal. If no `nodeOrPropertyName` is provided, the default value is `'key'`.
|
||||
* @param loopType - The type of loop to use for the depth-first search traversal. The default value is `LoopType.ITERATIVE`.
|
||||
* @returns an instance of the BinaryTreeNodeProperties class, which contains the accumulated properties of the binary tree nodes based on the specified pattern and node or property name.
|
||||
*/
|
||||
dfs(pattern: DFSOrderPattern = 'in', nodeOrPropertyName: NodeOrPropertyName = 'key'): BinaryTreeNodeProperties<N> {
|
||||
dfs(
|
||||
pattern: DFSOrderPattern = 'in',
|
||||
nodeOrPropertyName: NodeOrPropertyName = 'key',
|
||||
loopType: LoopType = LoopType.ITERATIVE
|
||||
): BinaryTreeNodeProperties<N> {
|
||||
this._clearResults();
|
||||
const _traverse = (node: N) => {
|
||||
switch (pattern) {
|
||||
case 'in':
|
||||
if (node.left) _traverse(node.left);
|
||||
this._accumulatedByPropertyName(node, nodeOrPropertyName);
|
||||
if (node.right) _traverse(node.right);
|
||||
break;
|
||||
case 'pre':
|
||||
this._accumulatedByPropertyName(node, nodeOrPropertyName);
|
||||
if (node.left) _traverse(node.left);
|
||||
if (node.right) _traverse(node.right);
|
||||
break;
|
||||
case 'post':
|
||||
if (node.left) _traverse(node.left);
|
||||
if (node.right) _traverse(node.right);
|
||||
this._accumulatedByPropertyName(node, nodeOrPropertyName);
|
||||
break;
|
||||
}
|
||||
};
|
||||
if (loopType === LoopType.RECURSIVE) {
|
||||
const _traverse = (node: N) => {
|
||||
switch (pattern) {
|
||||
case 'in':
|
||||
if (node.left) _traverse(node.left);
|
||||
this._accumulatedByPropertyName(node, nodeOrPropertyName);
|
||||
if (node.right) _traverse(node.right);
|
||||
break;
|
||||
case 'pre':
|
||||
this._accumulatedByPropertyName(node, nodeOrPropertyName);
|
||||
if (node.left) _traverse(node.left);
|
||||
if (node.right) _traverse(node.right);
|
||||
break;
|
||||
case 'post':
|
||||
if (node.left) _traverse(node.left);
|
||||
if (node.right) _traverse(node.right);
|
||||
this._accumulatedByPropertyName(node, nodeOrPropertyName);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
this.root && _traverse(this.root);
|
||||
} else {
|
||||
if (!this.root) return this._getResultByPropertyName(nodeOrPropertyName);
|
||||
// 0: visit, 1: print
|
||||
const stack: {opt: 0 | 1; node: N | null | undefined}[] = [{opt: 0, node: this.root}];
|
||||
|
||||
while (stack.length > 0) {
|
||||
const cur = stack.pop();
|
||||
if (!cur || !cur.node) continue;
|
||||
if (cur.opt === 1) {
|
||||
this._accumulatedByPropertyName(cur.node, nodeOrPropertyName);
|
||||
} else {
|
||||
switch (pattern) {
|
||||
case 'in':
|
||||
stack.push({opt: 0, node: cur.node.right});
|
||||
stack.push({opt: 1, node: cur.node});
|
||||
stack.push({opt: 0, node: cur.node.left});
|
||||
break;
|
||||
case 'pre':
|
||||
stack.push({opt: 0, node: cur.node.right});
|
||||
stack.push({opt: 0, node: cur.node.left});
|
||||
stack.push({opt: 1, node: cur.node});
|
||||
break;
|
||||
case 'post':
|
||||
stack.push({opt: 1, node: cur.node});
|
||||
stack.push({opt: 0, node: cur.node.right});
|
||||
stack.push({opt: 0, node: cur.node.left});
|
||||
break;
|
||||
default:
|
||||
stack.push({opt: 0, node: cur.node.right});
|
||||
stack.push({opt: 1, node: cur.node});
|
||||
stack.push({opt: 0, node: cur.node.left});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.root && _traverse(this.root);
|
||||
return this._getResultByPropertyName(nodeOrPropertyName);
|
||||
}
|
||||
|
||||
// --- start additional methods ---
|
||||
|
||||
/**
|
||||
* Performs an iterative depth-first search (dfs) traversal on a binary tree and accumulates properties of each node based on their 'key' property.
|
||||
* @returns An array of binary tree node IDs.
|
||||
*/
|
||||
dfsIterative(): BinaryTreeNodeKey[];
|
||||
|
||||
/**
|
||||
* Performs an iterative depth-first search (dfs) traversal on a binary tree and accumulates properties of each node based on their 'key' property.
|
||||
* @param {'in' | 'pre' | 'post'} [pattern] - The traversal pattern: 'in' (in-order), 'pre' (pre-order), or 'post' (post-order).
|
||||
* @returns An array of values corresponding to the specified property.
|
||||
*/
|
||||
dfsIterative(pattern: DFSOrderPattern): BinaryTreeNodeKey[];
|
||||
|
||||
/**
|
||||
* Performs an iterative depth-first search (dfs) traversal on a binary tree and accumulates properties of each node based on the specified property name.
|
||||
* @param {'in' | 'pre' | 'post'} [pattern] - The traversal pattern: 'in' (in-order), 'pre' (pre-order), or 'post' (post-order).
|
||||
* @param {string} nodeOrPropertyName - The name of the property to accumulate.
|
||||
* @returns An array of values corresponding to the specified property.
|
||||
*/
|
||||
dfsIterative(pattern: DFSOrderPattern, nodeOrPropertyName: 'key'): BinaryTreeNodeKey[];
|
||||
|
||||
/**
|
||||
* Performs an iterative depth-first search (dfs) traversal on a binary tree and accumulates the 'val' property of each node.
|
||||
* @param {'in' | 'pre' | 'post'} [pattern] - The traversal pattern: 'in' (in-order), 'pre' (pre-order), or 'post' (post-order).
|
||||
* @param {'val'} nodeOrPropertyName - The name of the property to accumulate.
|
||||
* @returns An array of 'val' properties from each node.
|
||||
*/
|
||||
dfsIterative(pattern: DFSOrderPattern, nodeOrPropertyName: 'val'): N['val'][];
|
||||
|
||||
/**
|
||||
* Performs an iterative depth-first search (dfs) traversal on a binary tree and accumulates nodes themselves.
|
||||
* @param {'in' | 'pre' | 'post'} [pattern] - The traversal pattern: 'in' (in-order), 'pre' (pre-order), or 'post' (post-order).
|
||||
* @param {'node'} nodeOrPropertyName - The name of the property to accumulate.
|
||||
* @returns An array of binary tree nodes.
|
||||
*/
|
||||
dfsIterative(pattern: DFSOrderPattern, nodeOrPropertyName: 'node'): N[];
|
||||
|
||||
/**
|
||||
* The dfsIterative function performs an iterative depth-first search traversal on a binary tree, with the option to
|
||||
* specify the traversal pattern and the property name to accumulate results by.
|
||||
* @param {'in' | 'pre' | 'post'} [pattern] - The traversal pattern: 'in' (in-order), 'pre' (pre-order), or 'post' (post-order).
|
||||
* @param {NodeOrPropertyName} [nodeOrPropertyName] - The name of a property of the nodes in the binary tree. This property will be used to accumulate values during the depth-first search traversal. By default, it is set to `'key'`.
|
||||
* @returns An object of type BinaryTreeNodeProperties<N>.
|
||||
*/
|
||||
dfsIterative(
|
||||
pattern: DFSOrderPattern = 'in',
|
||||
nodeOrPropertyName: NodeOrPropertyName = 'key'
|
||||
): BinaryTreeNodeProperties<N> {
|
||||
this._clearResults();
|
||||
if (!this.root) return this._getResultByPropertyName(nodeOrPropertyName);
|
||||
// 0: visit, 1: print
|
||||
const stack: {opt: 0 | 1; node: N | null | undefined}[] = [{opt: 0, node: this.root}];
|
||||
|
||||
while (stack.length > 0) {
|
||||
const cur = stack.pop();
|
||||
if (!cur || !cur.node) continue;
|
||||
if (cur.opt === 1) {
|
||||
this._accumulatedByPropertyName(cur.node, nodeOrPropertyName);
|
||||
} else {
|
||||
switch (pattern) {
|
||||
case 'in':
|
||||
stack.push({opt: 0, node: cur.node.right});
|
||||
stack.push({opt: 1, node: cur.node});
|
||||
stack.push({opt: 0, node: cur.node.left});
|
||||
break;
|
||||
case 'pre':
|
||||
stack.push({opt: 0, node: cur.node.right});
|
||||
stack.push({opt: 0, node: cur.node.left});
|
||||
stack.push({opt: 1, node: cur.node});
|
||||
break;
|
||||
case 'post':
|
||||
stack.push({opt: 1, node: cur.node});
|
||||
stack.push({opt: 0, node: cur.node.right});
|
||||
stack.push({opt: 0, node: cur.node.left});
|
||||
break;
|
||||
default:
|
||||
stack.push({opt: 0, node: cur.node.right});
|
||||
stack.push({opt: 1, node: cur.node});
|
||||
stack.push({opt: 0, node: cur.node.left});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this._getResultByPropertyName(nodeOrPropertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a level-order traversal on a binary tree starting from the specified node and accumulates properties of each node based on their 'key' property.
|
||||
* @returns An array of binary tree node IDs.
|
||||
*/
|
||||
levelIterative(): BinaryTreeNodeKey[];
|
||||
|
||||
/**
|
||||
* Performs a level-order traversal on a binary tree starting from the specified node and accumulates properties of each node based on their 'key' property.
|
||||
* @param {N | null} node - The starting node for the level order traversal. If null, the root node of the tree is used as the starting node.
|
||||
* @returns An array of binary tree node IDs.
|
||||
*/
|
||||
levelIterative(node: N | null): BinaryTreeNodeKey[];
|
||||
|
||||
/**
|
||||
* Performs a level-order traversal on a binary tree starting from the specified node and accumulates properties of each node based on the specified property name.
|
||||
* @param {N | null} node - The starting node for the level order traversal. If null, the root node of the tree is used as the starting node.
|
||||
* @param {string} nodeOrPropertyName - The name of the property to accumulate.
|
||||
* @returns An array of values corresponding to the specified property.
|
||||
*/
|
||||
levelIterative(node: N | null, nodeOrPropertyName: 'key'): BinaryTreeNodeKey[];
|
||||
|
||||
/**
|
||||
* Performs a level-order traversal on a binary tree starting from the specified node and accumulates the 'val' property of each node.
|
||||
* @param {N | null} node - The starting node for the level order traversal. If null, the root node of the tree is used as the starting node.
|
||||
* @param {'val'} nodeOrPropertyName - The name of the property to accumulate.
|
||||
* @returns An array of 'val' properties from each node.
|
||||
*/
|
||||
levelIterative(node: N | null, nodeOrPropertyName: 'val'): N['val'][];
|
||||
|
||||
/**
|
||||
* Performs a level-order traversal on a binary tree starting from the specified node and accumulates nodes themselves.
|
||||
* @param {N | null} node - The starting node for the level order traversal. If null, the root node of the tree is used as the starting node.
|
||||
* @param {'node'} nodeOrPropertyName - The name of the property to accumulate.
|
||||
* @returns An array of binary tree nodes.
|
||||
*/
|
||||
levelIterative(node: N | null, nodeOrPropertyName: 'node'): N[];
|
||||
|
||||
/**
|
||||
* The `levelIterative` function performs a level-order traversal on a binary tree and returns the values of the nodes
|
||||
* in an array, based on a specified property name.
|
||||
* @param {N | null} node - The `node` parameter is a BinaryTreeNode object representing the starting
|
||||
* node for the level order traversal. It can be null if no specific node is provided, in which case the root node of
|
||||
* the tree is used as the starting node.
|
||||
* @param {NodeOrPropertyName} [nodeOrPropertyName] - The `nodeOrPropertyName` parameter is an optional parameter that
|
||||
* can be either a `BinaryTreeNode` property name or the string `'key'`. If a property name is provided, the function
|
||||
* will accumulate results based on that property. If no property name is provided, the function will default to
|
||||
* accumulating results based on the 'key' property.
|
||||
* @returns An object of type `BinaryTreeNodeProperties<N>`.
|
||||
*/
|
||||
levelIterative(
|
||||
node: N | null = this.root,
|
||||
nodeOrPropertyName: NodeOrPropertyName = 'key'
|
||||
): BinaryTreeNodeProperties<N> {
|
||||
if (!node) return [];
|
||||
|
||||
this._clearResults();
|
||||
const queue: N[] = [node];
|
||||
|
||||
while (queue.length > 0) {
|
||||
const cur = queue.shift();
|
||||
if (cur) {
|
||||
this._accumulatedByPropertyName(cur, nodeOrPropertyName);
|
||||
if (cur.left) {
|
||||
queue.push(cur.left);
|
||||
}
|
||||
if (cur.right) {
|
||||
queue.push(cur.right);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this._getResultByPropertyName(nodeOrPropertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects nodes from a binary tree by a specified property and organizes them into levels.
|
||||
* @returns A 2D array of AbstractBinaryTreeNodeProperty<N> objects.
|
||||
|
@ -1425,14 +1298,6 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The function sets the loop type for a protected variable.
|
||||
* @param {LoopType} value - The value parameter is of type LoopType.
|
||||
*/
|
||||
protected _setLoopType(value: LoopType) {
|
||||
this._loopType = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The function sets the root property of an object to a given value, and if the value is not null, it also sets the
|
||||
* parent property of the value to undefined.
|
||||
|
|
|
@ -164,10 +164,10 @@ export class RBTree<N extends RBTreeNode<N['val'], N> = RBTreeNode> extends BST<
|
|||
// // Remove a node
|
||||
// private _removeNode(node: N, replacement: N | null | undefined): void {
|
||||
// if (node === this.root && !replacement) {
|
||||
// // If there's only the root node and no replacement, simply remove the root node
|
||||
// // If there's only the root node and no replacement, simply delete the root node
|
||||
// this._setRoot(null);
|
||||
// } else if (node === this.root || this._isNodeRed(node)) {
|
||||
// // If the node is the root or a red node, remove it directly
|
||||
// // If the node is the root or a red node, delete it directly
|
||||
// if (node.parent!.left === node) {
|
||||
// node.parent!.left = replacement;
|
||||
// } else {
|
||||
|
@ -205,7 +205,7 @@ export class RBTree<N extends RBTreeNode<N['val'], N> = RBTreeNode> extends BST<
|
|||
// node.right = null;
|
||||
// }
|
||||
//
|
||||
// override remove(nodeOrKey: BinaryTreeNodeKey | N): BinaryTreeDeletedResult<N>[] {
|
||||
// override delete(nodeOrKey: BinaryTreeNodeKey | N): BinaryTreeDeletedResult<N>[] {
|
||||
// const node = this.get(nodeOrKey);
|
||||
// const result: BinaryTreeDeletedResult<N>[] = [{deleted: undefined, needBalanced: null}];
|
||||
// if (!node) return result; // Node does not exist
|
||||
|
|
|
@ -70,12 +70,12 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
|
||||
/**
|
||||
* The function swaps the location of two nodes in a tree data structure.
|
||||
* @param {N} srcNode - The source node that we want to swap with the destination node.
|
||||
* @param {N} srcNode - The source node that we want to _swap with the destination node.
|
||||
* @param {N} destNode - The `destNode` parameter represents the destination node where the values from `srcNode` will
|
||||
* be swapped with.
|
||||
* @returns the `destNode` after swapping its values with the `srcNode`.
|
||||
*/
|
||||
override swapLocation(srcNode: N, destNode: N): N {
|
||||
protected override _swap(srcNode: N, destNode: N): N {
|
||||
const {key, val, count, height} = destNode;
|
||||
const tempNode = this.createNode(key, val, count);
|
||||
if (tempNode) {
|
||||
|
@ -285,15 +285,15 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
}
|
||||
|
||||
/**
|
||||
* The `remove` function removes a node from a binary search tree and returns the deleted node along with the parent
|
||||
* The `delete` function removes a node from a binary search tree and returns the deleted node along with the parent
|
||||
* node that needs to be balanced.
|
||||
* @param {N | BinaryTreeNodeKey | null} nodeOrKey - The `nodeOrKey` parameter can be one of the following:
|
||||
* @param {boolean} [ignoreCount] - The `ignoreCount` parameter is an optional boolean parameter that determines
|
||||
* whether to ignore the count of the node being removed. If `ignoreCount` is set to `true`, the count of the node will
|
||||
* not be taken into account when removing it. If `ignoreCount` is set to `false
|
||||
* @returns The function `remove` returns an array of `BinaryTreeDeletedResult<N>` objects.
|
||||
* @returns The function `delete` returns an array of `BinaryTreeDeletedResult<N>` objects.
|
||||
*/
|
||||
override remove(nodeOrKey: N | BinaryTreeNodeKey, ignoreCount = false): BinaryTreeDeletedResult<N>[] {
|
||||
override delete(nodeOrKey: N | BinaryTreeNodeKey, ignoreCount = false): BinaryTreeDeletedResult<N>[] {
|
||||
const bstDeletedResult: BinaryTreeDeletedResult<N>[] = [];
|
||||
if (!this.root) return bstDeletedResult;
|
||||
|
||||
|
@ -324,7 +324,7 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
const leftSubTreeRightMost = curr.left ? this.getRightMost(curr.left) : null;
|
||||
if (leftSubTreeRightMost) {
|
||||
const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;
|
||||
orgCurrent = this.swapLocation(curr, leftSubTreeRightMost);
|
||||
orgCurrent = this._swap(curr, leftSubTreeRightMost);
|
||||
if (parentOfLeftSubTreeMax) {
|
||||
if (parentOfLeftSubTreeMax.right === leftSubTreeRightMost) {
|
||||
parentOfLeftSubTreeMax.right = leftSubTreeRightMost.left;
|
||||
|
@ -515,7 +515,7 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
* @returns The BFSCount() function returns an array of numbers, specifically the count property of each node in the
|
||||
* bfs traversal.
|
||||
*/
|
||||
BFSCount(): number[] {
|
||||
bfsCount(): number[] {
|
||||
const nodes = super.bfs('node');
|
||||
return nodes.map(node => node.count);
|
||||
}
|
||||
|
@ -550,23 +550,12 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
|
|||
* the specified traversal pattern.
|
||||
* @param {'in' | 'pre' | 'post'} [pattern] - The pattern parameter is a string that specifies the traversal order for
|
||||
* the Depth-First Search (dfs) algorithm. It can have three possible values: 'in', 'pre', or 'post'.
|
||||
* @param loopType - The loopType parameter is a string that specifies the type of loop to use when traversing the
|
||||
* @returns The dfsCountIterative function returns an array of numbers, which represents the count property of each node
|
||||
* in the dfs traversal.
|
||||
*/
|
||||
dfsCountIterative(pattern: DFSOrderPattern = 'in'): number[] {
|
||||
const nodes = super.dfsIterative(pattern, 'node');
|
||||
return nodes.map(node => node.count);
|
||||
}
|
||||
|
||||
/**
|
||||
* The dfsCount function returns an array of counts for each node in a depth-first search traversal.
|
||||
* @param {DFSOrderPattern} [pattern] - The pattern parameter is an optional parameter that specifies the order in which
|
||||
* the Depth-First Search (dfs) algorithm should traverse the nodes. It can have one of the following values:
|
||||
* @returns The dfsCount function returns an array of numbers, specifically the count property of each node in the dfs
|
||||
* traversal.
|
||||
*/
|
||||
dfsCount(pattern: DFSOrderPattern = 'in'): number[] {
|
||||
const nodes = super.dfs(pattern, 'node');
|
||||
dfsCount(pattern: DFSOrderPattern = 'in', loopType: LoopType = LoopType.ITERATIVE): number[] {
|
||||
const nodes = super.dfs(pattern, 'node', loopType);
|
||||
return nodes.map(node => node.count);
|
||||
}
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ export class HashMap<K, V> {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
remove(key: K): void {
|
||||
delete(key: K): void {
|
||||
const index = this._hash(key);
|
||||
if (!this.table[index]) {
|
||||
return;
|
||||
|
|
|
@ -213,13 +213,13 @@ export class HashTable<K, V> {
|
|||
}
|
||||
|
||||
/**
|
||||
* The remove function removes a key-value pair from a hash table.
|
||||
* The delete function removes a key-value pair from a hash table.
|
||||
* @param {K} key - The `key` parameter represents the key of the key-value pair that needs to be removed from the hash
|
||||
* table.
|
||||
* @returns Nothing is being returned. The `remove` method has a return type of `void`, which means it does not return
|
||||
* @returns Nothing is being returned. The `delete` method has a return type of `void`, which means it does not return
|
||||
* any value.
|
||||
*/
|
||||
remove(key: K): void {
|
||||
delete(key: K): void {
|
||||
const index = this._hash(key);
|
||||
let currentNode = this._buckets[index];
|
||||
let prevNode: HashTableNode<K, V> | null = null;
|
||||
|
|
|
@ -375,7 +375,7 @@ export class FibonacciHeap<E> {
|
|||
* @protected
|
||||
* @returns FibonacciHeapNode<E>[] - An array containing the nodes of the linked list.
|
||||
*/
|
||||
consumeLinkedList(head?: FibonacciHeapNode<E>): FibonacciHeapNode<E>[] {
|
||||
consumeLinkedList(head?: FibonacciHeapNode<E>): FibonacciHeapNode<E>[] {
|
||||
const nodes: FibonacciHeapNode<E>[] = [];
|
||||
if (!head) return nodes;
|
||||
|
||||
|
@ -448,7 +448,10 @@ export class FibonacciHeap<E> {
|
|||
protected consolidate(): void {
|
||||
const A: (FibonacciHeapNode<E> | undefined)[] = new Array(this.size);
|
||||
const nodes = this.consumeLinkedList(this.root);
|
||||
let x: FibonacciHeapNode<E> | undefined, y: FibonacciHeapNode<E> | undefined, d: number, t: FibonacciHeapNode<E> | undefined;
|
||||
let x: FibonacciHeapNode<E> | undefined,
|
||||
y: FibonacciHeapNode<E> | undefined,
|
||||
d: number,
|
||||
t: FibonacciHeapNode<E> | undefined;
|
||||
|
||||
for (const node of nodes) {
|
||||
x = node;
|
||||
|
|
|
@ -130,12 +130,12 @@ export class SkipList<K, V> {
|
|||
}
|
||||
|
||||
/**
|
||||
* The `remove` function removes a node with a specific key from a Skip List data structure.
|
||||
* The `delete` function removes a node with a specific key from a Skip List data structure.
|
||||
* @param {K} key - The key parameter represents the key of the node that needs to be removed from the skip list.
|
||||
* @returns The `remove` method returns a boolean value. It returns `true` if the key was successfully removed from the
|
||||
* @returns The `delete` method returns a boolean value. It returns `true` if the key was successfully removed from the
|
||||
* skip list, and `false` if the key was not found in the skip list.
|
||||
*/
|
||||
remove(key: K): boolean {
|
||||
delete(key: K): boolean {
|
||||
const update: SkipListNode<K, V>[] = new Array(this.maxLevel).fill(this.head);
|
||||
let current = this.head;
|
||||
|
||||
|
|
|
@ -277,12 +277,12 @@ export class ArrayDeque<E> {
|
|||
}
|
||||
|
||||
/**
|
||||
* The remove function removes an element from an array at a specified index.
|
||||
* The delete function removes an element from an array at a specified index.
|
||||
* @param {number} index - The index parameter specifies the position of the element to be removed from the array. It
|
||||
* is a number that represents the index of the element to be removed.
|
||||
* @returns The method is returning an array containing the removed element.
|
||||
*/
|
||||
remove(index: number) {
|
||||
delete(index: number) {
|
||||
return this._nodes.splice(index, 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -106,7 +106,7 @@ export class Queue<E = any> {
|
|||
|
||||
if (this.offset * 2 < this.nodes.length) return first;
|
||||
|
||||
// only remove dequeued elements when reaching half size
|
||||
// only delete dequeued elements when reaching half size
|
||||
// to decrease latency of shifting elements.
|
||||
this.nodes = this.nodes.slice(this.offset);
|
||||
this.offset = 0;
|
||||
|
|
|
@ -119,10 +119,10 @@ export class Trie {
|
|||
|
||||
/**
|
||||
* Remove a word from the Trie structure.
|
||||
* @param{string} word - The word to remove.
|
||||
* @param{string} word - The word to delete.
|
||||
* @returns {boolean} True if the word was successfully removed.
|
||||
*/
|
||||
remove(word: string) {
|
||||
delete(word: string) {
|
||||
word = this._caseProcess(word);
|
||||
let isDeleted = false;
|
||||
const dfs = (cur: TrieNode, i: number): boolean => {
|
||||
|
|
|
@ -6,5 +6,5 @@ export interface IBinaryTree<N extends BinaryTreeNode<N['val'], N>> {
|
|||
|
||||
add(keyOrNode: BinaryTreeNodeKey | N | null, val?: N['val']): N | null | undefined;
|
||||
|
||||
remove(nodeOrKey: N | BinaryTreeNodeKey): BinaryTreeDeletedResult<N>[];
|
||||
delete(nodeOrKey: N | BinaryTreeNodeKey): BinaryTreeDeletedResult<N>[];
|
||||
}
|
||||
|
|
|
@ -41,56 +41,56 @@ describe('AVL Tree Test', () => {
|
|||
expect(bfs[0].key).toBe(8);
|
||||
expect(bfs[bfs.length - 1].key).toBe(16);
|
||||
|
||||
expect(tree.remove(11)[0].deleted?.key).toBe(11);
|
||||
expect(tree.delete(11)[0].deleted?.key).toBe(11);
|
||||
expect(tree.isAVLBalanced()).toBe(true);
|
||||
expect(node15 && tree.getHeight(node15)).toBe(2);
|
||||
|
||||
expect(tree.remove(1)[0].deleted?.key).toBe(1);
|
||||
expect(tree.delete(1)[0].deleted?.key).toBe(1);
|
||||
expect(tree.isAVLBalanced()).toBe(true);
|
||||
expect(tree.getHeight()).toBe(4);
|
||||
|
||||
expect(tree.remove(4)[0].deleted?.key).toBe(4);
|
||||
expect(tree.delete(4)[0].deleted?.key).toBe(4);
|
||||
expect(tree.isAVLBalanced()).toBe(true);
|
||||
expect(tree.getHeight()).toBe(4);
|
||||
|
||||
expect(tree.remove(10)[0].deleted?.key).toBe(10);
|
||||
expect(tree.delete(10)[0].deleted?.key).toBe(10);
|
||||
expect(tree.isAVLBalanced()).toBe(true);
|
||||
expect(tree.getHeight()).toBe(3);
|
||||
|
||||
expect(tree.remove(15)[0].deleted?.key).toBe(15);
|
||||
expect(tree.delete(15)[0].deleted?.key).toBe(15);
|
||||
expect(tree.isAVLBalanced()).toBe(true);
|
||||
|
||||
expect(tree.getHeight()).toBe(3);
|
||||
|
||||
expect(tree.remove(5)[0].deleted?.key).toBe(5);
|
||||
expect(tree.delete(5)[0].deleted?.key).toBe(5);
|
||||
expect(tree.isAVLBalanced()).toBe(true);
|
||||
expect(tree.getHeight()).toBe(3);
|
||||
|
||||
expect(tree.remove(13)[0].deleted?.key).toBe(13);
|
||||
expect(tree.delete(13)[0].deleted?.key).toBe(13);
|
||||
expect(tree.isAVLBalanced()).toBe(true);
|
||||
expect(tree.getHeight()).toBe(3);
|
||||
|
||||
expect(tree.remove(3)[0].deleted?.key).toBe(3);
|
||||
expect(tree.delete(3)[0].deleted?.key).toBe(3);
|
||||
expect(tree.isAVLBalanced()).toBe(true);
|
||||
expect(tree.getHeight()).toBe(3);
|
||||
|
||||
expect(tree.remove(8)[0].deleted?.key).toBe(8);
|
||||
expect(tree.delete(8)[0].deleted?.key).toBe(8);
|
||||
expect(tree.isAVLBalanced()).toBe(true);
|
||||
expect(tree.getHeight()).toBe(3);
|
||||
|
||||
expect(tree.remove(6)[0].deleted?.key).toBe(6);
|
||||
expect(tree.remove(6).length).toBe(0);
|
||||
expect(tree.delete(6)[0].deleted?.key).toBe(6);
|
||||
expect(tree.delete(6).length).toBe(0);
|
||||
expect(tree.isAVLBalanced()).toBe(true);
|
||||
expect(tree.getHeight()).toBe(2);
|
||||
|
||||
expect(tree.remove(7)[0].deleted?.key).toBe(7);
|
||||
expect(tree.delete(7)[0].deleted?.key).toBe(7);
|
||||
expect(tree.isAVLBalanced()).toBe(true);
|
||||
expect(tree.getHeight()).toBe(2);
|
||||
|
||||
expect(tree.remove(9)[0].deleted?.key).toBe(9);
|
||||
expect(tree.delete(9)[0].deleted?.key).toBe(9);
|
||||
expect(tree.isAVLBalanced()).toBe(true);
|
||||
expect(tree.getHeight()).toBe(2);
|
||||
expect(tree.remove(14)[0].deleted?.key).toBe(14);
|
||||
expect(tree.delete(14)[0].deleted?.key).toBe(14);
|
||||
expect(tree.isAVLBalanced()).toBe(true);
|
||||
expect(tree.getHeight()).toBe(1);
|
||||
|
||||
|
|
|
@ -83,12 +83,12 @@ describe('BinaryTree', () => {
|
|||
expect(binaryTree.size).toBe(1);
|
||||
});
|
||||
|
||||
test('should remove a node', () => {
|
||||
test('should delete a node', () => {
|
||||
const node = binaryTree.add(1);
|
||||
expect(binaryTree.size).toBe(1);
|
||||
|
||||
if (node) {
|
||||
const result = binaryTree.remove(node);
|
||||
const result = binaryTree.delete(node);
|
||||
expect(result).toHaveLength(1);
|
||||
expect(binaryTree.size).toBe(0);
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ describe('BST operations test', () => {
|
|||
expect(bfsNodesAfterBalanced[0].key).toBe(8);
|
||||
expect(bfsNodesAfterBalanced[bfsNodesAfterBalanced.length - 1].key).toBe(16);
|
||||
|
||||
const removed11 = bst.remove(11);
|
||||
const removed11 = bst.delete(11);
|
||||
expect(removed11).toBeInstanceOf(Array);
|
||||
expect(removed11[0]).toBeDefined();
|
||||
expect(removed11[0].deleted).toBeDefined();
|
||||
|
@ -66,7 +66,7 @@ describe('BST operations test', () => {
|
|||
|
||||
expect(bst.getHeight(15)).toBe(1);
|
||||
|
||||
const removed1 = bst.remove(1);
|
||||
const removed1 = bst.delete(1);
|
||||
expect(removed1).toBeInstanceOf(Array);
|
||||
expect(removed1[0]).toBeDefined();
|
||||
expect(removed1[0].deleted).toBeDefined();
|
||||
|
@ -76,7 +76,7 @@ describe('BST operations test', () => {
|
|||
|
||||
expect(bst.getHeight()).toBe(4);
|
||||
|
||||
const removed4 = bst.remove(4);
|
||||
const removed4 = bst.delete(4);
|
||||
expect(removed4).toBeInstanceOf(Array);
|
||||
expect(removed4[0]).toBeDefined();
|
||||
expect(removed4[0].deleted).toBeDefined();
|
||||
|
@ -84,7 +84,7 @@ describe('BST operations test', () => {
|
|||
expect(bst.isAVLBalanced()).toBe(true);
|
||||
expect(bst.getHeight()).toBe(4);
|
||||
|
||||
const removed10 = bst.remove(10);
|
||||
const removed10 = bst.delete(10);
|
||||
expect(removed10).toBeInstanceOf(Array);
|
||||
expect(removed10[0]).toBeDefined();
|
||||
expect(removed10[0].deleted).toBeDefined();
|
||||
|
@ -92,7 +92,7 @@ describe('BST operations test', () => {
|
|||
expect(bst.isAVLBalanced()).toBe(false);
|
||||
expect(bst.getHeight()).toBe(4);
|
||||
|
||||
const removed15 = bst.remove(15);
|
||||
const removed15 = bst.delete(15);
|
||||
expect(removed15).toBeInstanceOf(Array);
|
||||
expect(removed15[0]).toBeDefined();
|
||||
expect(removed15[0].deleted).toBeDefined();
|
||||
|
@ -101,7 +101,7 @@ describe('BST operations test', () => {
|
|||
expect(bst.isAVLBalanced()).toBe(true);
|
||||
expect(bst.getHeight()).toBe(3);
|
||||
|
||||
const removed5 = bst.remove(5);
|
||||
const removed5 = bst.delete(5);
|
||||
expect(removed5).toBeInstanceOf(Array);
|
||||
expect(removed5[0]).toBeDefined();
|
||||
expect(removed5[0].deleted).toBeDefined();
|
||||
|
@ -110,7 +110,7 @@ describe('BST operations test', () => {
|
|||
expect(bst.isAVLBalanced()).toBe(true);
|
||||
expect(bst.getHeight()).toBe(3);
|
||||
|
||||
const removed13 = bst.remove(13);
|
||||
const removed13 = bst.delete(13);
|
||||
expect(removed13).toBeInstanceOf(Array);
|
||||
expect(removed13[0]).toBeDefined();
|
||||
expect(removed13[0].deleted).toBeDefined();
|
||||
|
@ -118,7 +118,7 @@ describe('BST operations test', () => {
|
|||
expect(bst.isAVLBalanced()).toBe(true);
|
||||
expect(bst.getHeight()).toBe(3);
|
||||
|
||||
const removed3 = bst.remove(3);
|
||||
const removed3 = bst.delete(3);
|
||||
expect(removed3).toBeInstanceOf(Array);
|
||||
expect(removed3[0]).toBeDefined();
|
||||
expect(removed3[0].deleted).toBeDefined();
|
||||
|
@ -126,7 +126,7 @@ describe('BST operations test', () => {
|
|||
expect(bst.isAVLBalanced()).toBe(false);
|
||||
expect(bst.getHeight()).toBe(3);
|
||||
|
||||
const removed8 = bst.remove(8);
|
||||
const removed8 = bst.delete(8);
|
||||
expect(removed8).toBeInstanceOf(Array);
|
||||
expect(removed8[0]).toBeDefined();
|
||||
expect(removed8[0].deleted).toBeDefined();
|
||||
|
@ -134,16 +134,16 @@ describe('BST operations test', () => {
|
|||
expect(bst.isAVLBalanced()).toBe(true);
|
||||
expect(bst.getHeight()).toBe(3);
|
||||
|
||||
const removed6 = bst.remove(6);
|
||||
const removed6 = bst.delete(6);
|
||||
expect(removed6).toBeInstanceOf(Array);
|
||||
expect(removed6[0]).toBeDefined();
|
||||
expect(removed6[0].deleted).toBeDefined();
|
||||
if (removed6[0].deleted) expect(removed6[0].deleted.key).toBe(6);
|
||||
expect(bst.remove(6).length).toBe(0);
|
||||
expect(bst.delete(6).length).toBe(0);
|
||||
expect(bst.isAVLBalanced()).toBe(false);
|
||||
expect(bst.getHeight()).toBe(3);
|
||||
|
||||
const removed7 = bst.remove(7);
|
||||
const removed7 = bst.delete(7);
|
||||
expect(removed7).toBeInstanceOf(Array);
|
||||
expect(removed7[0]).toBeDefined();
|
||||
expect(removed7[0].deleted).toBeDefined();
|
||||
|
@ -151,7 +151,7 @@ describe('BST operations test', () => {
|
|||
expect(bst.isAVLBalanced()).toBe(false);
|
||||
expect(bst.getHeight()).toBe(3);
|
||||
|
||||
const removed9 = bst.remove(9);
|
||||
const removed9 = bst.delete(9);
|
||||
expect(removed9).toBeInstanceOf(Array);
|
||||
expect(removed9[0]).toBeDefined();
|
||||
expect(removed9[0].deleted).toBeDefined();
|
||||
|
@ -159,7 +159,7 @@ describe('BST operations test', () => {
|
|||
expect(bst.isAVLBalanced()).toBe(false);
|
||||
expect(bst.getHeight()).toBe(3);
|
||||
|
||||
const removed14 = bst.remove(14);
|
||||
const removed14 = bst.delete(14);
|
||||
expect(removed14).toBeInstanceOf(Array);
|
||||
expect(removed14[0]).toBeDefined();
|
||||
expect(removed14[0].deleted).toBeDefined();
|
||||
|
@ -253,7 +253,7 @@ describe('BST operations test', () => {
|
|||
expect(bfsNodesAfterBalanced[0].key).toBe(8);
|
||||
expect(bfsNodesAfterBalanced[bfsNodesAfterBalanced.length - 1].key).toBe(16);
|
||||
|
||||
const removed11 = objBST.remove(11);
|
||||
const removed11 = objBST.delete(11);
|
||||
expect(removed11).toBeInstanceOf(Array);
|
||||
expect(removed11[0]).toBeDefined();
|
||||
expect(removed11[0].deleted).toBeDefined();
|
||||
|
@ -264,7 +264,7 @@ describe('BST operations test', () => {
|
|||
|
||||
expect(node15 && objBST.getHeight(node15)).toBe(2);
|
||||
|
||||
const removed1 = objBST.remove(1);
|
||||
const removed1 = objBST.delete(1);
|
||||
expect(removed1).toBeInstanceOf(Array);
|
||||
expect(removed1[0]).toBeDefined();
|
||||
expect(removed1[0].deleted).toBeDefined();
|
||||
|
@ -274,7 +274,7 @@ describe('BST operations test', () => {
|
|||
|
||||
expect(objBST.getHeight()).toBe(4);
|
||||
|
||||
const removed4 = objBST.remove(4);
|
||||
const removed4 = objBST.delete(4);
|
||||
expect(removed4).toBeInstanceOf(Array);
|
||||
expect(removed4[0]).toBeDefined();
|
||||
expect(removed4[0].deleted).toBeDefined();
|
||||
|
@ -282,7 +282,7 @@ describe('BST operations test', () => {
|
|||
expect(objBST.isAVLBalanced()).toBe(true);
|
||||
expect(objBST.getHeight()).toBe(4);
|
||||
|
||||
const removed10 = objBST.remove(10);
|
||||
const removed10 = objBST.delete(10);
|
||||
expect(removed10).toBeInstanceOf(Array);
|
||||
expect(removed10[0]).toBeDefined();
|
||||
expect(removed10[0].deleted).toBeDefined();
|
||||
|
@ -290,7 +290,7 @@ describe('BST operations test', () => {
|
|||
expect(objBST.isAVLBalanced()).toBe(false);
|
||||
expect(objBST.getHeight()).toBe(4);
|
||||
|
||||
const removed15 = objBST.remove(15);
|
||||
const removed15 = objBST.delete(15);
|
||||
expect(removed15).toBeInstanceOf(Array);
|
||||
expect(removed15[0]).toBeDefined();
|
||||
expect(removed15[0].deleted).toBeDefined();
|
||||
|
@ -299,7 +299,7 @@ describe('BST operations test', () => {
|
|||
expect(objBST.isAVLBalanced()).toBe(true);
|
||||
expect(objBST.getHeight()).toBe(3);
|
||||
|
||||
const removed5 = objBST.remove(5);
|
||||
const removed5 = objBST.delete(5);
|
||||
expect(removed5).toBeInstanceOf(Array);
|
||||
expect(removed5[0]).toBeDefined();
|
||||
expect(removed5[0].deleted).toBeDefined();
|
||||
|
@ -308,7 +308,7 @@ describe('BST operations test', () => {
|
|||
expect(objBST.isAVLBalanced()).toBe(true);
|
||||
expect(objBST.getHeight()).toBe(3);
|
||||
|
||||
const removed13 = objBST.remove(13);
|
||||
const removed13 = objBST.delete(13);
|
||||
expect(removed13).toBeInstanceOf(Array);
|
||||
expect(removed13[0]).toBeDefined();
|
||||
expect(removed13[0].deleted).toBeDefined();
|
||||
|
@ -316,7 +316,7 @@ describe('BST operations test', () => {
|
|||
expect(objBST.isAVLBalanced()).toBe(true);
|
||||
expect(objBST.getHeight()).toBe(3);
|
||||
|
||||
const removed3 = objBST.remove(3);
|
||||
const removed3 = objBST.delete(3);
|
||||
expect(removed3).toBeInstanceOf(Array);
|
||||
expect(removed3[0]).toBeDefined();
|
||||
expect(removed3[0].deleted).toBeDefined();
|
||||
|
@ -324,7 +324,7 @@ describe('BST operations test', () => {
|
|||
expect(objBST.isAVLBalanced()).toBe(false);
|
||||
expect(objBST.getHeight()).toBe(3);
|
||||
|
||||
const removed8 = objBST.remove(8);
|
||||
const removed8 = objBST.delete(8);
|
||||
expect(removed8).toBeInstanceOf(Array);
|
||||
expect(removed8[0]).toBeDefined();
|
||||
expect(removed8[0].deleted).toBeDefined();
|
||||
|
@ -332,16 +332,16 @@ describe('BST operations test', () => {
|
|||
expect(objBST.isAVLBalanced()).toBe(true);
|
||||
expect(objBST.getHeight()).toBe(3);
|
||||
|
||||
const removed6 = objBST.remove(6);
|
||||
const removed6 = objBST.delete(6);
|
||||
expect(removed6).toBeInstanceOf(Array);
|
||||
expect(removed6[0]).toBeDefined();
|
||||
expect(removed6[0].deleted).toBeDefined();
|
||||
if (removed6[0].deleted) expect(removed6[0].deleted.key).toBe(6);
|
||||
expect(objBST.remove(6).length).toBe(0);
|
||||
expect(objBST.delete(6).length).toBe(0);
|
||||
expect(objBST.isAVLBalanced()).toBe(false);
|
||||
expect(objBST.getHeight()).toBe(3);
|
||||
|
||||
const removed7 = objBST.remove(7);
|
||||
const removed7 = objBST.delete(7);
|
||||
expect(removed7).toBeInstanceOf(Array);
|
||||
expect(removed7[0]).toBeDefined();
|
||||
expect(removed7[0].deleted).toBeDefined();
|
||||
|
@ -349,7 +349,7 @@ describe('BST operations test', () => {
|
|||
expect(objBST.isAVLBalanced()).toBe(false);
|
||||
expect(objBST.getHeight()).toBe(3);
|
||||
|
||||
const removed9 = objBST.remove(9);
|
||||
const removed9 = objBST.delete(9);
|
||||
expect(removed9).toBeInstanceOf(Array);
|
||||
expect(removed9[0]).toBeDefined();
|
||||
expect(removed9[0].deleted).toBeDefined();
|
||||
|
@ -357,7 +357,7 @@ describe('BST operations test', () => {
|
|||
expect(objBST.isAVLBalanced()).toBe(false);
|
||||
expect(objBST.getHeight()).toBe(3);
|
||||
|
||||
const removed14 = objBST.remove(14);
|
||||
const removed14 = objBST.delete(14);
|
||||
expect(removed14).toBeInstanceOf(Array);
|
||||
expect(removed14[0]).toBeDefined();
|
||||
expect(removed14[0].deleted).toBeDefined();
|
||||
|
|
|
@ -19,7 +19,7 @@ describe('Overall BinaryTree Test', () => {
|
|||
const leftMost = bst.getLeftMost();
|
||||
leftMost?.key === 1; // true
|
||||
expect(leftMost?.key).toBe(1);
|
||||
bst.remove(6);
|
||||
bst.delete(6);
|
||||
bst.get(6); // null
|
||||
expect(bst.get(6)).toBeNull();
|
||||
bst.isAVLBalanced(); // true or false
|
||||
|
@ -52,13 +52,13 @@ describe('Overall BinaryTree Test', () => {
|
|||
]
|
||||
);
|
||||
|
||||
objBST.remove(11);
|
||||
objBST.delete(11);
|
||||
|
||||
const avlTree = new AVLTree();
|
||||
avlTree.addMany([11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]);
|
||||
avlTree.isAVLBalanced(); // true
|
||||
expect(avlTree.isAVLBalanced()).toBe(true); // true
|
||||
avlTree.remove(10);
|
||||
avlTree.delete(10);
|
||||
avlTree.isAVLBalanced(); // true
|
||||
expect(avlTree.isAVLBalanced()).toBe(true); // true
|
||||
});
|
||||
|
|
|
@ -31,7 +31,7 @@ describe('Red-Black Tree Tests', () => {
|
|||
// tree.add(8);
|
||||
//
|
||||
// // Delete a node (e.g., 3) and check if it's gone
|
||||
// tree.remove(3);
|
||||
// tree.delete(3);
|
||||
// expect(tree.has(3)).toBe(false);
|
||||
//
|
||||
// // Perform in-order traversal to check if the tree is still balanced
|
||||
|
|
|
@ -70,7 +70,7 @@ describe('TreeMultiset operations test', () => {
|
|||
expect(bfsNodesAfterBalanced[0].key).toBe(8);
|
||||
expect(bfsNodesAfterBalanced[bfsNodesAfterBalanced.length - 1].key).toBe(16);
|
||||
|
||||
const removed11 = treeMultiset.remove(11, true);
|
||||
const removed11 = treeMultiset.delete(11, true);
|
||||
expect(removed11 instanceof Array);
|
||||
expect(removed11[0]);
|
||||
expect(removed11[0].deleted);
|
||||
|
@ -81,7 +81,7 @@ describe('TreeMultiset operations test', () => {
|
|||
|
||||
expect(treeMultiset.getHeight(15)).toBe(1);
|
||||
|
||||
const removed1 = treeMultiset.remove(1, true);
|
||||
const removed1 = treeMultiset.delete(1, true);
|
||||
expect(removed1 instanceof Array);
|
||||
expect(removed1[0]);
|
||||
expect(removed1[0].deleted);
|
||||
|
@ -91,7 +91,7 @@ describe('TreeMultiset operations test', () => {
|
|||
|
||||
expect(treeMultiset.getHeight()).toBe(4);
|
||||
|
||||
const removed4 = treeMultiset.remove(4, true);
|
||||
const removed4 = treeMultiset.delete(4, true);
|
||||
expect(removed4 instanceof Array);
|
||||
expect(removed4[0]);
|
||||
expect(removed4[0].deleted);
|
||||
|
@ -100,7 +100,7 @@ describe('TreeMultiset operations test', () => {
|
|||
expect(treeMultiset.isAVLBalanced()).toBe(true);
|
||||
expect(treeMultiset.getHeight()).toBe(4);
|
||||
|
||||
const removed10 = treeMultiset.remove(10, true);
|
||||
const removed10 = treeMultiset.delete(10, true);
|
||||
expect(removed10 instanceof Array);
|
||||
expect(removed10[0]);
|
||||
expect(removed10[0].deleted);
|
||||
|
@ -109,7 +109,7 @@ describe('TreeMultiset operations test', () => {
|
|||
|
||||
expect(treeMultiset.getHeight()).toBe(3);
|
||||
|
||||
const removed15 = treeMultiset.remove(15, true);
|
||||
const removed15 = treeMultiset.delete(15, true);
|
||||
expect(removed15 instanceof Array);
|
||||
expect(removed15[0]);
|
||||
expect(removed15[0].deleted);
|
||||
|
@ -118,7 +118,7 @@ describe('TreeMultiset operations test', () => {
|
|||
expect(treeMultiset.isAVLBalanced()).toBe(true);
|
||||
expect(treeMultiset.getHeight()).toBe(3);
|
||||
|
||||
const removed5 = treeMultiset.remove(5, true);
|
||||
const removed5 = treeMultiset.delete(5, true);
|
||||
expect(removed5 instanceof Array);
|
||||
expect(removed5[0]);
|
||||
expect(removed5[0].deleted);
|
||||
|
@ -127,7 +127,7 @@ describe('TreeMultiset operations test', () => {
|
|||
expect(treeMultiset.isAVLBalanced()).toBe(true);
|
||||
expect(treeMultiset.getHeight()).toBe(3);
|
||||
|
||||
const removed13 = treeMultiset.remove(13, true);
|
||||
const removed13 = treeMultiset.delete(13, true);
|
||||
expect(removed13 instanceof Array);
|
||||
expect(removed13[0]);
|
||||
expect(removed13[0].deleted);
|
||||
|
@ -135,7 +135,7 @@ describe('TreeMultiset operations test', () => {
|
|||
expect(treeMultiset.isAVLBalanced()).toBe(true);
|
||||
expect(treeMultiset.getHeight()).toBe(3);
|
||||
|
||||
const removed3 = treeMultiset.remove(3, true);
|
||||
const removed3 = treeMultiset.delete(3, true);
|
||||
expect(removed3 instanceof Array);
|
||||
expect(removed3[0]);
|
||||
expect(removed3[0].deleted);
|
||||
|
@ -143,7 +143,7 @@ describe('TreeMultiset operations test', () => {
|
|||
expect(treeMultiset.isAVLBalanced()).toBe(true);
|
||||
expect(treeMultiset.getHeight()).toBe(3);
|
||||
|
||||
const removed8 = treeMultiset.remove(8, true);
|
||||
const removed8 = treeMultiset.delete(8, true);
|
||||
expect(removed8 instanceof Array);
|
||||
expect(removed8[0]);
|
||||
expect(removed8[0].deleted);
|
||||
|
@ -151,17 +151,17 @@ describe('TreeMultiset operations test', () => {
|
|||
expect(treeMultiset.isAVLBalanced()).toBe(true);
|
||||
expect(treeMultiset.getHeight()).toBe(3);
|
||||
|
||||
const removed6 = treeMultiset.remove(6, true);
|
||||
const removed6 = treeMultiset.delete(6, true);
|
||||
expect(removed6 instanceof Array);
|
||||
expect(removed6[0]);
|
||||
expect(removed6[0].deleted);
|
||||
if (removed6[0].deleted) expect(removed6[0].deleted.key).toBe(6);
|
||||
expect(treeMultiset.remove(6, true).length).toBe(0);
|
||||
expect(treeMultiset.delete(6, true).length).toBe(0);
|
||||
expect(treeMultiset.isAVLBalanced()).toBe(true);
|
||||
|
||||
expect(treeMultiset.getHeight()).toBe(2);
|
||||
|
||||
const removed7 = treeMultiset.remove(7, true);
|
||||
const removed7 = treeMultiset.delete(7, true);
|
||||
expect(removed7 instanceof Array);
|
||||
expect(removed7[0]);
|
||||
expect(removed7[0].deleted);
|
||||
|
@ -169,7 +169,7 @@ describe('TreeMultiset operations test', () => {
|
|||
expect(treeMultiset.isAVLBalanced()).toBe(true);
|
||||
expect(treeMultiset.getHeight()).toBe(2);
|
||||
|
||||
const removed9 = treeMultiset.remove(9, true);
|
||||
const removed9 = treeMultiset.delete(9, true);
|
||||
expect(removed9 instanceof Array);
|
||||
expect(removed9[0]);
|
||||
expect(removed9[0].deleted);
|
||||
|
@ -177,7 +177,7 @@ describe('TreeMultiset operations test', () => {
|
|||
expect(treeMultiset.isAVLBalanced()).toBe(true);
|
||||
expect(treeMultiset.getHeight()).toBe(2);
|
||||
|
||||
const removed14 = treeMultiset.remove(14, true);
|
||||
const removed14 = treeMultiset.delete(14, true);
|
||||
expect(removed14 instanceof Array);
|
||||
expect(removed14[0]);
|
||||
expect(removed14[0].deleted);
|
||||
|
@ -288,7 +288,7 @@ describe('TreeMultiset operations test', () => {
|
|||
// expect(bfsNodesAfterBalanced[0].key).toBe(8);
|
||||
// expect(bfsNodesAfterBalanced[bfsNodesAfterBalanced.length - 1].key).toBe(16);
|
||||
//
|
||||
// const removed11 = objTreeMultiset.remove(11, true);
|
||||
// const removed11 = objTreeMultiset.delete(11, true);
|
||||
// expect(removed11).toBeInstanceOf(Array);
|
||||
// expect(removed11[0]).toBeDefined();
|
||||
// expect(removed11[0].deleted).toBeDefined();
|
||||
|
@ -299,7 +299,7 @@ describe('TreeMultiset operations test', () => {
|
|||
//
|
||||
// expect(node15 && objTreeMultiset.getHeight(node15)).toBe(2);
|
||||
//
|
||||
// const removed1 = objTreeMultiset.remove(1, true);
|
||||
// const removed1 = objTreeMultiset.delete(1, true);
|
||||
// expect(removed1).toBeInstanceOf(Array);
|
||||
// expect(removed1[0]).toBeDefined();
|
||||
// expect(removed1[0].deleted).toBeDefined();
|
||||
|
@ -309,7 +309,7 @@ describe('TreeMultiset operations test', () => {
|
|||
//
|
||||
// expect(objTreeMultiset.getHeight()).toBe(4);
|
||||
//
|
||||
// const removed4 = objTreeMultiset.remove(4, true);
|
||||
// const removed4 = objTreeMultiset.delete(4, true);
|
||||
// expect(removed4).toBeInstanceOf(Array);
|
||||
// expect(removed4[0]).toBeDefined();
|
||||
// expect(removed4[0].deleted).toBeDefined();
|
||||
|
@ -317,7 +317,7 @@ describe('TreeMultiset operations test', () => {
|
|||
// expect(objTreeMultiset.isAVLBalanced()).toBe(true);
|
||||
// expect(objTreeMultiset.getHeight()).toBe(4);
|
||||
//
|
||||
// const removed10 = objTreeMultiset.remove(10, true);
|
||||
// const removed10 = objTreeMultiset.delete(10, true);
|
||||
// expect(removed10).toBeInstanceOf(Array);
|
||||
// expect(removed10[0]).toBeDefined();
|
||||
// expect(removed10[0].deleted).toBeDefined();
|
||||
|
@ -325,7 +325,7 @@ describe('TreeMultiset operations test', () => {
|
|||
// expect(objTreeMultiset.isAVLBalanced()).toBe(false);
|
||||
// expect(objTreeMultiset.getHeight()).toBe(4);
|
||||
//
|
||||
// const removed15 = objTreeMultiset.remove(15, true);
|
||||
// const removed15 = objTreeMultiset.delete(15, true);
|
||||
// expect(removed15).toBeInstanceOf(Array);
|
||||
// expect(removed15[0]).toBeDefined();
|
||||
// expect(removed15[0].deleted).toBeDefined();
|
||||
|
@ -334,7 +334,7 @@ describe('TreeMultiset operations test', () => {
|
|||
// expect(objTreeMultiset.isAVLBalanced()).toBe(true);
|
||||
// expect(objTreeMultiset.getHeight()).toBe(3);
|
||||
//
|
||||
// const removed5 = objTreeMultiset.remove(5, true);
|
||||
// const removed5 = objTreeMultiset.delete(5, true);
|
||||
// expect(removed5).toBeInstanceOf(Array);
|
||||
// expect(removed5[0]).toBeDefined();
|
||||
// expect(removed5[0].deleted).toBeDefined();
|
||||
|
@ -343,7 +343,7 @@ describe('TreeMultiset operations test', () => {
|
|||
// expect(objTreeMultiset.isAVLBalanced()).toBe(true);
|
||||
// expect(objTreeMultiset.getHeight()).toBe(3);
|
||||
//
|
||||
// const removed13 = objTreeMultiset.remove(13, true);
|
||||
// const removed13 = objTreeMultiset.delete(13, true);
|
||||
// expect(removed13).toBeInstanceOf(Array);
|
||||
// expect(removed13[0]).toBeDefined();
|
||||
// expect(removed13[0].deleted).toBeDefined();
|
||||
|
@ -351,7 +351,7 @@ describe('TreeMultiset operations test', () => {
|
|||
// expect(objTreeMultiset.isAVLBalanced()).toBe(true);
|
||||
// expect(objTreeMultiset.getHeight()).toBe(3);
|
||||
//
|
||||
// const removed3 = objTreeMultiset.remove(3, true);
|
||||
// const removed3 = objTreeMultiset.delete(3, true);
|
||||
// expect(removed3).toBeInstanceOf(Array);
|
||||
// expect(removed3[0]).toBeDefined();
|
||||
// expect(removed3[0].deleted).toBeDefined();
|
||||
|
@ -359,7 +359,7 @@ describe('TreeMultiset operations test', () => {
|
|||
// expect(objTreeMultiset.isAVLBalanced()).toBe(false);
|
||||
// expect(objTreeMultiset.getHeight()).toBe(3);
|
||||
//
|
||||
// const removed8 = objTreeMultiset.remove(8, true);
|
||||
// const removed8 = objTreeMultiset.delete(8, true);
|
||||
// expect(removed8).toBeInstanceOf(Array);
|
||||
// expect(removed8[0]).toBeDefined();
|
||||
// expect(removed8[0].deleted).toBeDefined();
|
||||
|
@ -367,16 +367,16 @@ describe('TreeMultiset operations test', () => {
|
|||
// expect(objTreeMultiset.isAVLBalanced()).toBe(true);
|
||||
// expect(objTreeMultiset.getHeight()).toBe(3);
|
||||
//
|
||||
// const removed6 = objTreeMultiset.remove(6, true);
|
||||
// const removed6 = objTreeMultiset.delete(6, true);
|
||||
// expect(removed6).toBeInstanceOf(Array);
|
||||
// expect(removed6[0]).toBeDefined();
|
||||
// expect(removed6[0].deleted).toBeDefined();
|
||||
// if (removed6[0].deleted) expect(removed6[0].deleted.key).toBe(6);
|
||||
// expect(objTreeMultiset.remove(6, true).length).toBe(0);
|
||||
// expect(objTreeMultiset.delete(6, true).length).toBe(0);
|
||||
// expect(objTreeMultiset.isAVLBalanced()).toBe(false);
|
||||
// expect(objTreeMultiset.getHeight()).toBe(3);
|
||||
//
|
||||
// const removed7 = objTreeMultiset.remove(7, true);
|
||||
// const removed7 = objTreeMultiset.delete(7, true);
|
||||
// expect(removed7).toBeInstanceOf(Array);
|
||||
// expect(removed7[0]).toBeDefined();
|
||||
// expect(removed7[0].deleted).toBeDefined();
|
||||
|
@ -384,7 +384,7 @@ describe('TreeMultiset operations test', () => {
|
|||
// expect(objTreeMultiset.isAVLBalanced()).toBe(false);
|
||||
// expect(objTreeMultiset.getHeight()).toBe(3);
|
||||
//
|
||||
// const removed9 = objTreeMultiset.remove(9, true);
|
||||
// const removed9 = objTreeMultiset.delete(9, true);
|
||||
// expect(removed9).toBeInstanceOf(Array);
|
||||
// expect(removed9[0]).toBeDefined();
|
||||
// expect(removed9[0].deleted).toBeDefined();
|
||||
|
@ -392,7 +392,7 @@ describe('TreeMultiset operations test', () => {
|
|||
// expect(objTreeMultiset.isAVLBalanced()).toBe(false);
|
||||
// expect(objTreeMultiset.getHeight()).toBe(3);
|
||||
//
|
||||
// const removed14 = objTreeMultiset.remove(14, true);
|
||||
// const removed14 = objTreeMultiset.delete(14, true);
|
||||
// expect(removed14).toBeInstanceOf(Array);
|
||||
// expect(removed14[0]).toBeDefined();
|
||||
// expect(removed14[0].deleted).toBeDefined();
|
||||
|
|
|
@ -31,7 +31,7 @@ describe('DirectedGraph Operation Test', () => {
|
|||
expect(graph.hasEdge('B', 'A')).toBe(false);
|
||||
});
|
||||
|
||||
it('should remove edges', () => {
|
||||
it('should delete edges', () => {
|
||||
const vertex1 = new DirectedVertex('A');
|
||||
const vertex2 = new DirectedVertex('B');
|
||||
const edge = new DirectedEdge('A', 'B');
|
||||
|
|
|
@ -31,7 +31,7 @@ describe('UndirectedGraph Operation Test', () => {
|
|||
expect(graph.hasEdge('B', 'A')).toBe(true);
|
||||
});
|
||||
|
||||
it('should remove edges', () => {
|
||||
it('should delete edges', () => {
|
||||
const vertex1 = new UndirectedVertex('A');
|
||||
const vertex2 = new UndirectedVertex('B');
|
||||
const edge = new UndirectedEdge('A', 'B');
|
||||
|
|
|
@ -36,11 +36,11 @@ describe('HashMap', () => {
|
|||
expect(hashMap.get('key2')).toBe(2);
|
||||
});
|
||||
|
||||
it('should remove values', () => {
|
||||
it('should delete values', () => {
|
||||
hashMap.set('one', 1);
|
||||
hashMap.set('two', 2);
|
||||
|
||||
hashMap.remove('one');
|
||||
hashMap.delete('one');
|
||||
expect(hashMap.get('one')).toBeUndefined();
|
||||
expect(hashMap.size).toBe(1);
|
||||
});
|
||||
|
|
|
@ -81,13 +81,13 @@ describe('HashTable', () => {
|
|||
expect(retrievedValue).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should remove key-value pair correctly', () => {
|
||||
it('should delete key-value pair correctly', () => {
|
||||
const hashTable = new HashTable<string, string>();
|
||||
const key = 'testKey';
|
||||
const value = 'testValue';
|
||||
|
||||
hashTable.set(key, value);
|
||||
hashTable.remove(key);
|
||||
hashTable.delete(key);
|
||||
|
||||
const retrievedValue = hashTable.get(key);
|
||||
|
||||
|
@ -128,10 +128,10 @@ describe('HashTable', () => {
|
|||
expect(hashTable.get('two')).toBe(2);
|
||||
});
|
||||
|
||||
it('should remove values correctly', () => {
|
||||
it('should delete values correctly', () => {
|
||||
hashTable.set('one', 1);
|
||||
hashTable.set('two', 2);
|
||||
hashTable.remove('one');
|
||||
hashTable.delete('one');
|
||||
|
||||
expect(hashTable.get('one')).toBeUndefined();
|
||||
expect(hashTable.get('two')).toBe(2);
|
||||
|
@ -139,7 +139,7 @@ describe('HashTable', () => {
|
|||
|
||||
it('should handle non-existent keys correctly', () => {
|
||||
expect(hashTable.get('non-existent')).toBeUndefined();
|
||||
hashTable.remove('non-existent'); // Removing a non-existent key should not cause errors
|
||||
hashTable.delete('non-existent'); // Removing a non-existent key should not cause errors
|
||||
});
|
||||
|
||||
it('should handle custom hash function correctly', () => {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {FibonacciHeap, MaxHeap, MinHeap} from '../../../../src';
|
||||
import {logBigOMetricsWrap} from "../../../utils";
|
||||
import {logBigOMetricsWrap} from '../../../utils';
|
||||
|
||||
describe('Heap Operation Test', () => {
|
||||
it('should numeric heap work well', function () {
|
||||
|
@ -201,10 +201,8 @@ describe('FibonacciHeap', () => {
|
|||
});
|
||||
});
|
||||
|
||||
|
||||
describe('FibonacciHeap Stress Test', () => {
|
||||
it('should handle a large number of elements efficiently', () => {
|
||||
|
||||
const testByMagnitude = (magnitude: number) => {
|
||||
const heap = new FibonacciHeap<number>();
|
||||
|
||||
|
@ -229,7 +227,7 @@ describe('FibonacciHeap Stress Test', () => {
|
|||
|
||||
// Verify that the heap is now empty
|
||||
expect(heap.size).toBe(0);
|
||||
}
|
||||
};
|
||||
|
||||
testByMagnitude(1000);
|
||||
|
||||
|
@ -238,13 +236,18 @@ describe('FibonacciHeap Stress Test', () => {
|
|||
// 150000, 200000, 250000, 300000, 400000, 500000, 600000, 700000, 800000, 900000, 1000000
|
||||
// ].forEach(m => logBigOMetricsWrap<typeof testByMagnitude>(testByMagnitude, [m]));
|
||||
[
|
||||
10, 100, 1000, 5000, 10000, 20000, 50000, 75000, 100000,
|
||||
150000, 200000, 250000, 300000, 400000, 500000, 600000, 700000, 800000, 900000, 1000000
|
||||
].forEach(m => logBigOMetricsWrap((c: number) => {
|
||||
const result: number[] = [];
|
||||
for (let i = 0; i < c; i++) result.push(i);
|
||||
return result;
|
||||
} , [m], 'loopPush'));
|
||||
|
||||
10, 100, 1000, 5000, 10000, 20000, 50000, 75000, 100000, 150000, 200000, 250000, 300000, 400000, 500000, 600000,
|
||||
700000, 800000, 900000, 1000000
|
||||
].forEach(m =>
|
||||
logBigOMetricsWrap(
|
||||
(c: number) => {
|
||||
const result: number[] = [];
|
||||
for (let i = 0; i < c; i++) result.push(i);
|
||||
return result;
|
||||
},
|
||||
[m],
|
||||
'loopPush'
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -18,7 +18,7 @@ describe('SinglyLinkedList Operation Test', () => {
|
|||
});
|
||||
|
||||
describe('pop', () => {
|
||||
it('should remove and return the last element of the list', () => {
|
||||
it('should delete and return the last element of the list', () => {
|
||||
list.push(1);
|
||||
list.push(2);
|
||||
const popped = list.pop();
|
||||
|
@ -33,7 +33,7 @@ describe('SinglyLinkedList Operation Test', () => {
|
|||
});
|
||||
|
||||
describe('shift', () => {
|
||||
it('should remove and return the first element of the list', () => {
|
||||
it('should delete and return the first element of the list', () => {
|
||||
list.push(1);
|
||||
list.push(2);
|
||||
const shifted = list.shift();
|
||||
|
@ -109,7 +109,7 @@ describe('SinglyLinkedList Operation Test', () => {
|
|||
});
|
||||
|
||||
describe('removeValue', () => {
|
||||
it('should remove the first occurrence of a value from the list', () => {
|
||||
it('should delete the first occurrence of a value from the list', () => {
|
||||
list.push(1);
|
||||
list.push(2);
|
||||
list.push(3);
|
||||
|
@ -240,8 +240,8 @@ describe('SinglyLinkedList Operation Test', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('remove', () => {
|
||||
it('should remove and return the element at the specified index', () => {
|
||||
describe('delete', () => {
|
||||
it('should delete and return the element at the specified index', () => {
|
||||
list.push(1);
|
||||
list.push(2);
|
||||
list.push(3);
|
||||
|
@ -256,7 +256,7 @@ describe('SinglyLinkedList Operation Test', () => {
|
|||
expect(removed).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should remove and return the first element', () => {
|
||||
it('should delete and return the first element', () => {
|
||||
list.push(1);
|
||||
list.push(2);
|
||||
const removed = list.deleteAt(0);
|
||||
|
@ -264,7 +264,7 @@ describe('SinglyLinkedList Operation Test', () => {
|
|||
expect(list.toArray()).toEqual([2]);
|
||||
});
|
||||
|
||||
it('should remove and return the last element', () => {
|
||||
it('should delete and return the last element', () => {
|
||||
list.push(1);
|
||||
list.push(2);
|
||||
const removed = list.deleteAt(1);
|
||||
|
|
|
@ -25,12 +25,12 @@ describe('SkipList', () => {
|
|||
expect(skipList.get(0)).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should remove elements correctly', () => {
|
||||
it('should delete elements correctly', () => {
|
||||
skipList.add(1, 'One');
|
||||
skipList.add(2, 'Two');
|
||||
skipList.add(3, 'Three');
|
||||
|
||||
skipList.remove(2);
|
||||
skipList.delete(2);
|
||||
|
||||
expect(skipList.get(2)).toBeUndefined(); // 修改这里的断言
|
||||
});
|
||||
|
|
|
@ -27,7 +27,7 @@ describe('MaxPriorityQueue Operation Test', () => {
|
|||
expect(priorityQueue.poll()?.keyA).toBe(1);
|
||||
});
|
||||
|
||||
it('should return and remove the smallest element', () => {
|
||||
it('should return and delete the smallest element', () => {
|
||||
const priorityQueue = new MaxPriorityQueue<number>();
|
||||
priorityQueue.add(5);
|
||||
priorityQueue.add(3);
|
||||
|
|
|
@ -16,7 +16,7 @@ describe('Deque Tests', () => {
|
|||
expect(deque.peekLast()).toBe(2);
|
||||
});
|
||||
|
||||
it('should remove elements from the beginning and end', () => {
|
||||
it('should delete elements from the beginning and end', () => {
|
||||
deque.addFirst(1);
|
||||
deque.addLast(2);
|
||||
deque.pollFirst();
|
||||
|
@ -69,7 +69,7 @@ describe('Deque Tests', () => {
|
|||
expect(objectDeque.peekLast()).toBe('two');
|
||||
});
|
||||
|
||||
it('should remove elements from the beginning and end', () => {
|
||||
it('should delete elements from the beginning and end', () => {
|
||||
objectDeque.addFirst('one');
|
||||
objectDeque.addLast('two');
|
||||
objectDeque.pollFirst();
|
||||
|
@ -106,7 +106,7 @@ describe('Deque Tests', () => {
|
|||
expect(arrayDeque.peekLast()).toBe(2);
|
||||
});
|
||||
|
||||
it('should remove elements from the beginning and end', () => {
|
||||
it('should delete elements from the beginning and end', () => {
|
||||
arrayDeque.addFirst(1);
|
||||
arrayDeque.addLast(2);
|
||||
arrayDeque.pollFirst();
|
||||
|
|
|
@ -81,15 +81,15 @@ describe('Trie', () => {
|
|||
expect(words).toEqual(['apple', 'application', 'app']);
|
||||
});
|
||||
|
||||
it('should remove words from Trie', () => {
|
||||
it('should delete words from Trie', () => {
|
||||
const trie = new Trie();
|
||||
trie.add('apple');
|
||||
trie.add('app');
|
||||
expect(trie.has('apple')).toBe(true);
|
||||
trie.remove('apple');
|
||||
trie.delete('apple');
|
||||
expect(trie.has('apple')).toBe(false);
|
||||
expect(trie.has('app')).toBe(true);
|
||||
trie.remove('app');
|
||||
trie.delete('app');
|
||||
expect(trie.has('app')).toBe(false);
|
||||
});
|
||||
|
||||
|
@ -772,9 +772,9 @@ describe('Trie operations', () => {
|
|||
test('Remove Words', () => {
|
||||
trie.add('apple');
|
||||
trie.add('banana');
|
||||
expect(trie.remove('apple')).toBe(true);
|
||||
expect(trie.delete('apple')).toBe(true);
|
||||
expect(trie.has('apple')).toBe(false);
|
||||
expect(trie.remove('cherry')).toBe(false);
|
||||
expect(trie.delete('cherry')).toBe(false);
|
||||
});
|
||||
|
||||
test('Case Sensitivity', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {AnyFunction} from "../types";
|
||||
import {AnyFunction} from '../types';
|
||||
|
||||
const orderReducedBy = 2; // reduction of bigO's order compared to the baseline bigO
|
||||
|
||||
|
@ -22,10 +22,9 @@ export const bigO = {
|
|||
FACTORIAL: 10000
|
||||
};
|
||||
|
||||
|
||||
function findPotentialN(input: any): number {
|
||||
let longestArray: any[] = [];
|
||||
let mostProperties: { [key: string]: any } = {};
|
||||
let mostProperties: {[key: string]: any} = {};
|
||||
|
||||
function recurse(obj: any) {
|
||||
if (Array.isArray(obj)) {
|
||||
|
@ -37,14 +36,14 @@ function findPotentialN(input: any): number {
|
|||
if (keys.length > Object.keys(mostProperties).length) {
|
||||
mostProperties = obj;
|
||||
}
|
||||
keys.forEach((key) => {
|
||||
keys.forEach(key => {
|
||||
recurse(obj[key]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(input)) {
|
||||
input.forEach((item) => {
|
||||
input.forEach(item => {
|
||||
recurse(item);
|
||||
});
|
||||
} else {
|
||||
|
@ -67,20 +66,20 @@ function linearRegression(x: number[], y: number[]) {
|
|||
const slope = (n * sumXY - sumX * sumY) / (n * sumXSquared - sumX ** 2);
|
||||
const intercept = (sumY - slope * sumX) / n;
|
||||
|
||||
const yHat = x.map((val) => slope * val + intercept);
|
||||
const yHat = x.map(val => slope * val + intercept);
|
||||
|
||||
const totalVariation = y.map((val, i) => (val - yHat[i]) ** 2).reduce((acc, val) => acc + val, 0);
|
||||
const explainedVariation = y.map((val) => (val - (sumY / n)) ** 2).reduce((acc, val) => acc + val, 0);
|
||||
const explainedVariation = y.map(val => (val - sumY / n) ** 2).reduce((acc, val) => acc + val, 0);
|
||||
|
||||
const rSquared = 1 - totalVariation / explainedVariation;
|
||||
|
||||
return { slope, intercept, rSquared };
|
||||
return {slope, intercept, rSquared};
|
||||
}
|
||||
|
||||
function estimateBigO(runtimes: number[], dataSizes: number[]): string {
|
||||
// Make sure the input runtimes and data sizes have the same length
|
||||
if (runtimes.length !== dataSizes.length) {
|
||||
return "Lengths of input arrays do not match";
|
||||
return 'Lengths of input arrays do not match';
|
||||
}
|
||||
|
||||
// Create an array to store the computational complexity of each data point
|
||||
|
@ -88,32 +87,32 @@ function estimateBigO(runtimes: number[], dataSizes: number[]): string {
|
|||
|
||||
// Traverse different possible complexities
|
||||
const complexitiesToCheck: string[] = [
|
||||
"O(1)", // constant time complexity
|
||||
"O(log n)", // Logarithmic time complexity
|
||||
"O(n)", // linear time complexity
|
||||
"O(n log n)", // linear logarithmic time complexity
|
||||
"O(n^2)", // squared time complexity
|
||||
'O(1)', // constant time complexity
|
||||
'O(log n)', // Logarithmic time complexity
|
||||
'O(n)', // linear time complexity
|
||||
'O(n log n)', // linear logarithmic time complexity
|
||||
'O(n^2)' // squared time complexity
|
||||
];
|
||||
|
||||
for (const complexity of complexitiesToCheck) {
|
||||
// Calculate data points for fitting
|
||||
const fittedData: number[] = dataSizes.map((size) => {
|
||||
if (complexity === "O(1)") {
|
||||
// Calculate data points for fitting
|
||||
const fittedData: number[] = dataSizes.map(size => {
|
||||
if (complexity === 'O(1)') {
|
||||
return 1; // constant time complexity
|
||||
} else if (complexity === "O(log n)") {
|
||||
} else if (complexity === 'O(log n)') {
|
||||
return Math.log(size);
|
||||
} else if (complexity === "O(n)") {
|
||||
} else if (complexity === 'O(n)') {
|
||||
return size;
|
||||
} else if (complexity === "O(n log n)") {
|
||||
} else if (complexity === 'O(n log n)') {
|
||||
return size * Math.log(size);
|
||||
} else if (complexity === "O(n^2)") {
|
||||
} else if (complexity === 'O(n^2)') {
|
||||
return size ** 2;
|
||||
} else {
|
||||
return size ** 10
|
||||
return size ** 10;
|
||||
}
|
||||
});
|
||||
|
||||
// Fit the data points using linear regression analysis
|
||||
// Fit the data points using linear regression analysis
|
||||
const regressionResult = linearRegression(fittedData, runtimes);
|
||||
|
||||
// Check the R-squared value of the fit. It is usually considered a valid fit if it is greater than 0.9.
|
||||
|
@ -124,39 +123,42 @@ function estimateBigO(runtimes: number[], dataSizes: number[]): string {
|
|||
|
||||
// If there is no valid fitting result, return "cannot estimate", otherwise return the estimated time complexity
|
||||
if (complexities.length === 0) {
|
||||
return "Unable to estimate";
|
||||
return 'Unable to estimate';
|
||||
} else {
|
||||
return complexities.join(" or ");
|
||||
return complexities.join(' or ');
|
||||
}
|
||||
}
|
||||
|
||||
const methodLogs: Map<string, [number, number][] > = new Map();
|
||||
const methodLogs: Map<string, [number, number][]> = new Map();
|
||||
|
||||
export function logBigOMetricsWrap<F extends AnyFunction>(fn: F, args: Parameters<F>, fnName: string) {
|
||||
const startTime = performance.now();
|
||||
const result = fn(args);
|
||||
const endTime = performance.now();
|
||||
const runTime = endTime - startTime;
|
||||
const methodName = `${fnName}`;
|
||||
if (!methodLogs.has(methodName)) {
|
||||
methodLogs.set(methodName, []);
|
||||
const startTime = performance.now();
|
||||
const result = fn(args);
|
||||
const endTime = performance.now();
|
||||
const runTime = endTime - startTime;
|
||||
const methodName = `${fnName}`;
|
||||
if (!methodLogs.has(methodName)) {
|
||||
methodLogs.set(methodName, []);
|
||||
}
|
||||
|
||||
const methodLog = methodLogs.get(methodName);
|
||||
|
||||
const maxDataSize = args.length === 1 && typeof args[0] === 'number' ? args[0] : findPotentialN(args);
|
||||
if (methodLog) {
|
||||
methodLog.push([runTime, maxDataSize]);
|
||||
|
||||
if (methodLog.length >= 20) {
|
||||
console.log('triggered', methodName, methodLog);
|
||||
const bigO = estimateBigO(
|
||||
methodLog.map(([runTime]) => runTime),
|
||||
methodLog.map(([runTime]) => runTime)
|
||||
);
|
||||
console.log(`Estimated Big O: ${bigO}`);
|
||||
methodLogs.delete(methodName);
|
||||
}
|
||||
}
|
||||
|
||||
const methodLog = methodLogs.get(methodName);
|
||||
|
||||
const maxDataSize = args.length === 1 && typeof args[0] === "number" ? args[0] : findPotentialN(args);
|
||||
if (methodLog) {
|
||||
methodLog.push([runTime, maxDataSize]);
|
||||
|
||||
if (methodLog.length >= 20) {
|
||||
console.log('triggered', methodName, methodLog);
|
||||
const bigO = estimateBigO(methodLog.map(([runTime,]) => runTime), methodLog.map(([runTime,]) => runTime));
|
||||
console.log(`Estimated Big O: ${bigO}`);
|
||||
methodLogs.delete(methodName)
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
export function logBigOMetrics(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
|
||||
|
@ -175,15 +177,18 @@ export function logBigOMetrics(target: any, propertyKey: string, descriptor: Pro
|
|||
|
||||
const methodLog = methodLogs.get(methodName);
|
||||
|
||||
const maxDataSize = args.length === 1 && typeof args[0] === "number" ? args[0] : findPotentialN(args);
|
||||
const maxDataSize = args.length === 1 && typeof args[0] === 'number' ? args[0] : findPotentialN(args);
|
||||
if (methodLog) {
|
||||
methodLog.push([runTime, maxDataSize]);
|
||||
|
||||
if (methodLog.length >= 20) {
|
||||
console.log('triggered', methodName, methodLog);
|
||||
const bigO = estimateBigO(methodLog.map(([runTime,]) => runTime), methodLog.map(([runTime,]) => runTime));
|
||||
const bigO = estimateBigO(
|
||||
methodLog.map(([runTime]) => runTime),
|
||||
methodLog.map(([runTime]) => runTime)
|
||||
);
|
||||
console.log(`Estimated Big O: ${bigO}`);
|
||||
methodLogs.delete(methodName)
|
||||
methodLogs.delete(methodName);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue