From 24a961f692ccedab03e34744f8d1ba3473e8f027 Mon Sep 17 00:00:00 2001 From: Revone Date: Sat, 4 Nov 2023 10:00:51 +0800 Subject: [PATCH] [BST, AVL] The 'get' method follows the binary search of a BST for bug fixes during queries. [Project] The editor uses 'tsconfig.json' for code checking to be compatible with the 'test' directory, but compiles using their respective configuration files. --- README.md | 34 ++++++++++++++ package.json | 14 +++--- src/data-structures/binary-tree/avl-tree.ts | 4 +- .../binary-tree/binary-tree.ts | 38 ++++++++-------- src/data-structures/binary-tree/bst.ts | 14 +++--- .../binary-tree/tree-multiset.ts | 4 +- .../graph/undirected-graph.test.ts | 16 +++++++ tsconfig-base.json | 44 +++++++++---------- tsconfig-cjs.json | 6 ++- tsconfig-mjs.json | 12 +++++ tsconfig.json | 6 ++- 11 files changed, 130 insertions(+), 62 deletions(-) create mode 100644 tsconfig-mjs.json diff --git a/README.md b/README.md index 9cc3d12..cf6b329 100644 --- a/README.md +++ b/README.md @@ -654,6 +654,40 @@ inherit the existing data structures to implement the customized ones you need. optimal approach to data structure design. ## Benchmark +
+
avl-tree
+
test nametime taken (ms)executions per secexecuted timessample mean (secs)sample deviation
1000 add randomly2.12470.70240.003.55e-5
1000 add & delete randomly5.12195.21110.018.78e-4
1000 addMany3.95253.32180.000.00
1000 get3.04328.49220.000.00
+
+
binary-tree
+
test nametime taken (ms)executions per secexecuted timessample mean (secs)sample deviation
1000 add randomly13.4474.3940.010.00
1000 add & delete randomly15.9362.7840.022.08e-4
1000 addMany10.7193.4150.012.11e-4
1000 get17.9055.8630.021.30e-4
1000 dfs68.5214.5910.073.98e-4
1000 bfs54.5718.3310.054.34e-4
1000 morris37.3726.7620.043.60e-4
+
+
bst
+
test nametime taken (ms)executions per secexecuted timessample mean (secs)sample deviation
1000 add randomly2.15465.28240.001.79e-5
1000 add & delete randomly5.08196.92100.014.34e-5
1000 addMany2.14467.28240.004.18e-5
1000 get2.35426.21220.005.24e-5
+
+
directed-graph
+
test nametime taken (ms)executions per secexecuted timessample mean (secs)sample deviation
1000 addVertex0.109846.765051.02e-42.82e-6
1000 addEdge6.23160.4790.015.72e-4
1000 getVertex0.052.18e+411004.59e-53.84e-7
1000 getEdge23.9641.7330.020.00
tarjan217.414.6010.220.01
tarjan all242.304.1310.240.06
topologicalSort184.855.4110.180.01
+
+
heap
+
test nametime taken (ms)executions per secexecuted timessample mean (secs)sample deviation
1000 add & pop0.352823.441493.54e-45.10e-5
1000 fib add & pop3.92255.12140.006.68e-5
+
+
doubly-linked-list
+
test nametime taken (ms)executions per secexecuted timessample mean (secs)sample deviation
1000000 unshift206.784.8410.210.03
1000000 unshift & shift170.955.8510.170.04
1000 insertBefore0.033.75e+419062.67e-53.24e-7
+
+
singly-linked-list
+
test nametime taken (ms)executions per secexecuted timessample mean (secs)sample deviation
1000 push & pop1.77565.87300.005.05e-5
1000 insertBefore2.32430.56230.007.66e-5
+
+
max-priority-queue
+
test nametime taken (ms)executions per secexecuted timessample mean (secs)sample deviation
10000 refill & poll11.4587.3150.011.45e-4
+
+
deque
+
test nametime taken (ms)executions per secexecuted timessample mean (secs)sample deviation
1000000 push214.854.6510.210.03
1000000 shift26.0838.3430.030.00
+
+
queue
+
test nametime taken (ms)executions per secexecuted timessample mean (secs)sample deviation
1000000 push44.3222.5620.040.01
1000000 push & shift79.0812.6410.080.00
+
+
trie
+
test nametime taken (ms)executions per secexecuted timessample mean (secs)sample deviation
100000 push56.2017.7910.060.01
100000 getWords95.2610.5010.100.00
+
avl-tree
test nametime taken (ms)executions per secexecuted timessample mean (secs)sample deviation
1000 add randomly2.22449.77230.002.65e-5
1000 add & delete randomly11.5886.3750.015.00e-4
1000 addMany3.10322.62170.001.23e-4
1000 get24.9140.1430.027.25e-4
diff --git a/package.json b/package.json index 4d92375..4975c1b 100644 --- a/package.json +++ b/package.json @@ -2,20 +2,20 @@ "name": "data-structure-typed", "version": "1.41.5", "description": "Data Structures of Javascript & TypeScript. Binary Tree, BST, Graph, Heap, Priority Queue, Linked List, Queue, Deque, Stack, AVL Tree, Tree Multiset, Trie, Directed Graph, Undirected Graph, Singly Linked List, Doubly Linked List, Max Heap, Max Priority Queue, Min Heap, Min Priority Queue.", - "main": "dist/cjs/index.js", - "module": "dist/mjs/index.js", - "types": "dist/mjs/index.d.ts", + "main": "dist/cjs/src/index.js", + "module": "dist/mjs/src/index.js", + "types": "dist/mjs/src/index.d.ts", "umd:main": "dist/umd/data-structure-typed.min.js", "exports": { ".": { - "import": "./dist/mjs/index.js", - "require": "./dist/cjs/index.js", - "types": "./dist/mjs/index.d.ts" + "import": "./dist/mjs/src/index.js", + "require": "./dist/cjs/src/index.js", + "types": "./dist/mjs/src/index.d.ts" } }, "scripts": { "build": "npm run build:mjs && npm run build:cjs && npm run build:umd && npm run build:docs", - "build:mjs": "rm -rf dist/mjs && tsc -p tsconfig.json", + "build:mjs": "rm -rf dist/mjs && tsc -p tsconfig-mjs.json", "build:cjs": "rm -rf dist/cjs && tsc -p tsconfig-cjs.json", "build:umd": "tsup", "build:docs": "typedoc --out docs ./src", diff --git a/src/data-structures/binary-tree/avl-tree.ts b/src/data-structures/binary-tree/avl-tree.ts index df4790a..47d99fd 100644 --- a/src/data-structures/binary-tree/avl-tree.ts +++ b/src/data-structures/binary-tree/avl-tree.ts @@ -70,12 +70,12 @@ export class AVLTree = AVLTreeNode node.key)` + * `this.defaultOneParamCallback` * @returns The method is returning an array of `BinaryTreeDeletedResult` objects. */ override delete>( identifier: ReturnType, - callback: C = ((node: N) => node.key) as C + callback: C = this.defaultOneParamCallback as C ): BinaryTreeDeletedResult[] { 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 0372053..c44befc 100644 --- a/src/data-structures/binary-tree/binary-tree.ts +++ b/src/data-structures/binary-tree/binary-tree.ts @@ -141,6 +141,8 @@ export class BinaryTree = BinaryTreeNode return this._size; } + protected defaultOneParamCallback = (node: N) => node.key; + /** * Creates a new instance of BinaryTreeNode with the given key and value. * @param {BTNKey} key - The key for the new node. @@ -284,11 +286,11 @@ export class BinaryTree = BinaryTreeNode * @param callback - The `callback` parameter is a function that takes a node as input and returns a * value. This value is compared with the `identifier` parameter to determine if the node should be * included in the result. The `callback` parameter has a default value of - * `((node: N) => node.key)`, which + * `this.defaultOneParamCallback`, which */ delete>( identifier: ReturnType | null, - callback: C = ((node: N) => node.key) as C + callback: C = this.defaultOneParamCallback as C ): BinaryTreeDeletedResult[] { const bstDeletedResult: BinaryTreeDeletedResult[] = []; if (!this.root) return bstDeletedResult; @@ -506,7 +508,7 @@ export class BinaryTree = BinaryTreeNode * @param callback - The `callback` parameter is a function that takes a node as input and returns a * value. This value is compared with the `identifier` parameter to determine if the node should be * included in the result. The `callback` parameter has a default value of - * `((node: N) => node.key)`, which + * `this.defaultOneParamCallback`, which * @param [onlyOne=false] - A boolean value indicating whether to stop searching after finding the * first node that matches the identifier. If set to true, the function will return an array with * only one element (or an empty array if no matching node is found). If set to false (default), the @@ -520,7 +522,7 @@ export class BinaryTree = BinaryTreeNode */ getNodes>( identifier: ReturnType | null, - callback: C = ((node: N) => node.key) as C, + callback: C = this.defaultOneParamCallback as C, onlyOne = false, beginRoot: N | null = this.root, iterationType = this.iterationType @@ -588,7 +590,7 @@ export class BinaryTree = BinaryTreeNode * @param callback - The `callback` parameter is a function that is used to determine whether a node * matches the desired criteria. It takes a node as input and returns a boolean value indicating * whether the node matches the criteria or not. The default callback function - * `((node: N) => node.key)` is used if no callback function is + * `this.defaultOneParamCallback` is used if no callback function is * @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies * the node from which the search should begin. By default, it is set to `this.root`, which means the * search will start from the root node of the binary tree. However, you can provide a different node @@ -599,7 +601,7 @@ export class BinaryTree = BinaryTreeNode */ has>( identifier: ReturnType | null, - callback: C = ((node: N) => node.key) as C, + callback: C = this.defaultOneParamCallback as C, beginRoot = this.root, iterationType = this.iterationType ): boolean { @@ -637,7 +639,7 @@ export class BinaryTree = BinaryTreeNode * @param callback - The `callback` parameter is a function that is used to determine whether a node * matches the desired criteria. It takes a node as input and returns a boolean value indicating * whether the node matches the criteria or not. The default callback function - * (`((node: N) => node.key)`) is used if no callback function is + * (`this.defaultOneParamCallback`) is used if no callback function is * @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies * the root node from which the search should begin. * @param iterationType - The `iterationType` parameter specifies the type of iteration to be @@ -646,7 +648,7 @@ export class BinaryTree = BinaryTreeNode */ getNode>( identifier: ReturnType | null, - callback: C = ((node: N) => node.key) as C, + callback: C = this.defaultOneParamCallback as C, beginRoot = this.root, iterationType = this.iterationType ): N | null { @@ -684,7 +686,7 @@ export class BinaryTree = BinaryTreeNode * @param callback - The `callback` parameter is a function that is used to determine whether a node * matches the desired criteria. It takes a node as input and returns a boolean value indicating * whether the node matches the criteria or not. The default callback function - * (`((node: N) => node.key)`) is used if no callback function is + * (`this.defaultOneParamCallback`) is used if no callback function is * @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies * the root node from which the search should begin. * @param iterationType - The `iterationType` parameter specifies the type of iteration to be @@ -693,7 +695,7 @@ export class BinaryTree = BinaryTreeNode */ get>( identifier: ReturnType | null, - callback: C = ((node: N) => node.key) as C, + callback: C = this.defaultOneParamCallback as C, beginRoot = this.root, iterationType = this.iterationType ): V | undefined { @@ -859,7 +861,7 @@ export class BinaryTree = BinaryTreeNode * @returns The function `subTreeTraverse` returns an array of `ReturnType>`. */ subTreeTraverse>( - callback: C = ((node: N) => node.key) as C, + callback: C = this.defaultOneParamCallback as C, beginRoot: BTNKey | N | null = this.root, iterationType = this.iterationType ): ReturnType[] { @@ -895,7 +897,7 @@ export class BinaryTree = BinaryTreeNode * function on each node according to a specified order pattern. * @param callback - The `callback` parameter is a function that will be called on each node during * the depth-first search traversal. It takes a node as input and returns a value. The default value - * is `((node: N) => node.key)`, which is a callback function defined elsewhere in the code. + * is `this.defaultOneParamCallback`, which is a callback function defined elsewhere in the code. * @param {DFSOrderPattern} [pattern=in] - The `pattern` parameter determines the order in which the * nodes are visited during the depth-first search. There are three possible values for `pattern`: * @param {N | null} beginRoot - The `beginRoot` parameter is the starting node for the depth-first @@ -906,7 +908,7 @@ export class BinaryTree = BinaryTreeNode * @returns The function `dfs` returns an array of `ReturnType>` values. */ dfs>( - callback: C = ((node: N) => node.key) as C, + callback: C = this.defaultOneParamCallback as C, pattern: DFSOrderPattern = 'in', beginRoot: N | null = this.root, iterationType: IterationType = IterationType.ITERATIVE @@ -981,7 +983,7 @@ export class BinaryTree = BinaryTreeNode * function on each node. * @param callback - The `callback` parameter is a function that will be called for each node in the * breadth-first search. It takes a node of type `N` as its argument and returns a value of type - * `ReturnType>`. The default value for this parameter is `((node: N) => node.key) + * `ReturnType>`. The default value for this parameter is `this.defaultOneParamCallback * @param {N | null} beginRoot - The `beginRoot` parameter is the starting node for the breadth-first * search. It determines from which node the search will begin. If `beginRoot` is `null`, the search * will not be performed and an empty array will be returned. @@ -990,7 +992,7 @@ export class BinaryTree = BinaryTreeNode * @returns The function `bfs` returns an array of `ReturnType>[]`. */ bfs>( - callback: C = ((node: N) => node.key) as C, + callback: C = this.defaultOneParamCallback as C, beginRoot: N | null = this.root, iterationType = this.iterationType ): ReturnType[] { @@ -1047,7 +1049,7 @@ export class BinaryTree = BinaryTreeNode * function `C` applied to the nodes at that level. */ listLevels>( - callback: C = ((node: N) => node.key) as C, + callback: C = this.defaultOneParamCallback as C, beginRoot: N | null = this.root, iterationType = this.iterationType ): ReturnType[][] { @@ -1126,7 +1128,7 @@ export class BinaryTree = BinaryTreeNode * algorithm and returns an array of values obtained by applying a callback function to each node. * @param callback - The `callback` parameter is a function that will be called on each node in the * tree. It takes a node of type `N` as input and returns a value of type `ReturnType>`. The - * default value for this parameter is `((node: N) => node.key)`. + * default value for this parameter is `this.defaultOneParamCallback`. * @param {DFSOrderPattern} [pattern=in] - The `pattern` parameter in the `morris` function * determines the order in which the nodes of a binary tree are traversed. It can have one of the * following values: @@ -1136,7 +1138,7 @@ export class BinaryTree = BinaryTreeNode * @returns The `morris` function returns an array of `ReturnType>` values. */ morris>( - callback: C = ((node: N) => node.key) as C, + callback: C = this.defaultOneParamCallback as C, pattern: DFSOrderPattern = 'in', beginRoot: N | null = this.root ): ReturnType[] { diff --git a/src/data-structures/binary-tree/bst.ts b/src/data-structures/binary-tree/bst.ts index 7fad37f..34e7c8e 100644 --- a/src/data-structures/binary-tree/bst.ts +++ b/src/data-structures/binary-tree/bst.ts @@ -36,7 +36,7 @@ export class BST = BSTNode> } } } - + /** * The function creates a new binary search tree node with the given key and value. * @param {BTNKey} key - The key parameter is the key value that will be associated with @@ -236,7 +236,7 @@ export class BST = BSTNode> */ override getNode>( identifier: ReturnType | null, - callback: C = ((node: N) => node.key) as C, + callback: C = this.defaultOneParamCallback as C, beginRoot = this.root, iterationType = this.iterationType ): N | null { @@ -272,7 +272,7 @@ export class BST = BSTNode> * generic type `N`. * @param callback - The `callback` parameter is a function that takes a node as input and returns a * value. This value is compared with the `nodeProperty` parameter to determine if the node should be - * included in the result. The default value for `callback` is `((node: N) => node.key)`, which is + * included in the result. The default value for `callback` is `this.defaultOneParamCallback`, which is * a * @param [onlyOne=false] - A boolean value indicating whether to stop the traversal after finding * the first node that matches the nodeProperty. If set to true, the function will return an array @@ -287,7 +287,7 @@ export class BST = BSTNode> */ override getNodes>( identifier: ReturnType | null, - callback: C = ((node: N) => node.key) as C, + callback: C = this.defaultOneParamCallback as C, onlyOne = false, beginRoot: N | null = this.root, iterationType = this.iterationType @@ -305,7 +305,7 @@ export class BST = BSTNode> if (!cur.left && !cur.right) return; // TODO potential bug - if (callback === ((node: N) => node.key)) { + if (callback === this.defaultOneParamCallback) { if (this._compare(cur.key, identifier as number) === CP.gt) cur.left && _traverse(cur.left); if (this._compare(cur.key, identifier as number) === CP.lt) cur.right && _traverse(cur.right); } else { @@ -326,7 +326,7 @@ export class BST = BSTNode> if (onlyOne) return ans; } // TODO potential bug - if (callback === ((node: N) => node.key)) { + if (callback === this.defaultOneParamCallback) { if (this._compare(cur.key, identifier as number) === CP.gt) cur.left && queue.push(cur.left); if (this._compare(cur.key, identifier as number) === CP.lt) cur.right && queue.push(cur.right); } else { @@ -360,7 +360,7 @@ export class BST = BSTNode> * @returns The function `lesserOrGreaterTraverse` returns an array of `ReturnType>`. */ lesserOrGreaterTraverse>( - callback: C = ((node: N) => node.key) as C, + callback: C = this.defaultOneParamCallback as C, lesserOrGreater: CP = CP.lt, targetNode: BTNKey | N | null = this.root, iterationType = this.iterationType diff --git a/src/data-structures/binary-tree/tree-multiset.ts b/src/data-structures/binary-tree/tree-multiset.ts index 84e2b64..7be1720 100644 --- a/src/data-structures/binary-tree/tree-multiset.ts +++ b/src/data-structures/binary-tree/tree-multiset.ts @@ -268,7 +268,7 @@ export class TreeMultiset = TreeMultis * @param callback - The `callback` parameter is a function that takes a node as input and returns a * value. This value is compared with the `identifier` parameter to determine if the node should be * included in the result. The `callback` parameter has a default value of - * `((node: N) => node.key)` + * `this.defaultOneParamCallback` * @param [ignoreCount=false] - A boolean flag indicating whether to ignore the count of the node * being deleted. If set to true, the count of the node will not be considered and the node will be * deleted regardless of its count. If set to false (default), the count of the node will be @@ -277,7 +277,7 @@ export class TreeMultiset = TreeMultis */ override delete>( identifier: ReturnType, - callback: C = ((node: N) => node.key) as C, + callback: C = this.defaultOneParamCallback as C, ignoreCount = false ): BinaryTreeDeletedResult[] { const bstDeletedResult: BinaryTreeDeletedResult[] = []; diff --git a/test/unit/data-structures/graph/undirected-graph.test.ts b/test/unit/data-structures/graph/undirected-graph.test.ts index e8129cb..537cdb5 100644 --- a/test/unit/data-structures/graph/undirected-graph.test.ts +++ b/test/unit/data-structures/graph/undirected-graph.test.ts @@ -1,4 +1,6 @@ import {UndirectedEdge, UndirectedGraph, UndirectedVertex} from '../../../../src'; +import saltyVertexes from './SaltyGateStreetIntersections.json'; +import saltyEdges from './SaltyGateStreetConnections.json'; describe('UndirectedGraph Operation Test', () => { let graph: UndirectedGraph; @@ -146,4 +148,18 @@ describe('UndirectedGraph', () => { expect(degreeOfB).toBe(2); expect(degreeOfC).toBe(1); }); + + it('xxx', () => { + const start = performance.now(); + const graph = new UndirectedGraph<{ fromFeatureId: number; name: string; parentName: string; distanceFromParent: number; coordinates: number[]; }, number >() + for (const v of saltyVertexes) { + graph.addVertex(v.name, v); + } + for (const e of saltyEdges) { + const [s,d] = e; + graph.addEdge( s.name, d.name, d.distanceFromParent ); + } + const result = graph.getAllPathsBetween('Intersection_1','Intersection_5'); + console.log('---xxx', performance.now() - start, result) + }) }); diff --git a/tsconfig-base.json b/tsconfig-base.json index a10109a..47e809e 100644 --- a/tsconfig-base.json +++ b/tsconfig-base.json @@ -1,27 +1,23 @@ { "compilerOptions": { - "allowJs": true, - "allowSyntheticDefaultImports": true, - "baseUrl": "src", - "declaration": true, - "esModuleInterop": true, - "inlineSourceMap": false, - "lib": ["esnext"], - "listEmittedFiles": false, - "listFiles": false, - "moduleResolution": "node", - "noFallthroughCasesInSwitch": true, - "pretty": true, - "resolveJsonModule": true, - "rootDir": "src", - "skipLibCheck": true, - "strict": true, - "traceResolution": false, - "types": ["node", "jest"] + "allowJs": true, // Allow the compiler to compile JavaScript files (.js). + "allowSyntheticDefaultImports": true, // Allow synthetic default imports to improve module interoperability. + "baseUrl": "./", // Specify the base path of the root directory for module import. + "declaration": true, // Generate declaration files (.d.ts) for type checking and code hints. + "esModuleInterop": true, // Enable ECMAScript module interop for correct handling of CommonJS modules. + "inlineSourceMap": false, // Whether to map inline sources to compiled JavaScript files. + "lib": ["esnext"], // Specify the standard library version of the compilation target. + "listEmittedFiles": false, // List generated output files. + "listFiles": false, // List source files compiled by the compiler. + "noFallthroughCasesInSwitch": true, // Forced to check whether the case statement in the switch statement has the fallthrough mark. + "pretty": true, // Output a pretty error message. + "resolveJsonModule": true, // Enable parsing of the JSON module. + "rootDir": "./", // Specify the root directory of the source files in the project. + "skipLibCheck": true, // Skip type checking of type libraries. + "strict": true, // Enable strict type checking, including enabling all strict options. + "traceResolution": false, // Whether to trace the module resolution process. + "types": ["node", "jest"] // Specifies the name of the type declaration file to include. }, - "compileOnSave": false, - "exclude": ["node_modules", "dist"], - "include": [ - "./src/**/*.ts", // Include your .ts files - ] -} + "compileOnSave": false, // Whether to automatically compile when saving. + "exclude": ["node_modules", "dist"], // Specify files or directories that should not be included in the compilation. +} \ No newline at end of file diff --git a/tsconfig-cjs.json b/tsconfig-cjs.json index 9141737..8d735bd 100644 --- a/tsconfig-cjs.json +++ b/tsconfig-cjs.json @@ -2,8 +2,12 @@ "extends": "./tsconfig-base.json", "compilerOptions": { "module": "CommonJS", + "moduleResolution": "node", "outDir": "dist/cjs", "target": "ES2015", "sourceMap": true - } + }, + "include": [ + "./src/**/*.ts" + ] } diff --git a/tsconfig-mjs.json b/tsconfig-mjs.json new file mode 100644 index 0000000..ed6b9d9 --- /dev/null +++ b/tsconfig-mjs.json @@ -0,0 +1,12 @@ +{ + "extends": "./tsconfig-base.json", + "compilerOptions": { + "module": "NodeNext", + "moduleResolution": "NodeNext", + "outDir": "dist/mjs", + "target": "ESNext" + }, + "include": [ + "./src/**/*.ts" + ] +} diff --git a/tsconfig.json b/tsconfig.json index 65bb75a..bb1d7e1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,5 +5,9 @@ "moduleResolution": "NodeNext", "outDir": "dist/mjs", "target": "ESNext" - } + }, + "include": [ + "./src/**/*.ts", + "./test/**/*.ts" + ] }