mirror of
https://github.com/zrwusa/data-structure-typed.git
synced 2024-11-23 12:54:04 +00:00
feat: Implement forEach, filter, map, reduce, and [Symbol.iterator] methods for all binary tree data structures
This commit is contained in:
parent
01b969edca
commit
a41e222481
|
@ -29,7 +29,7 @@ Now you can use this library in Node.js and browser environments in CommonJS(req
|
|||
### npm
|
||||
|
||||
```bash
|
||||
npm i data-structure-typed
|
||||
npm i --save data-structure-typed
|
||||
```
|
||||
|
||||
### yarn
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
* @license MIT License
|
||||
*/
|
||||
import { BST, BSTNode } from './bst';
|
||||
import type { AVLTreeNodeNested, AVLTreeOptions, BiTreeDeleteResult, BTNKey } from '../../types';
|
||||
import { BTNCallback } from '../../types';
|
||||
import type { AVLTreeNested, AVLTreeNodeNested, AVLTreeOptions, BiTreeDeleteResult, BTNKey } from '../../types';
|
||||
import { BTNCallback, IterationType } from '../../types';
|
||||
import { IBinaryTree } from '../../interfaces';
|
||||
|
||||
export class AVLTreeNode<V = any, N extends AVLTreeNode<V, N> = AVLTreeNodeNested<V>> extends BSTNode<V, N> {
|
||||
|
@ -19,9 +19,12 @@ export class AVLTreeNode<V = any, N extends AVLTreeNode<V, N> = AVLTreeNodeNeste
|
|||
}
|
||||
}
|
||||
|
||||
export class AVLTree<V = any, N extends AVLTreeNode<V, N> = AVLTreeNode<V, AVLTreeNodeNested<V>>>
|
||||
extends BST<V, N>
|
||||
implements IBinaryTree<V, N> {
|
||||
export class AVLTree<V = any, N extends AVLTreeNode<V, N> = AVLTreeNode<V, AVLTreeNodeNested<V>>, TREE extends AVLTree<V, N, TREE> = AVLTree<V, N, AVLTreeNested<V, N>>>
|
||||
extends BST<V, N, TREE>
|
||||
implements IBinaryTree<V, N, TREE> {
|
||||
|
||||
override options: AVLTreeOptions;
|
||||
|
||||
/**
|
||||
* This is a constructor function for an AVL tree data structure in TypeScript.
|
||||
* @param {AVLTreeOptions} [options] - The `options` parameter is an optional object that can be passed to the
|
||||
|
@ -30,6 +33,11 @@ export class AVLTree<V = any, N extends AVLTreeNode<V, N> = AVLTreeNode<V, AVLTr
|
|||
*/
|
||||
constructor(options?: AVLTreeOptions) {
|
||||
super(options);
|
||||
if (options) {
|
||||
this.options = { iterationType: IterationType.ITERATIVE, comparator: (a, b) => a - b, ...options }
|
||||
} else {
|
||||
this.options = { iterationType: IterationType.ITERATIVE, comparator: (a, b) => a - b };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -45,6 +53,10 @@ export class AVLTree<V = any, N extends AVLTreeNode<V, N> = AVLTreeNode<V, AVLTr
|
|||
return new AVLTreeNode<V, N>(key, value) as N;
|
||||
}
|
||||
|
||||
override createTree(options?: AVLTreeOptions) {
|
||||
return new AVLTree<V, N, TREE>({ ...this.options, ...options }) as TREE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
import type { BinaryTreeNodeNested, BinaryTreeOptions, BTNCallback, BTNKey } from '../../types';
|
||||
import {
|
||||
BinaryTreeNested,
|
||||
BinaryTreePrintOptions,
|
||||
BiTreeDeleteResult,
|
||||
DFSOrderPattern,
|
||||
|
@ -114,9 +115,10 @@ export class BinaryTreeNode<V = any, N extends BinaryTreeNode<V, N> = BinaryTree
|
|||
* Represents a binary tree data structure.
|
||||
* @template N - The type of the binary tree's nodes.
|
||||
*/
|
||||
export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode<V, BinaryTreeNodeNested<V>>>
|
||||
implements IBinaryTree<V, N> {
|
||||
iterationType: IterationType = IterationType.ITERATIVE;
|
||||
export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode<V, BinaryTreeNodeNested<V>>, TREE extends BinaryTree<V, N, TREE> = BinaryTree<V, N, BinaryTreeNested<V, N>>>
|
||||
implements IBinaryTree<V, N, TREE> {
|
||||
|
||||
options: BinaryTreeOptions;
|
||||
|
||||
/**
|
||||
* Creates a new instance of BinaryTree.
|
||||
|
@ -124,9 +126,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
*/
|
||||
constructor(options?: BinaryTreeOptions) {
|
||||
if (options) {
|
||||
const { iterationType = IterationType.ITERATIVE } = options;
|
||||
this.iterationType = iterationType;
|
||||
this.options = { iterationType: IterationType.ITERATIVE, ...options }
|
||||
} else {
|
||||
this.options = { iterationType: IterationType.ITERATIVE };
|
||||
}
|
||||
|
||||
this._size = 0;
|
||||
}
|
||||
|
||||
|
@ -158,6 +162,10 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
return new BinaryTreeNode<V, N>(key, value) as N;
|
||||
}
|
||||
|
||||
createTree(options?: BinaryTreeOptions): TREE {
|
||||
return new BinaryTree<V, N, TREE>({ ...this.options, ...options }) as TREE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
|
@ -404,7 +412,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
* values:
|
||||
* @returns the height of the binary tree.
|
||||
*/
|
||||
getHeight(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.iterationType): number {
|
||||
getHeight(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.options.iterationType): number {
|
||||
beginRoot = this.ensureNotKey(beginRoot);
|
||||
if (!beginRoot) return -1;
|
||||
|
||||
|
@ -453,7 +461,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
* to calculate the minimum height of a binary tree. It can have two possible values:
|
||||
* @returns The function `getMinHeight` returns the minimum height of a binary tree.
|
||||
*/
|
||||
getMinHeight(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.iterationType): number {
|
||||
getMinHeight(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.options.iterationType): number {
|
||||
beginRoot = this.ensureNotKey(beginRoot);
|
||||
if (!beginRoot) return -1;
|
||||
|
||||
|
@ -575,7 +583,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
callback: C = this._defaultOneParamCallback as C,
|
||||
onlyOne = false,
|
||||
beginRoot: BTNKey | N | null | undefined = this.root,
|
||||
iterationType = this.iterationType
|
||||
iterationType = this.options.iterationType
|
||||
): N[] {
|
||||
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
|
||||
callback = (node => node) as C;
|
||||
|
@ -664,7 +672,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
identifier: ReturnType<C> | null | undefined,
|
||||
callback: C = this._defaultOneParamCallback as C,
|
||||
beginRoot: BTNKey | N | null | undefined = this.root,
|
||||
iterationType = this.iterationType
|
||||
iterationType = this.options.iterationType
|
||||
): boolean {
|
||||
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
|
||||
callback = (node => node) as C;
|
||||
|
@ -723,7 +731,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
identifier: ReturnType<C> | null | undefined,
|
||||
callback: C = this._defaultOneParamCallback as C,
|
||||
beginRoot: BTNKey | N | null | undefined = this.root,
|
||||
iterationType = this.iterationType
|
||||
iterationType = this.options.iterationType
|
||||
): N | null | undefined {
|
||||
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
|
||||
callback = (node => node) as C;
|
||||
|
@ -842,7 +850,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
identifier: ReturnType<C> | null | undefined,
|
||||
callback: C = this._defaultOneParamCallback as C,
|
||||
beginRoot: BTNKey | N | null | undefined = this.root,
|
||||
iterationType = this.iterationType
|
||||
iterationType = this.options.iterationType
|
||||
): V | undefined {
|
||||
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
|
||||
callback = (node => node) as C;
|
||||
|
@ -923,7 +931,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
*/
|
||||
getLeftMost(
|
||||
beginRoot: BTNKey | N | null | undefined = this.root,
|
||||
iterationType = this.iterationType
|
||||
iterationType = this.options.iterationType
|
||||
): N | null | undefined {
|
||||
beginRoot = this.ensureNotKey(beginRoot);
|
||||
|
||||
|
@ -969,7 +977,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
*/
|
||||
getRightMost(
|
||||
beginRoot: BTNKey | N | null | undefined = this.root,
|
||||
iterationType = this.iterationType
|
||||
iterationType = this.options.iterationType
|
||||
): N | null | undefined {
|
||||
// TODO support get right most by passing key in
|
||||
beginRoot = this.ensureNotKey(beginRoot);
|
||||
|
@ -1010,7 +1018,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
* possible values:
|
||||
* @returns a boolean value.
|
||||
*/
|
||||
isSubtreeBST(beginRoot: BTNKey | N | null | undefined, iterationType = this.iterationType): boolean {
|
||||
isSubtreeBST(beginRoot: BTNKey | N | null | undefined, iterationType = this.options.iterationType): boolean {
|
||||
// TODO there is a bug
|
||||
beginRoot = this.ensureNotKey(beginRoot);
|
||||
if (!beginRoot) return true;
|
||||
|
@ -1057,7 +1065,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
* expected to be
|
||||
* @returns a boolean value.
|
||||
*/
|
||||
isBST(iterationType = this.iterationType): boolean {
|
||||
isBST(iterationType = this.options.iterationType): boolean {
|
||||
if (this.root === null) return true;
|
||||
return this.isSubtreeBST(this.root, iterationType);
|
||||
}
|
||||
|
@ -1104,7 +1112,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
* @param iterationType - The `iterationType` parameter determines the type of traversal to be
|
||||
* performed on the subtree. It can have two possible values:
|
||||
* @param [includeNull=false] - The `includeNull` parameter is a boolean value that determines
|
||||
* whether or not to include null values in the traversal. If `includeNull` is set to `true`, the
|
||||
* whether to include null values in the traversal. If `includeNull` is set to `true`, the
|
||||
* traversal will include null values, otherwise it will skip them.
|
||||
* @returns The function `subTreeTraverse` returns an array of values that are the result of invoking
|
||||
* the `callback` function on each node in the subtree. The type of the array elements is determined
|
||||
|
@ -1113,7 +1121,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
subTreeTraverse<C extends BTNCallback<N | null | undefined>>(
|
||||
callback: C = this._defaultOneParamCallback as C,
|
||||
beginRoot: BTNKey | N | null | undefined = this.root,
|
||||
iterationType = this.iterationType,
|
||||
iterationType = this.options.iterationType,
|
||||
includeNull = false
|
||||
): ReturnType<C>[] {
|
||||
beginRoot = this.ensureNotKey(beginRoot);
|
||||
|
@ -1383,7 +1391,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
* @param iterationType - The `iterationType` parameter determines the type of iteration to be
|
||||
* performed during the breadth-first search (BFS). It can have two possible values:
|
||||
* @param [includeNull=false] - The `includeNull` parameter is a boolean flag that determines whether
|
||||
* or not to include null values in the breadth-first search traversal. If `includeNull` is set to
|
||||
* to include null values in the breadth-first search traversal. If `includeNull` is set to
|
||||
* `true`, null values will be included in the traversal, otherwise they will be skipped.
|
||||
* @returns an array of values that are the result of invoking the callback function on each node in
|
||||
* the breadth-first traversal of a binary tree.
|
||||
|
@ -1391,7 +1399,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
bfs<C extends BTNCallback<N | null | undefined>>(
|
||||
callback: C = this._defaultOneParamCallback as C,
|
||||
beginRoot: BTNKey | N | null | undefined = this.root,
|
||||
iterationType = this.iterationType,
|
||||
iterationType = this.options.iterationType,
|
||||
includeNull = false
|
||||
): ReturnType<C>[] {
|
||||
beginRoot = this.ensureNotKey(beginRoot);
|
||||
|
@ -1484,7 +1492,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
* @param iterationType - The `iterationType` parameter determines the type of iteration to be
|
||||
* performed on the tree. It can have two possible values:
|
||||
* @param [includeNull=false] - The `includeNull` parameter is a boolean value that determines
|
||||
* whether or not to include null values in the resulting levels. If `includeNull` is set to `true`,
|
||||
* whether to include null values in the resulting levels. If `includeNull` is set to `true`,
|
||||
* null values will be included in the levels. If `includeNull` is set to `false`, null values will
|
||||
* be excluded
|
||||
* @returns The function `listLevels` returns a two-dimensional array of type `ReturnType<C>[][]`.
|
||||
|
@ -1492,7 +1500,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
listLevels<C extends BTNCallback<N | null | undefined>>(
|
||||
callback: C = this._defaultOneParamCallback as C,
|
||||
beginRoot: BTNKey | N | null | undefined = this.root,
|
||||
iterationType = this.iterationType,
|
||||
iterationType = this.options.iterationType,
|
||||
includeNull = false
|
||||
): ReturnType<C>[][] {
|
||||
beginRoot = this.ensureNotKey(beginRoot);
|
||||
|
@ -1692,6 +1700,48 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
return ans;
|
||||
}
|
||||
|
||||
forEach(callback: (entry: [BTNKey, V | undefined], tree: typeof this) => void): void {
|
||||
for (const entry of this) {
|
||||
callback(entry, this);
|
||||
}
|
||||
}
|
||||
|
||||
filter(predicate: (entry: [BTNKey, V | undefined], tree: typeof this) => boolean) {
|
||||
const newTree = this.createTree();
|
||||
for (const [key, value] of this) {
|
||||
if (predicate([key, value], this)) {
|
||||
newTree.add(key, value);
|
||||
}
|
||||
}
|
||||
return newTree;
|
||||
}
|
||||
|
||||
// TODO Type error, need to return a TREE<NV> that is a value type only for callback function.
|
||||
// map<NV>(callback: (entry: [BTNKey, V | undefined], tree: typeof this) => NV) {
|
||||
// const newTree = this.createTree();
|
||||
// for (const [key, value] of this) {
|
||||
// newTree.add(key, callback([key, value], this));
|
||||
// }
|
||||
// return newTree;
|
||||
// }
|
||||
|
||||
map(callback: (entry: [BTNKey, V | undefined], tree: typeof this) => V) {
|
||||
const newTree = this.createTree();
|
||||
for (const [key, value] of this) {
|
||||
newTree.add(key, callback([key, value], this));
|
||||
}
|
||||
return newTree;
|
||||
}
|
||||
|
||||
reduce<T>(callback: (accumulator: T, entry: [BTNKey, V | undefined], tree: typeof this) => T, initialValue: T): T {
|
||||
let accumulator = initialValue;
|
||||
for (const [key, value] of this) {
|
||||
accumulator = callback(accumulator, [key, value], this);
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The above function is an iterator for a binary tree that can be used to traverse the tree in
|
||||
* either an iterative or recursive manner.
|
||||
|
@ -1701,32 +1751,32 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
* @returns The `*[Symbol.iterator]` method returns a generator object that yields the keys of the
|
||||
* binary tree nodes in a specific order.
|
||||
*/
|
||||
* [Symbol.iterator](node = this.root): Generator<BTNKey, void, undefined> {
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
* [Symbol.iterator](node = this.root): Generator<[BTNKey, V | undefined], void, undefined> {
|
||||
if (!node) return;
|
||||
|
||||
if (this.iterationType === IterationType.ITERATIVE) {
|
||||
if (this.options.iterationType === IterationType.ITERATIVE) {
|
||||
const stack: (N | null | undefined)[] = [];
|
||||
let current: N | null | undefined = node;
|
||||
|
||||
while (current || stack.length > 0) {
|
||||
while (current) {
|
||||
while (current && !isNaN(current.key)) {
|
||||
stack.push(current);
|
||||
current = current.left;
|
||||
}
|
||||
|
||||
current = stack.pop();
|
||||
|
||||
if (current) yield current.key;
|
||||
if (current) current = current.right;
|
||||
if (current && !isNaN(current.key)) {
|
||||
yield [current.key, current.value];
|
||||
current = current.right;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (node.left) {
|
||||
if (node.left && !isNaN(node.key)) {
|
||||
yield* this[Symbol.iterator](node.left);
|
||||
}
|
||||
yield node.key;
|
||||
if (node.right) {
|
||||
yield [node.key, node.value];
|
||||
if (node.right && !isNaN(node.key)) {
|
||||
yield* this[Symbol.iterator](node.right);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
||||
* @license MIT License
|
||||
*/
|
||||
import type { BSTComparator, BSTNodeNested, BSTOptions, BTNCallback, BTNKey } from '../../types';
|
||||
import type { BSTNested, BSTNodeNested, BSTOptions, BTNCallback, BTNKey } from '../../types';
|
||||
import { CP, IterationType } from '../../types';
|
||||
import { BinaryTree, BinaryTreeNode } from './binary-tree';
|
||||
import { IBinaryTree } from '../../interfaces';
|
||||
|
@ -62,9 +62,12 @@ export class BSTNode<V = any, N extends BSTNode<V, N> = BSTNodeNested<V>> extend
|
|||
}
|
||||
}
|
||||
|
||||
export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>>
|
||||
extends BinaryTree<V, N>
|
||||
implements IBinaryTree<V, N> {
|
||||
export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>, TREE extends BST<V, N, TREE> = BST<V, N, BSTNested<V, N>>>
|
||||
extends BinaryTree<V, N, TREE>
|
||||
implements IBinaryTree<V, N, TREE> {
|
||||
|
||||
override options: BSTOptions;
|
||||
|
||||
/**
|
||||
* The constructor function initializes a binary search tree with an optional comparator function.
|
||||
* @param {BSTOptions} [options] - An optional object that contains additional configuration options
|
||||
|
@ -72,13 +75,12 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|||
*/
|
||||
constructor(options?: BSTOptions) {
|
||||
super(options);
|
||||
this._root = undefined;
|
||||
if (options !== undefined) {
|
||||
const { comparator } = options;
|
||||
if (comparator !== undefined) {
|
||||
this._comparator = comparator;
|
||||
}
|
||||
if (options) {
|
||||
this.options = { iterationType: IterationType.ITERATIVE, comparator: (a, b) => a - b, ...options }
|
||||
} else {
|
||||
this.options = { iterationType: IterationType.ITERATIVE, comparator: (a, b) => a - b };
|
||||
}
|
||||
this._root = undefined;
|
||||
}
|
||||
|
||||
protected override _root?: N;
|
||||
|
@ -102,6 +104,10 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|||
return new BSTNode<V, N>(key, value) as N;
|
||||
}
|
||||
|
||||
override createTree(options?: BSTOptions): TREE {
|
||||
return new BST<V, N, TREE>({ ...this.options, ...options }) as TREE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(log n) - Average case for a balanced tree. In the worst case (unbalanced tree), it can be O(n).
|
||||
* Space Complexity: O(1) - Constant space is used.
|
||||
|
@ -215,7 +221,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|||
keysOrNodes: (BTNKey | N | undefined)[],
|
||||
data?: (V | undefined)[],
|
||||
isBalanceAdd = true,
|
||||
iterationType = this.iterationType
|
||||
iterationType = this.options.iterationType
|
||||
): (N | undefined)[] {
|
||||
// TODO this addMany function is inefficient, it should be optimized
|
||||
function hasNoUndefined(arr: (BTNKey | N | undefined)[]): arr is (BTNKey | N)[] {
|
||||
|
@ -310,7 +316,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|||
* the key of the leftmost node if the comparison result is greater than, and the key of the
|
||||
* rightmost node otherwise. If no node is found, it returns 0.
|
||||
*/
|
||||
lastKey(beginRoot: BTNKey | N | undefined = this.root, iterationType = this.iterationType): BTNKey {
|
||||
lastKey(beginRoot: BTNKey | N | undefined = this.root, iterationType = this.options.iterationType): BTNKey {
|
||||
if (this._compare(0, 1) === CP.lt) return this.getRightMost(beginRoot, iterationType)?.key ?? 0;
|
||||
else if (this._compare(0, 1) === CP.gt) return this.getLeftMost(beginRoot, iterationType)?.key ?? 0;
|
||||
else return this.getRightMost(beginRoot, iterationType)?.key ?? 0;
|
||||
|
@ -406,7 +412,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|||
callback: C = this._defaultOneParamCallback as C,
|
||||
onlyOne = false,
|
||||
beginRoot: BTNKey | N | undefined = this.root,
|
||||
iterationType = this.iterationType
|
||||
iterationType = this.options.iterationType
|
||||
): N[] {
|
||||
beginRoot = this.ensureNotKey(beginRoot);
|
||||
if (!beginRoot) return [];
|
||||
|
@ -487,7 +493,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|||
callback: C = this._defaultOneParamCallback as C,
|
||||
lesserOrGreater: CP = CP.lt,
|
||||
targetNode: BTNKey | N | undefined = this.root,
|
||||
iterationType = this.iterationType
|
||||
iterationType = this.options.iterationType
|
||||
): ReturnType<C>[] {
|
||||
targetNode = this.ensureNotKey(targetNode);
|
||||
const ans: ReturnType<BTNCallback<N>>[] = [];
|
||||
|
@ -550,7 +556,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|||
* values:
|
||||
* @returns The function `perfectlyBalance` returns a boolean value.
|
||||
*/
|
||||
perfectlyBalance(iterationType = this.iterationType): boolean {
|
||||
perfectlyBalance(iterationType = this.options.iterationType): boolean {
|
||||
const sorted = this.dfs(node => node, 'in'),
|
||||
n = sorted.length;
|
||||
this.clear();
|
||||
|
@ -602,7 +608,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|||
* to check if the AVL tree is balanced. It can have two possible values:
|
||||
* @returns a boolean value.
|
||||
*/
|
||||
isAVLBalanced(iterationType = this.iterationType): boolean {
|
||||
isAVLBalanced(iterationType = this.options.iterationType): boolean {
|
||||
if (!this.root) return true;
|
||||
|
||||
let balanced = true;
|
||||
|
@ -646,8 +652,6 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|||
return balanced;
|
||||
}
|
||||
|
||||
protected _comparator: BSTComparator = (a, b) => a - b;
|
||||
|
||||
protected _setRoot(v: N | undefined) {
|
||||
if (v) {
|
||||
v.parent = undefined;
|
||||
|
@ -664,7 +668,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|||
* than), CP.lt (less than), or CP.eq (equal).
|
||||
*/
|
||||
protected _compare(a: BTNKey, b: BTNKey): CP {
|
||||
const compared = this._comparator(a, b);
|
||||
const compared = this.options.comparator!(a, b);
|
||||
if (compared > 0) return CP.gt;
|
||||
else if (compared < 0) return CP.lt;
|
||||
else return CP.eq;
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
IterationType,
|
||||
RBTNColor,
|
||||
RBTreeOptions,
|
||||
RedBlackTreeNested,
|
||||
RedBlackTreeNodeNested
|
||||
} from '../../types';
|
||||
import { BST, BSTNode } from './bst';
|
||||
|
@ -38,10 +39,11 @@ export class RedBlackTreeNode<V = any, N extends RedBlackTreeNode<V, N> = RedBla
|
|||
* 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<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTreeNode<V, RedBlackTreeNodeNested<V>>>
|
||||
extends BST<V, N>
|
||||
implements IBinaryTree<V, N> {
|
||||
export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTreeNode<V, RedBlackTreeNodeNested<V>>, TREE extends RedBlackTree<V, N, TREE> = RedBlackTree<V, N, RedBlackTreeNested<V, N>>>
|
||||
extends BST<V, N, TREE>
|
||||
implements IBinaryTree<V, N, TREE> {
|
||||
Sentinel: N = new RedBlackTreeNode<V>(NaN) as unknown as N;
|
||||
override options: RBTreeOptions;
|
||||
|
||||
/**
|
||||
* The constructor function initializes a Red-Black Tree with an optional set of options.
|
||||
|
@ -50,6 +52,11 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
|
|||
*/
|
||||
constructor(options?: RBTreeOptions) {
|
||||
super(options);
|
||||
if (options) {
|
||||
this.options = { iterationType: IterationType.ITERATIVE, comparator: (a, b) => a - b, ...options }
|
||||
} else {
|
||||
this.options = { iterationType: IterationType.ITERATIVE, comparator: (a, b) => a - b };
|
||||
}
|
||||
this._root = this.Sentinel;
|
||||
}
|
||||
|
||||
|
@ -65,6 +72,14 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
|
|||
return this._size;
|
||||
}
|
||||
|
||||
override createNode(key: BTNKey, value?: V, color: RBTNColor = RBTNColor.BLACK): N {
|
||||
return new RedBlackTreeNode<V, N>(key, value, color) as N;
|
||||
}
|
||||
|
||||
override createTree(options?: RBTreeOptions): TREE {
|
||||
return new RedBlackTree<V, N, TREE>({ ...this.options, ...options }) as TREE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(log n) on average (where n is the number of nodes in the tree)
|
||||
* Space Complexity: O(1)
|
||||
|
@ -139,10 +154,6 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
|
|||
this._size++;
|
||||
}
|
||||
|
||||
override createNode(key: BTNKey, value?: V, color: RBTNColor = RBTNColor.BLACK): N {
|
||||
return new RedBlackTreeNode<V, N>(key, value, color) as N;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(log n) on average (where n is the number of nodes in the tree)
|
||||
* Space Complexity: O(1)
|
||||
|
@ -279,7 +290,7 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
|
|||
identifier: ReturnType<C> | undefined,
|
||||
callback: C = this._defaultOneParamCallback as C,
|
||||
beginRoot: BTNKey | N | undefined = this.root,
|
||||
iterationType = this.iterationType
|
||||
iterationType = this.options.iterationType
|
||||
): N | null | undefined {
|
||||
if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;
|
||||
beginRoot = this.ensureNotKey(beginRoot);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* @license MIT License
|
||||
*/
|
||||
import type { BTNKey, TreeMultimapNodeNested, TreeMultimapOptions } from '../../types';
|
||||
import { BiTreeDeleteResult, BTNCallback, CP, FamilyPosition, IterationType } from '../../types';
|
||||
import { BiTreeDeleteResult, BTNCallback, CP, FamilyPosition, IterationType, TreeMultimapNested } from '../../types';
|
||||
import { IBinaryTree } from '../../interfaces';
|
||||
import { AVLTree, AVLTreeNode } from './avl-tree';
|
||||
|
||||
|
@ -35,17 +35,26 @@ 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<V = any, N extends TreeMultimapNode<V, N> = TreeMultimapNode<V, TreeMultimapNodeNested<V>>>
|
||||
extends AVLTree<V, N>
|
||||
implements IBinaryTree<V, N> {
|
||||
export class TreeMultimap<V = any, N extends TreeMultimapNode<V, N> = TreeMultimapNode<V, TreeMultimapNodeNested<V>>,
|
||||
TREE extends TreeMultimap<V, N, TREE> = TreeMultimap<V, N, TreeMultimapNested<V, N>>>
|
||||
extends AVLTree<V, N, TREE>
|
||||
implements IBinaryTree<V, N, TREE> {
|
||||
|
||||
override options: TreeMultimapOptions;
|
||||
|
||||
/**
|
||||
* The constructor function for a TreeMultimap class in TypeScript, which extends another class and sets an option to
|
||||
* merge duplicated values.
|
||||
* @param {TreeMultimapOptions} [options] - An optional object that contains additional configuration options for the
|
||||
* TreeMultimap.
|
||||
*/
|
||||
constructor(options?: TreeMultimapOptions) {
|
||||
constructor(options: TreeMultimapOptions = { iterationType: IterationType.ITERATIVE }) {
|
||||
super(options);
|
||||
if (options) {
|
||||
this.options = { iterationType: IterationType.ITERATIVE, comparator: (a, b) => a - b, ...options }
|
||||
} else {
|
||||
this.options = { iterationType: IterationType.ITERATIVE, comparator: (a, b) => a - b };
|
||||
}
|
||||
}
|
||||
|
||||
private _count = 0;
|
||||
|
@ -67,6 +76,10 @@ export class TreeMultimap<V = any, N extends TreeMultimapNode<V, N> = TreeMultim
|
|||
return new TreeMultimapNode(key, value, count) as N;
|
||||
}
|
||||
|
||||
override createTree(options?: TreeMultimapOptions): TREE {
|
||||
return new TreeMultimap<V, N, TREE>({ ...this.options, ...options }) as TREE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(log n) - logarithmic time, where "n" is the number of nodes in the tree. The add method of the superclass (AVLTree) has logarithmic time complexity.
|
||||
* Space Complexity: O(1) - constant space, as it doesn't use additional data structures that scale with input size.
|
||||
|
@ -210,7 +223,7 @@ export class TreeMultimap<V = any, N extends TreeMultimapNode<V, N> = TreeMultim
|
|||
* values:
|
||||
* @returns a boolean value.
|
||||
*/
|
||||
override perfectlyBalance(iterationType = this.iterationType): boolean {
|
||||
override perfectlyBalance(iterationType = this.options.iterationType): boolean {
|
||||
const sorted = this.dfs(node => node, 'in'),
|
||||
n = sorted.length;
|
||||
if (sorted.length < 1) return false;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { BinaryTreeNode } from '../data-structures';
|
||||
import { BinaryTreeNodeNested, BiTreeDeleteResult, BTNCallback, BTNKey } from '../types';
|
||||
import { BinaryTree, BinaryTreeNode } from '../data-structures';
|
||||
import { BinaryTreeNested, BinaryTreeNodeNested, BiTreeDeleteResult, BTNCallback, BTNKey } from '../types';
|
||||
|
||||
export interface IBinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNodeNested<V>> {
|
||||
export interface IBinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNodeNested<V>, TREE extends BinaryTree<V, N, TREE> = BinaryTreeNested<V, N>> {
|
||||
createNode(key: BTNKey, value?: N['value']): N;
|
||||
|
||||
add(keyOrNode: BTNKey | N | null, value?: N['value']): N | null | undefined;
|
||||
|
|
|
@ -20,4 +20,4 @@ export interface IterableWithLength<T> extends Iterable<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 }
|
|
@ -1,5 +1,9 @@
|
|||
import { AVLTreeNode } from '../../../data-structures';
|
||||
import { AVLTree, AVLTreeNode } from '../../../data-structures';
|
||||
import { BSTOptions } from './bst';
|
||||
|
||||
export type AVLTreeNodeNested<T> = AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, AVLTreeNode<T, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
|
||||
export type AVLTreeNested<T, N extends AVLTreeNode<T, N>> = AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, AVLTree<T, N, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
|
||||
|
||||
export type AVLTreeOptions = BSTOptions & {};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { BinaryTreeNode } from '../../../data-structures';
|
||||
import { BinaryTree, BinaryTreeNode } from '../../../data-structures';
|
||||
|
||||
/**
|
||||
* Enum representing different loop types.
|
||||
|
@ -28,6 +28,8 @@ export type BiTreeDeleteResult<N> = { deleted: N | null | undefined; needBalance
|
|||
|
||||
export type BinaryTreeNodeNested<T> = BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
|
||||
export type BinaryTreeNested<T, N extends BinaryTreeNode<T, N>> = BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, BinaryTree<T, N, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
|
||||
export type BinaryTreeOptions = { iterationType?: IterationType }
|
||||
|
||||
export type NodeDisplayLayout = [string[], number, number, number];
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { BSTNode } from '../../../data-structures';
|
||||
import { BST, BSTNode } from '../../../data-structures';
|
||||
import type { BinaryTreeOptions, BTNKey } from './binary-tree';
|
||||
|
||||
export type BSTComparator = (a: BTNKey, b: BTNKey) => number;
|
||||
|
@ -6,6 +6,8 @@ export type BSTComparator = (a: BTNKey, b: BTNKey) => number;
|
|||
// prettier-ignore
|
||||
export type BSTNodeNested<T> = BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, BSTNode<T, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
|
||||
export type BSTNested<T, N extends BSTNode<T, N>> = BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, BST<T, N, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
|
||||
export type BSTOptions = BinaryTreeOptions & {
|
||||
comparator?: BSTComparator,
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import { RedBlackTreeNode } from '../../../data-structures';
|
||||
import { RedBlackTree, RedBlackTreeNode } from '../../../data-structures';
|
||||
import { BSTOptions } from "./bst";
|
||||
|
||||
export enum RBTNColor { RED = 1, BLACK = 0}
|
||||
|
||||
export type RedBlackTreeNodeNested<T> = RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, RedBlackTreeNode<T, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
|
||||
export type RedBlackTreeNested<T, N extends RedBlackTreeNode<T, N>> = RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, RedBlackTree<T, N, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
|
||||
export type RBTreeOptions = BSTOptions & {};
|
|
@ -1,6 +1,8 @@
|
|||
import { TreeMultimapNode } from '../../../data-structures';
|
||||
import { TreeMultimap, TreeMultimapNode } from '../../../data-structures';
|
||||
import { AVLTreeOptions } from './avl-tree';
|
||||
|
||||
export type TreeMultimapNodeNested<T> = TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
|
||||
export type TreeMultimapNested<T, N extends TreeMultimapNode<T, N>> = TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, TreeMultimap<T, N, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
|
||||
export type TreeMultimapOptions = Omit<AVLTreeOptions, 'isMergeDuplicatedNodeByKey'> & {}
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
<head>
|
||||
<meta charset='UTF-8'>
|
||||
<title>CDN Test</title>
|
||||
<!-- <script src="../../dist/umd/data-structure-typed.min.js"></script>-->
|
||||
<script src="../../dist/umd/data-structure-typed.js"></script>
|
||||
<!-- <script src="../../dist/umd/data-structure-typed.min.js"></script>-->
|
||||
<script src="../../dist/umd/data-structure-typed.js"></script>
|
||||
<!-- <script src='https://cdn.jsdelivr.net/npm/data-structure-typed/dist/umd/data-structure-typed.min.js'></script>-->
|
||||
<!-- <script src='https://cdn.jsdelivr.net/npm/data-structure-typed@1.42.2/dist/umd/data-structure-typed.min.js'></script>-->
|
||||
<!-- <script src='https://cdn.jsdelivr.net/npm/data-structure-typed@1.43.3/dist/umd/data-structure-typed.min.js'></script>-->
|
||||
|
@ -38,7 +38,7 @@
|
|||
last = queue.dequeue();
|
||||
}
|
||||
|
||||
console.log((performance.now() - startTime).toFixed(2) ,`Queue ${n.toLocaleString()} dequeue `);
|
||||
console.log((performance.now() - startTime).toFixed(2), `Queue ${n.toLocaleString()} dequeue `);
|
||||
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
|
@ -69,7 +69,7 @@
|
|||
tree.addMany([1, 6, 9, 8, 5, 2, 3, 4, 7])
|
||||
tree.add(10);
|
||||
console.log(tree.isPerfectlyBalanced(), `tree.isPerfectlyBalanced()`);
|
||||
tree.print(undefined, {isShowUndefined: true});
|
||||
tree.print(undefined, { isShowUndefined: true });
|
||||
|
||||
const node3 = tree.getNode(3);
|
||||
if (node3) node3.right = tree.createNode(1);
|
||||
|
@ -79,7 +79,7 @@
|
|||
tree.clear();
|
||||
tree.addMany([1, null, 2, null, 3, null, 4, null, 5, null, 6, null]);
|
||||
console.log(tree.isPerfectlyBalanced(), `tree.isPerfectlyBalanced()`);
|
||||
tree.print(undefined, {isShowNull: true});
|
||||
tree.print(undefined, { isShowNull: true });
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
@ -95,12 +95,12 @@
|
|||
for (let i = 0; i < n; i++) {
|
||||
rbTree.add(i, i);
|
||||
}
|
||||
console.log(( performance.now() - tS).toFixed(2), `RedBlackTree ${n.toLocaleString()} add`);
|
||||
console.log((performance.now() - tS).toFixed(2), `RedBlackTree ${n.toLocaleString()} add`);
|
||||
console.log(`rbTree.size`, rbTree.size);
|
||||
for (let i = 0; i < n - 20; i++) {
|
||||
rbTree.delete(i)
|
||||
}
|
||||
rbTree.print(rbTree.root,{isShowRedBlackNIL: true});
|
||||
rbTree.print(rbTree.root, { isShowRedBlackNIL: true });
|
||||
const cS = performance.now();
|
||||
for (let i = 1; i < 100000; i++) {
|
||||
cRBTree.setElement(i, i);
|
||||
|
@ -125,7 +125,7 @@
|
|||
for (let i = 0; i < n; i++) {
|
||||
pq.pop();
|
||||
}
|
||||
console.log(( performance.now() - tS).toFixed(2), `PriorityQueue ${n.toLocaleString()} add`);
|
||||
console.log((performance.now() - tS).toFixed(2), `PriorityQueue ${n.toLocaleString()} add`);
|
||||
console.log(pq.size, `pq.size`);
|
||||
const cS = performance.now();
|
||||
const cpq = new CPriorityQueue();
|
||||
|
|
|
@ -41,4 +41,11 @@ suite
|
|||
}
|
||||
});
|
||||
|
||||
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
|
||||
});
|
||||
|
||||
export { suite };
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { AVLTree, AVLTreeNode, CP, IterationType } from '../../../../src';
|
||||
import { AVLTree, AVLTreeNode, BinaryTreeNode, BSTNode, CP, IterationType } from '../../../../src';
|
||||
|
||||
describe('AVL Tree Test', () => {
|
||||
it('should perform various operations on a AVL Tree', () => {
|
||||
|
@ -286,3 +286,59 @@ describe('AVLTree', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('AVLTree iterative methods test', () => {
|
||||
let avl: AVLTree<string>;
|
||||
beforeEach(() => {
|
||||
avl = new AVLTree();
|
||||
avl.add(1, 'a');
|
||||
avl.add(2, 'b');
|
||||
avl.add(3, 'c');
|
||||
});
|
||||
|
||||
test('The node obtained by get Node should match the node type', () => {
|
||||
const node3 = avl.getNode(3);
|
||||
expect(node3).toBeInstanceOf(BinaryTreeNode);
|
||||
expect(node3).toBeInstanceOf(BSTNode);
|
||||
expect(node3).toBeInstanceOf(AVLTreeNode);
|
||||
});
|
||||
|
||||
test('forEach should iterate over all elements', () => {
|
||||
const mockCallback = jest.fn();
|
||||
avl.forEach((entry) => {
|
||||
mockCallback(entry);
|
||||
});
|
||||
|
||||
expect(mockCallback.mock.calls.length).toBe(3);
|
||||
expect(mockCallback.mock.calls[0][0]).toEqual([1, 'a']);
|
||||
expect(mockCallback.mock.calls[1][0]).toEqual([2, 'b']);
|
||||
expect(mockCallback.mock.calls[2][0]).toEqual([3, 'c']);
|
||||
});
|
||||
|
||||
test('filter should return a new tree with filtered elements', () => {
|
||||
const filteredTree = avl.filter(([key]) => key > 1);
|
||||
expect(filteredTree.size).toBe(2);
|
||||
expect([...filteredTree]).toEqual([[2, 'b'], [3, 'c']]);
|
||||
});
|
||||
|
||||
test('map should return a new tree with modified elements', () => {
|
||||
const mappedTree = avl.map(([key]) => (key * 2).toString());
|
||||
expect(mappedTree.size).toBe(3);
|
||||
expect([...mappedTree]).toEqual([[1, '2'], [2, '4'], [3, '6']]);
|
||||
});
|
||||
|
||||
test('reduce should accumulate values', () => {
|
||||
const sum = avl.reduce((acc, [key]) => acc + key, 0);
|
||||
expect(sum).toBe(6);
|
||||
});
|
||||
|
||||
test('[Symbol.iterator] should provide an iterator', () => {
|
||||
const entries = [];
|
||||
for (const entry of avl) {
|
||||
entries.push(entry);
|
||||
}
|
||||
|
||||
expect(entries.length).toBe(3);
|
||||
expect(entries).toEqual([[1, 'a'], [2, 'b'], [3, 'c']]);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -189,9 +189,9 @@ describe('BinaryTree', () => {
|
|||
tree.add(4);
|
||||
tree.add(2);
|
||||
expect(tree.getHeight()).toBe(1);
|
||||
tree.iterationType = IterationType.RECURSIVE;
|
||||
tree.options.iterationType = IterationType.RECURSIVE;
|
||||
expect(tree.getHeight()).toBe(1);
|
||||
tree.iterationType = IterationType.ITERATIVE;
|
||||
tree.options.iterationType = IterationType.ITERATIVE;
|
||||
|
||||
tree.add(6);
|
||||
tree.add(1);
|
||||
|
@ -541,11 +541,11 @@ describe('BinaryTree', () => {
|
|||
tree.add(3, 'B');
|
||||
tree.add(7, 'C');
|
||||
|
||||
tree.iterationType = IterationType.ITERATIVE;
|
||||
expect([...tree]).toEqual([3, 5, 7]);
|
||||
tree.iterationType = IterationType.RECURSIVE;
|
||||
expect([...tree]).toEqual([3, 5, 7]);
|
||||
tree.iterationType = IterationType.ITERATIVE;
|
||||
tree.options.iterationType = IterationType.ITERATIVE;
|
||||
expect([...tree]).toEqual([[3, "B"], [5, "A"], [7, "C"]]);
|
||||
tree.options.iterationType = IterationType.RECURSIVE;
|
||||
expect([...tree]).toEqual([[3, "B"], [5, "A"], [7, "C"]]);
|
||||
tree.options.iterationType = IterationType.ITERATIVE;
|
||||
|
||||
const result = tree.morris();
|
||||
expect(result).toEqual([3, 5, 7]);
|
||||
|
@ -564,3 +564,58 @@ describe('BinaryTree', () => {
|
|||
expect(tree.getHeight()).toBe(-1);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('BinaryTree iterative methods test', () => {
|
||||
let binaryTree: BinaryTree<string>;
|
||||
beforeEach(() => {
|
||||
binaryTree = new BinaryTree();
|
||||
binaryTree.add(1, 'a');
|
||||
binaryTree.add(2, 'b');
|
||||
binaryTree.add(3, 'c');
|
||||
});
|
||||
|
||||
test('The node obtained by get Node should match the node type', () => {
|
||||
const node3 = binaryTree.getNode(3);
|
||||
expect(node3).toBeInstanceOf(BinaryTreeNode);
|
||||
});
|
||||
|
||||
test('forEach should iterate over all elements', () => {
|
||||
const mockCallback = jest.fn();
|
||||
binaryTree.forEach((entry) => {
|
||||
mockCallback(entry);
|
||||
});
|
||||
|
||||
expect(mockCallback.mock.calls.length).toBe(3);
|
||||
expect(mockCallback.mock.calls[0][0]).toEqual([2, 'b']);
|
||||
expect(mockCallback.mock.calls[1][0]).toEqual([1, 'a']);
|
||||
expect(mockCallback.mock.calls[2][0]).toEqual([3, 'c']);
|
||||
});
|
||||
|
||||
test('filter should return a new tree with filtered elements', () => {
|
||||
const filteredTree = binaryTree.filter(([key]) => key > 1);
|
||||
expect(filteredTree.size).toBe(2);
|
||||
expect([...filteredTree]).toEqual([[3, 'c'], [2, 'b']]);
|
||||
});
|
||||
|
||||
test('map should return a new tree with modified elements', () => {
|
||||
const mappedTree = binaryTree.map(([key]) => (key * 2).toString());
|
||||
expect(mappedTree.size).toBe(3);
|
||||
expect([...mappedTree]).toEqual([[1, '2'], [2, '4'], [3, '6']]);
|
||||
});
|
||||
|
||||
test('reduce should accumulate values', () => {
|
||||
const sum = binaryTree.reduce((acc, [key]) => acc + key, 0);
|
||||
expect(sum).toBe(6);
|
||||
});
|
||||
|
||||
test('[Symbol.iterator] should provide an iterator', () => {
|
||||
const entries = [];
|
||||
for (const entry of binaryTree) {
|
||||
entries.push(entry);
|
||||
}
|
||||
|
||||
expect(entries.length).toBe(3);
|
||||
expect(entries).toEqual([[2, 'b'], [1, 'a'], [3, 'c']]);
|
||||
});
|
||||
});
|
|
@ -1,4 +1,4 @@
|
|||
import { BST, BSTNode, CP, IterationType } from '../../../../src';
|
||||
import { BinaryTreeNode, BST, BSTNode, CP, IterationType } from '../../../../src';
|
||||
import { isDebugTest } from '../../../config';
|
||||
|
||||
const isDebug = isDebugTest;
|
||||
|
@ -851,3 +851,58 @@ describe('BST Performance test', function () {
|
|||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('BST iterative methods test', () => {
|
||||
let bst: BST<string>;
|
||||
beforeEach(() => {
|
||||
bst = new BST();
|
||||
bst.add(1, 'a');
|
||||
bst.add(2, 'b');
|
||||
bst.add(3, 'c');
|
||||
});
|
||||
|
||||
test('The node obtained by get Node should match the node type', () => {
|
||||
const node3 = bst.getNode(3);
|
||||
expect(node3).toBeInstanceOf(BinaryTreeNode);
|
||||
expect(node3).toBeInstanceOf(BSTNode);
|
||||
});
|
||||
|
||||
test('forEach should iterate over all elements', () => {
|
||||
const mockCallback = jest.fn();
|
||||
bst.forEach((entry) => {
|
||||
mockCallback(entry);
|
||||
});
|
||||
|
||||
expect(mockCallback.mock.calls.length).toBe(3);
|
||||
expect(mockCallback.mock.calls[0][0]).toEqual([1, 'a']);
|
||||
expect(mockCallback.mock.calls[1][0]).toEqual([2, 'b']);
|
||||
expect(mockCallback.mock.calls[2][0]).toEqual([3, 'c']);
|
||||
});
|
||||
|
||||
test('filter should return a new tree with filtered elements', () => {
|
||||
const filteredTree = bst.filter(([key]) => key > 1);
|
||||
expect(filteredTree.size).toBe(2);
|
||||
expect([...filteredTree]).toEqual([[2, 'b'], [3, 'c']]);
|
||||
});
|
||||
|
||||
test('map should return a new tree with modified elements', () => {
|
||||
const mappedTree = bst.map(([key]) => (key * 2).toString());
|
||||
expect(mappedTree.size).toBe(3);
|
||||
expect([...mappedTree]).toEqual([[1, '2'], [2, '4'], [3, '6']]);
|
||||
});
|
||||
|
||||
test('reduce should accumulate values', () => {
|
||||
const sum = bst.reduce((acc, [key]) => acc + key, 0);
|
||||
expect(sum).toBe(6);
|
||||
});
|
||||
|
||||
test('[Symbol.iterator] should provide an iterator', () => {
|
||||
const entries = [];
|
||||
for (const entry of bst) {
|
||||
entries.push(entry);
|
||||
}
|
||||
|
||||
expect(entries.length).toBe(3);
|
||||
expect(entries).toEqual([[1, 'a'], [2, 'b'], [3, 'c']]);
|
||||
});
|
||||
});
|
|
@ -1,4 +1,4 @@
|
|||
import { IterationType, RBTNColor, RedBlackTree, RedBlackTreeNode } from '../../../../src';
|
||||
import { BinaryTreeNode, BSTNode, IterationType, RBTNColor, RedBlackTree, RedBlackTreeNode } from '../../../../src';
|
||||
import { getRandomInt, getRandomIntArray, magnitude } from '../../../utils';
|
||||
import { isDebugTest } from '../../../config';
|
||||
import { OrderedMap } from 'js-sdsl';
|
||||
|
@ -490,7 +490,7 @@ describe('RedBlackTree', () => {
|
|||
|
||||
it('duplicates', () => {
|
||||
tree.addMany([9, 8, 7, 8, 8, 8, 2, 3, 6, 5, 5, 4]);
|
||||
tree.print();
|
||||
isDebug && tree.print();
|
||||
|
||||
expect(tree.size).toBe(8);
|
||||
expect(tree.isBST()).toBe(true);
|
||||
|
@ -505,3 +505,59 @@ describe('RedBlackTree', () => {
|
|||
expect(tree.isAVLBalanced()).toBe(false);
|
||||
})
|
||||
});
|
||||
|
||||
describe('RedBlackTree iterative methods test', () => {
|
||||
let rbTree: RedBlackTree<string>;
|
||||
beforeEach(() => {
|
||||
rbTree = new RedBlackTree();
|
||||
rbTree.add(1, 'a');
|
||||
rbTree.add(2, 'b');
|
||||
rbTree.add(3, 'c');
|
||||
});
|
||||
|
||||
test('The node obtained by get Node should match the node type', () => {
|
||||
const node3 = rbTree.getNode(3);
|
||||
expect(node3).toBeInstanceOf(BinaryTreeNode);
|
||||
expect(node3).toBeInstanceOf(BSTNode);
|
||||
expect(node3).toBeInstanceOf(RedBlackTreeNode);
|
||||
});
|
||||
|
||||
test('forEach should iterate over all elements', () => {
|
||||
const mockCallback = jest.fn();
|
||||
rbTree.forEach((entry) => {
|
||||
mockCallback(entry);
|
||||
});
|
||||
|
||||
expect(mockCallback.mock.calls.length).toBe(3);
|
||||
expect(mockCallback.mock.calls[0][0]).toEqual([1, 'a']);
|
||||
expect(mockCallback.mock.calls[1][0]).toEqual([2, 'b']);
|
||||
expect(mockCallback.mock.calls[2][0]).toEqual([3, 'c']);
|
||||
});
|
||||
|
||||
test('filter should return a new tree with filtered elements', () => {
|
||||
const filteredTree = rbTree.filter(([key]) => key > 1);
|
||||
expect(filteredTree.size).toBe(2);
|
||||
expect([...filteredTree]).toEqual([[2, 'b'], [3, 'c']]);
|
||||
});
|
||||
|
||||
test('map should return a new tree with modified elements', () => {
|
||||
const mappedTree = rbTree.map(([key]) => (key * 2).toString());
|
||||
expect(mappedTree.size).toBe(3);
|
||||
expect([...mappedTree]).toEqual([[1, '2'], [2, '4'], [3, '6']]);
|
||||
});
|
||||
|
||||
test('reduce should accumulate values', () => {
|
||||
const sum = rbTree.reduce((acc, [key]) => acc + key, 0);
|
||||
expect(sum).toBe(6);
|
||||
});
|
||||
|
||||
test('[Symbol.iterator] should provide an iterator', () => {
|
||||
const entries = [];
|
||||
for (const entry of rbTree) {
|
||||
entries.push(entry);
|
||||
}
|
||||
|
||||
expect(entries.length).toBe(3);
|
||||
expect(entries).toEqual([[1, 'a'], [2, 'b'], [3, 'c']]);
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue