diff --git a/CHANGELOG.md b/CHANGELOG.md index 15df49a..bb0a83a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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.50.9](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming) +## [v1.51.0](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming) ### Changes diff --git a/README.md b/README.md index 1edd0c8..a379ff5 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,7 @@ Performance surpasses that of native JS/TS ### Conciseness and uniformity In [java.utils](), you need to memorize a table for all sequential data structures(Queue, Deque, LinkedList), - +
@@ -687,43 +687,43 @@ Version 11.7.9 [//]: # (No deletion!!! Start of Replace Section)
heap
-
Java ArrayList
test nametime taken (ms)executions per secsample deviation
100,000 add6.58152.073.13e-4
100,000 add & poll35.6728.030.01
+
test nametime taken (ms)executions per secsample deviation
100,000 add6.36157.241.88e-4
100,000 add & poll32.5630.720.01
rb-tree
-
test nametime taken (ms)executions per secsample deviation
100,000 add55.9117.890.01
100,000 get125.117.990.01
100,000 iterator27.9735.760.01
100,000 add & delete orderly125.068.000.00
100,000 add & delete randomly242.784.120.01
+
test nametime taken (ms)executions per secsample deviation
100,000 add55.4618.030.00
100,000 get114.638.720.00
100,000 iterator26.5237.710.01
100,000 add & delete orderly128.137.800.02
100,000 add & delete randomly228.894.370.00
queue
-
test nametime taken (ms)executions per secsample deviation
1,000,000 push44.8122.320.01
100,000 push & shift4.99200.397.40e-4
Native JS Array 100,000 push & shift2234.970.450.19
+
test nametime taken (ms)executions per secsample deviation
1,000,000 push43.5322.970.01
100,000 push & shift4.80208.145.81e-4
Native JS Array 100,000 push & shift2201.640.450.11
deque
-
test nametime taken (ms)executions per secsample deviation
1,000,000 push24.3441.080.01
1,000,000 push & pop31.4131.830.00
1,000,000 push & shift31.1232.130.00
100,000 push & shift3.27306.172.62e-4
Native JS Array 100,000 push & shift2362.950.420.12
100,000 unshift & shift2.89345.463.23e-4
Native JS Array 100,000 unshift & shift4313.810.230.13
+
test nametime taken (ms)executions per secsample deviation
1,000,000 push25.9138.590.01
1,000,000 push & pop30.7132.570.00
1,000,000 push & shift30.5932.690.00
100,000 push & shift3.23309.942.61e-4
Native JS Array 100,000 push & shift2525.120.400.39
100,000 unshift & shift2.87347.922.86e-4
Native JS Array 100,000 unshift & shift4400.380.230.14
hash-map
-
test nametime taken (ms)executions per secsample deviation
1,000,000 set118.818.420.02
Native JS Map 1,000,000 set218.244.580.02
Native JS Set 1,000,000 add180.645.540.03
1,000,000 set & get121.238.250.01
Native JS Map 1,000,000 set & get273.713.650.01
Native JS Set 1,000,000 add & has173.695.760.01
1,000,000 ObjKey set & get331.893.010.04
Native JS Map 1,000,000 ObjKey set & get331.493.020.05
Native JS Set 1,000,000 ObjKey add & has308.153.250.04
+
test nametime taken (ms)executions per secsample deviation
1,000,000 set113.028.850.02
Native JS Map 1,000,000 set201.234.970.00
Native JS Set 1,000,000 add168.535.930.01
1,000,000 set & get118.498.440.02
Native JS Map 1,000,000 set & get263.493.800.01
Native JS Set 1,000,000 add & has168.285.940.01
1,000,000 ObjKey set & get309.883.230.01
Native JS Map 1,000,000 ObjKey set & get282.503.540.04
Native JS Set 1,000,000 ObjKey add & has268.423.730.03
trie
-
test nametime taken (ms)executions per secsample deviation
100,000 push58.7817.010.02
100,000 getWords95.9910.420.01
+
test nametime taken (ms)executions per secsample deviation
100,000 push44.8522.300.01
100,000 getWords84.8411.790.01
avl-tree
-
test nametime taken (ms)executions per secsample deviation
10,000 add randomly50.1719.930.01
10,000 get20.8647.940.00
10,000 add & delete randomly79.1812.630.00
10,000 addMany52.9218.900.00
+
test nametime taken (ms)executions per secsample deviation
100,000 add381.632.620.00
100,000 get354.692.820.00
100,000 iterator29.8733.480.01
100,000 add & delete orderly652.771.530.00
100,000 add & delete randomly929.071.080.00
binary-tree-overall
-
test nametime taken (ms)executions per secsample deviation
10,000 RBTree add5.69175.825.70e-4
10,000 RBTree add & delete randomly19.9450.160.00
10,000 RBTree get0.651543.771.81e-5
10,000 AVLTree add44.4622.490.00
10,000 AVLTree get20.0749.840.00
10,000 AVLTree add & delete randomly77.2912.940.01
+
test nametime taken (ms)executions per secsample deviation
10,000 RBTree add5.55180.057.09e-5
10,000 RBTree add & delete randomly19.0652.461.94e-4
10,000 RBTree get0.611647.376.11e-6
10,000 AVLTree add32.0331.227.32e-4
10,000 AVLTree get19.6550.893.12e-4
10,000 AVLTree add & delete randomly62.0716.114.26e-4
directed-graph
-
test nametime taken (ms)executions per secsample deviation
1,000 addVertex0.109883.759.48e-7
1,000 addEdge6.05165.151.08e-4
1,000 getVertex0.052.15e+45.74e-7
1,000 getEdge23.5842.410.00
tarjan208.844.790.01
topologicalSort180.275.550.00
+
test nametime taken (ms)executions per secsample deviation
1,000 addVertex0.109939.309.29e-7
1,000 addEdge6.15162.548.71e-4
1,000 getVertex0.052.18e+42.83e-7
1,000 getEdge23.9341.780.00
tarjan207.834.810.01
topologicalSort181.915.500.00
doubly-linked-list
-
test nametime taken (ms)executions per secsample deviation
1,000,000 push208.914.790.07
1,000,000 unshift202.734.930.03
1,000,000 unshift & shift182.705.470.06
1,000,000 addBefore314.163.180.06
+
test nametime taken (ms)executions per secsample deviation
1,000,000 push210.214.760.03
1,000,000 unshift218.634.570.05
1,000,000 unshift & shift162.146.170.01
1,000,000 addBefore319.753.130.06
singly-linked-list
-
test nametime taken (ms)executions per secsample deviation
1,000,000 push & shift207.944.810.05
10,000 push & pop216.074.630.01
10,000 addBefore246.194.060.00
+
test nametime taken (ms)executions per secsample deviation
1,000,000 push & shift191.555.220.03
10,000 push & pop215.954.630.01
10,000 addBefore249.824.000.01
priority-queue
-
test nametime taken (ms)executions per secsample deviation
100,000 add27.0037.042.43e-4
100,000 add & poll77.1612.960.00
+
test nametime taken (ms)executions per secsample deviation
100,000 add27.5436.312.55e-4
100,000 add & poll75.8813.184.27e-4
stack
-
test nametime taken (ms)executions per secsample deviation
1,000,000 push39.2925.450.00
1,000,000 push & pop48.0520.810.00
+
test nametime taken (ms)executions per secsample deviation
1,000,000 push39.7825.140.01
1,000,000 push & pop46.9021.320.01
[//]: # (No deletion!!! End of Replace Section) diff --git a/package-lock.json b/package-lock.json index a83a61c..8fae293 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "data-structure-typed", - "version": "1.50.9", + "version": "1.51.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "data-structure-typed", - "version": "1.50.9", + "version": "1.51.0", "license": "MIT", "devDependencies": { "@swc/core": "^1.3.96", diff --git a/package.json b/package.json index a15f1eb..b6ae07a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "data-structure-typed", - "version": "1.50.9", + "version": "1.51.0", "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", diff --git a/src/data-structures/binary-tree/avl-tree-multi-map.ts b/src/data-structures/binary-tree/avl-tree-multi-map.ts index b095a92..281eb41 100644 --- a/src/data-structures/binary-tree/avl-tree-multi-map.ts +++ b/src/data-structures/binary-tree/avl-tree-multi-map.ts @@ -240,7 +240,7 @@ export class AVLTreeMultiMap< */ override delete>( identifier: ReturnType, - callback: C = this._defaultOneParamCallback as C, + callback: C = this._DEFAULT_CALLBACK as C, ignoreCount = false ): BinaryTreeDeleteResult[] { const deletedResult: BinaryTreeDeleteResult[] = []; diff --git a/src/data-structures/binary-tree/avl-tree.ts b/src/data-structures/binary-tree/avl-tree.ts index b8e5074..8ec899e 100644 --- a/src/data-structures/binary-tree/avl-tree.ts +++ b/src/data-structures/binary-tree/avl-tree.ts @@ -164,13 +164,13 @@ export class AVLTree< * `callback` function. * @param {C} callback - The `callback` parameter is a function that will be called for each node * that is deleted from the binary tree. It is an optional parameter and if not provided, it will - * default to the `_defaultOneParamCallback` function. The `callback` function should have a single + * default to the `_DEFAULT_CALLBACK` function. The `callback` function should have a single * parameter of type `NODE * @returns The method is returning an array of `BinaryTreeDeleteResult`. */ override delete>( identifier: ReturnType, - callback: C = this._defaultOneParamCallback as C + callback: C = this._DEFAULT_CALLBACK as C ): BinaryTreeDeleteResult[] { if ((identifier as any) instanceof AVLTreeNode) callback = (node => node) as C; const deletedResults = super.delete(identifier, callback); diff --git a/src/data-structures/binary-tree/binary-tree.ts b/src/data-structures/binary-tree/binary-tree.ts index 6467200..a111f74 100644 --- a/src/data-structures/binary-tree/binary-tree.ts +++ b/src/data-structures/binary-tree/binary-tree.ts @@ -268,17 +268,17 @@ export class BinaryTree< keyOrNodeOrEntry: KeyOrNodeOrEntry, iterationType: IterationType = 'ITERATIVE' ): NODE | null | undefined { - let res: NODE | null | undefined; if (this.isRealNode(keyOrNodeOrEntry)) { - res = keyOrNodeOrEntry; + return keyOrNodeOrEntry; } else if (this.isEntry(keyOrNodeOrEntry)) { - if (keyOrNodeOrEntry[0] === null) res = null; - else if (keyOrNodeOrEntry[0] !== undefined) res = this.getNodeByKey(keyOrNodeOrEntry[0], iterationType); + if (keyOrNodeOrEntry[0] === null) return null; + if (keyOrNodeOrEntry[0] === undefined) return; + return this.getNodeByKey(keyOrNodeOrEntry[0], iterationType); } else { - if (keyOrNodeOrEntry === null) res = null; - else if (keyOrNodeOrEntry !== undefined) res = this.getNodeByKey(keyOrNodeOrEntry, iterationType); + if (keyOrNodeOrEntry === null) return null; + if (keyOrNodeOrEntry === undefined) return; + return this.getNodeByKey(keyOrNodeOrEntry, iterationType); } - return res; } /** @@ -486,16 +486,16 @@ export class BinaryTree< * specific node based on its value or object. * @param {C} callback - The `callback` parameter is a function that is used to determine the * identifier of the node to be deleted. It is optional and has a default value of - * `this._defaultOneParamCallback`. The `callback` function should return the identifier of the node. + * `this._DEFAULT_CALLBACK`. The `callback` function should return the identifier of the node. * @returns an array of `BinaryTreeDeleteResult`. */ delete>( identifier: ReturnType | null | undefined, - callback: C = this._defaultOneParamCallback as C + callback: C = this._DEFAULT_CALLBACK as C ): BinaryTreeDeleteResult[] { const deletedResult: BinaryTreeDeleteResult[] = []; if (!this.root) return deletedResult; - if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode) + if ((!callback || callback === this._DEFAULT_CALLBACK) && (identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C; const curr = this.getNode(identifier, callback); @@ -579,7 +579,7 @@ export class BinaryTree< * specific value. * @param {C} callback - The `callback` parameter is a function that takes a node of type `NODE` as * input and returns a value of type `C`. It is used to determine if a node matches the given - * identifier. If no callback is provided, the `_defaultOneParamCallback` function is used as the + * identifier. If no callback is provided, the `_DEFAULT_CALLBACK` function is used as the * default * @param [onlyOne=false] - A boolean value indicating whether to only return the first node that * matches the identifier. If set to true, the function will stop iterating once it finds a matching @@ -594,12 +594,12 @@ export class BinaryTree< */ getNodes>( identifier: ReturnType | null | undefined, - callback: C = this._defaultOneParamCallback as C, + callback: C = this._DEFAULT_CALLBACK as C, onlyOne = false, beginRoot: KeyOrNodeOrEntry = this.root, iterationType: IterationType = this.iterationType ): NODE[] { - if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode) + if ((!callback || callback === this._DEFAULT_CALLBACK) && (identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C; beginRoot = this.ensureNode(beginRoot); if (!beginRoot) return []; @@ -607,28 +607,28 @@ export class BinaryTree< const ans: NODE[] = []; if (iterationType === 'RECURSIVE') { - const _traverse = (cur: NODE) => { + const dfs = (cur: NODE) => { if (callback(cur) === identifier) { ans.push(cur); if (onlyOne) return; } if (!cur.left && !cur.right) return; - cur.left && _traverse(cur.left); - cur.right && _traverse(cur.right); + cur.left && dfs(cur.left); + cur.right && dfs(cur.right); }; - _traverse(beginRoot); + dfs(beginRoot); } else { - const queue = new Queue([beginRoot]); - while (queue.size > 0) { - const cur = queue.shift(); + const stack = [beginRoot]; + while (stack.length > 0) { + const cur = stack.pop(); if (cur) { if (callback(cur) === identifier) { ans.push(cur); if (onlyOne) return ans; } - cur.left && queue.push(cur.left); - cur.right && queue.push(cur.right); + cur.left && stack.push(cur.left); + cur.right && stack.push(cur.right); } } } @@ -685,11 +685,11 @@ export class BinaryTree< */ getNode>( identifier: ReturnType | null | undefined, - callback: C = this._defaultOneParamCallback as C, + callback: C = this._DEFAULT_CALLBACK as C, beginRoot: KeyOrNodeOrEntry = this.root, iterationType: IterationType = this.iterationType ): NODE | null | undefined { - if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode) + if ((!callback || callback === this._DEFAULT_CALLBACK) && (identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C; return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? null; @@ -717,23 +717,23 @@ export class BinaryTree< getNodeByKey(key: K, iterationType: IterationType = 'ITERATIVE'): NODE | undefined { if (!this.root) return undefined; if (iterationType === 'RECURSIVE') { - const _dfs = (cur: NODE): NODE | undefined => { + const dfs = (cur: NODE): NODE | undefined => { if (cur.key === key) return cur; if (!cur.left && !cur.right) return; - if (cur.left) return _dfs(cur.left); - if (cur.right) return _dfs(cur.right); + if (cur.left) return dfs(cur.left); + if (cur.right) return dfs(cur.right); }; - return _dfs(this.root); + return dfs(this.root); } else { - const queue = new Queue([this.root]); - while (queue.size > 0) { - const cur = queue.shift(); + const stack = [this.root]; + while (stack.length > 0) { + const cur = stack.pop(); if (cur) { if (cur.key === key) return cur; - cur.left && queue.push(cur.left); - cur.right && queue.push(cur.right); + cur.left && stack.push(cur.left); + cur.right && stack.push(cur.right); } } } @@ -789,11 +789,11 @@ export class BinaryTree< */ override get>( identifier: ReturnType | null | undefined, - callback: C = this._defaultOneParamCallback as C, + callback: C = this._DEFAULT_CALLBACK as C, beginRoot: KeyOrNodeOrEntry = this.root, iterationType: IterationType = this.iterationType ): V | undefined { - if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode) + if ((!callback || callback === this._DEFAULT_CALLBACK) && (identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C; return this.getNode(identifier, callback, beginRoot, iterationType)?.value ?? undefined; @@ -848,11 +848,11 @@ export class BinaryTree< */ override has>( identifier: ReturnType | null | undefined, - callback: C = this._defaultOneParamCallback as C, + callback: C = this._DEFAULT_CALLBACK as C, beginRoot: KeyOrNodeOrEntry = this.root, iterationType: IterationType = this.iterationType ): boolean { - if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode) + if ((!callback || callback === this._DEFAULT_CALLBACK) && (identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C; return this.getNodes(identifier, callback, true, beginRoot, iterationType).length > 0; @@ -1184,20 +1184,20 @@ export class BinaryTree< if (!this.isRealNode(beginRoot)) return beginRoot; if (iterationType === 'RECURSIVE') { - const _traverse = (cur: NODE): NODE => { + const dfs = (cur: NODE): NODE => { if (!this.isRealNode(cur.left)) return cur; - return _traverse(cur.left); + return dfs(cur.left); }; - return _traverse(beginRoot); + return dfs(beginRoot); } else { // Indirect implementation of iteration using tail recursion optimization - const _traverse = trampoline((cur: NODE) => { + const dfs = trampoline((cur: NODE) => { if (!this.isRealNode(cur.left)) return cur; - return _traverse.cont(cur.left); + return dfs.cont(cur.left); }); - return _traverse(beginRoot); + return dfs(beginRoot); } } @@ -1231,20 +1231,20 @@ export class BinaryTree< if (!beginRoot) return beginRoot; if (iterationType === 'RECURSIVE') { - const _traverse = (cur: NODE): NODE => { + const dfs = (cur: NODE): NODE => { if (!this.isRealNode(cur.right)) return cur; - return _traverse(cur.right); + return dfs(cur.right); }; - return _traverse(beginRoot); + return dfs(beginRoot); } else { // Indirect implementation of iteration using tail recursion optimization - const _traverse = trampoline((cur: NODE) => { + const dfs = trampoline((cur: NODE) => { if (!this.isRealNode(cur.right)) return cur; - return _traverse.cont(cur.right); + return dfs.cont(cur.right); }); - return _traverse(beginRoot); + return dfs(beginRoot); } } @@ -1351,7 +1351,7 @@ export class BinaryTree< * @returns an array of values that are the return values of the callback function. */ dfs>( - callback: C = this._defaultOneParamCallback as C, + callback: C = this._DEFAULT_CALLBACK as C, pattern: DFSOrderPattern = 'IN', beginRoot: KeyOrNodeOrEntry = this.root, iterationType: IterationType = 'ITERATIVE', @@ -1361,38 +1361,38 @@ export class BinaryTree< if (!beginRoot) return []; const ans: ReturnType[] = []; if (iterationType === 'RECURSIVE') { - const _traverse = (node: NODE | null | undefined) => { + const dfs = (node: NODE | null | undefined) => { switch (pattern) { case 'IN': if (includeNull) { - if (this.isRealNode(node) && this.isNodeOrNull(node.left)) _traverse(node.left); + if (this.isRealNode(node) && this.isNodeOrNull(node.left)) dfs(node.left); this.isNodeOrNull(node) && ans.push(callback(node)); - if (this.isRealNode(node) && this.isNodeOrNull(node.right)) _traverse(node.right); + if (this.isRealNode(node) && this.isNodeOrNull(node.right)) dfs(node.right); } else { - if (this.isRealNode(node) && this.isRealNode(node.left)) _traverse(node.left); + if (this.isRealNode(node) && this.isRealNode(node.left)) dfs(node.left); this.isRealNode(node) && ans.push(callback(node)); - if (this.isRealNode(node) && this.isRealNode(node.right)) _traverse(node.right); + if (this.isRealNode(node) && this.isRealNode(node.right)) dfs(node.right); } break; case 'PRE': if (includeNull) { this.isNodeOrNull(node) && ans.push(callback(node)); - if (this.isRealNode(node) && this.isNodeOrNull(node.left)) _traverse(node.left); - if (this.isRealNode(node) && this.isNodeOrNull(node.right)) _traverse(node.right); + if (this.isRealNode(node) && this.isNodeOrNull(node.left)) dfs(node.left); + if (this.isRealNode(node) && this.isNodeOrNull(node.right)) dfs(node.right); } else { this.isRealNode(node) && ans.push(callback(node)); - if (this.isRealNode(node) && this.isRealNode(node.left)) _traverse(node.left); - if (this.isRealNode(node) && this.isRealNode(node.right)) _traverse(node.right); + if (this.isRealNode(node) && this.isRealNode(node.left)) dfs(node.left); + if (this.isRealNode(node) && this.isRealNode(node.right)) dfs(node.right); } break; case 'POST': if (includeNull) { - if (this.isRealNode(node) && this.isNodeOrNull(node.left)) _traverse(node.left); - if (this.isRealNode(node) && this.isNodeOrNull(node.right)) _traverse(node.right); + if (this.isRealNode(node) && this.isNodeOrNull(node.left)) dfs(node.left); + if (this.isRealNode(node) && this.isNodeOrNull(node.right)) dfs(node.right); this.isNodeOrNull(node) && ans.push(callback(node)); } else { - if (this.isRealNode(node) && this.isRealNode(node.left)) _traverse(node.left); - if (this.isRealNode(node) && this.isRealNode(node.right)) _traverse(node.right); + if (this.isRealNode(node) && this.isRealNode(node.left)) dfs(node.left); + if (this.isRealNode(node) && this.isRealNode(node.right)) dfs(node.right); this.isRealNode(node) && ans.push(callback(node)); } @@ -1400,7 +1400,7 @@ export class BinaryTree< } }; - _traverse(beginRoot); + dfs(beginRoot); } else { // 0: visit, 1: print const stack: { opt: 0 | 1; node: NODE | null | undefined }[] = [{ opt: 0, node: beginRoot }]; @@ -1486,7 +1486,7 @@ export class BinaryTree< * the breadth-first traversal of a binary tree. */ bfs>( - callback: C = this._defaultOneParamCallback as C, + callback: C = this._DEFAULT_CALLBACK as C, beginRoot: KeyOrNodeOrEntry = this.root, iterationType: IterationType = this.iterationType, includeNull = false @@ -1499,7 +1499,7 @@ export class BinaryTree< if (iterationType === 'RECURSIVE') { const queue: Queue = new Queue([beginRoot]); - const traverse = (level: number) => { + const dfs = (level: number) => { if (queue.size === 0) return; const current = queue.shift()!; @@ -1513,10 +1513,10 @@ export class BinaryTree< if (this.isRealNode(current.right)) queue.push(current.right); } - traverse(level + 1); + dfs(level + 1); }; - traverse(0); + dfs(0); } else { const queue = new Queue([beginRoot]); while (queue.size > 0) { @@ -1580,7 +1580,7 @@ export class BinaryTree< * @returns The function `listLevels` returns a two-dimensional array of type `ReturnType[][]`. */ listLevels>( - callback: C = this._defaultOneParamCallback as C, + callback: C = this._DEFAULT_CALLBACK as C, beginRoot: KeyOrNodeOrEntry = this.root, iterationType: IterationType = this.iterationType, includeNull = false @@ -1651,7 +1651,7 @@ export class BinaryTree< * by the return type of the `callback` function. */ morris>( - callback: C = this._defaultOneParamCallback as C, + callback: C = this._DEFAULT_CALLBACK as C, pattern: DFSOrderPattern = 'IN', beginRoot: KeyOrNodeOrEntry = this.root ): ReturnType[] { @@ -1995,7 +1995,7 @@ export class BinaryTree< } } - protected _defaultOneParamCallback = (node: NODE | null | undefined) => (node ? node.key : undefined); + protected _DEFAULT_CALLBACK = (node: NODE | null | undefined) => (node ? node.key : undefined); /** * Swap the data of two nodes in the binary tree. diff --git a/src/data-structures/binary-tree/bst.ts b/src/data-structures/binary-tree/bst.ts index 8199ea1..cee0877 100644 --- a/src/data-structures/binary-tree/bst.ts +++ b/src/data-structures/binary-tree/bst.ts @@ -214,15 +214,15 @@ export class BST< keyOrNodeOrEntry: KeyOrNodeOrEntry, iterationType: IterationType = 'ITERATIVE' ): NODE | undefined { - let res: NODE | undefined; if (this.isRealNode(keyOrNodeOrEntry)) { - res = keyOrNodeOrEntry; + return keyOrNodeOrEntry; } else if (this.isEntry(keyOrNodeOrEntry)) { - if (keyOrNodeOrEntry[0]) res = this.getNodeByKey(keyOrNodeOrEntry[0], iterationType); + if (keyOrNodeOrEntry[0] === null || keyOrNodeOrEntry[0] === undefined) return; + return this.getNodeByKey(keyOrNodeOrEntry[0], iterationType); } else { - if (keyOrNodeOrEntry) res = this.getNodeByKey(keyOrNodeOrEntry, iterationType); + if (keyOrNodeOrEntry === null || keyOrNodeOrEntry === undefined) return; + return this.getNodeByKey(keyOrNodeOrEntry, iterationType); } - return res; } /** @@ -426,26 +426,26 @@ export class BST< * found in the binary tree. If no node is found, it returns `undefined`. */ override getNodeByKey(key: K, iterationType: IterationType = 'ITERATIVE'): NODE | undefined { - // return this.getNodes(key, this._defaultOneParamCallback, true, this.root, iterationType)[0]; - if (!this.isRealNode(this.root)) return undefined; + // return this.getNodes(key, this._DEFAULT_CALLBACK, true, this.root, iterationType)[0]; + if (!this.isRealNode(this.root)) return; if (iterationType === 'RECURSIVE') { - const _dfs = (cur: NODE): NODE | undefined => { + const dfs = (cur: NODE): NODE | undefined => { if (cur.key === key) return cur; if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return; - if (this._compare(cur.key, key) === 'GT' && this.isRealNode(cur.left)) return _dfs(cur.left); - if (this._compare(cur.key, key) === 'LT' && this.isRealNode(cur.right)) return _dfs(cur.right); + if (this.isRealNode(cur.left) && this._compare(cur.key, key) === 'GT') return dfs(cur.left); + if (this.isRealNode(cur.right) && this._compare(cur.key, key) === 'LT') return dfs(cur.right); }; - return _dfs(this.root); + return dfs(this.root); } else { - const queue = new Queue([this.root]); - while (queue.size > 0) { - const cur = queue.shift(); + const stack = [this.root]; + while (stack.length > 0) { + const cur = stack.pop(); if (this.isRealNode(cur)) { if (this._compare(cur.key, key) === 'EQ') return cur; - if (this._compare(cur.key, key) === 'GT') this.isRealNode(cur.left) && queue.push(cur.left); - if (this._compare(cur.key, key) === 'LT') this.isRealNode(cur.right) && queue.push(cur.right); + if (this.isRealNode(cur.left) && this._compare(cur.key, key) === 'GT') stack.push(cur.left); + if (this.isRealNode(cur.right) && this._compare(cur.key, key) === 'LT') stack.push(cur.right); } } } @@ -481,7 +481,7 @@ export class BST< */ override getNodes>( identifier: ReturnType | undefined, - callback: C = this._defaultOneParamCallback as C, + callback: C = this._DEFAULT_CALLBACK as C, onlyOne = false, beginRoot: KeyOrNodeOrEntry = this.root, iterationType: IterationType = this.iterationType @@ -491,7 +491,7 @@ export class BST< const ans: NODE[] = []; if (iterationType === 'RECURSIVE') { - const _traverse = (cur: NODE) => { + const dfs = (cur: NODE) => { const callbackResult = callback(cur); if (callbackResult === identifier) { ans.push(cur); @@ -500,16 +500,16 @@ export class BST< if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return; // TODO potential bug - if (callback === this._defaultOneParamCallback) { - if (this.isRealNode(cur.left) && this._compare(cur.key, identifier as K) === 'GT') _traverse(cur.left); - if (this.isRealNode(cur.right) && this._compare(cur.key, identifier as K) === 'LT') _traverse(cur.right); + if (callback === this._DEFAULT_CALLBACK) { + if (this.isRealNode(cur.left) && this._compare(cur.key, identifier as K) === 'GT') dfs(cur.left); + if (this.isRealNode(cur.right) && this._compare(cur.key, identifier as K) === 'LT') dfs(cur.right); } else { - this.isRealNode(cur.left) && _traverse(cur.left); - this.isRealNode(cur.right) && _traverse(cur.right); + this.isRealNode(cur.left) && dfs(cur.left); + this.isRealNode(cur.right) && dfs(cur.right); } }; - _traverse(beginRoot); + dfs(beginRoot); } else { const stack = [beginRoot]; while (stack.length > 0) { @@ -521,7 +521,7 @@ export class BST< if (onlyOne) return ans; } // TODO potential bug - if (callback === this._defaultOneParamCallback) { + if (callback === this._DEFAULT_CALLBACK) { if (this.isRealNode(cur.right) && this._compare(cur.key, identifier as K) === 'LT') stack.push(cur.right); if (this.isRealNode(cur.left) && this._compare(cur.key, identifier as K) === 'GT') stack.push(cur.left); @@ -568,7 +568,7 @@ export class BST< * @returns The method is returning an array of the return type of the callback function. */ override dfs>( - callback: C = this._defaultOneParamCallback as C, + callback: C = this._DEFAULT_CALLBACK as C, pattern: DFSOrderPattern = 'IN', beginRoot: KeyOrNodeOrEntry = this.root, iterationType: IterationType = 'ITERATIVE' @@ -599,7 +599,7 @@ export class BST< * @returns The method is returning an array of the return type of the callback function. */ override bfs>( - callback: C = this._defaultOneParamCallback as C, + callback: C = this._DEFAULT_CALLBACK as C, beginRoot: KeyOrNodeOrEntry = this.root, iterationType: IterationType = this.iterationType ): ReturnType[] { @@ -630,7 +630,7 @@ export class BST< * function. */ override listLevels>( - callback: C = this._defaultOneParamCallback as C, + callback: C = this._DEFAULT_CALLBACK as C, beginRoot: KeyOrNodeOrEntry = this.root, iterationType: IterationType = this.iterationType ): ReturnType[][] { @@ -700,7 +700,7 @@ export class BST< * `ReturnType`, which is the return type of the callback function passed as an argument. */ lesserOrGreaterTraverse>( - callback: C = this._defaultOneParamCallback as C, + callback: C = this._DEFAULT_CALLBACK as C, lesserOrGreater: CP = 'LT', targetNode: KeyOrNodeOrEntry = this.root, iterationType: IterationType = this.iterationType @@ -713,15 +713,15 @@ export class BST< const targetKey = targetNode.key; if (iterationType === 'RECURSIVE') { - const _traverse = (cur: NODE) => { + const dfs = (cur: NODE) => { const compared = this._compare(cur.key, targetKey); if (compared === lesserOrGreater) ans.push(callback(cur)); - if (this.isRealNode(cur.left)) _traverse(cur.left); - if (this.isRealNode(cur.right)) _traverse(cur.right); + if (this.isRealNode(cur.left)) dfs(cur.left); + if (this.isRealNode(cur.right)) dfs(cur.right); }; - _traverse(this.root); + dfs(this.root); return ans; } else { const queue = new Queue([this.root]); diff --git a/src/data-structures/binary-tree/rb-tree.ts b/src/data-structures/binary-tree/rb-tree.ts index 16066cf..1e48309 100644 --- a/src/data-structures/binary-tree/rb-tree.ts +++ b/src/data-structures/binary-tree/rb-tree.ts @@ -231,7 +231,7 @@ export class RedBlackTree< */ override getNode>( identifier: ReturnType | undefined, - callback: C = this._defaultOneParamCallback as C, + callback: C = this._DEFAULT_CALLBACK as C, beginRoot: BSTNKeyOrNode = this.root, iterationType: IterationType = this.iterationType ): NODE | null | undefined { @@ -308,13 +308,13 @@ export class RedBlackTree< * deleted is not found. * @param {C} callback - The `callback` parameter is a function that is used to retrieve a node from * the binary tree based on its identifier. It is an optional parameter and if not provided, the - * `_defaultOneParamCallback` function is used as the default callback. The callback function should + * `_DEFAULT_CALLBACK` function is used as the default callback. The callback function should * return the identifier of the node to * @returns an array of BinaryTreeDeleteResult objects. */ override delete>( identifier: ReturnType | null | undefined, - callback: C = this._defaultOneParamCallback as C + callback: C = this._DEFAULT_CALLBACK as C ): BinaryTreeDeleteResult[] { if (identifier === null) return []; const results: BinaryTreeDeleteResult[] = []; diff --git a/src/data-structures/binary-tree/tree-multi-map.ts b/src/data-structures/binary-tree/tree-multi-map.ts index 9b0e3aa..025520b 100644 --- a/src/data-structures/binary-tree/tree-multi-map.ts +++ b/src/data-structures/binary-tree/tree-multi-map.ts @@ -242,7 +242,7 @@ export class TreeMultiMap< * function. It can also be null or undefined if no node needs to be deleted. * @param {C} callback - The `callback` parameter is a function that takes a node of type `NODE` as * input and returns a value of type `ReturnType`. It is used to determine if a node matches the - * identifier for deletion. If no callback is provided, the `_defaultOneParamCallback` function is + * identifier for deletion. If no callback is provided, the `_DEFAULT_CALLBACK` function is * used * @param [ignoreCount=false] - A boolean value indicating whether to ignore the count of the target * node when performing deletion. If set to true, the count of the target node will not be considered @@ -252,7 +252,7 @@ export class TreeMultiMap< */ override delete>( identifier: ReturnType | null | undefined, - callback: C = this._defaultOneParamCallback as C, + callback: C = this._DEFAULT_CALLBACK as C, ignoreCount = false ): BinaryTreeDeleteResult[] { if (identifier === null) return []; diff --git a/test/integration/avl-tree.test.ts b/test/integration/avl-tree.test.ts index 4a6d967..09af032 100644 --- a/test/integration/avl-tree.test.ts +++ b/test/integration/avl-tree.test.ts @@ -1,4 +1,4 @@ -import { AVLTree, CP } from 'avl-tree-typed'; +import { AVLTree } from 'avl-tree-typed'; describe('AVL Tree Test', () => { it('should perform various operations on a AVL Tree', () => { diff --git a/test/integration/bst.test.ts b/test/integration/bst.test.ts index ad3440b..61c915a 100644 --- a/test/integration/bst.test.ts +++ b/test/integration/bst.test.ts @@ -1,4 +1,4 @@ -import { BST, BSTNode, CP } from 'bst-typed'; +import { BST, BSTNode } from 'bst-typed'; describe('Individual package BST operations test', () => { it('should perform various operations on a Binary Search Tree with numeric values', () => { diff --git a/test/integration/index.html b/test/integration/index.html index 50e80bd..41866b4 100644 --- a/test/integration/index.html +++ b/test/integration/index.html @@ -28,14 +28,14 @@ const n = 1000000; const startEn = performance.now(); for (let i = 0; i < n; i++) { - queue.enqueue(i); + queue.push(i); } console.log((performance.now() - startEn).toFixed(2), `Queue ${n.toLocaleString()} enqueue `); let last = 0; const startTime = performance.now(); for (let i = 0; i < n; i++) { - last = queue.dequeue(); + last = queue.shift(); } console.log((performance.now() - startTime).toFixed(2), `Queue ${n.toLocaleString()} dequeue `); diff --git a/test/unit/data-structures/binary-tree/tree-multi-map.test.ts b/test/unit/data-structures/binary-tree/tree-multi-map.test.ts index d6ff398..a3bf093 100644 --- a/test/unit/data-structures/binary-tree/tree-multi-map.test.ts +++ b/test/unit/data-structures/binary-tree/tree-multi-map.test.ts @@ -45,6 +45,7 @@ describe('TreeMultiMap operations test1', () => { expect(tmm.getMinHeight()).toBe(-1); tmm.addMany([1, 6, 7, 2, 3, 4, 9, 11, 8, 5, 10, 12, 16, 14, 13, 15]); + // tmm.print() expect(tmm.getHeight()).toBe(5); expect(tmm.getMinHeight()).toBe(2); }); diff --git a/test/utils/big-o.ts b/test/utils/big-o.ts index b639463..1c9175f 100644 --- a/test/utils/big-o.ts +++ b/test/utils/big-o.ts @@ -205,3 +205,15 @@ export function logBigOMetrics(target: any, propertyKey: string, descriptor: Pro return descriptor; } + +export const logPerf = function (fn: (...args: any[]) => any, args: any[], thisArg?: any) { + const start = performance.now(); + if (thisArg) { + if (args && args.length > 0) fn.apply(thisArg, args); + else fn.apply(thisArg); + } else { + if (args && args.length > 0) fn(...args); + else fn(); + } + console.log(`function running cost : ${(performance.now() - start).toFixed(2)} ms`); +};