fix: Adjust type safety for the map method of all binary trees, ensuring it no longer returns the TREE type to its parent class and limiting Node type nesting to a maximum of 10 levels. Fix the issue with RedBlackTree objects being incorrectly compared when used as keys. Rename extractComparable to specificComparable. Correct the order of key and value in callback functions for the map and filter methods.

This commit is contained in:
Revone 2024-11-25 01:10:33 +13:00
parent 1494ffa84f
commit 1a1ea21444
32 changed files with 842 additions and 491 deletions

View file

@ -8,7 +8,7 @@ All notable changes to this project will be documented in this file.
- [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
- [`auto-changelog`](https://github.com/CookPete/auto-changelog)
## [v1.53.7](https://github.com/zrwusa/data-structure-typed/compare/v1.51.5...main) (upcoming)
## [v1.53.8](https://github.com/zrwusa/data-structure-typed/compare/v1.51.5...main) (upcoming)
### Changes

View file

@ -86,7 +86,7 @@
- Make your pull requests to be **specific** and **focused**. Instead of
contributing "several data structures" all at once contribute them all
one by one separately (i.e. one pull request for "RBTree", another one
one by one separately (i.e. one pull request for "RedBlackTree", another one
for "AATree" and so on).
- Modify **README.md** for each of the data structure **with explanations** of
the algorithm and **with links** to further readings.

52
package-lock.json generated
View file

@ -1,12 +1,12 @@
{
"name": "data-structure-typed",
"version": "1.53.7",
"version": "1.53.8",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "data-structure-typed",
"version": "1.53.7",
"version": "1.53.8",
"license": "MIT",
"devDependencies": {
"@eslint/compat": "^1.2.2",
@ -19,11 +19,11 @@
"@typescript-eslint/eslint-plugin": "^8.12.1",
"@typescript-eslint/parser": "^8.12.1",
"auto-changelog": "^2.5.0",
"avl-tree-typed": "^1.53.6",
"avl-tree-typed": "^1.53.7",
"benchmark": "^2.1.4",
"binary-tree-typed": "^1.53.6",
"bst-typed": "^1.53.6",
"data-structure-typed": "^1.53.6",
"binary-tree-typed": "^1.53.7",
"bst-typed": "^1.53.7",
"data-structure-typed": "^1.53.7",
"dependency-cruiser": "^16.5.0",
"doctoc": "^2.2.1",
"eslint": "^9.13.0",
@ -32,7 +32,7 @@
"eslint-import-resolver-typescript": "^3.6.3",
"eslint-plugin-import": "^2.31.0",
"fast-glob": "^3.3.2",
"heap-typed": "^1.53.6",
"heap-typed": "^1.53.7",
"istanbul-badges-readme": "^1.9.0",
"jest": "^29.7.0",
"js-sdsl": "^4.4.2",
@ -3437,13 +3437,13 @@
}
},
"node_modules/avl-tree-typed": {
"version": "1.53.6",
"resolved": "https://registry.npmjs.org/avl-tree-typed/-/avl-tree-typed-1.53.6.tgz",
"integrity": "sha512-BmWYQG+mvfoS9yPVAm3CRL3omYdCO1Rohe7BGkYjvC1WHhd0A6FIrwu5Ge9kyrPxxqQsZWK/D4YHDqTyWkX4+A==",
"version": "1.53.7",
"resolved": "https://registry.npmjs.org/avl-tree-typed/-/avl-tree-typed-1.53.7.tgz",
"integrity": "sha512-+HyMQY+1FoOQm6ESwSbtJL6LnR9XNYxqJc6IdDEAhBZovRx2m3bwgse5q+3SLyEqQAUwSY9LsGD3A80UQq4fjQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"data-structure-typed": "^1.53.6"
"data-structure-typed": "^1.53.7"
}
},
"node_modules/babel-jest": {
@ -3602,13 +3602,13 @@
}
},
"node_modules/binary-tree-typed": {
"version": "1.53.6",
"resolved": "https://registry.npmjs.org/binary-tree-typed/-/binary-tree-typed-1.53.6.tgz",
"integrity": "sha512-cLjhoqLjoY+iMbMcvQsjT1jhCHkdGI4j3cEdLG4g3Vy99jipxiXQ3h9qSmWYo5HO7w5DBfU4v+xw4yI5lM3+AQ==",
"version": "1.53.7",
"resolved": "https://registry.npmjs.org/binary-tree-typed/-/binary-tree-typed-1.53.7.tgz",
"integrity": "sha512-Pd/N1QOFm7qgBhdp4T43lBpUhPUex5hwL/9JuZ7qgfN++qxCQLAwU72tgPAvSjwb4z6njqG8/4hfLdnLUbDWUg==",
"dev": true,
"license": "MIT",
"dependencies": {
"data-structure-typed": "^1.53.6"
"data-structure-typed": "^1.53.7"
}
},
"node_modules/brace-expansion": {
@ -3691,13 +3691,13 @@
}
},
"node_modules/bst-typed": {
"version": "1.53.6",
"resolved": "https://registry.npmjs.org/bst-typed/-/bst-typed-1.53.6.tgz",
"integrity": "sha512-LKY9GMNdhYlb8Iprc8Z4143bQ6cWYhE8thSHb8jhvVzsEuqXqetM0tSG88a5QjURgxt+Mr9GGJruSeBYX7/vQw==",
"version": "1.53.7",
"resolved": "https://registry.npmjs.org/bst-typed/-/bst-typed-1.53.7.tgz",
"integrity": "sha512-Sj2nJb/2SUAqcSg4oXNWMt9OxlF4NcxPQ6o2wMKbqiKp4JCblmLpVEjbaZBVrpRMTKHEZctW/is21QPcxQ9Hnw==",
"dev": true,
"license": "MIT",
"dependencies": {
"data-structure-typed": "^1.53.6"
"data-structure-typed": "^1.53.7"
}
},
"node_modules/buffer-from": {
@ -4069,9 +4069,9 @@
}
},
"node_modules/data-structure-typed": {
"version": "1.53.6",
"resolved": "https://registry.npmjs.org/data-structure-typed/-/data-structure-typed-1.53.6.tgz",
"integrity": "sha512-o3j49Yb5nPWyMIYvm6KOqlaj6SbUP/nq26kl6KmT0UknbOPfrElGIAdYwV9J87dHkHxGPGJG7Ee754jv8XjIIQ==",
"version": "1.53.7",
"resolved": "https://registry.npmjs.org/data-structure-typed/-/data-structure-typed-1.53.7.tgz",
"integrity": "sha512-8higtCbppFIeHaz7JMJL2WdZ/vc4wtO8+Yh6qZtONDAy+shqafASqpTsYnKJaE8gNiPzOkP2YOMiEbVdpKLhhQ==",
"dev": true,
"license": "MIT"
},
@ -5946,13 +5946,13 @@
}
},
"node_modules/heap-typed": {
"version": "1.53.6",
"resolved": "https://registry.npmjs.org/heap-typed/-/heap-typed-1.53.6.tgz",
"integrity": "sha512-MS8mjgg/rjV6wQmD/sqdr93M0WGezju/Q4KFULvF+JpD7XVmdpfN/w+h9fA4ZYkkI5Ih7JarJvvh8hHHWfpqIg==",
"version": "1.53.7",
"resolved": "https://registry.npmjs.org/heap-typed/-/heap-typed-1.53.7.tgz",
"integrity": "sha512-iXPgPtyCxDY/+e8eCvWUVSsQ2h+7L6upoP1QGJrIm47+tdTovV/EZ0PhCIKWERRzHI4Us/PM9hZbX0Jt8KBeRg==",
"dev": true,
"license": "MIT",
"dependencies": {
"data-structure-typed": "^1.53.6"
"data-structure-typed": "^1.53.7"
}
},
"node_modules/html-escaper": {

View file

@ -1,6 +1,6 @@
{
"name": "data-structure-typed",
"version": "1.53.8",
"version": "1.53.9",
"description": "Javascript Data Structure. Heap, Binary Tree, Red Black Tree, Linked List, Deque, Trie, HashMap, Directed Graph, Undirected Graph, Binary Search Tree(BST), AVL Tree, Priority Queue, Graph, Queue, Tree Multiset, Singly Linked List, Doubly Linked List, Max Heap, Max Priority Queue, Min Heap, Min Priority Queue, Stack. Benchmark compared with C++ STL. API aligned with ES6 and Java.util. Usability is comparable to Python",
"main": "dist/cjs/index.js",
"module": "dist/mjs/index.js",
@ -70,11 +70,11 @@
"@typescript-eslint/eslint-plugin": "^8.12.1",
"@typescript-eslint/parser": "^8.12.1",
"auto-changelog": "^2.5.0",
"avl-tree-typed": "^1.53.6",
"avl-tree-typed": "^1.53.7",
"benchmark": "^2.1.4",
"binary-tree-typed": "^1.53.6",
"bst-typed": "^1.53.6",
"data-structure-typed": "^1.53.6",
"binary-tree-typed": "^1.53.7",
"bst-typed": "^1.53.7",
"data-structure-typed": "^1.53.7",
"dependency-cruiser": "^16.5.0",
"doctoc": "^2.2.1",
"eslint": "^9.13.0",
@ -83,7 +83,7 @@
"eslint-import-resolver-typescript": "^3.6.3",
"eslint-plugin-import": "^2.31.0",
"fast-glob": "^3.3.2",
"heap-typed": "^1.53.6",
"heap-typed": "^1.53.7",
"istanbul-badges-readme": "^1.9.0",
"jest": "^29.7.0",
"js-sdsl": "^4.4.2",

View file

@ -6,12 +6,12 @@
* @license MIT License
*/
import type {
AVLTreeMultiMapNested,
AVLTreeMultiMapNodeNested,
AVLTreeMultiMapOptions,
BinaryTreeDeleteResult,
BSTNOptKeyOrNode,
BTNRep,
EntryCallback,
IterationType
} from '../../types';
import { IBinaryTree } from '../../interfaces';
@ -64,17 +64,10 @@ export class AVLTreeMultiMap<
K = any,
V = any,
R = object,
NODE extends AVLTreeMultiMapNode<K, V, NODE> = AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNodeNested<K, V>>,
TREE extends AVLTreeMultiMap<K, V, R, NODE, TREE> = AVLTreeMultiMap<
K,
V,
R,
NODE,
AVLTreeMultiMapNested<K, V, R, NODE>
>
NODE extends AVLTreeMultiMapNode<K, V, NODE> = AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNodeNested<K, V>>
>
extends AVLTree<K, V, R, NODE, TREE>
implements IBinaryTree<K, V, R, NODE, TREE>
extends AVLTree<K, V, R, NODE>
implements IBinaryTree<K, V, R, NODE>
{
/**
* The constructor initializes a new AVLTreeMultiMap object with optional initial elements.
@ -139,15 +132,16 @@ export class AVLTreeMultiMap<
* @returns a new instance of the AVLTreeMultiMap class, with the specified options, as a TREE
* object.
*/
override createTree(options?: AVLTreeMultiMapOptions<K, V, R>): TREE {
return new AVLTreeMultiMap<K, V, R, NODE, TREE>([], {
// @ts-ignore
override createTree(options?: AVLTreeMultiMapOptions<K, V, R>) {
return new AVLTreeMultiMap<K, V, R, NODE>([], {
iterationType: this.iterationType,
isMapMode: this._isMapMode,
extractComparable: this._extractComparable,
specifyComparable: this._specifyComparable,
toEntryFn: this._toEntryFn,
isReverse: this._isReverse,
...options
}) as TREE;
});
}
/**
@ -161,44 +155,6 @@ export class AVLTreeMultiMap<
return keyNodeEntryOrRaw instanceof AVLTreeMultiMapNode;
}
/**
* The function `keyValueNodeEntryRawToNodeAndValue` converts a key, value, entry, or raw element into
* a node object.
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The
* `keyNodeEntryOrRaw` parameter can be of type `R` or `BTNRep<K, V, NODE>`.
* @param {V} [value] - The `value` parameter is an optional value that can be passed to the
* `override` function. It represents the value associated with the key in the data structure. If no
* value is provided, it will default to `undefined`.
* @param [count=1] - The `count` parameter is an optional parameter that specifies the number of
* times the key-value pair should be added to the data structure. If not provided, it defaults to 1.
* @returns either a NODE object or undefined.
*/
protected override _keyValueNodeEntryRawToNodeAndValue(
keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R,
value?: V,
count = 1
): [NODE | undefined, V | undefined] {
if (keyNodeEntryOrRaw === undefined || keyNodeEntryOrRaw === null) return [undefined, undefined];
if (this.isNode(keyNodeEntryOrRaw)) return [keyNodeEntryOrRaw, value];
if (this.isEntry(keyNodeEntryOrRaw)) {
const [key, entryValue] = keyNodeEntryOrRaw;
if (key === undefined || key === null) return [undefined, undefined];
const finalValue = value ?? entryValue;
return [this.createNode(key, finalValue, count), finalValue];
}
if (this.isRaw(keyNodeEntryOrRaw)) {
const [key, entryValue] = this._toEntryFn!(keyNodeEntryOrRaw);
const finalValue = value ?? entryValue;
if (this.isKey(key)) return [this.createNode(key, finalValue, count), finalValue];
}
if (this.isKey(keyNodeEntryOrRaw)) return [this.createNode(keyNodeEntryOrRaw, value, count), value];
return [undefined, undefined];
}
/**
* Time Complexity: O(log n)
* Space Complexity: O(1)
@ -374,7 +330,8 @@ export class AVLTreeMultiMap<
* The function overrides the clone method to create a deep copy of a tree object.
* @returns The `clone()` method is returning a cloned instance of the `TREE` object.
*/
override clone(): TREE {
// @ts-ignore
override clone() {
const cloned = this.createTree();
if (this._isMapMode) this.bfs(node => cloned.add(node.key, undefined, node.count));
else this.bfs(node => cloned.add(node.key, node.value, node.count));
@ -382,6 +339,76 @@ export class AVLTreeMultiMap<
return cloned;
}
/**
* The `map` function in TypeScript overrides the default behavior to create a new AVLTreeMultiMap
* with modified entries based on a provided callback.
* @param callback - The `callback` parameter is a function that will be called for each entry in the
* AVLTreeMultiMap. It takes four arguments:
* @param [options] - The `options` parameter in the `override map` function is of type
* `AVLTreeMultiMapOptions<MK, MV, MR>`. This parameter allows you to provide additional
* configuration options when creating a new `AVLTreeMultiMap` instance within the `map` function.
* These options
* @param {any} [thisArg] - The `thisArg` parameter in the `override map` function is used to specify
* the value of `this` when executing the `callback` function. It allows you to set the context
* (value of `this`) for the callback function. This can be useful when you want to access properties
* or
* @returns The `map` method is returning a new `AVLTreeMultiMap` instance with the entries
* transformed by the provided `callback` function. Each entry in the original tree is passed to the
* `callback` function along with the index and the original tree itself. The transformed entries are
* then added to the new `AVLTreeMultiMap` instance, which is returned at the end.
*/
// @ts-ignore
override map<MK, MV, MR>(
callback: EntryCallback<K, V | undefined, [MK, MV]>,
options?: AVLTreeMultiMapOptions<MK, MV, MR>,
thisArg?: any
) {
const newTree = new AVLTreeMultiMap<MK, MV, MR>([], options);
let index = 0;
for (const [key, value] of this) {
newTree.add(callback.call(thisArg, key, value, index++, this));
}
return newTree;
}
/**
* The function `keyValueNodeEntryRawToNodeAndValue` converts a key, value, entry, or raw element into
* a node object.
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The
* `keyNodeEntryOrRaw` parameter can be of type `R` or `BTNRep<K, V, NODE>`.
* @param {V} [value] - The `value` parameter is an optional value that can be passed to the
* `override` function. It represents the value associated with the key in the data structure. If no
* value is provided, it will default to `undefined`.
* @param [count=1] - The `count` parameter is an optional parameter that specifies the number of
* times the key-value pair should be added to the data structure. If not provided, it defaults to 1.
* @returns either a NODE object or undefined.
*/
protected override _keyValueNodeEntryRawToNodeAndValue(
keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R,
value?: V,
count = 1
): [NODE | undefined, V | undefined] {
if (keyNodeEntryOrRaw === undefined || keyNodeEntryOrRaw === null) return [undefined, undefined];
if (this.isNode(keyNodeEntryOrRaw)) return [keyNodeEntryOrRaw, value];
if (this.isEntry(keyNodeEntryOrRaw)) {
const [key, entryValue] = keyNodeEntryOrRaw;
if (key === undefined || key === null) return [undefined, undefined];
const finalValue = value ?? entryValue;
return [this.createNode(key, finalValue, count), finalValue];
}
if (this.isRaw(keyNodeEntryOrRaw)) {
const [key, entryValue] = this._toEntryFn!(keyNodeEntryOrRaw);
const finalValue = value ?? entryValue;
if (this.isKey(key)) return [this.createNode(key, finalValue, count), finalValue];
}
if (this.isKey(keyNodeEntryOrRaw)) return [this.createNode(keyNodeEntryOrRaw, value, count), value];
return [undefined, undefined];
}
/**
* Time Complexity: O(1)
* Space Complexity: O(1)

View file

@ -7,12 +7,12 @@
*/
import { BST, BSTNode } from './bst';
import type {
AVLTreeNested,
AVLTreeNodeNested,
AVLTreeOptions,
BinaryTreeDeleteResult,
BSTNOptKeyOrNode,
BTNRep
BTNRep,
EntryCallback
} from '../../types';
import { IBinaryTree } from '../../interfaces';
@ -67,11 +67,10 @@ export class AVLTree<
K = any,
V = any,
R = object,
NODE extends AVLTreeNode<K, V, NODE> = AVLTreeNode<K, V, AVLTreeNodeNested<K, V>>,
TREE extends AVLTree<K, V, R, NODE, TREE> = AVLTree<K, V, R, NODE, AVLTreeNested<K, V, R, NODE>>
NODE extends AVLTreeNode<K, V, NODE> = AVLTreeNode<K, V, AVLTreeNodeNested<K, V>>
>
extends BST<K, V, R, NODE, TREE>
implements IBinaryTree<K, V, R, NODE, TREE>
extends BST<K, V, R, NODE>
implements IBinaryTree<K, V, R, NODE>
{
/**
* This is a constructor function for an AVLTree class that initializes the tree with keys, nodes,
@ -103,21 +102,25 @@ export class AVLTree<
}
/**
* The function creates a new AVL tree with the specified options and returns it.
* @param {AVLTreeOptions} [options] - The `options` parameter is an optional object that can be
* passed to the `createTree` function. It is used to customize the behavior of the AVL tree that is
* being created.
* @returns a new AVLTree object.
* The function `createTree` in TypeScript overrides the default AVLTree creation with the provided
* options.
* @param [options] - The `options` parameter in the `createTree` function is an object that contains
* configuration options for creating an AVL tree. These options can include properties such as
* `iterationType`, `isMapMode`, `specifyComparable`, `toEntryFn`, and `isReverse`. The function
* creates a
* @returns An AVLTree object is being returned with the specified options and properties inherited
* from the current object.
*/
override createTree(options?: AVLTreeOptions<K, V, R>): TREE {
return new AVLTree<K, V, R, NODE, TREE>([], {
// @ts-ignore
override createTree(options?: AVLTreeOptions<K, V, R>) {
return new AVLTree<K, V, R, NODE>([], {
iterationType: this.iterationType,
isMapMode: this._isMapMode,
extractComparable: this._extractComparable,
specifyComparable: this._specifyComparable,
toEntryFn: this._toEntryFn,
isReverse: this._isReverse,
...options
}) as TREE;
});
}
/**
@ -174,6 +177,20 @@ export class AVLTree<
return deletedResults;
}
// @ts-ignore
override map<MK, MV, MR>(
callback: EntryCallback<K, V | undefined, [MK, MV]>,
options?: AVLTreeOptions<MK, MV, MR>,
thisArg?: any
) {
const newTree = new AVLTree<MK, MV, MR>([], options);
let index = 0;
for (const [key, value] of this) {
newTree.add(callback.call(thisArg, key, value, index++, this));
}
return newTree;
}
/**
* Time Complexity: O(1)
* Space Complexity: O(1)

View file

@ -8,7 +8,6 @@
import {
BinaryTreeDeleteResult,
BinaryTreeNested,
BinaryTreeNodeNested,
BinaryTreeOptions,
BinaryTreePrintOptions,
@ -105,11 +104,10 @@ export class BinaryTree<
K = any,
V = any,
R = object,
NODE extends BinaryTreeNode<K, V, NODE> = BinaryTreeNode<K, V, BinaryTreeNodeNested<K, V>>,
TREE extends BinaryTree<K, V, R, NODE, TREE> = BinaryTree<K, V, R, NODE, BinaryTreeNested<K, V, R, NODE>>
NODE extends BinaryTreeNode<K, V, NODE> = BinaryTreeNode<K, V, BinaryTreeNodeNested<K, V>>
>
extends IterableEntryBase<K, V | undefined>
implements IBinaryTree<K, V, R, NODE, TREE>
implements IBinaryTree<K, V, R, NODE>
{
iterationType: IterationType = 'ITERATIVE';
@ -172,6 +170,9 @@ export class BinaryTree<
}
/**
* Time Complexity: O(1)
* Space Complexity: O(1)
*
* The function creates a new binary tree node with a specified key and optional value.
* @param {K} key - The `key` parameter is the key of the node being created in the binary tree.
* @param {V} [value] - The `value` parameter in the `createNode` function is optional, meaning it is
@ -185,63 +186,26 @@ export class BinaryTree<
}
/**
* The function creates a binary tree with the specified options.
* @param [options] - The `options` parameter in the `createTree` function is an optional parameter
* that allows you to provide partial configuration options for creating a binary tree. It is of type
* `Partial<BinaryTreeOptions<K, V, R>>`, which means you can pass in an object containing a subset
* of properties
* @returns A new instance of a binary tree with the specified options is being returned.
* Time Complexity: O(1)
* Space Complexity: O(1)
*
* The `createTree` function creates a new binary tree based on the provided options.
* @param [options] - The `options` parameter in the `createTree` method is of type
* `BinaryTreeOptions<K, V, R>`. This type likely contains configuration options for creating a
* binary tree, such as the iteration type, whether the tree is in map mode, and functions for
* converting entries.
* @returns The `createTree` method is returning an instance of the `BinaryTree` class with the
* provided options. The method is creating a new `BinaryTree` object with an empty array as the
* initial data, and then setting various options such as `iterationType`, `isMapMode`, and
* `toEntryFn` based on the current object's properties and the provided `options`. Finally, it
*/
createTree(options?: BinaryTreeOptions<K, V, R>): TREE {
return new BinaryTree<K, V, R, NODE, TREE>([], {
createTree(options?: BinaryTreeOptions<K, V, R>): typeof this {
return new BinaryTree<K, V, R>([], {
iterationType: this.iterationType,
isMapMode: this._isMapMode,
toEntryFn: this._toEntryFn,
...options
}) as TREE;
}
/**
* The function `keyValueNodeEntryRawToNodeAndValue` converts various input types into a node object
* or returns null.
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The
* `keyValueNodeEntryRawToNodeAndValue` function takes in a parameter `keyNodeEntryOrRaw`, which
* can be of type `BTNRep<K, V, NODE>` or `R`. This parameter represents either a key, a
* node, an entry
* @param {V} [value] - The `value` parameter in the `keyValueNodeEntryRawToNodeAndValue` function is
* an optional parameter of type `V`. It represents the value associated with the key in the node
* being created. If a `value` is provided, it will be used when creating the node. If
* @returns The `keyValueNodeEntryRawToNodeAndValue` function returns an optional node
* (`OptNodeOrNull<NODE>`) based on the input parameters provided. The function checks the type of the
* input parameter (`keyNodeEntryOrRaw`) and processes it accordingly to return a node or null
* value.
*/
protected _keyValueNodeEntryRawToNodeAndValue(
keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R,
value?: V
): [OptNodeOrNull<NODE>, V | undefined] {
if (keyNodeEntryOrRaw === undefined) return [undefined, undefined];
if (keyNodeEntryOrRaw === null) return [null, undefined];
if (this.isNode(keyNodeEntryOrRaw)) return [keyNodeEntryOrRaw, value];
if (this.isEntry(keyNodeEntryOrRaw)) {
const [key, entryValue] = keyNodeEntryOrRaw;
if (key === undefined) return [undefined, undefined];
else if (key === null) return [null, undefined];
const finalValue = value ?? entryValue;
return [this.createNode(key, finalValue), finalValue];
}
if (this.isRaw(keyNodeEntryOrRaw)) {
const [key, entryValue] = this._toEntryFn!(keyNodeEntryOrRaw);
const finalValue = value ?? entryValue;
if (this.isKey(key)) return [this.createNode(key, finalValue), finalValue];
}
if (this.isKey(keyNodeEntryOrRaw)) return [this.createNode(keyNodeEntryOrRaw, value), value];
return [undefined, undefined];
}) as unknown as typeof this;
}
/**
@ -526,7 +490,7 @@ export class BinaryTree<
* elements from the other tree.
* @param anotherTree - `BinaryTree<K, V, R, NODE, TREE>`
*/
merge(anotherTree: BinaryTree<K, V, R, NODE, TREE>) {
merge(anotherTree: this) {
this.addMany(anotherTree, []);
}
@ -1635,7 +1599,7 @@ export class BinaryTree<
* original tree using breadth-first search (bfs), and adds the nodes to the new tree. If a node in
* the original tree is null, a null node is added to the cloned tree. If a node
*/
clone(): TREE {
clone() {
const cloned = this.createTree();
this.bfs(
node => {
@ -1673,7 +1637,7 @@ export class BinaryTree<
const newTree = this.createTree();
let index = 0;
for (const [key, value] of this) {
if (predicate.call(thisArg, value, key, index++, this)) {
if (predicate.call(thisArg, key, value, index++, this)) {
newTree.add([key, value]);
}
}
@ -1684,36 +1648,34 @@ export class BinaryTree<
* Time Complexity: O(n)
* Space Complexity: O(n)
*
* The `map` function iterates over key-value pairs in a tree data structure, applies a callback
* function to each value, and returns a new tree with the updated values.
* @param callback - The `callback` parameter in the `map` method is a function that will be called
* on each entry in the tree. It takes four arguments:
* @param {any} [thisArg] - The `thisArg` parameter in the `map` function is an optional parameter
* that specifies the value to be passed as `this` when executing the callback function. If provided,
* the `thisArg` value will be used as the `this` value within the callback function. If `thisArg
* @returns The `map` method is returning a new tree with the entries modified by the provided
* callback function. Each entry in the original tree is passed to the callback function, and the
* result of the callback function is added to the new tree.
* The `map` function in TypeScript creates a new BinaryTree by applying a callback function to each
* entry in the original BinaryTree.
* @param callback - A function that will be called for each entry in the current binary tree. It
* takes the key, value (which can be undefined), and an array containing the mapped key and value as
* arguments.
* @param [options] - The `options` parameter in the `map` method is of type `BinaryTreeOptions<MK,
* MV, MR>`. It is an optional parameter that allows you to specify additional options for the binary
* tree being created during the mapping process. These options could include things like custom
* comparators, initial
* @param {any} [thisArg] - The `thisArg` parameter in the `map` method is used to specify the value
* of `this` when executing the `callback` function. It allows you to set the context (value of
* `this`) within the callback function. If `thisArg` is provided, it will be passed
* @returns The `map` function is returning a new `BinaryTree` instance filled with entries that are
* the result of applying the provided `callback` function to each entry in the original tree.
*/
map(callback: EntryCallback<K, V | undefined, V>, thisArg?: any) {
const newTree = this.createTree();
map<MK, MV, MR>(
callback: EntryCallback<K, V | undefined, [MK, MV]>,
options?: BinaryTreeOptions<MK, MV, MR>,
thisArg?: any
) {
const newTree = new BinaryTree<MK, MV, MR>([], options);
let index = 0;
for (const [key, value] of this) {
newTree.add([key, callback.call(thisArg, value, key, index++, this)]);
newTree.add(callback.call(thisArg, key, value, index++, this));
}
return newTree;
}
// // TODO Type error, need to return a TREE<NV> that is a value type only for callback function.
// // map<NV>(callback: (entry: [K, V | undefined], tree: this) => NV) {
// // const newTree = this.createTree();
// // for (const [key, value] of this) {
// // newTree.add(key, callback([key, value], this));
// // }
// // return newTree;
// // }
//
/**
* Time Complexity: O(n)
* Space Complexity: O(n)
@ -1743,7 +1705,7 @@ export class BinaryTree<
if (opts.isShowRedBlackNIL) output += `S for Sentinel Node(NIL)\n`;
const display = (root: OptNodeOrNull<NODE>): void => {
const [lines, , ,] = this._displayAux(root, opts);
const [lines, ,] = this._displayAux(root, opts);
let paragraph = '';
for (const line of lines) {
paragraph += line + '\n';
@ -1774,6 +1736,49 @@ export class BinaryTree<
console.log(this.toVisual(startNode, options));
}
/**
* The function `keyValueNodeEntryRawToNodeAndValue` converts various input types into a node object
* or returns null.
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The
* `keyValueNodeEntryRawToNodeAndValue` function takes in a parameter `keyNodeEntryOrRaw`, which
* can be of type `BTNRep<K, V, NODE>` or `R`. This parameter represents either a key, a
* node, an entry
* @param {V} [value] - The `value` parameter in the `keyValueNodeEntryRawToNodeAndValue` function is
* an optional parameter of type `V`. It represents the value associated with the key in the node
* being created. If a `value` is provided, it will be used when creating the node. If
* @returns The `keyValueNodeEntryRawToNodeAndValue` function returns an optional node
* (`OptNodeOrNull<NODE>`) based on the input parameters provided. The function checks the type of the
* input parameter (`keyNodeEntryOrRaw`) and processes it accordingly to return a node or null
* value.
*/
protected _keyValueNodeEntryRawToNodeAndValue(
keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R,
value?: V
): [OptNodeOrNull<NODE>, V | undefined] {
if (keyNodeEntryOrRaw === undefined) return [undefined, undefined];
if (keyNodeEntryOrRaw === null) return [null, undefined];
if (this.isNode(keyNodeEntryOrRaw)) return [keyNodeEntryOrRaw, value];
if (this.isEntry(keyNodeEntryOrRaw)) {
const [key, entryValue] = keyNodeEntryOrRaw;
if (key === undefined) return [undefined, undefined];
else if (key === null) return [null, undefined];
const finalValue = value ?? entryValue;
return [this.createNode(key, finalValue), finalValue];
}
if (this.isRaw(keyNodeEntryOrRaw)) {
const [key, entryValue] = this._toEntryFn!(keyNodeEntryOrRaw);
const finalValue = value ?? entryValue;
if (this.isKey(key)) return [this.createNode(key, finalValue), finalValue];
}
if (this.isKey(keyNodeEntryOrRaw)) return [this.createNode(keyNodeEntryOrRaw, value), value];
return [undefined, undefined];
}
/**
* Time complexity: O(n)
* Space complexity: O(n)

View file

@ -5,8 +5,7 @@
* @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
* @license MIT License
*/
import type {
BSTNested,
import {
BSTNodeNested,
BSTNOptKeyOrNode,
BSTOptions,
@ -15,6 +14,7 @@ import type {
Comparator,
CP,
DFSOrderPattern,
EntryCallback,
IterationType,
NodeCallback,
NodePredicate,
@ -151,15 +151,9 @@ export class BSTNode<K = any, V = any, NODE extends BSTNode<K, V, NODE> = BSTNod
* console.log(findLCA(5, 35)); // 15
* console.log(findLCA(20, 30)); // 25
*/
export class BST<
K = any,
V = any,
R = object,
NODE extends BSTNode<K, V, NODE> = BSTNode<K, V, BSTNodeNested<K, V>>,
TREE extends BST<K, V, R, NODE, TREE> = BST<K, V, R, NODE, BSTNested<K, V, R, NODE>>
>
extends BinaryTree<K, V, R, NODE, TREE>
implements IBinaryTree<K, V, R, NODE, TREE>
export class BST<K = any, V = any, R = object, NODE extends BSTNode<K, V, NODE> = BSTNode<K, V, BSTNodeNested<K, V>>>
extends BinaryTree<K, V, R, NODE>
implements IBinaryTree<K, V, R, NODE>
{
/**
* This is the constructor function for a Binary Search Tree class in TypeScript.
@ -173,8 +167,8 @@ export class BST<
super([], options);
if (options) {
const { extractComparable, isReverse } = options;
if (typeof extractComparable === 'function') this._extractComparable = extractComparable;
const { specifyComparable, isReverse } = options;
if (typeof specifyComparable === 'function') this._specifyComparable = specifyComparable;
if (isReverse !== undefined) this._isReverse = isReverse;
}
@ -202,6 +196,45 @@ export class BST<
return this._isReverse;
}
protected _comparator: Comparator<K> = (a: K, b: K): number => {
if (isComparable(a) && isComparable(b)) {
if (a > b) return 1;
if (a < b) return -1;
return 0;
}
if (this._specifyComparable) {
if (this._specifyComparable(a) > this._specifyComparable(b)) return 1;
if (this._specifyComparable(a) < this._specifyComparable(b)) return -1;
return 0;
}
if (typeof a === 'object' || typeof b === 'object') {
throw TypeError(
`When comparing object types, a custom specifyComparable must be defined in the constructor's options parameter.`
);
}
return 0;
};
/**
* The function returns the value of the _comparator property.
* @returns The `_comparator` property is being returned.
*/
get comparator() {
return this._comparator;
}
protected _specifyComparable?: (key: K) => Comparable;
/**
* This function returns the value of the `_specifyComparable` property.
* @returns The method `specifyComparable()` is being returned, which is a getter method for the
* `_specifyComparable` property.
*/
get specifyComparable() {
return this._specifyComparable;
}
/**
* The function creates a new BSTNode with the given key and value and returns it.
* @param {K} key - The key parameter is of type K, which represents the type of the key for the node
@ -215,39 +248,26 @@ export class BST<
}
/**
* The function creates a new binary search tree with the specified options.
* @param [options] - The `options` parameter is an optional object that allows you to customize the
* behavior of the `createTree` method. It accepts a partial `BSTOptions` object, which has the
* following properties:
* @returns a new instance of the BST class with the provided options.
* Time Complexity: O(1)
* Space Complexity: O(1)
*
* The `createTree` function in TypeScript overrides the default options with the provided options to
* create a new Binary Search Tree.
* @param [options] - The `options` parameter in the `createTree` method is an optional object that
* can contain the following properties:
* @returns A new instance of a Binary Search Tree (BST) is being returned with the specified options
* and properties inherited from the current instance.
*/
override createTree(options?: BSTOptions<K, V, R>): TREE {
return new BST<K, V, R, NODE, TREE>([], {
// @ts-ignore
override createTree(options?: BSTOptions<K, V, R>) {
return new BST<K, V, R>([], {
iterationType: this.iterationType,
isMapMode: this._isMapMode,
extractComparable: this._extractComparable,
specifyComparable: this._specifyComparable,
toEntryFn: this._toEntryFn,
isReverse: this._isReverse,
...options
}) as TREE;
}
/**
* The function overrides a method and converts a key, value pair or entry or raw element to a node.
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - A variable that can be of
* type R or BTNRep<K, V, NODE>. It represents either a key, a node, an entry, or a raw
* element.
* @param {V} [value] - The `value` parameter is an optional value of type `V`. It represents the
* value associated with a key in a key-value pair.
* @returns either a NODE object or undefined.
*/
protected override _keyValueNodeEntryRawToNodeAndValue(
keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R,
value?: V
): [OptNode<NODE>, V | undefined] {
const [node, entryValue] = super._keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value);
if (node === null) return [undefined, undefined];
return [node, value ?? entryValue];
});
}
/**
@ -292,7 +312,7 @@ export class BST<
* this._DEFAULT_COMPARATOR`.
*/
override isKey(key: any): key is K {
return isComparable(key, this._extractComparable !== undefined);
return isComparable(key, this._specifyComparable !== undefined);
}
/**
@ -472,7 +492,7 @@ export class BST<
* @param anotherTree - `anotherTree` is an instance of a Binary Search Tree (BST) with key type `K`,
* value type `V`, return type `R`, node type `NODE`, and tree type `TREE`.
*/
override merge(anotherTree: BST<K, V, R, NODE, TREE>) {
override merge(anotherTree: this) {
this.addMany(anotherTree, [], false);
}
@ -924,43 +944,36 @@ export class BST<
return balanced;
}
protected _comparator: Comparator<K> = (a: K, b: K): number => {
if (isComparable(a) && isComparable(b)) {
if (a > b) return 1;
if (a < b) return -1;
return 0;
// @ts-ignore
override map<MK, MV, MR>(
callback: EntryCallback<K, V | undefined, [MK, MV]>,
options?: BSTOptions<MK, MV, MR>,
thisArg?: any
) {
const newTree = new BST<MK, MV, MR>([], options);
let index = 0;
for (const [key, value] of this) {
newTree.add(callback.call(thisArg, key, value, index++, this));
}
if (this._extractComparable) {
if (this._extractComparable(a) > this._extractComparable(b)) return 1;
if (this._extractComparable(a) < this._extractComparable(b)) return -1;
return 0;
}
if (typeof a === 'object' || typeof b === 'object') {
throw TypeError(
`When comparing object types, a custom extractComparable must be defined in the constructor's options parameter.`
);
}
return 0;
};
/**
* The function returns the value of the _comparator property.
* @returns The `_comparator` property is being returned.
*/
get comparator() {
return this._comparator;
return newTree;
}
protected _extractComparable?: (key: K) => Comparable;
/**
* This function returns the value of the `_extractComparable` property.
* @returns The method `extractComparable()` is being returned, which is a getter method for the
* `_extractComparable` property.
* The function overrides a method and converts a key, value pair or entry or raw element to a node.
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - A variable that can be of
* type R or BTNRep<K, V, NODE>. It represents either a key, a node, an entry, or a raw
* element.
* @param {V} [value] - The `value` parameter is an optional value of type `V`. It represents the
* value associated with a key in a key-value pair.
* @returns either a NODE object or undefined.
*/
get extractComparable() {
return this._extractComparable;
protected override _keyValueNodeEntryRawToNodeAndValue(
keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R,
value?: V
): [OptNode<NODE>, V | undefined] {
const [node, entryValue] = super._keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value);
if (node === null) return [undefined, undefined];
return [node, value ?? entryValue];
}
/**

View file

@ -2,10 +2,10 @@ import type {
BinaryTreeDeleteResult,
BTNRep,
CRUD,
EntryCallback,
OptNode,
RBTNColor,
RBTreeOptions,
RedBlackTreeNested,
RedBlackTreeOptions,
RedBlackTreeNodeNested
} from '../../types';
import { BST, BSTNode } from './bst';
@ -83,18 +83,15 @@ export class RedBlackTreeNode<
*
* // Create a Red-Black Tree to index stock records by price
* // Simulates a database index with stock price as the key for quick lookups
* const priceIndex = new RedBlackTree<number, StockTableRecord, StockRecord>(
* marketStockData,
* {
* toEntryFn: stockRecord => [
* stockRecord.price, // Use stock price as the key
* {
* ...stockRecord,
* lastUpdated: new Date() // Add a timestamp for when the record was indexed
* }
* ]
* }
* );
* const priceIndex = new RedBlackTree<number, StockTableRecord, StockRecord>(marketStockData, {
* toEntryFn: stockRecord => [
* stockRecord.price, // Use stock price as the key
* {
* ...stockRecord,
* lastUpdated: new Date() // Add a timestamp for when the record was indexed
* }
* ]
* });
*
* // Query the stock with the highest price
* const highestPricedStock = priceIndex.getRightMost();
@ -111,23 +108,22 @@ export class RedBlackTree<
K = any,
V = any,
R = object,
NODE extends RedBlackTreeNode<K, V, NODE> = RedBlackTreeNode<K, V, RedBlackTreeNodeNested<K, V>>,
TREE extends RedBlackTree<K, V, R, NODE, TREE> = RedBlackTree<K, V, R, NODE, RedBlackTreeNested<K, V, R, NODE>>
NODE extends RedBlackTreeNode<K, V, NODE> = RedBlackTreeNode<K, V, RedBlackTreeNodeNested<K, V>>
>
extends BST<K, V, R, NODE, TREE>
implements IBinaryTree<K, V, R, NODE, TREE>
extends BST<K, V, R, NODE>
implements IBinaryTree<K, V, R, NODE>
{
/**
* This is the constructor function for a Red-Black Tree data structure in TypeScript.
* @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter is an
* iterable object that can contain either keys, nodes, entries, or raw elements. It is used to
* initialize the RBTree with the provided elements.
* initialize the RedBlackTree with the provided elements.
* @param [options] - The `options` parameter is an optional object that can be passed to the
* constructor. It is of type `RBTreeOptions<K, V, R>`. This object can contain various options for
* constructor. It is of type `RedBlackTreeOptions<K, V, R>`. This object can contain various options for
* configuring the behavior of the Red-Black Tree. The specific properties and their meanings would
* depend on the implementation
*/
constructor(keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V, NODE>> = [], options?: RBTreeOptions<K, V, R>) {
constructor(keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V, NODE>> = [], options?: RedBlackTreeOptions<K, V, R>) {
super([], options);
this._root = this.NIL;
@ -166,19 +162,23 @@ export class RedBlackTree<
}
/**
* The function creates a new Red-Black Tree with the specified options.
* @param [options] - The `options` parameter is an optional object that contains additional
* configuration options for creating the Red-Black Tree. It has the following properties:
* @returns a new instance of a RedBlackTree object.
* The function `createTree` overrides the default implementation to create a Red-Black Tree with
* specified options in TypeScript.
* @param [options] - The `options` parameter in the `createTree` method is of type `RedBlackTreeOptions<K,
* V, R>`, which is a generic type with three type parameters `K`, `V`, and `R`. This parameter
* allows you to pass additional configuration options when creating a new Red-
* @returns A new instance of a RedBlackTree with the specified options and properties from the
* current object is being returned.
*/
override createTree(options?: RBTreeOptions<K, V, R>): TREE {
return new RedBlackTree<K, V, R, NODE, TREE>([], {
// @ts-ignore
override createTree(options?: RedBlackTreeOptions<K, V, R>) {
return new RedBlackTree<K, V, R>([], {
iterationType: this.iterationType,
isMapMode: this._isMapMode,
extractComparable: this._extractComparable,
specifyComparable: this._specifyComparable,
toEntryFn: this._toEntryFn,
...options
}) as TREE;
});
}
/**
@ -195,42 +195,6 @@ export class RedBlackTree<
return keyNodeEntryOrRaw instanceof RedBlackTreeNode;
}
// /**
// * Time Complexity: O(1)
// * Space Complexity: O(1)
// */
//
// /**
// * Time Complexity: O(1)
// * Space Complexity: O(1)
// *
// * The function `keyValueNodeEntryRawToNodeAndValue` takes a key, value, or entry and returns a node if it is
// * valid, otherwise it returns undefined.
// * @param {BTNRep<K, V, NODE>} keyNodeEntryOrRaw - The key, value, or entry to convert.
// * @param {V} [value] - The value associated with the key (if `keyNodeEntryOrRaw` is a key).
// * @returns {NODE | undefined} - The corresponding Red-Black Tree node, or `undefined` if conversion fails.
// */
// override keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R, value?: V): NODE | undefined {
//
// if (keyNodeEntryOrRaw === null || keyNodeEntryOrRaw === undefined) return;
// if (this.isNode(keyNodeEntryOrRaw)) return keyNodeEntryOrRaw;
//
// if (this._toEntryFn) {
// const [key, entryValue] = this._toEntryFn(keyNodeEntryOrRaw as R);
// if (this.isKey(key)) return this.createNode(key, value ?? entryValue, 'RED');
// }
//
// if (this.isEntry(keyNodeEntryOrRaw)) {
// const [key, value] = keyNodeEntryOrRaw;
// if (key === undefined || key === null) return;
// else return this.createNode(key, value, 'RED');
// }
//
// if (this.isKey(keyNodeEntryOrRaw)) return this.createNode(keyNodeEntryOrRaw, value, 'RED');
//
// return ;
// }
/**
* Time Complexity: O(1)
* Space Complexity: O(1)
@ -356,6 +320,40 @@ export class RedBlackTree<
return results;
}
/**
* Time Complexity: O(n)
* Space Complexity: O(n)
*
* The `map` function in TypeScript overrides the default behavior to create a new Red-Black Tree by
* applying a callback to each entry in the original tree.
* @param callback - A function that will be called for each entry in the tree, with parameters
* representing the key, value, index, and the tree itself. It should return an entry for the new
* tree.
* @param [options] - The `options` parameter in the `map` method is of type `RedBlackTreeOptions<MK, MV,
* MR>`. This parameter allows you to specify additional options or configurations for the Red-Black
* Tree that will be created during the mapping process. These options could include things like
* custom comparators
* @param {any} [thisArg] - The `thisArg` parameter in the `override map` function is used to specify
* the value of `this` when executing the `callback` function. It allows you to set the context
* (value of `this`) for the callback function. This can be useful when you want to access properties
* or
* @returns A new Red-Black Tree is being returned, where each entry has been transformed using the
* provided callback function.
*/
// @ts-ignore
override map<MK, MV, MR>(
callback: EntryCallback<K, V | undefined, [MK, MV]>,
options?: RedBlackTreeOptions<MK, MV, MR>,
thisArg?: any
) {
const newTree = new RedBlackTree<MK, MV, MR>([], options);
let index = 0;
for (const [key, value] of this) {
newTree.add(callback.call(thisArg, key, value, index++, this));
}
return newTree;
}
/**
* Time Complexity: O(1)
* Space Complexity: O(1)
@ -422,7 +420,7 @@ export class RedBlackTree<
if (!parent) {
this._setRoot(node);
} else if (node.key < parent.key) {
} else if (this._compare(node.key, parent.key) < 0) {
parent.left = node;
} else {
parent.right = node;

View file

@ -9,10 +9,10 @@ import type {
BinaryTreeDeleteResult,
BSTNOptKeyOrNode,
BTNRep,
EntryCallback,
IterationType,
OptNode,
RBTNColor,
TreeMultiMapNested,
TreeMultiMapNodeNested,
TreeMultiMapOptions
} from '../../types';
@ -65,11 +65,10 @@ export class TreeMultiMap<
K = any,
V = any,
R = object,
NODE extends TreeMultiMapNode<K, V, NODE> = TreeMultiMapNode<K, V, TreeMultiMapNodeNested<K, V>>,
TREE extends TreeMultiMap<K, V, R, NODE, TREE> = TreeMultiMap<K, V, R, NODE, TreeMultiMapNested<K, V, R, NODE>>
NODE extends TreeMultiMapNode<K, V, NODE> = TreeMultiMapNode<K, V, TreeMultiMapNodeNested<K, V>>
>
extends RedBlackTree<K, V, R, NODE, TREE>
implements IBinaryTree<K, V, R, NODE, TREE>
extends RedBlackTree<K, V, R, NODE>
implements IBinaryTree<K, V, R, NODE>
{
/**
* The constructor function initializes a TreeMultiMap object with optional initial data.
@ -135,53 +134,15 @@ export class TreeMultiMap<
* @returns a new instance of the `TreeMultiMap` class, with the provided options merged with the
* existing `iterationType` property. The returned value is casted as `TREE`.
*/
override createTree(options?: TreeMultiMapOptions<K, V, R>): TREE {
return new TreeMultiMap<K, V, R, NODE, TREE>([], {
// @ts-ignore
override createTree(options?: TreeMultiMapOptions<K, V, R>) {
return new TreeMultiMap<K, V, R, NODE>([], {
iterationType: this.iterationType,
isMapMode: this._isMapMode,
extractComparable: this._extractComparable,
specifyComparable: this._specifyComparable,
toEntryFn: this._toEntryFn,
...options
}) as TREE;
}
/**
* The function `keyValueNodeEntryRawToNodeAndValue` takes in a key, value, and count and returns a
* node based on the input.
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
* `keyNodeEntryOrRaw` can be of type `R` or `BTNRep<K, V, NODE>`.
* @param {V} [value] - The `value` parameter is an optional value that represents the value
* associated with the key in the node. It is used when creating a new node or updating the value of
* an existing node.
* @param [count=1] - The `count` parameter is an optional parameter that specifies the number of
* times the key-value pair should be added to the data structure. If not provided, it defaults to 1.
* @returns either a NODE object or undefined.
*/
protected override _keyValueNodeEntryRawToNodeAndValue(
keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R,
value?: V,
count = 1
): [NODE | undefined, V | undefined] {
if (keyNodeEntryOrRaw === undefined || keyNodeEntryOrRaw === null) return [undefined, undefined];
if (this.isNode(keyNodeEntryOrRaw)) return [keyNodeEntryOrRaw, value];
if (this.isEntry(keyNodeEntryOrRaw)) {
const [key, entryValue] = keyNodeEntryOrRaw;
if (key === undefined || key === null) return [undefined, undefined];
const finalValue = value ?? entryValue;
if (this.isKey(key)) return [this.createNode(key, finalValue, 'BLACK', count), finalValue];
}
if (this.isRaw(keyNodeEntryOrRaw)) {
const [key, entryValue] = this._toEntryFn!(keyNodeEntryOrRaw);
const finalValue = value ?? entryValue;
if (this.isKey(key)) return [this.createNode(key, finalValue, 'BLACK', count), finalValue];
}
if (this.isKey(keyNodeEntryOrRaw)) return [this.createNode(keyNodeEntryOrRaw, value, 'BLACK', count), value];
return [undefined, undefined];
});
}
/**
@ -402,13 +363,82 @@ export class TreeMultiMap<
* The function overrides the clone method to create a deep copy of a tree object.
* @returns The `clone()` method is returning a cloned instance of the `TREE` object.
*/
override clone(): TREE {
// @ts-ignore
override clone() {
const cloned = this.createTree();
this.bfs(node => cloned.add(node.key, undefined, node.count));
if (this._isMapMode) cloned._store = this._store;
return cloned;
}
/**
* The `map` function in TypeScript overrides the default behavior to create a new TreeMultiMap with
* modified entries based on a provided callback.
* @param callback - The `callback` parameter is a function that will be called for each entry in the
* map. It takes four arguments:
* @param [options] - The `options` parameter in the `override map` function is of type
* `TreeMultiMapOptions<MK, MV, MR>`. This parameter allows you to provide additional configuration
* options when creating a new `TreeMultiMap` instance within the `map` function. These options could
* include things like
* @param {any} [thisArg] - The `thisArg` parameter in the `override map` function is used to specify
* the value of `this` when executing the `callback` function. It allows you to set the context
* (value of `this`) for the callback function when it is called within the `map` function. This
* @returns A new TreeMultiMap instance is being returned, which is populated with entries generated
* by the provided callback function.
*/
// @ts-ignore
override map<MK, MV, MR>(
callback: EntryCallback<K, V | undefined, [MK, MV]>,
options?: TreeMultiMapOptions<MK, MV, MR>,
thisArg?: any
) {
const newTree = new TreeMultiMap<MK, MV, MR>([], options);
let index = 0;
for (const [key, value] of this) {
newTree.add(callback.call(thisArg, key, value, index++, this));
}
return newTree;
}
/**
* The function `keyValueNodeEntryRawToNodeAndValue` takes in a key, value, and count and returns a
* node based on the input.
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
* `keyNodeEntryOrRaw` can be of type `R` or `BTNRep<K, V, NODE>`.
* @param {V} [value] - The `value` parameter is an optional value that represents the value
* associated with the key in the node. It is used when creating a new node or updating the value of
* an existing node.
* @param [count=1] - The `count` parameter is an optional parameter that specifies the number of
* times the key-value pair should be added to the data structure. If not provided, it defaults to 1.
* @returns either a NODE object or undefined.
*/
protected override _keyValueNodeEntryRawToNodeAndValue(
keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R,
value?: V,
count = 1
): [NODE | undefined, V | undefined] {
if (keyNodeEntryOrRaw === undefined || keyNodeEntryOrRaw === null) return [undefined, undefined];
if (this.isNode(keyNodeEntryOrRaw)) return [keyNodeEntryOrRaw, value];
if (this.isEntry(keyNodeEntryOrRaw)) {
const [key, entryValue] = keyNodeEntryOrRaw;
if (key === undefined || key === null) return [undefined, undefined];
const finalValue = value ?? entryValue;
if (this.isKey(key)) return [this.createNode(key, finalValue, 'BLACK', count), finalValue];
}
if (this.isRaw(keyNodeEntryOrRaw)) {
const [key, entryValue] = this._toEntryFn!(keyNodeEntryOrRaw);
const finalValue = value ?? entryValue;
if (this.isKey(key)) return [this.createNode(key, finalValue, 'BLACK', count), finalValue];
}
if (this.isKey(keyNodeEntryOrRaw)) return [this.createNode(keyNodeEntryOrRaw, value, 'BLACK', count), value];
return [undefined, undefined];
}
/**
* Time Complexity: O(1)
* Space Complexity: O(1)

View file

@ -947,7 +947,7 @@ export abstract class AbstractGraph<
const filtered: [VertexKey, V | undefined][] = [];
let index = 0;
for (const [key, value] of this) {
if (predicate.call(thisArg, value, key, index, this)) {
if (predicate.call(thisArg, key, value, index, this)) {
filtered.push([key, value]);
}
index++;
@ -972,7 +972,7 @@ export abstract class AbstractGraph<
const mapped: T[] = [];
let index = 0;
for (const [key, value] of this) {
mapped.push(callback.call(thisArg, value, key, index, this));
mapped.push(callback.call(thisArg, key, value, index, this));
index++;
}
return mapped;

View file

@ -588,6 +588,19 @@ export class DoublyLinkedList<E = any, R = any> extends IterableElementBase<E, R
return this.tail?.value;
}
/**
* Time Complexity: O(n)
* Space Complexity: O(n)
*
* The `fromArray` function creates a new instance of a DoublyLinkedList and populates it with the elements from the
* given array.
* @param {E[]} data - The `data` parameter is an array of elements of type `E`.
* @returns The `fromArray` function returns a DoublyLinkedList object.
*/
static fromArray<E>(data: E[]) {
return new DoublyLinkedList<E>(data);
}
/**
* Time Complexity: O(1)
* Space Complexity: O(1)
@ -1252,19 +1265,6 @@ export class DoublyLinkedList<E = any, R = any> extends IterableElementBase<E, R
return count;
}
/**
* Time Complexity: O(n)
* Space Complexity: O(n)
*
* The `fromArray` function creates a new instance of a DoublyLinkedList and populates it with the elements from the
* given array.
* @param {E[]} data - The `data` parameter is an array of elements of type `E`.
* @returns The `fromArray` function returns a DoublyLinkedList object.
*/
static fromArray<E>(data: E[]) {
return new DoublyLinkedList<E>(data);
}
/**
* The function returns an iterator that iterates over the values of a linked list.
*/

View file

@ -116,6 +116,23 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
return this._size;
}
/**
* Time Complexity: O(n)
* Space Complexity: O(n)
*
* The `fromArray` function creates a new SinglyLinkedList instance and populates it with the elements from the given
* array.
* @param {E[]} data - The `data` parameter is an array of elements of type `E`.
* @returns The `fromArray` function returns a `SinglyLinkedList` object.
*/
static fromArray<E>(data: E[]) {
const singlyLinkedList = new SinglyLinkedList<E>();
for (const item of data) {
singlyLinkedList.push(item);
}
return singlyLinkedList;
}
/**
* Time Complexity: O(1)
* Space Complexity: O(1)
@ -763,23 +780,6 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
}
}
/**
* Time Complexity: O(n)
* Space Complexity: O(n)
*
* The `fromArray` function creates a new SinglyLinkedList instance and populates it with the elements from the given
* array.
* @param {E[]} data - The `data` parameter is an array of elements of type `E`.
* @returns The `fromArray` function returns a `SinglyLinkedList` object.
*/
static fromArray<E>(data: E[]) {
const singlyLinkedList = new SinglyLinkedList<E>();
for (const item of data) {
singlyLinkedList.push(item);
}
return singlyLinkedList;
}
/**
* The _isPredicate function in TypeScript checks if the input is a function that takes a
* SinglyLinkedListNode as an argument and returns a boolean.

View file

@ -1,24 +1,14 @@
import { BinaryTree, BinaryTreeNode } from '../data-structures';
import type {
BinaryTreeDeleteResult,
BinaryTreeNested,
BinaryTreeNodeNested,
BinaryTreeOptions,
BTNRep,
NodePredicate
} from '../types';
import { BinaryTreeNode } from '../data-structures';
import type { BinaryTreeDeleteResult, BinaryTreeNodeNested, BTNRep, NodePredicate } from '../types';
export interface IBinaryTree<
K = any,
V = any,
R = object,
NODE extends BinaryTreeNode<K, V, NODE> = BinaryTreeNodeNested<K, V>,
TREE extends BinaryTree<K, V, R, NODE, TREE> = BinaryTreeNested<K, V, R, NODE>
NODE extends BinaryTreeNode<K, V, NODE> = BinaryTreeNodeNested<K, V>
> {
createNode(key: K, value?: NODE['value']): NODE;
createTree(options?: Partial<BinaryTreeOptions<K, V, R>>): TREE;
add(keyOrNodeOrEntryOrRawElement: BTNRep<K, V, NODE>, value?: V, count?: number): boolean;
addMany(nodes: Iterable<BTNRep<K, V, NODE>>, values?: Iterable<V | undefined>): boolean[];

View file

@ -1,6 +1,6 @@
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 EntryCallback<K, V, R> = (key: K, value: V, index: number, container: IterableEntryBase<K, V>) => R;
export type ElementCallback<E, R, RT, C> = (element: E, index: number, container: IterableElementBase<E, R, C>) => RT;
export type ReduceEntryCallback<K, V, R> = (
accumulator: R,

View file

@ -1,8 +1,6 @@
import { AVLTreeMultiMap, AVLTreeMultiMapNode } from '../../../data-structures';
import { AVLTreeMultiMapNode } from '../../../data-structures';
import type { AVLTreeOptions } from './avl-tree';
export type AVLTreeMultiMapNodeNested<K, V> = AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
export type AVLTreeMultiMapNested<K, V, R, NODE extends AVLTreeMultiMapNode<K, V, NODE>> = AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, AVLTreeMultiMap<K, V, R, NODE, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
export type AVLTreeMultiMapNodeNested<K, V> = AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNode<K, V, any>>>>>>>>>>
export type AVLTreeMultiMapOptions<K, V, R> = AVLTreeOptions<K, V, R> & {}

View file

@ -1,8 +1,6 @@
import { AVLTree, AVLTreeNode } from '../../../data-structures';
import { AVLTreeNode } from '../../../data-structures';
import { BSTOptions } from './bst';
export type AVLTreeNodeNested<K, V> = AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
export type AVLTreeNested<K, V, R, NODE extends AVLTreeNode<K, V, NODE>> = AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, AVLTree<K, V, R, NODE, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
export type AVLTreeNodeNested<K, V> = AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, AVLTreeNode<K, V, any>>>>>>>>>>
export type AVLTreeOptions<K, V, R> = BSTOptions<K, V, R> & {};

View file

@ -1,10 +1,10 @@
import { BinaryTree, BinaryTreeNode } from '../../../data-structures';
import { BinaryTreeNode } from '../../../data-structures';
import { IterationType, OptValue } from '../../common';
import { DFSOperation } from '../../../common';
export type BinaryTreeNodeNested<K, V> = BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
export type BinaryTreeNodeNested<K, V> = BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, any>>>>>>>>>>
export type BinaryTreeNested<K, V, R, NODE extends BinaryTreeNode<K, V, NODE>> = BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// export type BinaryTreeNested<K, V, R, NODE extends BinaryTreeNode<K, V, NODE>> = BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
export type ToEntryFn<K, V, R> = (rawElement: R) => BTNEntry<K, V>;

View file

@ -1,13 +1,11 @@
import { BST, BSTNode } from '../../../data-structures';
import { BSTNode } from '../../../data-structures';
import type { BinaryTreeOptions } from './binary-tree';
import { Comparable } from '../../utils';
export type BSTNodeNested<K, V> = BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
export type BSTNested<K, V, R, NODE extends BSTNode<K, V, NODE>> = BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
export type BSTNodeNested<K, V> = BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, any>>>>>>>>>>
export type BSTOptions<K, V, R> = BinaryTreeOptions<K, V, R> & {
extractComparable?: (key: K) => Comparable
specifyComparable?: (key: K) => Comparable
isReverse?: boolean;
}

View file

@ -1,10 +1,8 @@
import { RedBlackTree, RedBlackTreeNode } from '../../../data-structures';
import type { BSTOptions } from "./bst";
import { RedBlackTreeNode } from '../../../data-structures';
import type { BSTOptions } from './bst';
export type RBTNColor = 'RED' | 'BLACK';
export type RedBlackTreeNodeNested<K, V> = RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
export type RedBlackTreeNodeNested<K, V> = RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, RedBlackTreeNode<K, V, any>>>>>>>>>>
export type RedBlackTreeNested<K, V, R, NODE extends RedBlackTreeNode<K, V, NODE>> = RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, RedBlackTree<K, V, R, NODE, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
export type RBTreeOptions<K, V, R> = Omit<BSTOptions<K, V, R>, 'isReverse'> & {};
export type RedBlackTreeOptions<K, V, R> = Omit<BSTOptions<K, V, R>, 'isReverse'> & {};

View file

@ -1,8 +1,6 @@
import { TreeMultiMap, TreeMultiMapNode } from '../../../data-structures';
import type { RBTreeOptions } from './rb-tree';
import { TreeMultiMapNode } from '../../../data-structures';
import type { RedBlackTreeOptions } from './rb-tree';
export type TreeMultiMapNodeNested<K, V> = TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
export type TreeMultiMapNodeNested<K, V> = TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, TreeMultiMapNode<K, V, any>>>>>>>>>>
export type TreeMultiMapNested<K, V, R, NODE extends TreeMultiMapNode<K, V, NODE>> = TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, TreeMultiMap<K, V, R, NODE, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
export type TreeMultiMapOptions<K, V, R> = RBTreeOptions<K, V, R> & {}
export type TreeMultiMapOptions<K, V, R> = RedBlackTreeOptions<K, V, R> & {}

View file

@ -102,7 +102,7 @@
try {
const { OrderedMap } = sdsl;
const { RedBlackTree } = dataStructureTyped;
const cRBTree = new OrderedMap();
const cRedBlackTree = new OrderedMap();
const rbTree = new RedBlackTree();
const tS = performance.now();
const n = 100000;
@ -117,10 +117,10 @@
rbTree.print(rbTree.root, { isShowRedBlackNIL: true });
const cS = performance.now();
for (let i = 1; i < 100000; i++) {
cRBTree.setElement(i, i);
cRedBlackTree.setElement(i, i);
}
console.log((performance.now() - cS).toFixed(2), `CRedBlackTree ${n.toLocaleString()} add`);
console.log(cRBTree.size(), `cRBTree.size()`);
console.log(cRedBlackTree.size(), `cRedBlackTree.size()`);
} catch (e) {
console.error(e);
}

View file

@ -9,14 +9,14 @@ const { TEN_THOUSAND } = magnitude;
const arr = getRandomIntArray(TEN_THOUSAND, 0, TEN_THOUSAND - 1, true);
suite
.add(`${TEN_THOUSAND.toLocaleString()} RBTree add randomly`, () => {
.add(`${TEN_THOUSAND.toLocaleString()} RedBlackTree add randomly`, () => {
rbTree.clear();
for (let i = 0; i < arr.length; i++) rbTree.add(arr[i]);
})
.add(`${TEN_THOUSAND.toLocaleString()} RBTree get randomly`, () => {
.add(`${TEN_THOUSAND.toLocaleString()} RedBlackTree get randomly`, () => {
for (let i = 0; i < arr.length; i++) rbTree.get(arr[i]);
})
.add(`${TEN_THOUSAND.toLocaleString()} RBTree add & delete randomly`, () => {
.add(`${TEN_THOUSAND.toLocaleString()} RedBlackTree add & delete randomly`, () => {
rbTree.clear();
for (let i = 0; i < arr.length; i++) rbTree.add(arr[i]);
for (let i = 0; i < arr.length; i++) rbTree.delete(arr[i]);

View file

@ -637,7 +637,7 @@ describe('AVLTreeMultiMap iterative methods test', () => {
});
it('filter should return a new tree with filtered elements', () => {
const filteredTree = treeMM.filter((value, key) => key > 1);
const filteredTree = treeMM.filter(key => key > 1);
expect(filteredTree.size).toBe(2);
expect([...filteredTree]).toEqual([
[2, 'b'],
@ -646,12 +646,12 @@ describe('AVLTreeMultiMap iterative methods test', () => {
});
it('map should return a new tree with modified elements', () => {
const mappedTree = treeMM.map((value, key) => (key * 2).toString());
const mappedTree = treeMM.map((key, value) => [(key * 2).toString(), value]);
expect(mappedTree.size).toBe(3);
expect([...mappedTree]).toEqual([
[1, '2'],
[2, '4'],
[3, '6']
['2', 'a'],
['4', 'b'],
['6', 'c']
]);
});
@ -736,7 +736,7 @@ describe('AVLTree toEntryFn', () => {
{ obj: { id: 5 } }
])
).toThrowError(
`When comparing object types, a custom extractComparable must be defined in the constructor's options parameter.`
`When comparing object types, a custom specifyComparable must be defined in the constructor's options parameter.`
);
});
@ -744,7 +744,7 @@ describe('AVLTree toEntryFn', () => {
const tree = new AVLTreeMultiMap<{ obj: { id: number } }, number>(
[{ obj: { id: 1 } }, { obj: { id: 2 } }, { obj: { id: 3 } }, { obj: { id: 4 } }, { obj: { id: 5 } }],
{
extractComparable: key => key.obj.id
specifyComparable: key => key.obj.id
}
);

View file

@ -397,7 +397,7 @@ describe('AVLTree iterative methods test', () => {
});
it('filter should return a new tree with filtered elements', () => {
const filteredTree = avl.filter((value, key) => key > 1);
const filteredTree = avl.filter(key => key > 1);
expect(filteredTree.size).toBe(2);
expect([...filteredTree]).toEqual([
[2, 'b'],
@ -406,12 +406,12 @@ describe('AVLTree iterative methods test', () => {
});
it('map should return a new tree with modified elements', () => {
const mappedTree = avl.map((value, key) => (key * 2).toString());
const mappedTree = avl.map((key, value) => [(key * 2).toString(), value]);
expect(mappedTree.size).toBe(3);
expect([...mappedTree]).toEqual([
[1, '2'],
[2, '4'],
[3, '6']
['2', 'a'],
['4', 'b'],
['6', 'c']
]);
});

View file

@ -1353,7 +1353,7 @@ describe('BinaryTree iterative methods test', () => {
});
it('filter should return a new tree with filtered elements', () => {
const filteredTree = binaryTree.filter((value, key) => key > 1);
const filteredTree = binaryTree.filter((key, value) => key > 1);
expect(filteredTree.size).toBe(2);
expect([...filteredTree]).toEqual([
[3, 'c'],
@ -1362,12 +1362,12 @@ describe('BinaryTree iterative methods test', () => {
});
it('map should return a new tree with modified elements', () => {
const mappedTree = binaryTree.map((value, key) => (key * 2).toString());
const mappedTree = binaryTree.map((key, value) => [(key * 2).toString(), value]);
expect(mappedTree.size).toBe(3);
expect([...mappedTree]).toEqual([
[1, '2'],
[2, '4'],
[3, '6']
['2', 'a'],
['4', 'b'],
['6', 'c']
]);
});

View file

@ -981,7 +981,7 @@ describe('BST operations test recursively', () => {
if (isTestStackOverflow) {
it('should getLeftMost', () => {
const bst = new BST<number>([], { extractComparable: key => key });
const bst = new BST<number>([], { specifyComparable: key => key });
for (let i = 1; i <= SYSTEM_MAX_CALL_STACK; i++) bst.add(i);
expect(() => {
@ -1121,7 +1121,7 @@ describe('BST iterative methods test', () => {
});
it('filter should return a new tree with filtered elements', () => {
const filteredTree = bst.filter((value, key) => key > 1);
const filteredTree = bst.filter((key, value) => key > 1);
expect(filteredTree.size).toBe(2);
expect([...filteredTree]).toEqual([
[2, 'b'],
@ -1130,12 +1130,12 @@ describe('BST iterative methods test', () => {
});
it('map should return a new tree with modified elements', () => {
const mappedTree = bst.map((value, key) => (key * 2).toString());
const mappedTree = bst.map((key, value) => [(key * 2).toString(), value]);
expect(mappedTree.size).toBe(3);
expect([...mappedTree]).toEqual([
[1, '2'],
[2, '4'],
[3, '6']
['2', 'a'],
['4', 'b'],
['6', 'c']
]);
});

View file

@ -0,0 +1,259 @@
export type CostOfLiving = {
rank: number;
country: string;
'Meal, Inexpensive Restaurant': number;
'Domestic Beer (0.5 liter draught)': number;
'Water (0.33 liter bottle)': number;
'Milk (regular), (1 liter)': number;
'Loaf of Fresh White Bread (500g)': number;
'Eggs (regular) (12)': number;
'Local Cheese (1kg)': number;
'Water (1.5 liter bottle)': number;
'One-way Ticket (Local Transport)': number;
'Gasoline (1 liter)': number;
'Apartment (3 bedrooms) in City Centre': number;
'Basic (Electricity, Heating, Cooling, Water, Garbage) for 85m2 Apartment': number;
'Internet (60 Mbps or More, Unlimited Data, Cable/ADSL)': number;
'Mobile Phone Monthly Plan with Calls and 10GB+ Data': number;
'Cinema, International Release, 1 Seat': number;
'1 Pair of Jeans (Levis 501 Or Similar)': number;
'Price per Square Meter to Buy Apartment in City Centre': number;
'Average Monthly Net Salary (After Tax)': number;
'Mortgage Interest Rate in Percentages (%), Yearly, for 20 Years Fixed-Rate': number;
'Taxi 1km (Normal Tariff)': number;
'Oranges (1kg)': number;
'Potato (1kg)': number;
'Lettuce (1 head)': number;
'Rice (white), (1kg)': number;
'Onion (1kg)': number;
'Beef Round (1kg) (or Equivalent Back Leg Red Meat)': number;
'Toyota Corolla Sedan 1.6l 97kW Comfort (Or Equivalent New Car)': number;
'Preschool (or Kindergarten), Full Day, Private, Monthly for 1 Child': number;
};
export const costOfLiving: CostOfLiving[] = [
{
rank: 1,
country: 'Switzerland',
'Meal, Inexpensive Restaurant': 27.98,
'Domestic Beer (0.5 liter draught)': 7.83,
'Water (0.33 liter bottle)': 4.49,
'Milk (regular), (1 liter)': 1.95,
'Loaf of Fresh White Bread (500g)': 3.63,
'Eggs (regular) (12)': 6.83,
'Local Cheese (1kg)': 26.02,
'Water (1.5 liter bottle)': 1.13,
'One-way Ticket (Local Transport)': 3.92,
'Gasoline (1 liter)': 2.06,
'Apartment (3 bedrooms) in City Centre': 3359.12,
'Basic (Electricity, Heating, Cooling, Water, Garbage) for 85m2 Apartment': 243.82,
'Internet (60 Mbps or More, Unlimited Data, Cable/ADSL)': 54.3,
'Mobile Phone Monthly Plan with Calls and 10GB+ Data': 51.26,
'Cinema, International Release, 1 Seat': 22.38,
'1 Pair of Jeans (Levis 501 Or Similar)': 120.18,
'Price per Square Meter to Buy Apartment in City Centre': 16439.97,
'Average Monthly Net Salary (After Tax)': 6628.35,
'Mortgage Interest Rate in Percentages (%), Yearly, for 20 Years Fixed-Rate': 2.49,
'Taxi 1km (Normal Tariff)': 4.36,
'Oranges (1kg)': 2.93,
'Potato (1kg)': 2.48,
'Lettuce (1 head)': 2.35,
'Rice (white), (1kg)': 3.98,
'Onion (1kg)': 2.29,
'Beef Round (1kg) (or Equivalent Back Leg Red Meat)': 45.89,
'Toyota Corolla Sedan 1.6l 97kW Comfort (Or Equivalent New Car)': 37549.18,
'Preschool (or Kindergarten), Full Day, Private, Monthly for 1 Child': 2832.82
},
{
rank: 23,
country: 'New Zealand',
'Meal, Inexpensive Restaurant': 14.58,
'Domestic Beer (0.5 liter draught)': 6.42,
'Water (0.33 liter bottle)': 2.01,
'Milk (regular), (1 liter)': 1.76,
'Loaf of Fresh White Bread (500g)': 1.87,
'Eggs (regular) (12)': 6.32,
'Local Cheese (1kg)': 8.02,
'Water (1.5 liter bottle)': 1.16,
'One-way Ticket (Local Transport)': 2.33,
'Gasoline (1 liter)': 1.63,
'Apartment (3 bedrooms) in City Centre': 1758.7,
'Basic (Electricity, Heating, Cooling, Water, Garbage) for 85m2 Apartment': 135.28,
'Internet (60 Mbps or More, Unlimited Data, Cable/ADSL)': 50.44,
'Mobile Phone Monthly Plan with Calls and 10GB+ Data': 34.27,
'Cinema, International Release, 1 Seat': 11.67,
'1 Pair of Jeans (Levis 501 Or Similar)': 67.67,
'Price per Square Meter to Buy Apartment in City Centre': 5371.0,
'Average Monthly Net Salary (After Tax)': 2920.79,
'Mortgage Interest Rate in Percentages (%), Yearly, for 20 Years Fixed-Rate': 6.84,
'Taxi 1km (Normal Tariff)': 2.01,
'Oranges (1kg)': 2.94,
'Potato (1kg)': 2.07,
'Lettuce (1 head)': 2.35,
'Rice (white), (1kg)': 1.82,
'Onion (1kg)': 1.77,
'Beef Round (1kg) (or Equivalent Back Leg Red Meat)': 12.58,
'Toyota Corolla Sedan 1.6l 97kW Comfort (Or Equivalent New Car)': 20980.7,
'Preschool (or Kindergarten), Full Day, Private, Monthly for 1 Child': 752.33
},
{
rank: 41,
country: 'Mexico',
'Meal, Inexpensive Restaurant': 9.79,
'Domestic Beer (0.5 liter draught)': 2.2,
'Water (0.33 liter bottle)': 0.83,
'Milk (regular), (1 liter)': 1.35,
'Loaf of Fresh White Bread (500g)': 2.36,
'Eggs (regular) (12)': 2.16,
'Local Cheese (1kg)': 7.87,
'Water (1.5 liter bottle)': 0.91,
'One-way Ticket (Local Transport)': 0.54,
'Gasoline (1 liter)': 1.18,
'Apartment (3 bedrooms) in City Centre': 1148.12,
'Basic (Electricity, Heating, Cooling, Water, Garbage) for 85m2 Apartment': 59.55,
'Internet (60 Mbps or More, Unlimited Data, Cable/ADSL)': 25.94,
'Mobile Phone Monthly Plan with Calls and 10GB+ Data': 21.52,
'Cinema, International Release, 1 Seat': 4.41,
'1 Pair of Jeans (Levis 501 Or Similar)': 49.23,
'Price per Square Meter to Buy Apartment in City Centre': 1781.03,
'Average Monthly Net Salary (After Tax)': 660.35,
'Mortgage Interest Rate in Percentages (%), Yearly, for 20 Years Fixed-Rate': 11.43,
'Taxi 1km (Normal Tariff)': 1.91,
'Oranges (1kg)': 1.61,
'Potato (1kg)': 1.81,
'Lettuce (1 head)': 1.17,
'Rice (white), (1kg)': 1.58,
'Onion (1kg)': 1.66,
'Beef Round (1kg) (or Equivalent Back Leg Red Meat)': 9.79,
'Toyota Corolla Sedan 1.6l 97kW Comfort (Or Equivalent New Car)': 21077.68,
'Preschool (or Kindergarten), Full Day, Private, Monthly for 1 Child': 224.39
},
{
rank: 52,
country: 'South Africa',
'Meal, Inexpensive Restaurant': 8.28,
'Domestic Beer (0.5 liter draught)': 2.21,
'Water (0.33 liter bottle)': 0.73,
'Milk (regular), (1 liter)': 1.07,
'Loaf of Fresh White Bread (500g)': 0.97,
'Eggs (regular) (12)': 2.26,
'Local Cheese (1kg)': 7.35,
'Water (1.5 liter bottle)': 0.92,
'One-way Ticket (Local Transport)': 1.66,
'Gasoline (1 liter)': 1.29,
'Apartment (3 bedrooms) in City Centre': 892.16,
'Basic (Electricity, Heating, Cooling, Water, Garbage) for 85m2 Apartment': 104.63,
'Internet (60 Mbps or More, Unlimited Data, Cable/ADSL)': 41.21,
'Mobile Phone Monthly Plan with Calls and 10GB+ Data': 31.79,
'Cinema, International Release, 1 Seat': 6.62,
'1 Pair of Jeans (Levis 501 Or Similar)': 47.28,
'Price per Square Meter to Buy Apartment in City Centre': 1031.57,
'Average Monthly Net Salary (After Tax)': 1383.11,
'Mortgage Interest Rate in Percentages (%), Yearly, for 20 Years Fixed-Rate': 11.58,
'Taxi 1km (Normal Tariff)': 1.1,
'Oranges (1kg)': 1.4,
'Potato (1kg)': 1.21,
'Lettuce (1 head)': 1.02,
'Rice (white), (1kg)': 1.53,
'Onion (1kg)': 1.34,
'Beef Round (1kg) (or Equivalent Back Leg Red Meat)': 6.55,
'Toyota Corolla Sedan 1.6l 97kW Comfort (Or Equivalent New Car)': 23105.93,
'Preschool (or Kindergarten), Full Day, Private, Monthly for 1 Child': 193.32
},
{
rank: 65,
country: 'Japan',
'Meal, Inexpensive Restaurant': 6.46,
'Domestic Beer (0.5 liter draught)': 3.23,
'Water (0.33 liter bottle)': 0.73,
'Milk (regular), (1 liter)': 1.4,
'Loaf of Fresh White Bread (500g)': 1.46,
'Eggs (regular) (12)': 2.08,
'Local Cheese (1kg)': 11.12,
'Water (1.5 liter bottle)': 0.85,
'One-way Ticket (Local Transport)': 1.42,
'Gasoline (1 liter)': 1.11,
'Apartment (3 bedrooms) in City Centre': 1248.4,
'Basic (Electricity, Heating, Cooling, Water, Garbage) for 85m2 Apartment': 166.85,
'Internet (60 Mbps or More, Unlimited Data, Cable/ADSL)': 32.64,
'Mobile Phone Monthly Plan with Calls and 10GB+ Data': 25.29,
'Cinema, International Release, 1 Seat': 12.28,
'1 Pair of Jeans (Levis 501 Or Similar)': 43.21,
'Price per Square Meter to Buy Apartment in City Centre': 6324.16,
'Average Monthly Net Salary (After Tax)': 2069.74,
'Mortgage Interest Rate in Percentages (%), Yearly, for 20 Years Fixed-Rate': 1.83,
'Taxi 1km (Normal Tariff)': 2.91,
'Oranges (1kg)': 4.35,
'Potato (1kg)': 2.63,
'Lettuce (1 head)': 1.26,
'Rice (white), (1kg)': 3.72,
'Onion (1kg)': 2.39,
'Beef Round (1kg) (or Equivalent Back Leg Red Meat)': 16.87,
'Toyota Corolla Sedan 1.6l 97kW Comfort (Or Equivalent New Car)': 16534.56,
'Preschool (or Kindergarten), Full Day, Private, Monthly for 1 Child': 353.95
},
{
rank: 72,
country: 'Brazil',
'Meal, Inexpensive Restaurant': 5.17,
'Domestic Beer (0.5 liter draught)': 1.72,
'Water (0.33 liter bottle)': 0.65,
'Milk (regular), (1 liter)': 0.93,
'Loaf of Fresh White Bread (500g)': 1.43,
'Eggs (regular) (12)': 1.92,
'Local Cheese (1kg)': 8.08,
'Water (1.5 liter bottle)': 0.63,
'One-way Ticket (Local Transport)': 0.86,
'Gasoline (1 liter)': 0.98,
'Apartment (3 bedrooms) in City Centre': 622.9,
'Basic (Electricity, Heating, Cooling, Water, Garbage) for 85m2 Apartment': 65.01,
'Internet (60 Mbps or More, Unlimited Data, Cable/ADSL)': 18.39,
'Mobile Phone Monthly Plan with Calls and 10GB+ Data': 13.92,
'Cinema, International Release, 1 Seat': 6.03,
'1 Pair of Jeans (Levis 501 Or Similar)': 46.84,
'Price per Square Meter to Buy Apartment in City Centre': 1513.42,
'Average Monthly Net Salary (After Tax)': 417.56,
'Mortgage Interest Rate in Percentages (%), Yearly, for 20 Years Fixed-Rate': 10.98,
'Taxi 1km (Normal Tariff)': 0.83,
'Oranges (1kg)': 1.04,
'Potato (1kg)': 1.11,
'Lettuce (1 head)': 0.68,
'Rice (white), (1kg)': 1.11,
'Onion (1kg)': 1.06,
'Beef Round (1kg) (or Equivalent Back Leg Red Meat)': 6.93,
'Toyota Corolla Sedan 1.6l 97kW Comfort (Or Equivalent New Car)': 26186.46,
'Preschool (or Kindergarten), Full Day, Private, Monthly for 1 Child': 279.87
},
{
rank: 74,
country: 'Taiwan',
'Meal, Inexpensive Restaurant': 4.6,
'Domestic Beer (0.5 liter draught)': 1.84,
'Water (0.33 liter bottle)': 0.65,
'Milk (regular), (1 liter)': 2.99,
'Loaf of Fresh White Bread (500g)': 1.84,
'Eggs (regular) (12)': 2.75,
'Local Cheese (1kg)': 15.19,
'Water (1.5 liter bottle)': 1.14,
'One-way Ticket (Local Transport)': 0.77,
'Gasoline (1 liter)': 0.95,
'Apartment (3 bedrooms) in City Centre': 1124.03,
'Basic (Electricity, Heating, Cooling, Water, Garbage) for 85m2 Apartment': 78.3,
'Internet (60 Mbps or More, Unlimited Data, Cable/ADSL)': 21.65,
'Mobile Phone Monthly Plan with Calls and 10GB+ Data': 22.18,
'Cinema, International Release, 1 Seat': 9.51,
'1 Pair of Jeans (Levis 501 Or Similar)': 63.34,
'Price per Square Meter to Buy Apartment in City Centre': 8859.94,
'Average Monthly Net Salary (After Tax)': 1654.66,
'Mortgage Interest Rate in Percentages (%), Yearly, for 20 Years Fixed-Rate': 2.0,
'Taxi 1km (Normal Tariff)': 0.77,
'Oranges (1kg)': 2.64,
'Potato (1kg)': 2.61,
'Lettuce (1 head)': 1.82,
'Rice (white), (1kg)': 2.97,
'Onion (1kg)': 2.15,
'Beef Round (1kg) (or Equivalent Back Leg Red Meat)': 18.14,
'Toyota Corolla Sedan 1.6l 97kW Comfort (Or Equivalent New Car)': 24143.1,
'Preschool (or Kindergarten), Full Day, Private, Monthly for 1 Child': 508.49
}
];

View file

@ -82,7 +82,9 @@ describe('Overall BinaryTree Test', () => {
expect(bst.has(9)).toBe(true);
expect(bst.has(7)).toBe(false);
expect(bst.bfs()).toEqual([6, 9, 3, 1]);
const clonedBST = bst.clone();
expect(clonedBST.size).toBe(4);
expect(clonedBST.root?.key).toBe(6);
expect(clonedBST.root?.left?.key).toBe(9);

View file

@ -3,6 +3,7 @@ import { getRandomInt, getRandomIntArray, magnitude } from '../../../utils';
import { OrderedMap } from 'js-sdsl';
import { isDebugTest } from '../../../config';
import { costOfLiving } from './data/cost-of-living-by-country';
const isDebug = isDebugTest;
// const isDebug = true;
@ -658,7 +659,7 @@ describe('RedBlackTree 2', () => {
});
it('filter should return a new rbTree with filtered elements', () => {
const filteredTree = rbTree.filter((value, key) => key > 1);
const filteredTree = rbTree.filter(key => key > 1);
expect(filteredTree.size).toBe(2);
expect([...filteredTree]).toEqual([
[2, 'b'],
@ -667,12 +668,12 @@ describe('RedBlackTree 2', () => {
});
it('map should return a new rbTree with modified elements', () => {
const mappedTree = rbTree.map((value, key) => (key * 2).toString());
const mappedTree = rbTree.map((key, value) => [(key * 2).toString(), value]);
expect(mappedTree.size).toBe(3);
expect([...mappedTree]).toEqual([
[1, '2'],
[2, '4'],
[3, '6']
['2', 'a'],
['4', 'b'],
['6', 'c']
]);
});
@ -820,6 +821,25 @@ describe('RedBlackTree - _deleteFixup', () => {
});
});
describe('real world data', () => {
it('cost of living', () => {
const indexedByRank = new RedBlackTree(costOfLiving, {
specifyComparable: node => node.rank,
toEntryFn: raw => [raw, undefined]
});
expect(indexedByRank.size).toBe(7);
expect(indexedByRank.dfs(node => node?.key?.country)).toEqual([
'Switzerland',
'New Zealand',
'Mexico',
'South Africa',
'Japan',
'Brazil',
'Taiwan'
]);
});
});
describe('classic use', () => {
// Test case for finding elements in a given range
it('@example Find elements in a range', () => {

View file

@ -775,7 +775,7 @@ describe('TreeMultiMap iterative methods test', () => {
});
it('filter should return a new tree with filtered elements', () => {
const filteredTree = treeMM.filter((value, key) => key > 1);
const filteredTree = treeMM.filter(key => key > 1);
expect(filteredTree.size).toBe(2);
expect([...filteredTree]).toEqual([
[2, 'b'],
@ -784,12 +784,12 @@ describe('TreeMultiMap iterative methods test', () => {
});
it('map should return a new tree with modified elements', () => {
const mappedTree = treeMM.map((value, key) => (key * 2).toString());
const mappedTree = treeMM.map((key, value) => [(key * 2).toString(), value]);
expect(mappedTree.size).toBe(3);
expect([...mappedTree]).toEqual([
[1, '2'],
[2, '4'],
[3, '6']
['2', 'a'],
['4', 'b'],
['6', 'c']
]);
});

View file

@ -685,7 +685,7 @@ describe('DirectedGraph iterative Methods', () => {
});
it('filter should return vertexMap that satisfy the condition', () => {
const filtered = graph.filter((value, vertex) => vertex === 'A' || vertex === 'B');
const filtered = graph.filter(vertex => vertex === 'A' || vertex === 'B');
expect(filtered).toEqual([
['A', undefined],
['B', undefined]
@ -693,8 +693,8 @@ describe('DirectedGraph iterative Methods', () => {
});
it('map should apply a function to each vertex and return a new array', () => {
const mapped = graph.map((value, vertex) => vertex + '_mapped');
expect(mapped).toEqual(vertexMap.map(v => v + '_mapped'));
const mapped = graph.map(vertex => vertex + '_mapped');
expect(mapped).toEqual(vertexMap.map(key => key + '_mapped'));
});
it('reduce should accumulate a value based on each vertex', () => {