mirror of
https://github.com/zrwusa/data-structure-typed.git
synced 2024-11-23 04:44:04 +00:00
style: code base reformat
This commit is contained in:
parent
bc000105d8
commit
dc6ef95f78
|
@ -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.3](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming)
|
||||
## [v1.49.4](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming)
|
||||
|
||||
### Changes
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
export * from './iterable-base';
|
||||
export * from './iterable-base';
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { ElementCallback, EntryCallback, ReduceElementCallback, ReduceEntryCallback } from "../../types";
|
||||
import { ElementCallback, EntryCallback, ReduceElementCallback, ReduceEntryCallback } from '../../types';
|
||||
|
||||
export abstract class IterableEntryBase<K = any, V = any> {
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
|
@ -147,7 +146,7 @@ export abstract class IterableEntryBase<K = any, V = any> {
|
|||
let index = 0;
|
||||
for (const item of this) {
|
||||
const [key, value] = item;
|
||||
callbackfn.call(thisArg, value, key, index++, this)
|
||||
callbackfn.call(thisArg, value, key, index++, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,7 +175,7 @@ export abstract class IterableEntryBase<K = any, V = any> {
|
|||
let index = 0;
|
||||
for (const item of this) {
|
||||
const [key, value] = item;
|
||||
accumulator = callbackfn(accumulator, value, key, index++, this)
|
||||
accumulator = callbackfn(accumulator, value, key, index++, this);
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
|
@ -193,14 +192,13 @@ export abstract class IterableEntryBase<K = any, V = any> {
|
|||
* Space Complexity: O(n)
|
||||
*/
|
||||
print(): void {
|
||||
console.log([...this])
|
||||
console.log([...this]);
|
||||
}
|
||||
|
||||
protected abstract _getIterator(...args: any[]): IterableIterator<[K, V]>;
|
||||
}
|
||||
|
||||
export abstract class IterableElementBase<V> {
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
|
@ -310,7 +308,7 @@ export abstract class IterableElementBase<V> {
|
|||
forEach(callbackfn: ElementCallback<V, void>, thisArg?: any): void {
|
||||
let index = 0;
|
||||
for (const item of this) {
|
||||
callbackfn.call(thisArg, item as V, index++, this)
|
||||
callbackfn.call(thisArg, item as V, index++, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -335,18 +333,17 @@ export abstract class IterableElementBase<V> {
|
|||
let accumulator = initialValue;
|
||||
let index = 0;
|
||||
for (const item of this) {
|
||||
accumulator = callbackfn(accumulator, item as V, index++, this)
|
||||
accumulator = callbackfn(accumulator, item as V, index++, this);
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
print(): void {
|
||||
console.log([...this])
|
||||
console.log([...this]);
|
||||
}
|
||||
|
||||
protected abstract _getIterator(...args: any[]): IterableIterator<V>;
|
||||
|
|
|
@ -18,7 +18,11 @@ import type {
|
|||
} from '../../types';
|
||||
import { IBinaryTree } from '../../interfaces';
|
||||
|
||||
export class AVLTreeNode<K = any, V = any, N extends AVLTreeNode<K, V, N> = AVLTreeNodeNested<K, V>> extends BSTNode<K, V, N> {
|
||||
export class AVLTreeNode<K = any, V = any, N extends AVLTreeNode<K, V, N> = AVLTreeNodeNested<K, V>> extends BSTNode<
|
||||
K,
|
||||
V,
|
||||
N
|
||||
> {
|
||||
height: number;
|
||||
|
||||
constructor(key: K, value?: V) {
|
||||
|
@ -36,10 +40,14 @@ export class AVLTreeNode<K = any, V = any, N extends AVLTreeNode<K, V, N> = AVLT
|
|||
* 6. Complex Insertions and Deletions: Due to rebalancing, these operations are more complex than in a regular BST.
|
||||
* 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>>>
|
||||
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>>
|
||||
>
|
||||
extends BST<K, V, N, TREE>
|
||||
implements IBinaryTree<K, V, N, TREE> {
|
||||
|
||||
/**
|
||||
* The constructor function initializes an AVLTree object with optional elements and options.
|
||||
* @param [elements] - The `elements` parameter is an optional iterable of `BTNExemplar<K, V, N>`
|
||||
|
@ -77,7 +85,8 @@ export class AVLTree<K = any, V = any, N extends AVLTreeNode<K, V, N> = AVLTreeN
|
|||
override createTree(options?: AVLTreeOptions<K>): TREE {
|
||||
return new AVLTree<K, V, N, TREE>([], {
|
||||
iterationType: this.iterationType,
|
||||
variant: this.variant, ...options
|
||||
variant: this.variant,
|
||||
...options
|
||||
}) as TREE;
|
||||
}
|
||||
|
||||
|
@ -97,7 +106,7 @@ export class AVLTree<K = any, V = any, N extends AVLTreeNode<K, V, N> = AVLTreeN
|
|||
* @returns a boolean value indicating whether the potentialKey is of type number or not.
|
||||
*/
|
||||
override isNotNodeInstance(potentialKey: BTNKeyOrNode<K, N>): potentialKey is K {
|
||||
return !(potentialKey instanceof AVLTreeNode)
|
||||
return !(potentialKey instanceof AVLTreeNode);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -105,7 +114,6 @@ export class AVLTree<K = any, V = any, N extends AVLTreeNode<K, V, N> = AVLTreeN
|
|||
* Space Complexity: O(1) - constant space, as it doesn't use additional data structures that scale with input size.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Time Complexity: O(log n) - logarithmic time, where "n" is the number of nodes in the tree. The add method of the superclass (BST) has logarithmic time complexity.
|
||||
* Space Complexity: O(1) - constant space, as it doesn't use additional data structures that scale with input size.
|
||||
|
@ -159,7 +167,6 @@ export class AVLTree<K = any, V = any, N extends AVLTreeNode<K, V, N> = AVLTreeN
|
|||
return deletedResults;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The `_swapProperties` function swaps the key, value, and height properties between two nodes in a binary
|
||||
* tree.
|
||||
|
@ -489,6 +496,6 @@ export class AVLTree<K = any, V = any, N extends AVLTreeNode<K, V, N> = AVLTreeN
|
|||
protected _replaceNode(oldNode: N, newNode: N): N {
|
||||
newNode.height = oldNode.height;
|
||||
|
||||
return super._replaceNode(oldNode, newNode)
|
||||
return super._replaceNode(oldNode, newNode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,14 +24,18 @@ import { FamilyPosition, IterationType } from '../../types';
|
|||
import { IBinaryTree } from '../../interfaces';
|
||||
import { trampoline } from '../../utils';
|
||||
import { Queue } from '../queue';
|
||||
import { IterableEntryBase } from "../base";
|
||||
import { IterableEntryBase } from '../base';
|
||||
|
||||
/**
|
||||
* Represents a node in a binary tree.
|
||||
* @template V - The type of data stored in the node.
|
||||
* @template N - The type of the family relationship in the binary tree.
|
||||
*/
|
||||
export class BinaryTreeNode<K = any, V = any, N extends BinaryTreeNode<K, V, N> = BinaryTreeNode<K, V, BinaryTreeNodeNested<K, V>>> {
|
||||
export class BinaryTreeNode<
|
||||
K = any,
|
||||
V = any,
|
||||
N extends BinaryTreeNode<K, V, N> = BinaryTreeNode<K, V, BinaryTreeNodeNested<K, V>>
|
||||
> {
|
||||
key: K;
|
||||
|
||||
value?: V;
|
||||
|
@ -97,10 +101,15 @@ export class BinaryTreeNode<K = any, V = any, N extends BinaryTreeNode<K, V, N>
|
|||
* 5. Leaf Nodes: Nodes without children are leaves.
|
||||
*/
|
||||
|
||||
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>>> extends IterableEntryBase<K, V | undefined>
|
||||
|
||||
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>>
|
||||
>
|
||||
extends IterableEntryBase<K, V | undefined>
|
||||
implements IBinaryTree<K, V, N, TREE> {
|
||||
iterationType = IterationType.ITERATIVE
|
||||
iterationType = IterationType.ITERATIVE;
|
||||
|
||||
/**
|
||||
* The constructor function initializes a binary tree object with optional elements and options.
|
||||
|
@ -128,7 +137,7 @@ export class BinaryTree<K = any, V = any, N extends BinaryTreeNode<K, V, N> = Bi
|
|||
if (elements) this.addMany(elements);
|
||||
}
|
||||
|
||||
protected _extractor = (key: K) => Number(key)
|
||||
protected _extractor = (key: K) => Number(key);
|
||||
|
||||
get extractor() {
|
||||
return this._extractor;
|
||||
|
@ -287,7 +296,6 @@ export class BinaryTree<K = any, V = any, N extends BinaryTreeNode<K, V, N> = Bi
|
|||
return undefined; // If the insertion position cannot be found, return undefined
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Time Complexity: O(k log n) - O(k * n)
|
||||
* Space Complexity: O(1)
|
||||
|
@ -329,7 +337,6 @@ export class BinaryTree<K = any, V = any, N extends BinaryTreeNode<K, V, N> = Bi
|
|||
return inserted;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Time Complexity: O(k * n) "n" is the number of nodes in the tree, and "k" is the number of keys to be inserted.
|
||||
* Space Complexity: O(1)
|
||||
|
@ -985,10 +992,7 @@ export class BinaryTree<K = any, V = any, N extends BinaryTreeNode<K, V, N> = Bi
|
|||
* @returns The function `getLeftMost` returns the leftmost node (`N`) in the binary tree. If there
|
||||
* is no leftmost node, it returns `null` or `undefined` depending on the input.
|
||||
*/
|
||||
getLeftMost(
|
||||
beginRoot: BTNKeyOrNode<K, N> = this.root,
|
||||
iterationType = this.iterationType
|
||||
): N | null | undefined {
|
||||
getLeftMost(beginRoot: BTNKeyOrNode<K, N> = this.root, iterationType = this.iterationType): N | null | undefined {
|
||||
beginRoot = this.ensureNode(beginRoot);
|
||||
|
||||
if (!beginRoot) return beginRoot;
|
||||
|
@ -1031,10 +1035,7 @@ export class BinaryTree<K = any, V = any, N extends BinaryTreeNode<K, V, N> = Bi
|
|||
* @returns The function `getRightMost` returns the rightmost node (`N`) in a binary tree. If there
|
||||
* is no rightmost node, it returns `null` or `undefined`, depending on the input.
|
||||
*/
|
||||
getRightMost(
|
||||
beginRoot: BTNKeyOrNode<K, N> = this.root,
|
||||
iterationType = this.iterationType
|
||||
): N | null | undefined {
|
||||
getRightMost(beginRoot: BTNKeyOrNode<K, N> = this.root, iterationType = this.iterationType): N | null | undefined {
|
||||
// TODO support get right most by passing key in
|
||||
beginRoot = this.ensureNode(beginRoot);
|
||||
if (!beginRoot) return beginRoot;
|
||||
|
@ -1262,7 +1263,7 @@ export class BinaryTree<K = any, V = any, N extends BinaryTreeNode<K, V, N> = Bi
|
|||
* @returns a boolean value indicating whether the potentialKey is of type number or not.
|
||||
*/
|
||||
isNotNodeInstance(potentialKey: BTNKeyOrNode<K, N>): potentialKey is K {
|
||||
return !(potentialKey instanceof BinaryTreeNode)
|
||||
return !(potentialKey instanceof BinaryTreeNode);
|
||||
}
|
||||
|
||||
dfs<C extends BTNCallback<N>>(
|
||||
|
@ -1637,7 +1638,6 @@ export class BinaryTree<K = any, V = any, N extends BinaryTreeNode<K, V, N> = Bi
|
|||
* after the given node in the inorder traversal of the binary tree.
|
||||
*/
|
||||
getSuccessor(x?: K | N | null): N | null | undefined {
|
||||
|
||||
x = this.ensureNode(x);
|
||||
if (!this.isRealNode(x)) return undefined;
|
||||
|
||||
|
@ -1858,11 +1858,14 @@ export class BinaryTree<K = any, V = any, N extends BinaryTreeNode<K, V, N> = Bi
|
|||
beginRoot = this.ensureNode(beginRoot);
|
||||
if (!beginRoot) return;
|
||||
|
||||
if (opts.isShowUndefined) console.log(`U for undefined
|
||||
if (opts.isShowUndefined)
|
||||
console.log(`U for undefined
|
||||
`);
|
||||
if (opts.isShowNull) console.log(`N for null
|
||||
if (opts.isShowNull)
|
||||
console.log(`N for null
|
||||
`);
|
||||
if (opts.isShowRedBlackNIL) console.log(`S for Sentinel Node
|
||||
if (opts.isShowRedBlackNIL)
|
||||
console.log(`S for Sentinel Node
|
||||
`);
|
||||
|
||||
const display = (root: N | null | undefined): void => {
|
||||
|
@ -1920,30 +1923,42 @@ export class BinaryTree<K = any, V = any, N extends BinaryTreeNode<K, V, N> = Bi
|
|||
} else if (node !== null && node !== undefined) {
|
||||
// Display logic of normal nodes
|
||||
|
||||
const key = node.key, line = isNaN(this.extractor(key)) ? 'S' : this.extractor(key).toString(),
|
||||
const key = node.key,
|
||||
line = isNaN(this.extractor(key)) ? 'S' : this.extractor(key).toString(),
|
||||
width = line.length;
|
||||
|
||||
return _buildNodeDisplay(line, width, this._displayAux(node.left, options), this._displayAux(node.right, options))
|
||||
|
||||
return _buildNodeDisplay(
|
||||
line,
|
||||
width,
|
||||
this._displayAux(node.left, options),
|
||||
this._displayAux(node.right, options)
|
||||
);
|
||||
} else {
|
||||
// For cases where none of the conditions are met, null, undefined, and NaN nodes are not displayed
|
||||
const line = node === undefined ? 'U' : 'N', width = line.length;
|
||||
const line = node === undefined ? 'U' : 'N',
|
||||
width = line.length;
|
||||
|
||||
return _buildNodeDisplay(line, width, [[''], 1, 0, 0], [[''], 1, 0, 0])
|
||||
return _buildNodeDisplay(line, width, [[''], 1, 0, 0], [[''], 1, 0, 0]);
|
||||
}
|
||||
|
||||
function _buildNodeDisplay(line: string, width: number, left: NodeDisplayLayout, right: NodeDisplayLayout) {
|
||||
const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
|
||||
const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
|
||||
const firstLine = ' '.repeat(Math.max(0, leftMiddle + 1))
|
||||
+ '_'.repeat(Math.max(0, leftWidth - leftMiddle - 1))
|
||||
+ line
|
||||
+ '_'.repeat(Math.max(0, rightMiddle))
|
||||
+ ' '.repeat(Math.max(0, rightWidth - rightMiddle));
|
||||
const firstLine =
|
||||
' '.repeat(Math.max(0, leftMiddle + 1)) +
|
||||
'_'.repeat(Math.max(0, leftWidth - leftMiddle - 1)) +
|
||||
line +
|
||||
'_'.repeat(Math.max(0, rightMiddle)) +
|
||||
' '.repeat(Math.max(0, rightWidth - rightMiddle));
|
||||
|
||||
const secondLine = (leftHeight > 0 ? ' '.repeat(leftMiddle) + '/' + ' '.repeat(leftWidth - leftMiddle - 1) : ' '.repeat(leftWidth))
|
||||
+ ' '.repeat(width)
|
||||
+ (rightHeight > 0 ? ' '.repeat(rightMiddle) + '\\' + ' '.repeat(rightWidth - rightMiddle - 1) : ' '.repeat(rightWidth));
|
||||
const secondLine =
|
||||
(leftHeight > 0
|
||||
? ' '.repeat(leftMiddle) + '/' + ' '.repeat(leftWidth - leftMiddle - 1)
|
||||
: ' '.repeat(leftWidth)) +
|
||||
' '.repeat(width) +
|
||||
(rightHeight > 0
|
||||
? ' '.repeat(rightMiddle) + '\\' + ' '.repeat(rightWidth - rightMiddle - 1)
|
||||
: ' '.repeat(rightWidth));
|
||||
|
||||
const mergedLines = [firstLine, secondLine];
|
||||
|
||||
|
@ -1953,11 +1968,16 @@ export class BinaryTree<K = any, V = any, N extends BinaryTreeNode<K, V, N> = Bi
|
|||
mergedLines.push(leftLine + ' '.repeat(width) + rightLine);
|
||||
}
|
||||
|
||||
return <NodeDisplayLayout>[mergedLines, leftWidth + width + rightWidth, Math.max(leftHeight, rightHeight) + 2, leftWidth + Math.floor(width / 2)];
|
||||
return <NodeDisplayLayout>[
|
||||
mergedLines,
|
||||
leftWidth + width + rightWidth,
|
||||
Math.max(leftHeight, rightHeight) + 2,
|
||||
leftWidth + Math.floor(width / 2)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
protected _defaultOneParamCallback = (node: N | null | undefined) => node ? node.key : undefined;
|
||||
protected _defaultOneParamCallback = (node: N | null | undefined) => (node ? node.key : undefined);
|
||||
|
||||
/**
|
||||
* Swap the data of two nodes in the binary tree.
|
||||
|
|
|
@ -20,7 +20,11 @@ import { BinaryTree, BinaryTreeNode } from './binary-tree';
|
|||
import { IBinaryTree } from '../../interfaces';
|
||||
import { Queue } from '../queue';
|
||||
|
||||
export class BSTNode<K = any, V = any, N extends BSTNode<K, V, N> = BSTNodeNested<K, V>> extends BinaryTreeNode<K, V, N> {
|
||||
export class BSTNode<K = any, V = any, N extends BSTNode<K, V, N> = BSTNodeNested<K, V>> extends BinaryTreeNode<
|
||||
K,
|
||||
V,
|
||||
N
|
||||
> {
|
||||
override parent?: N;
|
||||
|
||||
constructor(key: K, value?: V) {
|
||||
|
@ -80,11 +84,14 @@ export class BSTNode<K = any, V = any, N extends BSTNode<K, V, N> = BSTNodeNeste
|
|||
* 6. Balance Variability: Can become unbalanced; special types maintain balance.
|
||||
* 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>>>
|
||||
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>>
|
||||
>
|
||||
extends BinaryTree<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 elements and options.
|
||||
|
@ -114,7 +121,7 @@ export class BST<K = any, V = any, N extends BSTNode<K, V, N> = BSTNode<K, V, BS
|
|||
return this._root;
|
||||
}
|
||||
|
||||
protected _variant = BSTVariant.MIN
|
||||
protected _variant = BSTVariant.MIN;
|
||||
|
||||
get variant() {
|
||||
return this._variant;
|
||||
|
@ -142,7 +149,8 @@ export class BST<K = any, V = any, N extends BSTNode<K, V, N> = BSTNode<K, V, BS
|
|||
override createTree(options?: Partial<BSTOptions<K>>): TREE {
|
||||
return new BST<K, V, N, TREE>([], {
|
||||
iterationType: this.iterationType,
|
||||
variant: this.variant, ...options
|
||||
variant: this.variant,
|
||||
...options
|
||||
}) as TREE;
|
||||
}
|
||||
|
||||
|
@ -155,7 +163,6 @@ export class BST<K = any, V = any, N extends BSTNode<K, V, N> = BSTNode<K, V, BS
|
|||
return exemplar instanceof BSTNode;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The function `exemplarToNode` takes an exemplar and returns a node if the exemplar is valid,
|
||||
* otherwise it returns undefined.
|
||||
|
@ -301,7 +308,7 @@ export class BST<K = any, V = any, N extends BSTNode<K, V, N> = BSTNode<K, V, BS
|
|||
const isRealBTNExemplar = (kve: BTNExemplar<K, V, N>): kve is BTNodePureExemplar<K, V, N> => {
|
||||
if (kve === undefined || kve === null) return false;
|
||||
return !(this.isEntry(kve) && (kve[0] === undefined || kve[0] === null));
|
||||
}
|
||||
};
|
||||
|
||||
for (const kve of keysOrNodesOrEntries) {
|
||||
isRealBTNExemplar(kve) && realBTNExemplars.push(kve);
|
||||
|
@ -359,7 +366,6 @@ export class BST<K = any, V = any, N extends BSTNode<K, V, N> = BSTNode<K, V, BS
|
|||
return inserted;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n log n) - Adding each element individually in a balanced tree.
|
||||
* Space Complexity: O(n) - Additional space is required for the sorted array.
|
||||
|
@ -398,7 +404,6 @@ export class BST<K = any, V = any, N extends BSTNode<K, V, N> = BSTNode<K, V, BS
|
|||
return current.key;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Time Complexity: O(log n) - Average case for a balanced tree.
|
||||
* Space Complexity: O(1) - Constant space is used.
|
||||
|
@ -450,7 +455,7 @@ export class BST<K = any, V = any, N extends BSTNode<K, V, N> = BSTNode<K, V, BS
|
|||
* @returns a boolean value indicating whether the potentialKey is of type number or not.
|
||||
*/
|
||||
override isNotNodeInstance(potentialKey: BTNKeyOrNode<K, N>): potentialKey is K {
|
||||
return !(potentialKey instanceof BSTNode)
|
||||
return !(potentialKey instanceof BSTNode);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -738,7 +743,6 @@ export class BST<K = any, V = any, N extends BSTNode<K, V, N> = BSTNode<K, V, BS
|
|||
return balanced;
|
||||
}
|
||||
|
||||
|
||||
protected _setRoot(v: N | undefined) {
|
||||
if (v) {
|
||||
v.parent = undefined;
|
||||
|
@ -761,5 +765,4 @@ export class BST<K = any, V = any, N extends BSTNode<K, V, N> = BSTNode<K, V, BS
|
|||
|
||||
return compared > 0 ? CP.gt : compared < 0 ? CP.lt : CP.eq;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,10 +21,11 @@ import {
|
|||
import { BST, BSTNode } from './bst';
|
||||
import { IBinaryTree } from '../../interfaces';
|
||||
|
||||
export class RedBlackTreeNode<K = any, V = any, N extends RedBlackTreeNode<K, V, N> = RedBlackTreeNodeNested<K, V>> extends BSTNode<
|
||||
K, V,
|
||||
N
|
||||
> {
|
||||
export class RedBlackTreeNode<
|
||||
K = any,
|
||||
V = any,
|
||||
N extends RedBlackTreeNode<K, V, N> = RedBlackTreeNodeNested<K, V>
|
||||
> extends BSTNode<K, V, N> {
|
||||
color: RBTNColor;
|
||||
|
||||
constructor(key: K, value?: V, color: RBTNColor = RBTNColor.BLACK) {
|
||||
|
@ -40,7 +41,12 @@ export class RedBlackTreeNode<K = any, V = any, N extends RedBlackTreeNode<K, V,
|
|||
* 4. Red nodes must have black children.
|
||||
* 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>>>
|
||||
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>>
|
||||
>
|
||||
extends BST<K, V, N, TREE>
|
||||
implements IBinaryTree<K, V, N, TREE> {
|
||||
Sentinel: N = new RedBlackTreeNode<K, V>(NaN as K) as unknown as N;
|
||||
|
@ -101,7 +107,8 @@ export class RedBlackTree<K = any, V = any, N extends RedBlackTreeNode<K, V, N>
|
|||
override createTree(options?: RBTreeOptions<K>): TREE {
|
||||
return new RedBlackTree<K, V, N, TREE>([], {
|
||||
iterationType: this.iterationType,
|
||||
variant: this.variant, ...options
|
||||
variant: this.variant,
|
||||
...options
|
||||
}) as TREE;
|
||||
}
|
||||
|
||||
|
@ -122,7 +129,7 @@ export class RedBlackTree<K = any, V = any, N extends RedBlackTreeNode<K, V, N>
|
|||
* @returns a boolean value indicating whether the potentialKey is of type number or not.
|
||||
*/
|
||||
override isNotNodeInstance(potentialKey: BTNKeyOrNode<K, N>): potentialKey is K {
|
||||
return !(potentialKey instanceof RedBlackTreeNode)
|
||||
return !(potentialKey instanceof RedBlackTreeNode);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -191,12 +198,11 @@ export class RedBlackTree<K = any, V = any, N extends RedBlackTreeNode<K, V, N>
|
|||
x = x?.right;
|
||||
} else {
|
||||
if (newNode !== x) {
|
||||
this._replaceNode(x, newNode)
|
||||
this._replaceNode(x, newNode);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
newNode.parent = y;
|
||||
|
@ -649,6 +655,6 @@ export class RedBlackTree<K = any, V = any, N extends RedBlackTreeNode<K, V, N>
|
|||
protected _replaceNode(oldNode: N, newNode: N): N {
|
||||
newNode.color = oldNode.color;
|
||||
|
||||
return super._replaceNode(oldNode, newNode)
|
||||
return super._replaceNode(oldNode, newNode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,11 +45,14 @@ 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>>>
|
||||
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>>
|
||||
>
|
||||
extends AVLTree<K, V, N, TREE>
|
||||
implements IBinaryTree<K, V, N, TREE> {
|
||||
|
||||
constructor(elements?: Iterable<BTNExemplar<K, V, N>>, options?: Partial<TreeMultimapOptions<K>>) {
|
||||
super([], options);
|
||||
if (elements) this.addMany(elements);
|
||||
|
@ -60,7 +63,7 @@ export class TreeMultimap<K = any, V = any, N extends TreeMultimapNode<K, V, N>
|
|||
// TODO the _count is not accurate after nodes count modified
|
||||
get count(): number {
|
||||
let sum = 0;
|
||||
this.subTreeTraverse(node => sum += node.count);
|
||||
this.subTreeTraverse(node => (sum += node.count));
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
@ -80,7 +83,8 @@ export class TreeMultimap<K = any, V = any, N extends TreeMultimapNode<K, V, N>
|
|||
override createTree(options?: TreeMultimapOptions<K>): TREE {
|
||||
return new TreeMultimap<K, V, N, TREE>([], {
|
||||
iterationType: this.iterationType,
|
||||
variant: this.variant, ...options
|
||||
variant: this.variant,
|
||||
...options
|
||||
}) as TREE;
|
||||
}
|
||||
|
||||
|
@ -101,7 +105,7 @@ export class TreeMultimap<K = any, V = any, N extends TreeMultimapNode<K, V, N>
|
|||
* @returns a boolean value indicating whether the potentialKey is of type number or not.
|
||||
*/
|
||||
override isNotNodeInstance(potentialKey: BTNKeyOrNode<K, N>): potentialKey is K {
|
||||
return !(potentialKey instanceof TreeMultimapNode)
|
||||
return !(potentialKey instanceof TreeMultimapNode);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -433,7 +437,7 @@ export class TreeMultimap<K = any, V = any, N extends TreeMultimapNode<K, V, N>
|
|||
}
|
||||
|
||||
protected _replaceNode(oldNode: N, newNode: N): N {
|
||||
newNode.count = oldNode.count + newNode.count
|
||||
newNode.count = oldNode.count + newNode.count;
|
||||
return super._replaceNode(oldNode, newNode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
import type { DijkstraResult, EntryCallback, VertexKey } from '../../types';
|
||||
import { uuidV4 } from '../../utils';
|
||||
import { IterableEntryBase } from "../base";
|
||||
import { IterableEntryBase } from '../base';
|
||||
import { IGraph } from '../../interfaces';
|
||||
import { Heap } from '../heap';
|
||||
import { Queue } from '../queue';
|
||||
|
@ -65,7 +65,9 @@ export abstract class AbstractGraph<
|
|||
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> {
|
||||
>
|
||||
extends IterableEntryBase<VertexKey, V | undefined>
|
||||
implements IGraph<V, E, VO, EO> {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
@ -165,7 +167,7 @@ export abstract class AbstractGraph<
|
|||
|
||||
isVertexKey(potentialKey: any): potentialKey is VertexKey {
|
||||
const potentialKeyType = typeof potentialKey;
|
||||
return potentialKeyType === "string" || potentialKeyType === "number"
|
||||
return potentialKeyType === 'string' || potentialKeyType === 'number';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -662,7 +664,6 @@ export abstract class AbstractGraph<
|
|||
getMinDist: boolean = false,
|
||||
genPaths: boolean = false
|
||||
): DijkstraResult<VO> {
|
||||
|
||||
let minDist = Infinity;
|
||||
let minDest: VO | undefined = undefined;
|
||||
let minPath: VO[] = [];
|
||||
|
@ -1170,7 +1171,10 @@ export abstract class AbstractGraph<
|
|||
|
||||
const dfs = (vertex: VO, currentPath: VertexKey[], visited: Set<VO>) => {
|
||||
if (visited.has(vertex)) {
|
||||
if ((!isInclude2Cycle && currentPath.length > 2 || isInclude2Cycle && currentPath.length >= 2) && currentPath[0] === vertex.key) {
|
||||
if (
|
||||
((!isInclude2Cycle && currentPath.length > 2) || (isInclude2Cycle && currentPath.length >= 2)) &&
|
||||
currentPath[0] === vertex.key
|
||||
) {
|
||||
cycles.push([...currentPath]);
|
||||
}
|
||||
return;
|
||||
|
@ -1195,18 +1199,16 @@ export abstract class AbstractGraph<
|
|||
const uniqueCycles = new Map<string, VertexKey[]>();
|
||||
|
||||
for (const cycle of cycles) {
|
||||
const sorted = [...cycle].sort().toString()
|
||||
const sorted = [...cycle].sort().toString();
|
||||
|
||||
if (uniqueCycles.has(sorted)) continue
|
||||
if (uniqueCycles.has(sorted)) continue;
|
||||
else {
|
||||
uniqueCycles.set(sorted, cycle)
|
||||
uniqueCycles.set(sorted, cycle);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert the unique cycles back to an array
|
||||
return [...uniqueCycles].map(cycleString =>
|
||||
cycleString[1]
|
||||
);
|
||||
return [...uniqueCycles].map(cycleString => cycleString[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -182,7 +182,6 @@ export class DirectedGraph<
|
|||
* Space Complexity: O(1)
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Time Complexity: O(E) where E is the number of edgeMap
|
||||
* Space Complexity: O(1)
|
||||
|
@ -248,7 +247,7 @@ export class DirectedGraph<
|
|||
vertexKey = vertexOrKey;
|
||||
} else {
|
||||
vertex = vertexOrKey;
|
||||
vertexKey = this._getVertexKey(vertexOrKey)
|
||||
vertexKey = this._getVertexKey(vertexOrKey);
|
||||
}
|
||||
|
||||
if (vertex) {
|
||||
|
@ -600,7 +599,6 @@ export class DirectedGraph<
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Time Complexity: O(1)
|
||||
* Space Complexity: O(1)
|
||||
|
|
|
@ -84,7 +84,12 @@ export class MapGraph<
|
|||
* @param {number} long - The `long` parameter represents the longitude coordinate of the vertex.
|
||||
* @returns The method is returning a new instance of the `MapVertex` class, casted as type `VO`.
|
||||
*/
|
||||
override createVertex(key: VertexKey, value?: V, lat: number = this.originCoord[0], long: number = this.originCoord[1]): VO {
|
||||
override createVertex(
|
||||
key: VertexKey,
|
||||
value?: V,
|
||||
lat: number = this.originCoord[0],
|
||||
long: number = this.originCoord[1]
|
||||
): VO {
|
||||
return new MapVertex(key, value, lat, long) as VO;
|
||||
}
|
||||
|
||||
|
|
|
@ -162,7 +162,6 @@ export class UndirectedGraph<
|
|||
* Space Complexity: O(1)
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Time Complexity: O(E), where E is the number of edgeMap incident to the given vertex.
|
||||
* Space Complexity: O(1)
|
||||
|
@ -192,7 +191,6 @@ export class UndirectedGraph<
|
|||
|
||||
if (oneSide && otherSide) {
|
||||
return this.deleteEdgeBetween(oneSide, otherSide);
|
||||
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
@ -220,10 +218,10 @@ export class UndirectedGraph<
|
|||
vertexKey = vertexOrKey;
|
||||
} else {
|
||||
vertex = vertexOrKey;
|
||||
vertexKey = this._getVertexKey(vertexOrKey)
|
||||
vertexKey = this._getVertexKey(vertexOrKey);
|
||||
}
|
||||
|
||||
const neighbors = this.getNeighbors(vertexOrKey)
|
||||
const neighbors = this.getNeighbors(vertexOrKey);
|
||||
|
||||
if (vertex) {
|
||||
neighbors.forEach(neighbor => {
|
||||
|
@ -234,9 +232,8 @@ export class UndirectedGraph<
|
|||
});
|
||||
this._edgeMap.set(neighbor, restEdges);
|
||||
}
|
||||
})
|
||||
});
|
||||
this._edgeMap.delete(vertex);
|
||||
|
||||
}
|
||||
|
||||
return this._vertexMap.delete(vertexKey);
|
||||
|
|
|
@ -27,9 +27,12 @@ export class HashMap<K = any, V = any> extends IterableEntryBase<K, V> {
|
|||
* @param [options] - The `options` parameter is an optional object that can contain additional
|
||||
* configuration options for the constructor. In this case, it has one property:
|
||||
*/
|
||||
constructor(elements: Iterable<[K, V]> = [], options?: {
|
||||
hashFn: (key: K) => string
|
||||
}) {
|
||||
constructor(
|
||||
elements: Iterable<[K, V]> = [],
|
||||
options?: {
|
||||
hashFn: (key: K) => string;
|
||||
}
|
||||
) {
|
||||
super();
|
||||
if (options) {
|
||||
const { hashFn } = options;
|
||||
|
@ -73,7 +76,6 @@ export class HashMap<K = any, V = any> extends IterableEntryBase<K, V> {
|
|||
this._size++;
|
||||
}
|
||||
this._objMap.set(key, value);
|
||||
|
||||
} else {
|
||||
const strKey = this._getNoObjKey(key);
|
||||
if (this._store[strKey] === undefined) {
|
||||
|
@ -137,7 +139,7 @@ export class HashMap<K = any, V = any> extends IterableEntryBase<K, V> {
|
|||
delete(key: K): boolean {
|
||||
if (this._isObjKey(key)) {
|
||||
if (this._objMap.has(key)) {
|
||||
this._size--
|
||||
this._size--;
|
||||
}
|
||||
|
||||
return this._objMap.delete(key);
|
||||
|
@ -235,19 +237,19 @@ export class HashMap<K = any, V = any> extends IterableEntryBase<K, V> {
|
|||
|
||||
protected _hashFn: (key: K) => string = (key: K) => String(key);
|
||||
|
||||
protected _isObjKey(key: any): key is (object | ((...args: any[]) => any)) {
|
||||
protected _isObjKey(key: any): key is object | ((...args: any[]) => any) {
|
||||
const keyType = typeof key;
|
||||
return (keyType === 'object' || keyType === 'function') && key !== null
|
||||
return (keyType === 'object' || keyType === 'function') && key !== null;
|
||||
}
|
||||
|
||||
protected _getNoObjKey(key: K): string {
|
||||
const keyType = typeof key;
|
||||
|
||||
let strKey: string;
|
||||
if (keyType !== "string" && keyType !== "number" && keyType !== "symbol") {
|
||||
if (keyType !== 'string' && keyType !== 'number' && keyType !== 'symbol') {
|
||||
strKey = this._hashFn(key);
|
||||
} else {
|
||||
if (keyType === "number") {
|
||||
if (keyType === 'number') {
|
||||
// TODO numeric key should has its own hash
|
||||
strKey = <string>key;
|
||||
} else {
|
||||
|
@ -264,7 +266,6 @@ export class HashMap<K = any, V = any> extends IterableEntryBase<K, V> {
|
|||
* 3. Time Complexity: Similar to HashMap, LinkedHashMap offers constant-time performance for get and put operations in most cases.
|
||||
*/
|
||||
export class LinkedHashMap<K = any, V = any> extends IterableEntryBase<K, V> {
|
||||
|
||||
protected _noObjMap: Record<string, HashMapLinkedNode<K, V | undefined>> = {};
|
||||
protected _objMap = new WeakMap<object, HashMapLinkedNode<K, V | undefined>>();
|
||||
protected _head: HashMapLinkedNode<K, V | undefined>;
|
||||
|
@ -273,12 +274,13 @@ export class LinkedHashMap<K = any, V = any> extends IterableEntryBase<K, V> {
|
|||
protected _hashFn: (key: K) => string;
|
||||
protected _objHashFn: (key: K) => object;
|
||||
|
||||
|
||||
constructor(elements?: Iterable<[K, V]>, options: HashMapOptions<K> = {
|
||||
|
||||
hashFn: (key: K) => String(key),
|
||||
objHashFn: (key: K) => (<object>key)
|
||||
}) {
|
||||
constructor(
|
||||
elements?: Iterable<[K, V]>,
|
||||
options: HashMapOptions<K> = {
|
||||
hashFn: (key: K) => String(key),
|
||||
objHashFn: (key: K) => <object>key
|
||||
}
|
||||
) {
|
||||
super();
|
||||
this._sentinel = <HashMapLinkedNode<K, V>>{};
|
||||
this._sentinel.prev = this._sentinel.next = this._head = this._tail = this._sentinel;
|
||||
|
|
|
@ -31,13 +31,13 @@ export class Heap<E = any> extends IterableElementBase<E> {
|
|||
} else {
|
||||
return a - b;
|
||||
}
|
||||
}
|
||||
};
|
||||
if (options) {
|
||||
this.options = options
|
||||
this.options = options;
|
||||
} else {
|
||||
this.options = {
|
||||
comparator: defaultComparator
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (elements) {
|
||||
|
@ -225,7 +225,8 @@ export class Heap<E = any> extends IterableElementBase<E> {
|
|||
|
||||
// Auxiliary recursive function, traverses the binary heap according to the traversal order
|
||||
const _dfs = (index: number) => {
|
||||
const left = 2 * index + 1, right = left + 1;
|
||||
const left = 2 * index + 1,
|
||||
right = left + 1;
|
||||
if (index < this.size) {
|
||||
if (order === 'in') {
|
||||
_dfs(left);
|
||||
|
@ -380,7 +381,6 @@ export class Heap<E = any> extends IterableElementBase<E> {
|
|||
* original Heap.
|
||||
*/
|
||||
map<T>(callback: ElementCallback<E, T>, comparator: Comparator<T>, thisArg?: any): Heap<T> {
|
||||
|
||||
const mappedHeap: Heap<T> = new Heap<T>([], { comparator: comparator });
|
||||
let index = 0;
|
||||
for (const el of this) {
|
||||
|
@ -432,13 +432,10 @@ export class Heap<E = any> extends IterableElementBase<E> {
|
|||
protected _sinkDown(index: number, halfLength: number): boolean {
|
||||
const element = this.elements[index];
|
||||
while (index < halfLength) {
|
||||
let left = index << 1 | 1;
|
||||
let left = (index << 1) | 1;
|
||||
const right = left + 1;
|
||||
let minItem = this.elements[left];
|
||||
if (
|
||||
right < this.elements.length &&
|
||||
this.options.comparator(minItem, this.elements[right]) > 0
|
||||
) {
|
||||
if (right < this.elements.length && this.options.comparator(minItem, this.elements[right]) > 0) {
|
||||
left = right;
|
||||
minItem = this.elements[right];
|
||||
}
|
||||
|
|
|
@ -29,7 +29,8 @@ export class MaxHeap<E = any> extends Heap<E> {
|
|||
return b - a;
|
||||
}
|
||||
}
|
||||
}) {
|
||||
}
|
||||
) {
|
||||
super(elements, options);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,8 @@ export class MinHeap<E = any> extends Heap<E> {
|
|||
return a - b;
|
||||
}
|
||||
}
|
||||
}) {
|
||||
}
|
||||
) {
|
||||
super(elements, options);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
||||
* @license MIT License
|
||||
*/
|
||||
import type { ElementCallback } from "../../types";
|
||||
import { IterableElementBase } from "../base";
|
||||
import type { ElementCallback } from '../../types';
|
||||
import { IterableElementBase } from '../base';
|
||||
|
||||
export class SinglyLinkedListNode<E = any> {
|
||||
value: E;
|
||||
|
@ -715,7 +715,6 @@ export class SinglyLinkedList<E = any> extends IterableElementBase<E> {
|
|||
return filteredList;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n), where n is the number of elements in the linked list.
|
||||
* Space Complexity: O(n)
|
||||
|
|
|
@ -9,16 +9,17 @@ import type { PriorityQueueOptions } from '../../types';
|
|||
import { PriorityQueue } from './priority-queue';
|
||||
|
||||
export class MinPriorityQueue<E = any> extends PriorityQueue<E> {
|
||||
constructor(elements?: Iterable<E>,
|
||||
options: PriorityQueueOptions<E> = {
|
||||
comparator: (a: E, b: E) => {
|
||||
if (!(typeof a === 'number' && typeof b === 'number')) {
|
||||
throw new Error('The a, b params of compare function must be number');
|
||||
} else {
|
||||
return a - b;
|
||||
}
|
||||
}
|
||||
}
|
||||
constructor(
|
||||
elements?: Iterable<E>,
|
||||
options: PriorityQueueOptions<E> = {
|
||||
comparator: (a: E, b: E) => {
|
||||
if (!(typeof a === 'number' && typeof b === 'number')) {
|
||||
throw new Error('The a, b params of compare function must be number');
|
||||
} else {
|
||||
return a - b;
|
||||
}
|
||||
}
|
||||
}
|
||||
) {
|
||||
super(elements, options);
|
||||
}
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
||||
* @license MIT License
|
||||
*/
|
||||
import type { ElementCallback, IterableWithSizeOrLength } from "../../types";
|
||||
import { IterableElementBase } from "../base";
|
||||
import { calcMinUnitsRequired, rangeCheck } from "../../utils";
|
||||
import type { ElementCallback, IterableWithSizeOrLength } from '../../types';
|
||||
import { IterableElementBase } from '../base';
|
||||
import { calcMinUnitsRequired, rangeCheck } from '../../utils';
|
||||
|
||||
/**
|
||||
* 1. Operations at Both Ends: Supports adding and removing elements at both the front and back of the queue. This allows it to be used as a stack (last in, first out) and a queue (first in, first out).
|
||||
|
@ -33,13 +33,15 @@ export class Deque<E> extends IterableElementBase<E> {
|
|||
* @param bucketSize - The `bucketSize` parameter is the maximum number of elements that can be
|
||||
* stored in each bucket. It determines the size of each bucket in the data structure.
|
||||
*/
|
||||
constructor(elements: IterableWithSizeOrLength<E> = [], bucketSize = (1 << 12)) {
|
||||
constructor(elements: IterableWithSizeOrLength<E> = [], bucketSize = 1 << 12) {
|
||||
super();
|
||||
let _size: number;
|
||||
if ('length' in elements) {
|
||||
if (elements.length instanceof Function) _size = elements.length(); else _size = elements.length;
|
||||
if (elements.length instanceof Function) _size = elements.length();
|
||||
else _size = elements.length;
|
||||
} else {
|
||||
if (elements.size instanceof Function) _size = elements.size(); else _size = elements.size;
|
||||
if (elements.size instanceof Function) _size = elements.size();
|
||||
else _size = elements.size;
|
||||
}
|
||||
|
||||
this._bucketSize = bucketSize;
|
||||
|
@ -49,7 +51,7 @@ export class Deque<E> extends IterableElementBase<E> {
|
|||
}
|
||||
const needBucketNum = calcMinUnitsRequired(_size, this._bucketSize);
|
||||
this._bucketFirst = this._bucketLast = (this._bucketCount >> 1) - (needBucketNum >> 1);
|
||||
this._firstInBucket = this._lastInBucket = (this._bucketSize - _size % this._bucketSize) >> 1;
|
||||
this._firstInBucket = this._lastInBucket = (this._bucketSize - (_size % this._bucketSize)) >> 1;
|
||||
|
||||
for (const element of elements) {
|
||||
this.push(element);
|
||||
|
@ -108,10 +110,7 @@ export class Deque<E> extends IterableElementBase<E> {
|
|||
this._bucketLast = 0;
|
||||
this._lastInBucket = 0;
|
||||
}
|
||||
if (
|
||||
this._bucketLast === this._bucketFirst &&
|
||||
this._lastInBucket === this._firstInBucket
|
||||
) this._reallocate();
|
||||
if (this._bucketLast === this._bucketFirst && this._lastInBucket === this._firstInBucket) this._reallocate();
|
||||
}
|
||||
this._size += 1;
|
||||
this._buckets[this._bucketLast][this._lastInBucket] = element;
|
||||
|
@ -175,10 +174,7 @@ export class Deque<E> extends IterableElementBase<E> {
|
|||
this._bucketFirst = this._bucketCount - 1;
|
||||
this._firstInBucket = this._bucketSize - 1;
|
||||
}
|
||||
if (
|
||||
this._bucketFirst === this._bucketLast &&
|
||||
this._firstInBucket === this._lastInBucket
|
||||
) this._reallocate();
|
||||
if (this._bucketFirst === this._bucketLast && this._firstInBucket === this._lastInBucket) this._reallocate();
|
||||
}
|
||||
this._size += 1;
|
||||
this._buckets[this._bucketFirst][this._firstInBucket] = element;
|
||||
|
@ -260,7 +256,6 @@ export class Deque<E> extends IterableElementBase<E> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Time Complexity: O(1)
|
||||
* Space Complexity: O(1)
|
||||
|
@ -278,14 +273,10 @@ export class Deque<E> extends IterableElementBase<E> {
|
|||
*/
|
||||
getAt(pos: number): E {
|
||||
rangeCheck(pos, 0, this.size - 1);
|
||||
const {
|
||||
bucketIndex,
|
||||
indexInBucket
|
||||
} = this._getBucketAndPosition(pos);
|
||||
const { bucketIndex, indexInBucket } = this._getBucketAndPosition(pos);
|
||||
return this._buckets[bucketIndex][indexInBucket]!;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Time Complexity: O(1)
|
||||
* Space Complexity: O(1)
|
||||
|
@ -303,10 +294,7 @@ export class Deque<E> extends IterableElementBase<E> {
|
|||
*/
|
||||
setAt(pos: number, element: E): boolean {
|
||||
rangeCheck(pos, 0, this.size - 1);
|
||||
const {
|
||||
bucketIndex,
|
||||
indexInBucket
|
||||
} = this._getBucketAndPosition(pos);
|
||||
const { bucketIndex, indexInBucket } = this._getBucketAndPosition(pos);
|
||||
this._buckets[bucketIndex][indexInBucket] = element;
|
||||
return true;
|
||||
}
|
||||
|
@ -370,10 +358,7 @@ export class Deque<E> extends IterableElementBase<E> {
|
|||
this.clear();
|
||||
return 0;
|
||||
}
|
||||
const {
|
||||
bucketIndex,
|
||||
indexInBucket
|
||||
} = this._getBucketAndPosition(pos);
|
||||
const { bucketIndex, indexInBucket } = this._getBucketAndPosition(pos);
|
||||
this._bucketLast = bucketIndex;
|
||||
this._lastInBucket = indexInBucket;
|
||||
this._size = pos + 1;
|
||||
|
@ -402,15 +387,9 @@ export class Deque<E> extends IterableElementBase<E> {
|
|||
else if (pos === this.size - 1) this.pop();
|
||||
else {
|
||||
const length = this.size - 1;
|
||||
let {
|
||||
bucketIndex: curBucket,
|
||||
indexInBucket: curPointer
|
||||
} = this._getBucketAndPosition(pos);
|
||||
let { bucketIndex: curBucket, indexInBucket: curPointer } = this._getBucketAndPosition(pos);
|
||||
for (let i = pos; i < length; ++i) {
|
||||
const {
|
||||
bucketIndex: nextBucket,
|
||||
indexInBucket: nextPointer
|
||||
} = this._getBucketAndPosition(pos + 1);
|
||||
const { bucketIndex: nextBucket, indexInBucket: nextPointer } = this._getBucketAndPosition(pos + 1);
|
||||
this._buckets[curBucket][curPointer] = this._buckets[nextBucket][nextPointer];
|
||||
curBucket = nextBucket;
|
||||
curPointer = nextPointer;
|
||||
|
@ -827,11 +806,11 @@ export class Deque<E> extends IterableElementBase<E> {
|
|||
bucketIndex -= this._bucketCount;
|
||||
}
|
||||
|
||||
indexInBucket = (overallIndex + 1) % this._bucketSize - 1;
|
||||
indexInBucket = ((overallIndex + 1) % this._bucketSize) - 1;
|
||||
if (indexInBucket < 0) {
|
||||
indexInBucket = this._bucketSize - 1;
|
||||
}
|
||||
|
||||
return { bucketIndex, indexInBucket };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* @class
|
||||
*/
|
||||
import type { ElementCallback } from '../../types';
|
||||
import { IterableElementBase } from "../base";
|
||||
import { IterableElementBase } from '../base';
|
||||
import { SinglyLinkedList } from '../linked-list';
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,10 +5,15 @@ import {
|
|||
BinaryTreeNodeNested,
|
||||
BinaryTreeOptions,
|
||||
BTNCallback,
|
||||
BTNExemplar,
|
||||
BTNExemplar
|
||||
} from '../types';
|
||||
|
||||
export interface IBinaryTree<K = number, V = any, N extends BinaryTreeNode<K, V, N> = BinaryTreeNodeNested<K, V>, TREE extends BinaryTree<K, V, N, TREE> = BinaryTreeNested<K, V, N>> {
|
||||
export interface IBinaryTree<
|
||||
K = number,
|
||||
V = any,
|
||||
N extends BinaryTreeNode<K, V, N> = BinaryTreeNodeNested<K, V>,
|
||||
TREE extends BinaryTree<K, V, N, TREE> = BinaryTreeNested<K, V, N>
|
||||
> {
|
||||
createNode(key: K, value?: N['value']): N;
|
||||
|
||||
createTree(options?: Partial<BinaryTreeOptions<K>>): TREE;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
export enum BSTVariant {
|
||||
MIN = 'MIN',
|
||||
MAX = 'MAX',
|
||||
MAX = 'MAX'
|
||||
}
|
||||
|
||||
export enum CP {
|
||||
|
@ -46,15 +46,15 @@ export interface IterableWithLength<T> extends Iterable<T> {
|
|||
length: number | ((...args: any[]) => number);
|
||||
}
|
||||
|
||||
export type IterableWithSizeOrLength<T> = IterableWithSize<T> | IterableWithLength<T>
|
||||
export type IterableWithSizeOrLength<T> = IterableWithSize<T> | IterableWithLength<T>;
|
||||
|
||||
export type BinaryTreePrintOptions = { isShowUndefined?: boolean, isShowNull?: boolean, isShowRedBlackNIL?: boolean }
|
||||
export type BinaryTreePrintOptions = { isShowUndefined?: boolean; isShowNull?: boolean; isShowRedBlackNIL?: boolean };
|
||||
|
||||
export type BTNEntry<K, V> = [K | null | undefined, V | undefined];
|
||||
|
||||
export type BTNKeyOrNode<K, N> = K | null | undefined | N;
|
||||
|
||||
export type BTNExemplar<K, V, N> = BTNEntry<K, V> | BTNKeyOrNode<K, N>
|
||||
export type BTNExemplar<K, V, N> = BTNEntry<K, V> | BTNKeyOrNode<K, N>;
|
||||
|
||||
export type BTNodePureKeyOrNode<K, N> = K | N;
|
||||
|
||||
|
|
|
@ -1,6 +1,17 @@
|
|||
import { IterableElementBase, IterableEntryBase } from "../../../data-structures";
|
||||
import { IterableElementBase, IterableEntryBase } from '../../../data-structures';
|
||||
|
||||
export type EntryCallback<K, V, R> = (value: V, key: K, index: number, container: IterableEntryBase<K, V>) => R;
|
||||
export type ElementCallback<V, R> = (element: V, index: number, container: IterableElementBase<V>) => R;
|
||||
export type ReduceEntryCallback<K, V, R> = (accumulator: R, value: V, key: K, index: number, container: IterableEntryBase<K, V>) => R;
|
||||
export type ReduceElementCallback<V, R> = (accumulator: R, element: V, index: number, container: IterableElementBase<V>) => R;
|
||||
export type ReduceEntryCallback<K, V, R> = (
|
||||
accumulator: R,
|
||||
value: V,
|
||||
key: K,
|
||||
index: number,
|
||||
container: IterableEntryBase<K, V>
|
||||
) => R;
|
||||
export type ReduceElementCallback<V, R> = (
|
||||
accumulator: R,
|
||||
element: V,
|
||||
index: number,
|
||||
container: IterableElementBase<V>
|
||||
) => R;
|
||||
|
|
|
@ -1 +1 @@
|
|||
export * from './base';
|
||||
export * from './base';
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
export type VertexKey = string | number;
|
||||
|
||||
export type DijkstraResult<V> = {
|
||||
export type DijkstraResult<V> =
|
||||
| {
|
||||
distMap: Map<V, number>;
|
||||
distPaths?: Map<V, V[]>;
|
||||
preMap: Map<V, V | undefined>;
|
||||
|
@ -8,4 +9,5 @@ export type DijkstraResult<V> = {
|
|||
paths: V[][];
|
||||
minDist: number;
|
||||
minPath: V[];
|
||||
} | undefined;
|
||||
}
|
||||
| undefined;
|
||||
|
|
|
@ -7,7 +7,7 @@ export type HashMapLinkedNode<K, V> = {
|
|||
|
||||
export type HashMapOptions<K> = {
|
||||
hashFn: (key: K) => string;
|
||||
objHashFn: (key: K) => object
|
||||
}
|
||||
objHashFn: (key: K) => object;
|
||||
};
|
||||
|
||||
export type HashMapStoreItem<K, V> = { key: K, value: V };
|
||||
export type HashMapStoreItem<K, V> = { key: K; value: V };
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import { Comparator } from "../../common";
|
||||
import { Comparator } from '../../common';
|
||||
|
||||
export type HeapOptions<T> = { comparator: Comparator<T> }
|
||||
export type HeapOptions<T> = { comparator: Comparator<T> };
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import { HeapOptions } from "../heap";
|
||||
import { HeapOptions } from '../heap';
|
||||
|
||||
export type PriorityQueueOptions<T> = HeapOptions<T> & {}
|
||||
export type PriorityQueueOptions<T> = HeapOptions<T> & {};
|
||||
|
|
|
@ -98,4 +98,5 @@ export const isWeakKey = (input: unknown): input is object => {
|
|||
return (inputType === 'object' && input !== null) || inputType === 'function';
|
||||
};
|
||||
|
||||
export const calcMinUnitsRequired = (totalQuantity: number, unitSize: number) => Math.floor((totalQuantity + unitSize - 1) / unitSize)
|
||||
export const calcMinUnitsRequired = (totalQuantity: number, unitSize: number) =>
|
||||
Math.floor((totalQuantity + unitSize - 1) / unitSize);
|
||||
|
|
|
@ -2,7 +2,24 @@ import { AVLTree, CP } from 'avl-tree-typed';
|
|||
|
||||
describe('AVL Tree Test', () => {
|
||||
it('should perform various operations on a AVL Tree', () => {
|
||||
const arr: [number, number][] = [[11, 11], [3, 3], [15, 15], [1, 1], [8, 8], [13, 13], [16, 16], [2, 2], [6, 6], [9, 9], [12, 12], [14, 14], [4, 4], [7, 7], [10, 10], [5, 5]];
|
||||
const arr: [number, number][] = [
|
||||
[11, 11],
|
||||
[3, 3],
|
||||
[15, 15],
|
||||
[1, 1],
|
||||
[8, 8],
|
||||
[13, 13],
|
||||
[16, 16],
|
||||
[2, 2],
|
||||
[6, 6],
|
||||
[9, 9],
|
||||
[12, 12],
|
||||
[14, 14],
|
||||
[4, 4],
|
||||
[7, 7],
|
||||
[10, 10],
|
||||
[5, 5]
|
||||
];
|
||||
const tree = new AVLTree();
|
||||
|
||||
for (const i of arr) tree.add(i);
|
||||
|
|
|
@ -45,7 +45,7 @@ suite.add(`${HUNDRED_THOUSAND.toLocaleString()} add & iterator`, () => {
|
|||
rbTree.clear();
|
||||
for (let i = 0; i < arr.length; i++) rbTree.add(arr[i]);
|
||||
const entries = [...rbTree];
|
||||
return entries.length === HUNDRED_THOUSAND
|
||||
return entries.length === HUNDRED_THOUSAND;
|
||||
});
|
||||
|
||||
export { suite };
|
||||
|
|
|
@ -22,25 +22,20 @@ const arrHundredThousand = getRandomIntArray(HUNDRED_THOUSAND, 0, HUNDRED_THOUSA
|
|||
|
||||
suite
|
||||
.add(`SRC PQ ${TEN_THOUSAND.toLocaleString()} add`, () => {
|
||||
|
||||
const pq = new SRCPriorityQueue<number>();
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) pq.add(i);
|
||||
})
|
||||
.add(`CJS PQ ${TEN_THOUSAND.toLocaleString()} add`, () => {
|
||||
|
||||
|
||||
const pq = new CJSPriorityQueue<number>();
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) pq.add(i);
|
||||
})
|
||||
.add(`MJS PQ ${TEN_THOUSAND.toLocaleString()} add`, () => {
|
||||
|
||||
const pq = new MJSPriorityQueue<number>([], { comparator: (a, b) => b - a });
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) pq.add(i);
|
||||
});
|
||||
|
||||
if (isCompetitor) {
|
||||
suite.add(`CPT PQ ${TEN_THOUSAND.toLocaleString()} add`, () => {
|
||||
|
||||
const pq = new CPriorityQueue<number>();
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) pq.push(i);
|
||||
});
|
||||
|
@ -66,14 +61,14 @@ suite
|
|||
for (let i = 0; i < TEN_THOUSAND; i++) pq.poll();
|
||||
});
|
||||
|
||||
|
||||
if (isCompetitor) {
|
||||
suite.add(`CPT PQ ${TEN_THOUSAND.toLocaleString()} add & pop`, () => {
|
||||
const pq = new CPriorityQueue<number>();
|
||||
suite
|
||||
.add(`CPT PQ ${TEN_THOUSAND.toLocaleString()} add & pop`, () => {
|
||||
const pq = new CPriorityQueue<number>();
|
||||
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) pq.push(i);
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) pq.pop();
|
||||
})
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) pq.push(i);
|
||||
for (let i = 0; i < TEN_THOUSAND; i++) pq.pop();
|
||||
})
|
||||
.add(`CPT OM ${HUNDRED_THOUSAND.toLocaleString()} add`, () => {
|
||||
for (let i = 0; i < arrHundredThousand.length; i++) {
|
||||
cOrderedMap.setElement(arrHundredThousand[i], arrHundredThousand[i]);
|
||||
|
|
|
@ -78,7 +78,6 @@ suite.add(`Native Set ${MILLION.toLocaleString()} add & has`, () => {
|
|||
for (let i = 0; i < MILLION; i++) hs.add(i);
|
||||
|
||||
for (let i = 0; i < MILLION; i++) hs.has(i);
|
||||
|
||||
});
|
||||
|
||||
suite.add(`${MILLION.toLocaleString()} ObjKey set & get`, () => {
|
||||
|
@ -86,7 +85,7 @@ suite.add(`${MILLION.toLocaleString()} ObjKey set & get`, () => {
|
|||
const objKeys: [number, number][] = [];
|
||||
for (let i = 0; i < MILLION; i++) {
|
||||
const obj: [number, number] = [i, i];
|
||||
objKeys.push(obj)
|
||||
objKeys.push(obj);
|
||||
hm.set(obj, i);
|
||||
}
|
||||
for (let i = 0; i < MILLION; i++) {
|
||||
|
@ -99,7 +98,7 @@ suite.add(`Native Map ${MILLION.toLocaleString()} ObjKey set & get`, () => {
|
|||
const objs: [number, number][] = [];
|
||||
for (let i = 0; i < MILLION; i++) {
|
||||
const obj: [number, number] = [i, i];
|
||||
objs.push(obj)
|
||||
objs.push(obj);
|
||||
hm.set(obj, i);
|
||||
}
|
||||
for (let i = 0; i < MILLION; i++) {
|
||||
|
@ -112,7 +111,7 @@ suite.add(`Native Set ${MILLION.toLocaleString()} ObjKey add & has`, () => {
|
|||
const objs: [number, number][] = [];
|
||||
for (let i = 0; i < MILLION; i++) {
|
||||
const obj: [number, number] = [i, i];
|
||||
objs.push(obj)
|
||||
objs.push(obj);
|
||||
hs.add(obj);
|
||||
}
|
||||
for (let i = 0; i < MILLION; i++) {
|
||||
|
|
|
@ -13,7 +13,6 @@ suite.add(`${MILLION.toLocaleString()} push`, () => {
|
|||
for (let i = 0; i < MILLION; i++) list.push(i);
|
||||
});
|
||||
|
||||
|
||||
if (isCompetitor) {
|
||||
suite.add(`CPT ${MILLION.toLocaleString()} push`, () => {
|
||||
const list = new CLinkedList<number>();
|
||||
|
|
|
@ -19,14 +19,13 @@ if (isCompetitor) {
|
|||
});
|
||||
}
|
||||
|
||||
suite
|
||||
.add(`${MILLION.toLocaleString()} push & pop`, () => {
|
||||
const _deque = new Deque<number>();
|
||||
|
||||
suite.add(`${MILLION.toLocaleString()} push & pop`, () => {
|
||||
const _deque = new Deque<number>();
|
||||
|
||||
for (let i = 0; i < MILLION; i++) _deque.push(i);
|
||||
for (let i = 0; i < MILLION; i++) _deque.pop();
|
||||
|
||||
})
|
||||
for (let i = 0; i < MILLION; i++) _deque.push(i);
|
||||
for (let i = 0; i < MILLION; i++) _deque.pop();
|
||||
})
|
||||
.add(`${HUNDRED_THOUSAND.toLocaleString()} push & shift`, () => {
|
||||
const _deque = new Deque<number>();
|
||||
|
||||
|
|
|
@ -33,16 +33,17 @@ suite.add(`${HUNDRED_THOUSAND.toLocaleString()} push & shift`, () => {
|
|||
queue.shift();
|
||||
}
|
||||
});
|
||||
suite.add(`Native Array ${HUNDRED_THOUSAND.toLocaleString()} push & shift`, () => {
|
||||
const arr = new Array<number>();
|
||||
suite
|
||||
.add(`Native Array ${HUNDRED_THOUSAND.toLocaleString()} push & shift`, () => {
|
||||
const arr = new Array<number>();
|
||||
|
||||
for (let i = 0; i < HUNDRED_THOUSAND; i++) {
|
||||
arr.push(i);
|
||||
}
|
||||
for (let i = 0; i < HUNDRED_THOUSAND; i++) {
|
||||
arr.shift();
|
||||
}
|
||||
})
|
||||
for (let i = 0; i < HUNDRED_THOUSAND; i++) {
|
||||
arr.push(i);
|
||||
}
|
||||
for (let i = 0; i < HUNDRED_THOUSAND; i++) {
|
||||
arr.shift();
|
||||
}
|
||||
})
|
||||
.add(`Native Array ${HUNDRED_THOUSAND.toLocaleString()} push & pop`, () => {
|
||||
const arr = new Array<number>();
|
||||
|
||||
|
|
|
@ -5,20 +5,19 @@ import * as fastGlob from 'fast-glob';
|
|||
import { Color, numberFix, render } from '../utils';
|
||||
import { PerformanceTest } from './types';
|
||||
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
const { GREEN, BOLD, END, YELLOW, GRAY, CYAN, BG_YELLOW } = Color;
|
||||
|
||||
const getRelativePath = (file: string) => {
|
||||
return path.relative(__dirname, file);
|
||||
}
|
||||
};
|
||||
const coloredLabeled = (label: string, file: string) => {
|
||||
const relativeFilePath = getRelativePath(file);
|
||||
const directory = path.dirname(relativeFilePath);
|
||||
const fileName = path.basename(relativeFilePath);
|
||||
return `${BG_YELLOW} ${label} ${END} ${GRAY}${directory}/${END}${CYAN}${fileName}${END}`;
|
||||
}
|
||||
};
|
||||
|
||||
const parentDirectory = path.resolve(__dirname, '../..');
|
||||
const reportDistPath = path.join(parentDirectory, 'benchmark');
|
||||
|
@ -29,20 +28,19 @@ let testFiles: string[];
|
|||
|
||||
let isIndividual = false;
|
||||
if (args.length > 0) {
|
||||
console.log(`arguments: ${args.join(' ')}`)
|
||||
console.log(`arguments: ${args.join(' ')}`);
|
||||
|
||||
testFiles = allFiles.filter(file =>
|
||||
args.every(word => file.includes(word))
|
||||
);
|
||||
testFiles = allFiles.filter(file => args.every(word => file.includes(word)));
|
||||
isIndividual = true;
|
||||
console.log(`${testFiles.map(file => coloredLabeled('Matched', file)).join(`
|
||||
`)}`);
|
||||
console.log(
|
||||
`${testFiles.map(file => coloredLabeled('Matched', file)).join(`
|
||||
`)}`
|
||||
);
|
||||
} else {
|
||||
isIndividual = false;
|
||||
testFiles = allFiles;
|
||||
}
|
||||
|
||||
|
||||
const report: { [key: string]: any } = {};
|
||||
|
||||
let completedCount = 0;
|
||||
|
@ -132,11 +130,12 @@ const composeReport = () => {
|
|||
html += `</div>
|
||||
</body>
|
||||
</html>`;
|
||||
if (!isIndividual) replaceMarkdownContent(
|
||||
'[//]: # (No deletion!!! Start of Replace Section)', // Start tag
|
||||
'[//]: # (No deletion!!! End of Replace Section)', // end identifier
|
||||
htmlTables // New content to be inserted
|
||||
);
|
||||
if (!isIndividual)
|
||||
replaceMarkdownContent(
|
||||
'[//]: # (No deletion!!! Start of Replace Section)', // Start tag
|
||||
'[//]: # (No deletion!!! End of Replace Section)', // end identifier
|
||||
htmlTables // New content to be inserted
|
||||
);
|
||||
fs.writeFileSync(htmlFilePath, html);
|
||||
console.log(`Performance ${BOLD}${GREEN}report${END} file generated in file://${BOLD}${GREEN}${htmlFilePath}${END}`);
|
||||
};
|
||||
|
|
|
@ -318,13 +318,20 @@ describe('AVLTree iterative methods test', () => {
|
|||
test('filter should return a new tree with filtered elements', () => {
|
||||
const filteredTree = avl.filter((value, key) => key > 1);
|
||||
expect(filteredTree.size).toBe(2);
|
||||
expect([...filteredTree]).toEqual([[2, 'b'], [3, 'c']]);
|
||||
expect([...filteredTree]).toEqual([
|
||||
[2, 'b'],
|
||||
[3, 'c']
|
||||
]);
|
||||
});
|
||||
|
||||
test('map should return a new tree with modified elements', () => {
|
||||
const mappedTree = avl.map((value, key) => (key * 2).toString());
|
||||
expect(mappedTree.size).toBe(3);
|
||||
expect([...mappedTree]).toEqual([[1, '2'], [2, '4'], [3, '6']]);
|
||||
expect([...mappedTree]).toEqual([
|
||||
[1, '2'],
|
||||
[2, '4'],
|
||||
[3, '6']
|
||||
]);
|
||||
});
|
||||
|
||||
test('reduce should accumulate values', () => {
|
||||
|
@ -339,7 +346,11 @@ describe('AVLTree iterative methods test', () => {
|
|||
}
|
||||
|
||||
expect(entries.length).toBe(3);
|
||||
expect(entries).toEqual([[1, 'a'], [2, 'b'], [3, 'c']]);
|
||||
expect(entries).toEqual([
|
||||
[1, 'a'],
|
||||
[2, 'b'],
|
||||
[3, 'c']
|
||||
]);
|
||||
});
|
||||
|
||||
test('should clone work well', () => {
|
||||
|
|
|
@ -265,7 +265,22 @@ describe('BinaryTree', () => {
|
|||
tree.clear();
|
||||
tree.addMany([-10, -10, -10, 9, 9, 20, null, null, 15, 7, 8, null, 2, null, 6, null, null, 8, 8, 8]);
|
||||
|
||||
expect(tree.bfs(node => node ? node.key : null, undefined, undefined, true)).toEqual([-10, 9, 20, null, null, 15, 7, 8, null, 2, null, 6, null, null])
|
||||
expect(tree.bfs(node => (node ? node.key : null), undefined, undefined, true)).toEqual([
|
||||
-10,
|
||||
9,
|
||||
20,
|
||||
null,
|
||||
null,
|
||||
15,
|
||||
7,
|
||||
8,
|
||||
null,
|
||||
2,
|
||||
null,
|
||||
6,
|
||||
null,
|
||||
null
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -525,18 +540,12 @@ describe('BinaryTree', () => {
|
|||
tree.add([3, 'B']);
|
||||
tree.add([7, 'C']);
|
||||
|
||||
const nodes = tree.getNodes('B', (node) => node.value);
|
||||
const nodes = tree.getNodes('B', node => node.value);
|
||||
|
||||
expect(nodes.length).toBe(1);
|
||||
expect(nodes[0].key).toBe(3);
|
||||
|
||||
const nodesRec = tree.getNodes(
|
||||
'B',
|
||||
(node) => node.value,
|
||||
false,
|
||||
tree.root,
|
||||
IterationType.RECURSIVE
|
||||
);
|
||||
const nodesRec = tree.getNodes('B', node => node.value, false, tree.root, IterationType.RECURSIVE);
|
||||
|
||||
expect(nodesRec.length).toBe(1);
|
||||
expect(nodesRec[0].key).toBe(3);
|
||||
|
@ -548,9 +557,17 @@ describe('BinaryTree', () => {
|
|||
tree.add([7, 'C']);
|
||||
|
||||
tree.iterationType = IterationType.ITERATIVE;
|
||||
expect([...tree]).toEqual([[3, "B"], [5, "A"], [7, "C"]]);
|
||||
expect([...tree]).toEqual([
|
||||
[3, 'B'],
|
||||
[5, 'A'],
|
||||
[7, 'C']
|
||||
]);
|
||||
tree.iterationType = IterationType.RECURSIVE;
|
||||
expect([...tree]).toEqual([[3, "B"], [5, "A"], [7, "C"]]);
|
||||
expect([...tree]).toEqual([
|
||||
[3, 'B'],
|
||||
[5, 'A'],
|
||||
[7, 'C']
|
||||
]);
|
||||
tree.iterationType = IterationType.ITERATIVE;
|
||||
|
||||
const result = tree.morris();
|
||||
|
@ -600,13 +617,20 @@ describe('BinaryTree iterative methods test', () => {
|
|||
test('filter should return a new tree with filtered elements', () => {
|
||||
const filteredTree = binaryTree.filter((value, key) => key > 1);
|
||||
expect(filteredTree.size).toBe(2);
|
||||
expect([...filteredTree]).toEqual([[3, 'c'], [2, 'b']]);
|
||||
expect([...filteredTree]).toEqual([
|
||||
[3, 'c'],
|
||||
[2, 'b']
|
||||
]);
|
||||
});
|
||||
|
||||
test('map should return a new tree with modified elements', () => {
|
||||
const mappedTree = binaryTree.map((value, key) => (key * 2).toString());
|
||||
expect(mappedTree.size).toBe(3);
|
||||
expect([...mappedTree]).toEqual([[1, '2'], [2, '4'], [3, '6']]);
|
||||
expect([...mappedTree]).toEqual([
|
||||
[1, '2'],
|
||||
[2, '4'],
|
||||
[3, '6']
|
||||
]);
|
||||
});
|
||||
|
||||
test('reduce should accumulate values', () => {
|
||||
|
@ -621,7 +645,11 @@ describe('BinaryTree iterative methods test', () => {
|
|||
}
|
||||
|
||||
expect(entries.length).toBe(3);
|
||||
expect(entries).toEqual([[2, 'b'], [1, 'a'], [3, 'c']]);
|
||||
expect(entries).toEqual([
|
||||
[2, 'b'],
|
||||
[1, 'a'],
|
||||
[3, 'c']
|
||||
]);
|
||||
});
|
||||
|
||||
test('should clone work well', () => {
|
||||
|
@ -641,17 +669,24 @@ describe('BinaryTree iterative methods test', () => {
|
|||
});
|
||||
|
||||
test('should iterative method return undefined when the node is null', () => {
|
||||
const tree = new BinaryTree()
|
||||
const tree = new BinaryTree();
|
||||
tree.addMany([-10, -10, -10, 9, 9, 20, null, null, 15, 7, 8, null, 2, null, 6, null, null, 8, 8, 8]);
|
||||
const bfsResult = tree.bfs(undefined, undefined, undefined, true);
|
||||
expect(bfsResult).toEqual([
|
||||
-10, 9,
|
||||
20, undefined,
|
||||
undefined, 15,
|
||||
7, 8,
|
||||
undefined, 2,
|
||||
undefined, 6,
|
||||
undefined, undefined
|
||||
-10,
|
||||
9,
|
||||
20,
|
||||
undefined,
|
||||
undefined,
|
||||
15,
|
||||
7,
|
||||
8,
|
||||
undefined,
|
||||
2,
|
||||
undefined,
|
||||
6,
|
||||
undefined,
|
||||
undefined
|
||||
]);
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -9,7 +9,22 @@ describe('BST operations test', () => {
|
|||
expect(bst).toBeInstanceOf(BST);
|
||||
bst.add([11, 11]);
|
||||
bst.add([3, 3]);
|
||||
const idsAndValues: [number, number][] = [[15, 15], [1, 1], [8, 8], [13, 13], [16, 16], [2, 2], [6, 6], [9, 9], [12, 12], [14, 14], [4, 4], [7, 7], [10, 10], [5, 5]];
|
||||
const idsAndValues: [number, number][] = [
|
||||
[15, 15],
|
||||
[1, 1],
|
||||
[8, 8],
|
||||
[13, 13],
|
||||
[16, 16],
|
||||
[2, 2],
|
||||
[6, 6],
|
||||
[9, 9],
|
||||
[12, 12],
|
||||
[14, 14],
|
||||
[4, 4],
|
||||
[7, 7],
|
||||
[10, 10],
|
||||
[5, 5]
|
||||
];
|
||||
bst.addMany(idsAndValues, undefined, false);
|
||||
expect(bst.root).toBeInstanceOf(BSTNode);
|
||||
|
||||
|
@ -194,22 +209,26 @@ describe('BST operations test', () => {
|
|||
objBST.add([11, { name: '11', age: 11 }]);
|
||||
objBST.add([3, { name: '3', age: 3 }]);
|
||||
|
||||
objBST.addMany([15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5], [
|
||||
{ "name": "Alice", "age": 15 },
|
||||
{ "name": "Bob", "age": 1 },
|
||||
{ "name": "Charlie", "age": 8 },
|
||||
{ "name": "David", "age": 13 },
|
||||
{ "name": "Emma", "age": 16 },
|
||||
{ "name": "Frank", "age": 2 },
|
||||
{ "name": "Grace", "age": 6 },
|
||||
{ "name": "Hannah", "age": 9 },
|
||||
{ "name": "Isaac", "age": 12 },
|
||||
{ "name": "Jack", "age": 14 },
|
||||
{ "name": "Katie", "age": 4 },
|
||||
{ "name": "Liam", "age": 7 },
|
||||
{ "name": "Mia", "age": 10 },
|
||||
{ "name": "Noah", "age": 5 }
|
||||
], false);
|
||||
objBST.addMany(
|
||||
[15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5],
|
||||
[
|
||||
{ name: 'Alice', age: 15 },
|
||||
{ name: 'Bob', age: 1 },
|
||||
{ name: 'Charlie', age: 8 },
|
||||
{ name: 'David', age: 13 },
|
||||
{ name: 'Emma', age: 16 },
|
||||
{ name: 'Frank', age: 2 },
|
||||
{ name: 'Grace', age: 6 },
|
||||
{ name: 'Hannah', age: 9 },
|
||||
{ name: 'Isaac', age: 12 },
|
||||
{ name: 'Jack', age: 14 },
|
||||
{ name: 'Katie', age: 4 },
|
||||
{ name: 'Liam', age: 7 },
|
||||
{ name: 'Mia', age: 10 },
|
||||
{ name: 'Noah', age: 5 }
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
expect(objBST.root).toBeInstanceOf(BSTNode);
|
||||
|
||||
|
@ -596,11 +615,7 @@ describe('BST operations test recursively', () => {
|
|||
[5, { key: 5, keyA: 5 }]
|
||||
];
|
||||
|
||||
objBST.addMany(
|
||||
entries,
|
||||
undefined,
|
||||
false
|
||||
);
|
||||
objBST.addMany(entries, undefined, false);
|
||||
|
||||
expect(objBST.root).toBeInstanceOf(BSTNode);
|
||||
|
||||
|
@ -878,13 +893,20 @@ describe('BST iterative methods test', () => {
|
|||
test('filter should return a new tree with filtered elements', () => {
|
||||
const filteredTree = bst.filter((value, key) => key > 1);
|
||||
expect(filteredTree.size).toBe(2);
|
||||
expect([...filteredTree]).toEqual([[2, 'b'], [3, 'c']]);
|
||||
expect([...filteredTree]).toEqual([
|
||||
[2, 'b'],
|
||||
[3, 'c']
|
||||
]);
|
||||
});
|
||||
|
||||
test('map should return a new tree with modified elements', () => {
|
||||
const mappedTree = bst.map((value, key) => (key * 2).toString());
|
||||
expect(mappedTree.size).toBe(3);
|
||||
expect([...mappedTree]).toEqual([[1, '2'], [2, '4'], [3, '6']]);
|
||||
expect([...mappedTree]).toEqual([
|
||||
[1, '2'],
|
||||
[2, '4'],
|
||||
[3, '6']
|
||||
]);
|
||||
});
|
||||
|
||||
test('reduce should accumulate values', () => {
|
||||
|
@ -899,7 +921,11 @@ describe('BST iterative methods test', () => {
|
|||
}
|
||||
|
||||
expect(entries.length).toBe(3);
|
||||
expect(entries).toEqual([[1, 'a'], [2, 'b'], [3, 'c']]);
|
||||
expect(entries).toEqual([
|
||||
[1, 'a'],
|
||||
[2, 'b'],
|
||||
[3, 'c']
|
||||
]);
|
||||
});
|
||||
|
||||
test('should clone work well', () => {
|
||||
|
@ -917,4 +943,4 @@ describe('BST iterative methods test', () => {
|
|||
const values = bst.values();
|
||||
expect([...values]).toEqual(['a', 'b', 'c']);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -33,24 +33,22 @@ describe('Overall BinaryTree Test', () => {
|
|||
objBST.add([11, { key: 11, keyA: 11 }]);
|
||||
objBST.add([3, { key: 3, keyA: 3 }]);
|
||||
|
||||
objBST.addMany(
|
||||
[
|
||||
[15, { key: 15, keyA: 15 }],
|
||||
[1, { key: 1, keyA: 1 }],
|
||||
[8, { key: 8, keyA: 8 }],
|
||||
[13, { key: 13, keyA: 13 }],
|
||||
[16, { key: 16, keyA: 16 }],
|
||||
[2, { key: 2, keyA: 2 }],
|
||||
[6, { key: 6, keyA: 6 }],
|
||||
[9, { key: 9, keyA: 9 }],
|
||||
[12, { key: 12, keyA: 12 }],
|
||||
[14, { key: 14, keyA: 14 }],
|
||||
[4, { key: 4, keyA: 4 }],
|
||||
[7, { key: 7, keyA: 7 }],
|
||||
[10, { key: 10, keyA: 10 }],
|
||||
[5, { key: 5, keyA: 5 }]
|
||||
]
|
||||
);
|
||||
objBST.addMany([
|
||||
[15, { key: 15, keyA: 15 }],
|
||||
[1, { key: 1, keyA: 1 }],
|
||||
[8, { key: 8, keyA: 8 }],
|
||||
[13, { key: 13, keyA: 13 }],
|
||||
[16, { key: 16, keyA: 16 }],
|
||||
[2, { key: 2, keyA: 2 }],
|
||||
[6, { key: 6, keyA: 6 }],
|
||||
[9, { key: 9, keyA: 9 }],
|
||||
[12, { key: 12, keyA: 12 }],
|
||||
[14, { key: 14, keyA: 14 }],
|
||||
[4, { key: 4, keyA: 4 }],
|
||||
[7, { key: 7, keyA: 7 }],
|
||||
[10, { key: 10, keyA: 10 }],
|
||||
[5, { key: 5, keyA: 5 }]
|
||||
]);
|
||||
|
||||
objBST.delete(11);
|
||||
|
||||
|
|
|
@ -501,9 +501,9 @@ describe('RedBlackTree', () => {
|
|||
expect(tree.isAVLBalanced()).toBe(true);
|
||||
|
||||
tree.clear();
|
||||
tree.addMany([10, 20, 30, 40, 50, 60])
|
||||
tree.addMany([10, 20, 30, 40, 50, 60]);
|
||||
expect(tree.isAVLBalanced()).toBe(false);
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('RedBlackTree iterative methods test', () => {
|
||||
|
@ -537,13 +537,20 @@ describe('RedBlackTree iterative methods test', () => {
|
|||
test('filter should return a new tree with filtered elements', () => {
|
||||
const filteredTree = rbTree.filter((value, key) => key > 1);
|
||||
expect(filteredTree.size).toBe(2);
|
||||
expect([...filteredTree]).toEqual([[2, 'b'], [3, 'c']]);
|
||||
expect([...filteredTree]).toEqual([
|
||||
[2, 'b'],
|
||||
[3, 'c']
|
||||
]);
|
||||
});
|
||||
|
||||
test('map should return a new tree with modified elements', () => {
|
||||
const mappedTree = rbTree.map((value, key) => (key * 2).toString());
|
||||
expect(mappedTree.size).toBe(3);
|
||||
expect([...mappedTree]).toEqual([[1, '2'], [2, '4'], [3, '6']]);
|
||||
expect([...mappedTree]).toEqual([
|
||||
[1, '2'],
|
||||
[2, '4'],
|
||||
[3, '6']
|
||||
]);
|
||||
});
|
||||
|
||||
test('reduce should accumulate values', () => {
|
||||
|
@ -558,6 +565,10 @@ describe('RedBlackTree iterative methods test', () => {
|
|||
}
|
||||
|
||||
expect(entries.length).toBe(3);
|
||||
expect(entries).toEqual([[1, 'a'], [2, 'b'], [3, 'c']]);
|
||||
expect(entries).toEqual([
|
||||
[1, 'a'],
|
||||
[2, 'b'],
|
||||
[3, 'c']
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -15,21 +15,30 @@ describe('TreeMultimap count', () => {
|
|||
let tm: TreeMultimap<number>;
|
||||
beforeEach(() => {
|
||||
tm = new TreeMultimap<number>();
|
||||
|
||||
})
|
||||
});
|
||||
it('Should added isolated node count ', () => {
|
||||
tm.addMany([[1, 1], [2, 2], [3, 3], [4, 4], [5, 5]]);
|
||||
tm.addMany([
|
||||
[1, 1],
|
||||
[2, 2],
|
||||
[3, 3],
|
||||
[4, 4],
|
||||
[5, 5]
|
||||
]);
|
||||
const newNode = new TreeMultimapNode(3, 33, 10);
|
||||
tm.add(newNode);
|
||||
expect(tm.count).toBe(15)
|
||||
})
|
||||
expect(tm.count).toBe(15);
|
||||
});
|
||||
|
||||
it('Should count', () => {
|
||||
tm.addMany([[1, 1], [2, 2], [3, 3]]);
|
||||
tm.lesserOrGreaterTraverse(node => node.count += 2, CP.gt, 1);
|
||||
expect(tm.count).toBe(7)
|
||||
})
|
||||
})
|
||||
tm.addMany([
|
||||
[1, 1],
|
||||
[2, 2],
|
||||
[3, 3]
|
||||
]);
|
||||
tm.lesserOrGreaterTraverse(node => (node.count += 2), CP.gt, 1);
|
||||
expect(tm.count).toBe(7);
|
||||
});
|
||||
});
|
||||
|
||||
describe('TreeMultimap operations test1', () => {
|
||||
it('should perform various operations on a Binary Search Tree with numeric values1', () => {
|
||||
|
@ -256,7 +265,7 @@ describe('TreeMultimap operations test1', () => {
|
|||
expect(objTreeMultimap).toBeInstanceOf(TreeMultimap);
|
||||
objTreeMultimap.add([11, { key: 11, keyA: 11 }]);
|
||||
objTreeMultimap.add([3, { key: 3, keyA: 3 }]);
|
||||
const values: [number, { key: number, keyA: number }][] = [
|
||||
const values: [number, { key: number; keyA: number }][] = [
|
||||
[15, { key: 15, keyA: 15 }],
|
||||
[1, { key: 1, keyA: 1 }],
|
||||
[8, { key: 8, keyA: 8 }],
|
||||
|
@ -273,9 +282,7 @@ describe('TreeMultimap operations test1', () => {
|
|||
[5, { key: 5, keyA: 5 }]
|
||||
];
|
||||
|
||||
objTreeMultimap.addMany(
|
||||
values
|
||||
);
|
||||
objTreeMultimap.addMany(values);
|
||||
|
||||
expect(objTreeMultimap.root).toBeInstanceOf(TreeMultimapNode);
|
||||
|
||||
|
@ -529,9 +536,7 @@ describe('TreeMultimap operations test recursively1', () => {
|
|||
[5, { key: 5, keyA: 5 }]
|
||||
];
|
||||
|
||||
objTreeMultimap.addMany(
|
||||
values
|
||||
);
|
||||
objTreeMultimap.addMany(values);
|
||||
|
||||
expect(objTreeMultimap.root).toBeInstanceOf(TreeMultimapNode);
|
||||
|
||||
|
@ -632,13 +637,20 @@ describe('TreeMultimap iterative methods test', () => {
|
|||
test('filter should return a new tree with filtered elements', () => {
|
||||
const filteredTree = treeMM.filter((value, key) => key > 1);
|
||||
expect(filteredTree.size).toBe(2);
|
||||
expect([...filteredTree]).toEqual([[2, 'b'], [3, 'c']]);
|
||||
expect([...filteredTree]).toEqual([
|
||||
[2, 'b'],
|
||||
[3, 'c']
|
||||
]);
|
||||
});
|
||||
|
||||
test('map should return a new tree with modified elements', () => {
|
||||
const mappedTree = treeMM.map((value, key) => (key * 2).toString());
|
||||
expect(mappedTree.size).toBe(3);
|
||||
expect([...mappedTree]).toEqual([[1, '2'], [2, '4'], [3, '6']]);
|
||||
expect([...mappedTree]).toEqual([
|
||||
[1, '2'],
|
||||
[2, '4'],
|
||||
[3, '6']
|
||||
]);
|
||||
});
|
||||
|
||||
test('reduce should accumulate values', () => {
|
||||
|
@ -653,11 +665,15 @@ describe('TreeMultimap iterative methods test', () => {
|
|||
}
|
||||
|
||||
expect(entries.length).toBe(3);
|
||||
expect(entries).toEqual([[1, 'a'], [2, 'b'], [3, 'c']]);
|
||||
expect(entries).toEqual([
|
||||
[1, 'a'],
|
||||
[2, 'b'],
|
||||
[3, 'c']
|
||||
]);
|
||||
});
|
||||
|
||||
test('should clone work well', () => {
|
||||
expect(treeMM.count).toBe(21)
|
||||
expect(treeMM.count).toBe(21);
|
||||
const cloned = treeMM.clone();
|
||||
expect(cloned.root?.left?.key).toBe(1);
|
||||
expect(cloned.root?.right?.value).toBe('c');
|
||||
|
|
|
@ -378,11 +378,61 @@ describe('Inherit from DirectedGraph and perform operations test2.', () => {
|
|||
|
||||
expect(predecessor).toBeInstanceOf(Array);
|
||||
expect(predecessor.length).toBe(9);
|
||||
expect(predecessor[0]).toEqual([vertex2, undefined, vertex2, undefined, vertex3, undefined, vertex4, undefined, undefined]);
|
||||
expect(predecessor[1]).toEqual([undefined, vertex1, undefined, vertex1, vertex3, undefined, vertex4, undefined, vertex1]);
|
||||
expect(predecessor[5]).toEqual([undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined]);
|
||||
expect(predecessor[7]).toEqual([undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined]);
|
||||
expect(predecessor[8]).toEqual([vertex7, vertex7, vertex7, vertex7, vertex7, undefined, undefined, undefined, vertex7]);
|
||||
expect(predecessor[0]).toEqual([
|
||||
vertex2,
|
||||
undefined,
|
||||
vertex2,
|
||||
undefined,
|
||||
vertex3,
|
||||
undefined,
|
||||
vertex4,
|
||||
undefined,
|
||||
undefined
|
||||
]);
|
||||
expect(predecessor[1]).toEqual([
|
||||
undefined,
|
||||
vertex1,
|
||||
undefined,
|
||||
vertex1,
|
||||
vertex3,
|
||||
undefined,
|
||||
vertex4,
|
||||
undefined,
|
||||
vertex1
|
||||
]);
|
||||
expect(predecessor[5]).toEqual([
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined
|
||||
]);
|
||||
expect(predecessor[7]).toEqual([
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined
|
||||
]);
|
||||
expect(predecessor[8]).toEqual([
|
||||
vertex7,
|
||||
vertex7,
|
||||
vertex7,
|
||||
vertex7,
|
||||
vertex7,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
vertex7
|
||||
]);
|
||||
}
|
||||
|
||||
const dijkstraRes12tt = myGraph.dijkstra(1, 2, true, true);
|
||||
|
@ -622,7 +672,10 @@ describe('DirectedGraph iterative Methods', () => {
|
|||
|
||||
test('filter should return vertexMap that satisfy the condition', () => {
|
||||
const filtered = graph.filter((value, vertex) => vertex === 'A' || vertex === 'B');
|
||||
expect(filtered).toEqual([["A", undefined], ["B", undefined]]);
|
||||
expect(filtered).toEqual([
|
||||
['A', undefined],
|
||||
['B', undefined]
|
||||
]);
|
||||
});
|
||||
|
||||
test('map should apply a function to each vertex and return a new array', () => {
|
||||
|
@ -637,53 +690,53 @@ describe('DirectedGraph iterative Methods', () => {
|
|||
|
||||
test('Removing an edge of a DirectedGraph should delete additional edges', () => {
|
||||
const dg = new DirectedGraph();
|
||||
dg.addVertex('hello')
|
||||
dg.addVertex('hi')
|
||||
dg.addVertex('hey')
|
||||
dg.addEdge('hello', 'hi')
|
||||
dg.addEdge('hello', 'hey')
|
||||
expect(dg.getEdge('hello', 'hi')?.src).toBe('hello')
|
||||
expect(dg.getEdge('hello', 'hi')?.dest).toBe('hi')
|
||||
expect(dg.getEdge('hello', 'hey')?.src).toBe('hello')
|
||||
expect(dg.getEdge('hello', 'hey')?.dest).toBe('hey')
|
||||
dg.deleteEdge('hello', 'hi')
|
||||
expect(dg.getEdge('hello', 'hi')).toBe(undefined)
|
||||
expect(dg.getEdge('hello', 'hey')).toBeInstanceOf(DirectedEdge)
|
||||
expect(dg.incomingEdgesOf("Hi")).toEqual([])
|
||||
dg.addVertex('hello');
|
||||
dg.addVertex('hi');
|
||||
dg.addVertex('hey');
|
||||
dg.addEdge('hello', 'hi');
|
||||
dg.addEdge('hello', 'hey');
|
||||
expect(dg.getEdge('hello', 'hi')?.src).toBe('hello');
|
||||
expect(dg.getEdge('hello', 'hi')?.dest).toBe('hi');
|
||||
expect(dg.getEdge('hello', 'hey')?.src).toBe('hello');
|
||||
expect(dg.getEdge('hello', 'hey')?.dest).toBe('hey');
|
||||
dg.deleteEdge('hello', 'hi');
|
||||
expect(dg.getEdge('hello', 'hi')).toBe(undefined);
|
||||
expect(dg.getEdge('hello', 'hey')).toBeInstanceOf(DirectedEdge);
|
||||
expect(dg.incomingEdgesOf('Hi')).toEqual([]);
|
||||
});
|
||||
|
||||
test('Removing a vertex of a DirectedGraph should delete additional edges', () => {
|
||||
const graph = new DirectedGraph();
|
||||
|
||||
graph.addVertex("Hello");
|
||||
graph.addVertex("Hi");
|
||||
graph.addVertex('Hello');
|
||||
graph.addVertex('Hi');
|
||||
|
||||
graph.addEdge("Hello", "Hi");
|
||||
graph.deleteVertex("Hello");
|
||||
graph.addEdge('Hello', 'Hi');
|
||||
graph.deleteVertex('Hello');
|
||||
|
||||
expect(graph.incomingEdgesOf("Hi")).toEqual([]);
|
||||
})
|
||||
expect(graph.incomingEdgesOf('Hi')).toEqual([]);
|
||||
});
|
||||
|
||||
test('Removing a vertex from a DirectedGraph should remove its edges', () => {
|
||||
const dg = new DirectedGraph();
|
||||
dg.addVertex('hello')
|
||||
dg.addVertex('world')
|
||||
dg.addVertex('earth')
|
||||
dg.addVertex('hello');
|
||||
dg.addVertex('world');
|
||||
dg.addVertex('earth');
|
||||
|
||||
dg.addEdge('hello', 'world')
|
||||
dg.addEdge('hello', 'earth')
|
||||
dg.addEdge('world', 'earth')
|
||||
dg.addEdge('hello', 'world');
|
||||
dg.addEdge('hello', 'earth');
|
||||
dg.addEdge('world', 'earth');
|
||||
|
||||
expect(dg.getEdge('hello', 'world')?.src).toBe('hello');
|
||||
expect(dg.edgeSet().length).toBe(3)
|
||||
expect(dg.edgeSet()[0].dest).toBe('world')
|
||||
expect(dg.edgeSet().length).toBe(3);
|
||||
expect(dg.edgeSet()[0].dest).toBe('world');
|
||||
|
||||
dg.deleteVertex('hello')
|
||||
expect(dg.edgeSet().length).toBe(1)
|
||||
expect(dg.edgeSet()?.[0].src).toBe('world')
|
||||
dg.deleteVertex('hello');
|
||||
expect(dg.edgeSet().length).toBe(1);
|
||||
expect(dg.edgeSet()?.[0].src).toBe('world');
|
||||
|
||||
expect(dg.getEdge('hello', 'world')).toBe(undefined);
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('DirectedGraph getCycles', () => {
|
||||
|
@ -702,8 +755,8 @@ describe('DirectedGraph getCycles', () => {
|
|||
graph.addEdge('E', 'B');
|
||||
const cycles = graph.getCycles();
|
||||
expect(cycles.length).toBe(1);
|
||||
expect(cycles[0]).toEqual(["B", "D", "E"]);
|
||||
})
|
||||
expect(cycles[0]).toEqual(['B', 'D', 'E']);
|
||||
});
|
||||
|
||||
test('should simple cycles graph getCycles return correct result', () => {
|
||||
const graph = new DirectedGraph();
|
||||
|
@ -719,8 +772,11 @@ describe('DirectedGraph getCycles', () => {
|
|||
graph.addEdge('A', 'D');
|
||||
graph.addEdge('D', 'C');
|
||||
const cycles = graph.getCycles();
|
||||
expect(cycles.length).toBe(2)
|
||||
expect(cycles).toEqual([["A", "B", "C"], ["A", "D", "C"]])
|
||||
expect(cycles.length).toBe(2);
|
||||
expect(cycles).toEqual([
|
||||
['A', 'B', 'C'],
|
||||
['A', 'D', 'C']
|
||||
]);
|
||||
});
|
||||
|
||||
test('should 3 cycles graph getCycles return correct result', () => {
|
||||
|
@ -746,8 +802,11 @@ describe('DirectedGraph getCycles', () => {
|
|||
graph.addEdge('G', 'A');
|
||||
|
||||
const cycles = graph.getCycles();
|
||||
expect(cycles.length).toBe(3)
|
||||
expect(cycles).toEqual([["A", "C", "G"], ["B", "D", "E"], ["B", "F", "E"]]);
|
||||
expect(cycles.length).toBe(3);
|
||||
expect(cycles).toEqual([
|
||||
['A', 'C', 'G'],
|
||||
['B', 'D', 'E'],
|
||||
['B', 'F', 'E']
|
||||
]);
|
||||
});
|
||||
})
|
||||
|
||||
});
|
||||
|
|
|
@ -176,53 +176,52 @@ describe('UndirectedGraph', () => {
|
|||
|
||||
test('Removing an edge of a UndirectedGraph should not delete additional edges', () => {
|
||||
const dg = new UndirectedGraph();
|
||||
dg.addVertex('hello')
|
||||
dg.addVertex('hi')
|
||||
dg.addVertex('hey')
|
||||
dg.addEdge('hello', 'hi')
|
||||
dg.addEdge('hello', 'hey')
|
||||
expect(dg.getEdge('hello', 'hi')?.vertexMap[0]).toBe('hello')
|
||||
expect(dg.getEdge('hello', 'hi')?.vertexMap[1]).toBe('hi')
|
||||
expect(dg.getEdge('hello', 'hey')?.vertexMap[0]).toBe('hello')
|
||||
expect(dg.getEdge('hello', 'hey')?.vertexMap[1]).toBe('hey')
|
||||
dg.deleteEdge('hello', 'hi')
|
||||
expect(dg.getEdge('hello', 'hi')).toBe(undefined)
|
||||
expect(dg.getEdge('hello', 'hey')).toBeInstanceOf(UndirectedEdge)
|
||||
dg.addVertex('hello');
|
||||
dg.addVertex('hi');
|
||||
dg.addVertex('hey');
|
||||
dg.addEdge('hello', 'hi');
|
||||
dg.addEdge('hello', 'hey');
|
||||
expect(dg.getEdge('hello', 'hi')?.vertexMap[0]).toBe('hello');
|
||||
expect(dg.getEdge('hello', 'hi')?.vertexMap[1]).toBe('hi');
|
||||
expect(dg.getEdge('hello', 'hey')?.vertexMap[0]).toBe('hello');
|
||||
expect(dg.getEdge('hello', 'hey')?.vertexMap[1]).toBe('hey');
|
||||
dg.deleteEdge('hello', 'hi');
|
||||
expect(dg.getEdge('hello', 'hi')).toBe(undefined);
|
||||
expect(dg.getEdge('hello', 'hey')).toBeInstanceOf(UndirectedEdge);
|
||||
});
|
||||
|
||||
|
||||
test('Removing a vertex of a DirectedGraph should delete additional edges', () => {
|
||||
const graph = new UndirectedGraph();
|
||||
|
||||
graph.addVertex("Hello");
|
||||
graph.addVertex("Hi");
|
||||
graph.addVertex('Hello');
|
||||
graph.addVertex('Hi');
|
||||
|
||||
graph.addEdge("Hello", "Hi");
|
||||
graph.deleteVertex("Hello");
|
||||
graph.addEdge('Hello', 'Hi');
|
||||
graph.deleteVertex('Hello');
|
||||
|
||||
expect(graph.edgesOf("Hi")).toEqual([]);
|
||||
})
|
||||
expect(graph.edgesOf('Hi')).toEqual([]);
|
||||
});
|
||||
|
||||
test('Removing a vertex from a UndirectedGraph should remove its edges', () => {
|
||||
const dg = new UndirectedGraph();
|
||||
dg.addVertex('hello')
|
||||
dg.addVertex('world')
|
||||
dg.addVertex('earth')
|
||||
dg.addVertex('hello');
|
||||
dg.addVertex('world');
|
||||
dg.addVertex('earth');
|
||||
|
||||
dg.addEdge('hello', 'world')
|
||||
dg.addEdge('hello', 'earth')
|
||||
dg.addEdge('world', 'earth')
|
||||
dg.addEdge('hello', 'world');
|
||||
dg.addEdge('hello', 'earth');
|
||||
dg.addEdge('world', 'earth');
|
||||
|
||||
expect(dg.getEdge('hello', 'world')?.vertexMap[0]).toBe('hello');
|
||||
expect(dg.edgeSet().length).toBe(3)
|
||||
expect(dg.edgeSet()[0].vertexMap).toEqual(['hello', 'world'])
|
||||
expect(dg.edgeSet().length).toBe(3);
|
||||
expect(dg.edgeSet()[0].vertexMap).toEqual(['hello', 'world']);
|
||||
|
||||
dg.deleteVertex('hello')
|
||||
expect(dg.edgeSet().length).toBe(1)
|
||||
expect(dg.edgeSet()?.[0].vertexMap[0]).toBe('world')
|
||||
dg.deleteVertex('hello');
|
||||
expect(dg.edgeSet().length).toBe(1);
|
||||
expect(dg.edgeSet()?.[0].vertexMap[0]).toBe('world');
|
||||
|
||||
expect(dg.getEdge('hello', 'world')).toBe(undefined);
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('cycles, strongly connected components, bridges, articular points in UndirectedGraph', () => {
|
||||
|
@ -258,8 +257,7 @@ describe('cycles, strongly connected components, bridges, articular points in Un
|
|||
expect(lowMap.size).toBe(8);
|
||||
});
|
||||
|
||||
it("Should return Infinity if dest is not found", () => {
|
||||
|
||||
it('Should return Infinity if dest is not found', () => {
|
||||
const graph = new UndirectedGraph<string>();
|
||||
|
||||
for (let i = 0; i < 3; ++i) {
|
||||
|
@ -291,8 +289,12 @@ describe('UndirectedGraph getCycles', () => {
|
|||
graph.addEdge('E', 'B');
|
||||
const cycles = graph.getCycles();
|
||||
expect(cycles.length).toBe(3);
|
||||
expect(cycles).toEqual([["A", "B", "D", "C"], ["A", "B", "E", "D", "C"], ["B", "D", "E"]]);
|
||||
})
|
||||
expect(cycles).toEqual([
|
||||
['A', 'B', 'D', 'C'],
|
||||
['A', 'B', 'E', 'D', 'C'],
|
||||
['B', 'D', 'E']
|
||||
]);
|
||||
});
|
||||
|
||||
test('should simple cycles graph getCycles return correct result', () => {
|
||||
const graph = new UndirectedGraph();
|
||||
|
@ -308,8 +310,12 @@ describe('UndirectedGraph getCycles', () => {
|
|||
graph.addEdge('A', 'D');
|
||||
graph.addEdge('D', 'C');
|
||||
const cycles = graph.getCycles();
|
||||
expect(cycles.length).toBe(3)
|
||||
expect(cycles).toEqual([["A", "B", "C"], ["A", "B", "C", "D"], ["A", "C", "D"]])
|
||||
expect(cycles.length).toBe(3);
|
||||
expect(cycles).toEqual([
|
||||
['A', 'B', 'C'],
|
||||
['A', 'B', 'C', 'D'],
|
||||
['A', 'C', 'D']
|
||||
]);
|
||||
});
|
||||
|
||||
test('should 3 cycles graph getCycles return correct result', () => {
|
||||
|
@ -335,7 +341,18 @@ describe('UndirectedGraph getCycles', () => {
|
|||
graph.addEdge('G', 'A');
|
||||
|
||||
const cycles = graph.getCycles();
|
||||
expect(cycles.length).toBe(10)
|
||||
expect(cycles).toEqual([["A", "B", "D", "C"], ["A", "B", "D", "C", "G"], ["A", "B", "E", "D", "C"], ["A", "B", "E", "D", "C", "G"], ["A", "B", "F", "E", "D", "C"], ["A", "B", "F", "E", "D", "C", "G"], ["A", "C", "G"], ["B", "D", "E"], ["B", "D", "E", "F"], ["B", "E", "F"]]);
|
||||
expect(cycles.length).toBe(10);
|
||||
expect(cycles).toEqual([
|
||||
['A', 'B', 'D', 'C'],
|
||||
['A', 'B', 'D', 'C', 'G'],
|
||||
['A', 'B', 'E', 'D', 'C'],
|
||||
['A', 'B', 'E', 'D', 'C', 'G'],
|
||||
['A', 'B', 'F', 'E', 'D', 'C'],
|
||||
['A', 'B', 'F', 'E', 'D', 'C', 'G'],
|
||||
['A', 'C', 'G'],
|
||||
['B', 'D', 'E'],
|
||||
['B', 'D', 'E', 'F'],
|
||||
['B', 'E', 'F']
|
||||
]);
|
||||
});
|
||||
})
|
||||
});
|
||||
|
|
|
@ -54,7 +54,6 @@ describe('HashMap Test1', () => {
|
|||
hashMap.set('one', 1);
|
||||
hashMap.set('two', 2);
|
||||
hashMap.set('three', 3);
|
||||
|
||||
});
|
||||
|
||||
it('should resize the table when load factor is exceeded', () => {
|
||||
|
@ -181,7 +180,6 @@ describe('HashMap Test2', () => {
|
|||
}
|
||||
compareHashMaps(hashMap, stdMap);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('HashMap for coordinate object keys', () => {
|
||||
|
@ -207,30 +205,39 @@ describe('HashMap for coordinate object keys', () => {
|
|||
|
||||
test('delete elements in hash map', () => {
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
if (i === 500) expect(hashMap.size).toBe(500)
|
||||
if (i === 500) expect(hashMap.size).toBe(500);
|
||||
const codObj = codObjs[i];
|
||||
if (codObj) hashMap.delete(codObj);
|
||||
}
|
||||
expect(hashMap.size).toBe(0);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('HashMap setMany, keys, values', () => {
|
||||
const hm: HashMap<number, number> = new HashMap<number, number>();
|
||||
|
||||
beforeEach(() => {
|
||||
hm.clear()
|
||||
hm.setMany([[2, 2], [3, 3], [4, 4], [5, 5]])
|
||||
hm.setMany([[2, 2], [3, 3], [4, 4], [6, 6]])
|
||||
})
|
||||
hm.clear();
|
||||
hm.setMany([
|
||||
[2, 2],
|
||||
[3, 3],
|
||||
[4, 4],
|
||||
[5, 5]
|
||||
]);
|
||||
hm.setMany([
|
||||
[2, 2],
|
||||
[3, 3],
|
||||
[4, 4],
|
||||
[6, 6]
|
||||
]);
|
||||
});
|
||||
|
||||
test('keys', () => {
|
||||
expect([...hm.keys()]).toEqual([2, 3, 4, 5, 6])
|
||||
expect([...hm.keys()]).toEqual([2, 3, 4, 5, 6]);
|
||||
});
|
||||
|
||||
test('values', () => {
|
||||
expect([...hm.values()]).toEqual([2, 3, 4, 5, 6])
|
||||
expect([...hm.values()]).toEqual([2, 3, 4, 5, 6]);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -245,7 +252,7 @@ describe('HashMap HOF', () => {
|
|||
});
|
||||
|
||||
test('every() returns true if all elements match the condition', () => {
|
||||
expect(hashMap.every((value) => typeof value === 'string')).toBe(true);
|
||||
expect(hashMap.every(value => typeof value === 'string')).toBe(true);
|
||||
});
|
||||
|
||||
test('some() returns true if any element matches the condition', () => {
|
||||
|
@ -259,7 +266,7 @@ describe('HashMap HOF', () => {
|
|||
});
|
||||
|
||||
test('map() should transform each element', () => {
|
||||
const newHashMap = hashMap.map((value) => value.toUpperCase());
|
||||
const newHashMap = hashMap.map(value => value.toUpperCase());
|
||||
expect(newHashMap.get('key1')).toBe('VALUE1');
|
||||
});
|
||||
|
||||
|
@ -274,7 +281,6 @@ describe('HashMap HOF', () => {
|
|||
});
|
||||
});
|
||||
|
||||
|
||||
describe('LinkedHashMap Test1', () => {
|
||||
let hashMap: LinkedHashMap<string, number>;
|
||||
|
||||
|
@ -368,7 +374,6 @@ describe('LinkedHashMap Test1', () => {
|
|||
// expect(hashMap.table[0].length).toBe(2);
|
||||
});
|
||||
|
||||
|
||||
// it('should handle number keys correctly', () => {
|
||||
// const hm = new LinkedHashMap();
|
||||
// hm.set(999, { a: '999Value' });
|
||||
|
@ -529,50 +534,65 @@ describe('LinkedHashMap for coordinate object keys', () => {
|
|||
|
||||
test('delete elements in hash map', () => {
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
if (i === 500) expect(hashMap.size).toBe(500)
|
||||
if (i === 500) expect(hashMap.size).toBe(500);
|
||||
const codObj = codObjs[i];
|
||||
if (codObj) hashMap.delete(codObj);
|
||||
}
|
||||
expect(hashMap.size).toBe(0);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('LinkedHashMap setMany, keys, values', () => {
|
||||
const hm: LinkedHashMap<number, number> = new LinkedHashMap<number, number>();
|
||||
|
||||
beforeEach(() => {
|
||||
hm.clear()
|
||||
hm.setMany([[2, 2], [3, 3], [4, 4], [5, 5]])
|
||||
hm.setMany([[2, 2], [3, 3], [4, 4], [6, 6]])
|
||||
})
|
||||
hm.clear();
|
||||
hm.setMany([
|
||||
[2, 2],
|
||||
[3, 3],
|
||||
[4, 4],
|
||||
[5, 5]
|
||||
]);
|
||||
hm.setMany([
|
||||
[2, 2],
|
||||
[3, 3],
|
||||
[4, 4],
|
||||
[6, 6]
|
||||
]);
|
||||
});
|
||||
|
||||
test('keys', () => {
|
||||
expect([...hm.keys()]).toEqual([2, 3, 4, 5, 6])
|
||||
expect([...hm.keys()]).toEqual([2, 3, 4, 5, 6]);
|
||||
});
|
||||
|
||||
test('values', () => {
|
||||
expect([...hm.values()]).toEqual([2, 3, 4, 5, 6])
|
||||
expect([...hm.values()]).toEqual([2, 3, 4, 5, 6]);
|
||||
});
|
||||
|
||||
test('entries', () => {
|
||||
expect([...hm.entries()]).toEqual([[2, 2], [3, 3], [4, 4], [5, 5], [6, 6]])
|
||||
expect([...hm.entries()]).toEqual([
|
||||
[2, 2],
|
||||
[3, 3],
|
||||
[4, 4],
|
||||
[5, 5],
|
||||
[6, 6]
|
||||
]);
|
||||
});
|
||||
|
||||
test('every', () => {
|
||||
expect(hm.every(value => value > 4)).toBe(false)
|
||||
expect(hm.every(value => value > 4)).toBe(false);
|
||||
});
|
||||
|
||||
test('some', () => {
|
||||
expect(hm.some(value => value > 6)).toBe(false)
|
||||
expect(hm.some(value => value > 6)).toBe(false);
|
||||
});
|
||||
|
||||
test('hasValue', () => {
|
||||
expect(hm.hasValue(3)).toBe(true)
|
||||
expect(hm.hasValue(7)).toBe(false)
|
||||
expect(hm.hasValue(3)).toBe(true);
|
||||
expect(hm.hasValue(7)).toBe(false);
|
||||
});
|
||||
|
||||
test('print', () => {
|
||||
hm.print();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -185,7 +185,6 @@ describe('HashTable performance', function () {
|
|||
});
|
||||
});
|
||||
|
||||
|
||||
describe('HashTable methods', () => {
|
||||
let hashTable: HashTable<string, string>;
|
||||
|
||||
|
@ -215,7 +214,6 @@ describe('HashTable methods', () => {
|
|||
// }
|
||||
// });
|
||||
|
||||
|
||||
test('filter should return a new HashTable with elements that satisfy the condition', () => {
|
||||
const filtered = hashTable.filter(([key]) => key.endsWith('1') || key.endsWith('3'));
|
||||
|
||||
|
@ -237,6 +235,4 @@ describe('HashTable methods', () => {
|
|||
|
||||
expect(result).toBe('-value5-value7-value3-value4-value6-value0-value2-value8-value1-value9');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { FibonacciHeap, MaxHeap, MinHeap } from '../../../../src';
|
||||
import { logBigOMetricsWrap } from '../../../utils';
|
||||
|
||||
|
||||
describe('Heap Operation Test', () => {
|
||||
it('should numeric heap work well', function () {
|
||||
const minNumHeap = new MinHeap<number>();
|
||||
|
|
|
@ -50,17 +50,15 @@ describe('MinHeap', () => {
|
|||
expect(minHeap.isEmpty()).toBe(true);
|
||||
});
|
||||
|
||||
|
||||
const n = 100000;
|
||||
|
||||
it('should push & dfs', () => {
|
||||
for (let i = 0; i < n; i++) {
|
||||
minHeap.add(i);
|
||||
}
|
||||
expect(minHeap.dfs()[0]).toBe(0)
|
||||
expect(minHeap.dfs()[999]).toBe(4126)
|
||||
expect(minHeap.dfs()[0]).toBe(0);
|
||||
expect(minHeap.dfs()[999]).toBe(4126);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Heap iterative methods', () => {
|
||||
|
@ -89,7 +87,10 @@ describe('Heap iterative methods', () => {
|
|||
});
|
||||
|
||||
test('map method correctly maps elements', () => {
|
||||
const result = heap.map(x => x / 10, (a: number, b: number) => a - b);
|
||||
const result = heap.map(
|
||||
x => x / 10,
|
||||
(a: number, b: number) => a - b
|
||||
);
|
||||
expect([...result]).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
||||
});
|
||||
|
||||
|
|
|
@ -398,16 +398,15 @@ describe('DoublyLinkedList Operation Test', () => {
|
|||
});
|
||||
});
|
||||
|
||||
|
||||
describe('iterable methods', () => {
|
||||
it('should forEach, some, every, filter, map, reduce of the deque', () => {
|
||||
const dl = new DoublyLinkedList<number>()
|
||||
const dl = new DoublyLinkedList<number>();
|
||||
dl.push(1);
|
||||
dl.push(2);
|
||||
dl.push(3);
|
||||
|
||||
const mockCallback = jest.fn();
|
||||
dl.forEach((element) => {
|
||||
dl.forEach(element => {
|
||||
mockCallback(element);
|
||||
});
|
||||
|
||||
|
@ -426,7 +425,7 @@ describe('iterable methods', () => {
|
|||
});
|
||||
|
||||
test('values', () => {
|
||||
const dl = new DoublyLinkedList<number>()
|
||||
const dl = new DoublyLinkedList<number>();
|
||||
dl.push(1);
|
||||
dl.push(2);
|
||||
dl.push(3);
|
||||
|
@ -435,11 +434,11 @@ describe('iterable methods', () => {
|
|||
dl.shift();
|
||||
dl.pop();
|
||||
dl.unshift(3);
|
||||
expect([...dl.values()]).toEqual([3, 1])
|
||||
})
|
||||
expect([...dl.values()]).toEqual([3, 1]);
|
||||
});
|
||||
|
||||
test('some', () => {
|
||||
const dl = new DoublyLinkedList<number>()
|
||||
const dl = new DoublyLinkedList<number>();
|
||||
dl.push(1);
|
||||
dl.push(2);
|
||||
dl.push(3);
|
||||
|
@ -448,7 +447,7 @@ describe('iterable methods', () => {
|
|||
dl.shift();
|
||||
dl.pop();
|
||||
dl.unshift(3);
|
||||
expect(dl.some(value => value > 1)).toBe(true)
|
||||
expect(dl.some(value => value > 100)).toBe(false)
|
||||
})
|
||||
});
|
||||
expect(dl.some(value => value > 1)).toBe(true);
|
||||
expect(dl.some(value => value > 100)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -472,13 +472,12 @@ describe('SinglyLinkedList', () => {
|
|||
});
|
||||
});
|
||||
|
||||
|
||||
describe('iterable methods', () => {
|
||||
it('should forEach, some, every, filter, map, reduce of the deque', () => {
|
||||
const sl = new SinglyLinkedList<number>([1, 2, 3])
|
||||
const sl = new SinglyLinkedList<number>([1, 2, 3]);
|
||||
|
||||
const mockCallback = jest.fn();
|
||||
sl.forEach((element) => {
|
||||
sl.forEach(element => {
|
||||
mockCallback(element);
|
||||
});
|
||||
|
||||
|
@ -495,4 +494,4 @@ describe('iterable methods', () => {
|
|||
expect([...sl.map(element => element * 2)]).toEqual([2, 4, 6]);
|
||||
expect(sl.reduce((accumulator, element) => accumulator + element, 0)).toEqual(6);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -63,7 +63,7 @@ describe('MaxPriorityQueue Operation Test', () => {
|
|||
|
||||
it('should correctly heapify an object array', () => {
|
||||
const elements = [{ keyA: 5 }, { keyA: 3 }, { keyA: 7 }, { keyA: 1 }];
|
||||
debugger
|
||||
debugger;
|
||||
const maxPQ = MaxPriorityQueue.heapify<{ keyA: number }>(elements, { comparator: (a, b) => b.keyA - a.keyA });
|
||||
|
||||
expect(maxPQ.poll()?.keyA).toBe(7);
|
||||
|
|
|
@ -31,7 +31,6 @@ describe('PriorityQueue Operation Test', () => {
|
|||
expect(maxPriorityQueue.peek()).toBe(3);
|
||||
expect(
|
||||
PriorityQueue.heapify([3, 2, 1, 5, 6, 7, 8, 9, 10], {
|
||||
|
||||
comparator: (a, b) => a - b
|
||||
}).toArray()
|
||||
).toEqual([1, 3, 2, 5, 6, 7, 8, 9, 10]);
|
||||
|
|
|
@ -170,7 +170,6 @@ describe('Deque - Utility Operations', () => {
|
|||
deque.print();
|
||||
expect(consoleSpy).toHaveBeenCalledWith([1, 2]);
|
||||
});
|
||||
|
||||
});
|
||||
describe('Deque - Additional Operations', () => {
|
||||
let deque: Deque<number>;
|
||||
|
@ -229,7 +228,6 @@ describe('Deque - Additional Operations', () => {
|
|||
expect(iterator.next().value).toBe(2);
|
||||
expect(iterator.next().value).toBe(1);
|
||||
});
|
||||
|
||||
});
|
||||
describe('Deque - push Method', () => {
|
||||
let deque: Deque<number>;
|
||||
|
@ -264,7 +262,6 @@ describe('Deque - push Method', () => {
|
|||
});
|
||||
|
||||
test('push should add an element and reallocate when last bucket and lastInBucket are at max', () => {
|
||||
|
||||
for (let i = 0; i < 100; i++) {
|
||||
deque.push(i);
|
||||
}
|
||||
|
@ -303,8 +300,6 @@ describe('Deque - pop Method', () => {
|
|||
const lastElement = deque.last;
|
||||
expect(deque.pop()).toBe(lastElement);
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
describe('Deque - unshift Method', () => {
|
||||
|
@ -368,6 +363,5 @@ describe('Deque - shift Method', () => {
|
|||
const firstElement = deque.first;
|
||||
expect(deque.shift()).toBe(firstElement);
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
@ -241,4 +241,4 @@ describe('LinkedListQueue', () => {
|
|||
queue.enqueue('B');
|
||||
expect(queue.peek()).toBe('A');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -66,7 +66,6 @@ describe('Stack', () => {
|
|||
});
|
||||
});
|
||||
|
||||
|
||||
describe('Stack iterative methods', () => {
|
||||
let stack: Stack<number>; // Declare a Stack instance
|
||||
|
||||
|
@ -88,7 +87,7 @@ describe('Stack iterative methods', () => {
|
|||
|
||||
test('should apply forEach to the stack', () => {
|
||||
const result: number[] = [];
|
||||
stack.forEach((element) => {
|
||||
stack.forEach(element => {
|
||||
result.push(element);
|
||||
});
|
||||
|
||||
|
@ -96,14 +95,14 @@ describe('Stack iterative methods', () => {
|
|||
});
|
||||
|
||||
test('should filter elements in the stack', () => {
|
||||
const filteredStack = stack.filter((element) => element > 1);
|
||||
const filteredStack = stack.filter(element => element > 1);
|
||||
|
||||
expect(filteredStack.size).toBe(2);
|
||||
expect([...filteredStack]).toEqual([2, 3]);
|
||||
});
|
||||
|
||||
test('should map elements in the stack', () => {
|
||||
const mappedStack = stack.map((element) => element * 2);
|
||||
const mappedStack = stack.map(element => element * 2);
|
||||
|
||||
expect(mappedStack.size).toBe(3);
|
||||
expect([...mappedStack]).toEqual([2, 4, 6]);
|
||||
|
|
|
@ -17,122 +17,132 @@ import {
|
|||
TreeMultimap,
|
||||
Trie
|
||||
} from '../../src';
|
||||
import { isDebugTest } from "../config";
|
||||
import { isDebugTest } from '../config';
|
||||
|
||||
const isDebug = isDebugTest;
|
||||
const orgArr: number[] = [6, 1, 2, 7, 5, 3, 4, 9, 8];
|
||||
const orgStrArr: string[] = [
|
||||
"trie",
|
||||
"trial",
|
||||
"trick",
|
||||
"trip",
|
||||
"tree",
|
||||
"trend",
|
||||
"triangle",
|
||||
"track",
|
||||
"trace",
|
||||
"transmit"
|
||||
'trie',
|
||||
'trial',
|
||||
'trick',
|
||||
'trip',
|
||||
'tree',
|
||||
'trend',
|
||||
'triangle',
|
||||
'track',
|
||||
'trace',
|
||||
'transmit'
|
||||
];
|
||||
const entries: [number, number][] = [
|
||||
[6, 6],
|
||||
[1, 1],
|
||||
[2, 2],
|
||||
[7, 7],
|
||||
[5, 5],
|
||||
[3, 3],
|
||||
[4, 4],
|
||||
[9, 9],
|
||||
[8, 8]
|
||||
];
|
||||
const entries: [number, number][] = [[6, 6], [1, 1], [2, 2], [7, 7], [5, 5], [3, 3], [4, 4], [9, 9], [8, 8]];
|
||||
|
||||
describe('conversions', () => {
|
||||
it('Array to Queue', () => {
|
||||
const q = new Queue<number>(orgArr);
|
||||
isDebug && q.print();
|
||||
})
|
||||
});
|
||||
|
||||
it('Array to Deque', () => {
|
||||
const dq = new Deque<number>(orgArr);
|
||||
isDebug && dq.print();
|
||||
})
|
||||
});
|
||||
|
||||
it('Array to SinglyLinkedList', () => {
|
||||
const sl = new SinglyLinkedList<number>(orgArr);
|
||||
isDebug && sl.print();
|
||||
})
|
||||
});
|
||||
|
||||
it('Array to DoublyLinkedList', () => {
|
||||
const dl = new DoublyLinkedList<number>(orgArr);
|
||||
isDebug && dl.print();
|
||||
})
|
||||
});
|
||||
|
||||
it('Array to Stack', () => {
|
||||
const stack = new Stack<number>(orgArr);
|
||||
isDebug && stack.print();
|
||||
})
|
||||
});
|
||||
|
||||
it('Array to MinHeap', () => {
|
||||
const minHeap = new MinHeap<number>(orgArr);
|
||||
isDebug && minHeap.print();
|
||||
})
|
||||
});
|
||||
|
||||
it('Array to MaxHeap', () => {
|
||||
const maxHeap = new MaxHeap<number>(orgArr);
|
||||
isDebug && maxHeap.print();
|
||||
})
|
||||
});
|
||||
|
||||
it('Array to MinPriorityQueue', () => {
|
||||
const minPQ = new MinPriorityQueue<number>(orgArr);
|
||||
isDebug && minPQ.print();
|
||||
})
|
||||
});
|
||||
|
||||
it('Array to MaxPriorityQueue', () => {
|
||||
const maxPQ = new MaxPriorityQueue<number>(orgArr);
|
||||
isDebug && maxPQ.print();
|
||||
})
|
||||
});
|
||||
|
||||
it('Entry Array to BinaryTree', () => {
|
||||
const biTree = new BinaryTree<number>(entries);
|
||||
isDebug && biTree.print();
|
||||
})
|
||||
});
|
||||
|
||||
it('Entry Array to BST', () => {
|
||||
const bst = new BST<number>(entries);
|
||||
expect(bst.size).toBe(9)
|
||||
expect(bst.size).toBe(9);
|
||||
isDebug && bst.print();
|
||||
})
|
||||
});
|
||||
|
||||
it('Entry Array to RedBlackTree', () => {
|
||||
const rbTree = new RedBlackTree<number>(entries);
|
||||
expect(rbTree.size).toBe(9)
|
||||
expect(rbTree.size).toBe(9);
|
||||
isDebug && rbTree.print();
|
||||
})
|
||||
});
|
||||
|
||||
it('Entry Array to AVLTree', () => {
|
||||
const avl = new AVLTree<number>(entries);
|
||||
expect(avl.size).toBe(9)
|
||||
expect(avl.size).toBe(9);
|
||||
isDebug && avl.print();
|
||||
})
|
||||
});
|
||||
|
||||
it('Entry Array to TreeMultimap', () => {
|
||||
const treeMulti = new TreeMultimap<number>(entries);
|
||||
expect(treeMulti.size).toBe(9)
|
||||
expect(treeMulti.size).toBe(9);
|
||||
isDebug && treeMulti.print();
|
||||
})
|
||||
});
|
||||
|
||||
it('HashMap to RedBlackTree', () => {
|
||||
const hm = new HashMap(entries);
|
||||
isDebug && hm.print()
|
||||
isDebug && hm.print();
|
||||
const rbTree = new RedBlackTree<number>(hm);
|
||||
expect(rbTree.size).toBe(9)
|
||||
expect(rbTree.size).toBe(9);
|
||||
isDebug && rbTree.print();
|
||||
})
|
||||
});
|
||||
|
||||
it('PriorityQueue to BST', () => {
|
||||
const pq = new MinPriorityQueue(orgArr);
|
||||
isDebug && pq.print();
|
||||
const bst = new BST<number>(pq);
|
||||
expect(bst.size).toBe(9)
|
||||
expect(bst.size).toBe(9);
|
||||
isDebug && bst.print();
|
||||
})
|
||||
});
|
||||
|
||||
it('Deque to RedBlackTree', () => {
|
||||
const dq = new Deque(orgArr);
|
||||
isDebug && dq.print();
|
||||
const rbTree = new RedBlackTree<number>(dq);
|
||||
expect(rbTree.size).toBe(9)
|
||||
expect(rbTree.size).toBe(9);
|
||||
isDebug && rbTree.print();
|
||||
})
|
||||
});
|
||||
|
||||
it('Trie to Heap to Deque', () => {
|
||||
const trie = new Trie(orgStrArr);
|
||||
|
@ -146,11 +156,7 @@ describe('conversions', () => {
|
|||
isDebug && dq.print();
|
||||
const entries = dq.map((el, i) => <[number, string]>[i, el]);
|
||||
const avl = new AVLTree<number, string>(entries);
|
||||
expect(avl.size).toBe(10)
|
||||
expect(avl.size).toBe(10);
|
||||
isDebug && avl.print();
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,4 +4,4 @@ export const calcRunTime = (callback: (...args: any[]) => any) => {
|
|||
const startTime = performance.now();
|
||||
callback();
|
||||
return performance.now() - startTime;
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue