docs: playground project added

This commit is contained in:
Revone 2024-11-30 21:50:45 +13:00
parent dd27393049
commit 116324610d
16 changed files with 480 additions and 279 deletions

View file

@ -1,6 +1,6 @@
src/types/data-structures/binary-tree/binary-tree.ts
src/types/data-structures/binary-tree/bst.ts
src/types/data-structures/binary-tree/avl-tree.ts
src/types/data-structures/binary-tree/rb-tree.ts
src/types/data-structures/binary-tree/red-black-tree.ts
src/types/data-structures/binary-tree/tree-multi-map.ts
src/types/data-structures/binary-tree/avl-tree-multi-map.ts

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.54.1](https://github.com/zrwusa/data-structure-typed/compare/v1.51.5...main) (upcoming)
## [v1.54.2](https://github.com/zrwusa/data-structure-typed/compare/v1.51.5...main) (upcoming)
### Changes

View file

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.

View file

@ -830,37 +830,28 @@ Version 11.7.9
***Our performance testing is conducted directly on the TypeScript source code. The actual performance of the compiled JavaScript code is generally 3 times higher. We have compared it with C++, and it is only 30% slower than C++.***
Try it [on gitpod](https://gitpod.io#snapshot/93383de4-ca4c-4854-8c80-4359e681a96f)
Just run
```shell
pnpm perf:rbtree
```
```html
1,000,000 add randomly: 1.367s
1,000,000 add: 374.859ms
1,000,000 get: 8.025ms
1,000,000 getNode: 1.293s
```
[//]: # (No deletion!!! Start of Replace Section)
<div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>heap</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr><tr><td>100,000 add</td><td>6.85</td><td>0.01</td><td>3.38e-4</td></tr><tr><td>100,000 add & poll</td><td>35.35</td><td>0.04</td><td>8.44e-4</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>avl-tree</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr><tr><td>100,000 add</td><td>302.89</td><td>0.30</td><td>0.01</td></tr><tr><td>100,000 add randomly</td><td>381.83</td><td>0.38</td><td>0.00</td></tr><tr><td>100,000 get</td><td>0.60</td><td>5.95e-4</td><td>2.33e-4</td></tr><tr><td>100,000 getNode</td><td>150.61</td><td>0.15</td><td>0.00</td></tr><tr><td>100,000 iterator</td><td>28.23</td><td>0.03</td><td>0.00</td></tr><tr><td>100,000 add & delete orderly</td><td>505.57</td><td>0.51</td><td>0.01</td></tr><tr><td>100,000 add & delete randomly</td><td>677.36</td><td>0.68</td><td>0.00</td></tr></table></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr><tr><td>100,000 add randomly</td><td>526.46</td><td>0.53</td><td>0.01</td></tr><tr><td>100,000 add</td><td>474.38</td><td>0.47</td><td>0.00</td></tr><tr><td>100,000 get</td><td>0.72</td><td>7.17e-4</td><td>3.47e-4</td></tr><tr><td>100,000 getNode</td><td>252.58</td><td>0.25</td><td>0.01</td></tr><tr><td>100,000 iterator</td><td>24.84</td><td>0.02</td><td>0.00</td></tr><tr><td>100,000 add & delete orderly</td><td>717.48</td><td>0.72</td><td>0.02</td></tr><tr><td>100,000 add & delete randomly</td><td>898.45</td><td>0.90</td><td>0.02</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>rb-tree</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr><tr><td>100,000 add</td><td>212.77</td><td>0.21</td><td>9.84e-4</td></tr><tr><td>100,000 add randomly</td><td>163.70</td><td>0.16</td><td>0.00</td></tr><tr><td>100,000 get</td><td>1.19</td><td>0.00</td><td>2.44e-4</td></tr><tr><td>100,000 getNode</td><td>347.39</td><td>0.35</td><td>0.01</td></tr><tr><td>100,000 node mode add randomly</td><td>162.26</td><td>0.16</td><td>0.00</td></tr><tr><td>100,000 node mode get</td><td>344.90</td><td>0.34</td><td>0.00</td></tr><tr><td>100,000 iterator</td><td>27.48</td><td>0.03</td><td>0.00</td></tr><tr><td>100,000 add & delete orderly</td><td>386.33</td><td>0.39</td><td>0.00</td></tr><tr><td>100,000 add & delete randomly</td><td>520.66</td><td>0.52</td><td>0.00</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>doubly-linked-list</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>179.28</td><td>0.18</td><td>0.02</td></tr><tr><td>1,000,000 unshift</td><td>197.22</td><td>0.20</td><td>0.05</td></tr><tr><td>1,000,000 unshift & shift</td><td>153.16</td><td>0.15</td><td>0.00</td></tr><tr><td>1,000,000 addBefore</td><td>247.30</td><td>0.25</td><td>0.03</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>directed-graph</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr><tr><td>1,000 addVertex</td><td>0.10</td><td>9.92e-5</td><td>1.16e-6</td></tr><tr><td>1,000 addEdge</td><td>6.44</td><td>0.01</td><td>0.00</td></tr><tr><td>1,000 getVertex</td><td>0.10</td><td>9.82e-5</td><td>1.13e-6</td></tr><tr><td>1,000 getEdge</td><td>22.60</td><td>0.02</td><td>0.00</td></tr><tr><td>tarjan</td><td>186.56</td><td>0.19</td><td>0.00</td></tr><tr><td>topologicalSort</td><td>145.42</td><td>0.15</td><td>0.01</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>queue</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>47.74</td><td>0.05</td><td>0.02</td></tr><tr><td>100,000 push & shift</td><td>5.39</td><td>0.01</td><td>1.25e-4</td></tr><tr><td>Native JS Array 100,000 push & shift</td><td>2225.50</td><td>2.23</td><td>0.10</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>deque</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>22.88</td><td>0.02</td><td>0.01</td></tr><tr><td>1,000,000 push & pop</td><td>27.95</td><td>0.03</td><td>0.01</td></tr><tr><td>1,000,000 push & shift</td><td>29.83</td><td>0.03</td><td>0.01</td></tr><tr><td>100,000 push & shift</td><td>2.71</td><td>0.00</td><td>9.03e-4</td></tr><tr><td>Native JS Array 100,000 push & shift</td><td>2182.03</td><td>2.18</td><td>0.04</td></tr><tr><td>100,000 unshift & shift</td><td>2.61</td><td>0.00</td><td>8.71e-4</td></tr><tr><td>Native JS Array 100,000 unshift & shift</td><td>4185.90</td><td>4.19</td><td>0.04</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>hash-map</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr><tr><td>1,000,000 set</td><td>253.45</td><td>0.25</td><td>0.07</td></tr><tr><td>Native JS Map 1,000,000 set</td><td>228.90</td><td>0.23</td><td>0.02</td></tr><tr><td>Native JS Set 1,000,000 add</td><td>179.65</td><td>0.18</td><td>0.01</td></tr><tr><td>1,000,000 set & get</td><td>234.96</td><td>0.23</td><td>0.06</td></tr><tr><td>Native JS Map 1,000,000 set & get</td><td>284.90</td><td>0.28</td><td>0.01</td></tr><tr><td>Native JS Set 1,000,000 add & has</td><td>254.90</td><td>0.25</td><td>0.03</td></tr><tr><td>1,000,000 ObjKey set & get</td><td>403.74</td><td>0.40</td><td>0.10</td></tr><tr><td>Native JS Map 1,000,000 ObjKey set & get</td><td>340.18</td><td>0.34</td><td>0.07</td></tr><tr><td>Native JS Set 1,000,000 ObjKey add & has</td><td>300.25</td><td>0.30</td><td>0.06</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>trie</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr><tr><td>100,000 push</td><td>44.11</td><td>0.04</td><td>8.55e-4</td></tr><tr><td>100,000 getWords</td><td>86.67</td><td>0.09</td><td>0.00</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>stack</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>43.18</td><td>0.04</td><td>0.01</td></tr><tr><td>1,000,000 push & pop</td><td>48.40</td><td>0.05</td><td>0.02</td></tr></table></div>
<div class='collapsible level0' ><span class='json-to-html-label'>red-black-tree</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr><tr><td>100,000 add randomly</td><td>144.49</td><td>0.14</td><td>0.01</td></tr><tr><td>100,000 add</td><td>190.53</td><td>0.19</td><td>0.00</td></tr><tr><td>100,000 get</td><td>0.91</td><td>9.14e-4</td><td>2.11e-4</td></tr><tr><td>100,000 getNode</td><td>323.66</td><td>0.32</td><td>0.00</td></tr><tr><td>100,000 node mode add randomly</td><td>139.71</td><td>0.14</td><td>0.00</td></tr><tr><td>100,000 node mode get</td><td>322.39</td><td>0.32</td><td>7.58e-4</td></tr><tr><td>100,000 iterator</td><td>27.07</td><td>0.03</td><td>0.00</td></tr><tr><td>100,000 add & delete orderly</td><td>349.17</td><td>0.35</td><td>0.00</td></tr><tr><td>100,000 add & delete randomly</td><td>482.61</td><td>0.48</td><td>0.01</td></tr></table></div>
</div>
[//]: # (No deletion!!! End of Replace Section)

View file

@ -1161,7 +1161,7 @@ avl2.print();
<div class='collapsible level0' ><span class='json-to-html-label'>bst</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 add randomly</td><td>55.04</td><td>18.17</td><td>0.01</td></tr><tr><td>10,000 add & delete randomly</td><td>129.85</td><td>7.70</td><td>0.01</td></tr><tr><td>10,000 addMany</td><td>50.40</td><td>19.84</td><td>0.01</td></tr><tr><td>10,000 get</td><td>63.39</td><td>15.78</td><td>0.01</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>rb-tree</span></div>
<div class='collapsible level0' ><span class='json-to-html-label'>red-black-tree</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 add</td><td>113.25</td><td>8.83</td><td>0.02</td></tr><tr><td>100,000 add & delete randomly</td><td>305.28</td><td>3.28</td><td>0.03</td></tr><tr><td>100,000 getNode</td><td>73.20</td><td>13.66</td><td>0.03</td></tr><tr><td>100,000 add & iterator</td><td>159.80</td><td>6.26</td><td>0.06</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>comparison</span></div>

20
package-lock.json generated
View file

@ -1,12 +1,12 @@
{
"name": "data-structure-typed",
"version": "1.54.1",
"version": "1.54.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "data-structure-typed",
"version": "1.54.1",
"version": "1.54.2",
"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.54.0",
"avl-tree-typed": "^1.54.1",
"benchmark": "^2.1.4",
"binary-tree-typed": "^1.54.0",
"bst-typed": "^1.54.0",
"data-structure-typed": "^1.54.0",
"binary-tree-typed": "^1.54.1",
"bst-typed": "^1.54.1",
"data-structure-typed": "^1.54.2",
"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.54.0",
"heap-typed": "^1.54.1",
"istanbul-badges-readme": "^1.9.0",
"jest": "^29.7.0",
"js-sdsl": "^4.4.2",
@ -4083,9 +4083,9 @@
}
},
"node_modules/data-structure-typed": {
"version": "1.54.1",
"resolved": "https://registry.npmjs.org/data-structure-typed/-/data-structure-typed-1.54.1.tgz",
"integrity": "sha512-N6KmfDASsj4rHQdAlO/1tRQdXZri9waQz/AAFJtd76dHx5lIie0ldK5R2Co+CqG2KHxGNf8M8HlQtNUXGgFGoQ==",
"version": "1.54.2",
"resolved": "https://registry.npmjs.org/data-structure-typed/-/data-structure-typed-1.54.2.tgz",
"integrity": "sha512-H4Ct6XqKsGk7O6/6mb9MHsZdrp5fAYHTgv2Tb+LrbTHnbenKu2ZfM0wP7fbrkhrRPzCFFvZKKDTfSatgykolmw==",
"dev": true,
"license": "MIT"
},

View file

@ -18,7 +18,7 @@
"gen:examples": "ts-node scripts/testToExample.ts",
"test:in-band": "jest --runInBand",
"test": "npm run test:in-band",
"test:integration": "npm run update:subs && jest --config jest.integration.config.js && tsc test/integration/compile.ts",
"test:integration": "npm run update:subs && jest --config jest.integration.config.js && tsc test/integration/compile.ts && node test/integration/compile.mjs",
"test:perf": "npm run build:cjs && npm run build:esm && ts-node test/performance/reportor.ts",
"check": "tsc --noEmit",
"check:circular-refs": "dependency-cruiser src",
@ -65,11 +65,11 @@
"@typescript-eslint/eslint-plugin": "^8.12.1",
"@typescript-eslint/parser": "^8.12.1",
"auto-changelog": "^2.5.0",
"avl-tree-typed": "^1.54.0",
"avl-tree-typed": "^1.54.1",
"benchmark": "^2.1.4",
"binary-tree-typed": "^1.54.0",
"bst-typed": "^1.54.0",
"data-structure-typed": "^1.54.0",
"binary-tree-typed": "^1.54.1",
"bst-typed": "^1.54.1",
"data-structure-typed": "^1.54.2",
"dependency-cruiser": "^16.5.0",
"doctoc": "^2.2.1",
"eslint": "^9.13.0",
@ -78,7 +78,7 @@
"eslint-import-resolver-typescript": "^3.6.3",
"eslint-plugin-import": "^2.31.0",
"fast-glob": "^3.3.2",
"heap-typed": "^1.54.0",
"heap-typed": "^1.54.1",
"istanbul-badges-readme": "^1.9.0",
"jest": "^29.7.0",
"js-sdsl": "^4.4.2",

View file

@ -1,8 +1,8 @@
/**
* data-structure-typed
*
* @author Tyler Zeng
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
* @author Pablo Zeng
* @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
* @license MIT License
*/
import type { Comparable, ComparablePrimitive, Thunk, ToThunkFn, TrlAsyncFn, TrlFn } from '../types';

View file

@ -13,28 +13,28 @@ const entries = [
[8, '8']
];
const queue = new Queue(orgArr);
queue.print();
// [6, 1, 2, 7, 5, 3, 4, 9, 8]
const deque = new Deque(orgArr);
deque.print();
// [6, 1, 2, 7, 5, 3, 4, 9, 8]
const sList = new SinglyLinkedList(orgArr);
sList.print();
// [6, 1, 2, 7, 5, 3, 4, 9, 8]
const dList = new DoublyLinkedList(orgArr);
dList.print();
// [6, 1, 2, 7, 5, 3, 4, 9, 8]
const stack = new Stack(orgArr);
stack.print();
// [6, 1, 2, 7, 5, 3, 4, 9, 8]
const minHeap = new MinHeap(orgArr);
minHeap.print();
// [1, 5, 2, 7, 6, 3, 4, 9, 8]
const maxPQ = new MaxPriorityQueue(orgArr);
maxPQ.print();
// [9, 8, 4, 7, 5, 2, 3, 1, 6]
const biTree = new BinaryTree(entries);
biTree.print();
// ___6___
// / \
// ___1_ _2_
@ -43,7 +43,7 @@ biTree.print();
// / \
// 9 8
const bst = new BST(entries);
bst.print();
// _____5___
// / \
// _2_ _7_
@ -52,7 +52,7 @@ bst.print();
// \ \
// 4 9
const rbTree = new RedBlackTree(entries);
rbTree.print();
// ___4___
// / \
// _2_ _6___
@ -61,7 +61,7 @@ rbTree.print();
// / \
// 7 9
const avl = new AVLTree(entries);
avl.print();
// ___4___
// / \
// _2_ _6___
@ -70,7 +70,7 @@ avl.print();
// / \
// 7 9
const treeMulti = new TreeMultiMap(entries);
treeMulti.print();
// ___4___
// / \
// _2_ _6___
@ -79,10 +79,10 @@ treeMulti.print();
// / \
// 7 9
const hm = new HashMap(entries);
hm.print();
// [[6, "6"], [1, "1"], [2, "2"], [7, "7"], [5, "5"], [3, "3"], [4, "4"], [9, "9"], [8, "8"]]
const rbTreeH = new RedBlackTree(hm);
rbTreeH.print();
// ___4___
// / \
// _2_ _6___
@ -91,10 +91,10 @@ rbTreeH.print();
// / \
// 7 9
const pq = new MinPriorityQueue(orgArr);
pq.print();
// [1, 5, 2, 7, 6, 3, 4, 9, 8]
const bst1 = new BST(pq);
bst1.print();
// _____5___
// / \
// _2_ _7_
@ -103,10 +103,10 @@ bst1.print();
// \ \
// 4 9
const dq1 = new Deque(orgArr);
dq1.print();
// [6, 1, 2, 7, 5, 3, 4, 9, 8]
const rbTree1 = new RedBlackTree(dq1);
rbTree1.print();
// _____5___
// / \
// _2___ _7___
@ -115,13 +115,13 @@ rbTree1.print();
// / /
// 3 8
const trie2 = new Trie(orgStrArr);
trie2.print();
// ['trie', 'trial', 'triangle', 'trick', 'trip', 'tree', 'trend', 'track', 'trace', 'transmit']
const heap2 = new Heap(trie2, { comparator: (a, b) => Number(a) - Number(b) });
heap2.print();
// ['transmit', 'trace', 'tree', 'trend', 'track', 'trial', 'trip', 'trie', 'trick', 'triangle']
const dq2 = new Deque(heap2);
dq2.print();
// ['transmit', 'trace', 'tree', 'trend', 'track', 'trial', 'trip', 'trie', 'trick', 'triangle']
const entries2 = dq2.map((el, i) => [i, el]);
const avl2 = new AVLTree(entries2);

View file

@ -1,45 +0,0 @@
import { AVLTree } from '../../../../';
import * as Benchmark from 'benchmark';
// import { getRandomIntArray, magnitude } from '../../../utils';
// const suite = new Benchmark.Suite();
// const avlTree = new AVLTree();
// const { HUNDRED_THOUSAND } = magnitude;
// const randomArray = getRandomIntArray(HUNDRED_THOUSAND, 0, HUNDRED_THOUSAND - 1, true);
// suite
// .add(`${HUNDRED_THOUSAND.toLocaleString()} add randomly`, () => {
// avlTree.clear();
// for (let i = 0; i < randomArray.length; i++)
// avlTree.add(randomArray[i]);
// })
// .add(`${HUNDRED_THOUSAND.toLocaleString()} add`, () => {
// avlTree.clear();
// for (let i = 0; i < randomArray.length; i++)
// avlTree.add(i);
// })
// .add(`${HUNDRED_THOUSAND.toLocaleString()} get`, () => {
// for (let i = 0; i < randomArray.length; i++)
// avlTree.get(randomArray[i]);
// })
// .add(`${HUNDRED_THOUSAND.toLocaleString()} getNode`, () => {
// for (let i = 0; i < randomArray.length; i++)
// avlTree.getNode(randomArray[i]);
// })
// .add(`${HUNDRED_THOUSAND.toLocaleString()} iterator`, () => {
// const entries = [...avlTree];
// return entries.length === HUNDRED_THOUSAND;
// })
// .add(`${HUNDRED_THOUSAND.toLocaleString()} add & delete orderly`, () => {
// avlTree.clear();
// for (let i = 0; i < randomArray.length; i++)
// avlTree.add(i);
// for (let i = 0; i < randomArray.length; i++)
// avlTree.delete(i);
// })
// .add(`${HUNDRED_THOUSAND.toLocaleString()} add & delete randomly`, () => {
// avlTree.clear();
// for (let i = 0; i < randomArray.length; i++)
// avlTree.add(randomArray[i]);
// for (let i = 0; i < randomArray.length; i++)
// avlTree.delete(randomArray[i]);
// });
// export { suite };

View file

@ -0,0 +1,71 @@
import { AVLTree } from 'data-structure-typed';
import Benchmark from 'benchmark';
const magnitude = {
THOUSAND: 1000,
TEN_THOUSAND: 10000,
HUNDRED_THOUSAND: 100000,
MILLION: 1000000,
TEN_MILLION: 10000000,
BILLION: 100000000
};
function getRandomIntArray(length = 1000, min = -1000, max = 1000, unique = true) {
if (unique) {
if (max - min + 1 < length) {
throw new Error('Range too small for unique values with the specified length');
}
const allNumbers = Array.from({ length: max - min + 1 }, (_, i) => i + min);
for (let i = allNumbers.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[allNumbers[i], allNumbers[j]] = [allNumbers[j], allNumbers[i]];
}
return allNumbers.slice(0, length);
}
else {
return Array.from({ length }, () => Math.floor(Math.random() * (max - min + 1)) + min);
}
}
const suite = new Benchmark.Suite();
const avlTree = new AVLTree();
const { HUNDRED_THOUSAND } = magnitude;
const randomArray = getRandomIntArray(HUNDRED_THOUSAND, 0, HUNDRED_THOUSAND - 1, true);
suite
.add(`${HUNDRED_THOUSAND.toLocaleString()} add randomly`, () => {
avlTree.clear();
for (let i = 0; i < randomArray.length; i++)
avlTree.add(randomArray[i]);
})
.add(`${HUNDRED_THOUSAND.toLocaleString()} add`, () => {
avlTree.clear();
for (let i = 0; i < randomArray.length; i++)
avlTree.add(i);
})
.add(`${HUNDRED_THOUSAND.toLocaleString()} get`, () => {
for (let i = 0; i < randomArray.length; i++)
avlTree.get(randomArray[i]);
})
.add(`${HUNDRED_THOUSAND.toLocaleString()} getNode`, () => {
for (let i = 0; i < randomArray.length; i++)
avlTree.getNode(randomArray[i]);
})
.add(`${HUNDRED_THOUSAND.toLocaleString()} iterator`, () => {
const entries = [...avlTree];
return entries.length === HUNDRED_THOUSAND;
})
.add(`${HUNDRED_THOUSAND.toLocaleString()} add & delete orderly`, () => {
avlTree.clear();
for (let i = 0; i < randomArray.length; i++)
avlTree.add(i);
for (let i = 0; i < randomArray.length; i++)
avlTree.delete(i);
})
.add(`${HUNDRED_THOUSAND.toLocaleString()} add & delete randomly`, () => {
avlTree.clear();
for (let i = 0; i < randomArray.length; i++)
avlTree.add(randomArray[i]);
for (let i = 0; i < randomArray.length; i++)
avlTree.delete(randomArray[i]);
});
export { suite };

View file

@ -0,0 +1,81 @@
import { RedBlackTree } from 'data-structure-typed';
import Benchmark from 'benchmark';
const magnitude = {
THOUSAND: 1000,
TEN_THOUSAND: 10000,
HUNDRED_THOUSAND: 100000,
MILLION: 1000000,
TEN_MILLION: 10000000,
BILLION: 100000000
};
function getRandomIntArray(length = 1000, min = -1000, max = 1000, unique = true) {
if (unique) {
if (max - min + 1 < length) {
throw new Error('Range too small for unique values with the specified length');
}
const allNumbers = Array.from({ length: max - min + 1 }, (_, i) => i + min);
for (let i = allNumbers.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[allNumbers[i], allNumbers[j]] = [allNumbers[j], allNumbers[i]];
}
return allNumbers.slice(0, length);
}
else {
return Array.from({ length }, () => Math.floor(Math.random() * (max - min + 1)) + min);
}
}
const suite = new Benchmark.Suite();
const rbTree = new RedBlackTree();
const rbTreeNodeMode = new RedBlackTree([], { isMapMode: false });
const { HUNDRED_THOUSAND } = magnitude;
const randomArray = getRandomIntArray(HUNDRED_THOUSAND, 0, HUNDRED_THOUSAND - 1, true);
suite
.add(`${HUNDRED_THOUSAND.toLocaleString()} add randomly`, () => {
rbTree.clear();
for (let i = 0; i < randomArray.length; i++)
rbTree.add(randomArray[i]);
})
.add(`${HUNDRED_THOUSAND.toLocaleString()} add`, () => {
rbTree.clear();
for (let i = 0; i < randomArray.length; i++)
rbTree.add(i);
})
.add(`${HUNDRED_THOUSAND.toLocaleString()} get`, () => {
for (let i = 0; i < randomArray.length; i++)
rbTree.get(randomArray[i]);
})
.add(`${HUNDRED_THOUSAND.toLocaleString()} getNode`, () => {
for (let i = 0; i < randomArray.length; i++)
rbTree.getNode(randomArray[i]);
})
.add(`${HUNDRED_THOUSAND.toLocaleString()} node mode add randomly`, () => {
rbTreeNodeMode.clear();
for (let i = 0; i < randomArray.length; i++)
rbTreeNodeMode.add(randomArray[i]);
})
.add(`${HUNDRED_THOUSAND.toLocaleString()} node mode get`, () => {
for (let i = 0; i < randomArray.length; i++)
rbTreeNodeMode.get(randomArray[i]);
})
.add(`${HUNDRED_THOUSAND.toLocaleString()} iterator`, () => {
const entries = [...rbTree];
return entries.length === HUNDRED_THOUSAND;
})
.add(`${HUNDRED_THOUSAND.toLocaleString()} add & delete orderly`, () => {
rbTree.clear();
for (let i = 0; i < randomArray.length; i++)
rbTree.add(i);
for (let i = 0; i < randomArray.length; i++)
rbTree.delete(i);
})
.add(`${HUNDRED_THOUSAND.toLocaleString()} add & delete randomly`, () => {
rbTree.clear();
for (let i = 0; i < randomArray.length; i++)
rbTree.add(randomArray[i]);
for (let i = 0; i < randomArray.length; i++)
rbTree.delete(randomArray[i]);
});
export { suite };

View file

@ -1,14 +1,268 @@
import * as path from 'path';
import * as fs from 'fs';
import * as fastGlob from 'fast-glob';
import { ConsoleColor, numberFix, render } from '../utils';
import fastGlob from 'fast-glob';
import { fileURLToPath } from 'url';
const isNumber = (value) => {
return typeof value === 'number';
};
const isString = (value) => {
return typeof value === 'string';
};
const isBoolean = (value) => {
return typeof value === 'boolean';
};
const isDate = (value) => {
return value instanceof Date;
};
const isNull = (value) => {
return value === null;
};
const isUndefined = (value) => {
return typeof value === 'undefined';
};
const isFunction = (value) => {
return typeof value === 'function';
};
const isObject = (value) => {
return typeof value === 'object';
};
const isArray = (value) => {
return Array.isArray(value);
};
const isEqual = (objA, objB) => {
if (objA === objB) {
return true;
}
if (typeof objA !== 'object' || typeof objB !== 'object' || objA === null || objB === null) {
return false;
}
const keysA = Object.keys(objA);
const keysB = Object.keys(objB);
if (keysA.length !== keysB.length) {
return false;
}
for (const key of keysA) {
if (!keysB.includes(key)) {
return false;
}
if (!isEqual(objA[key], objB[key])) {
return false;
}
}
return true;
};
function toggleJS(options) {
if (options === null || options === void 0 ? void 0 : options.plainHtml) {
return '';
}
else {
return 'onclick="json-to-html.toggleVisibility(this);return false"';
}
}
function makeLabelDiv(options, level, keyName, datatype) {
if (typeof keyName === 'number') {
return `<div class='index'><span class='json-to-html-label'>${keyName}&nbsp;</span></div>`;
}
else if (typeof keyName === 'string') {
if (datatype === 'array') {
return `<div class='collapsible level${level}' ${toggleJS(options)}><span class='json-to-html-label'>${keyName}</span></div>`;
}
else if (datatype === 'object') {
return `<div class='attribute collapsible level${level}' ${toggleJS(options)}><span class='json-to-html-label'>${keyName}:</span></div>`;
}
else {
return `<div class='leaf level${level}'><span class='json-to-html-label'>${keyName}:</span></div>`;
}
}
else {
return '';
}
}
function getContentClass(keyName) {
if (typeof keyName === 'string') {
return 'content';
}
else {
return '';
}
}
function isPlainObject(val) {
let lastKey;
let lastOwnKey;
for (const key in val) {
if (val.hasOwnProperty(key)) {
lastOwnKey = key;
}
}
for (const key in val) {
lastKey = key;
}
return lastOwnKey === lastKey;
}
function isLeafValue(val) {
return (isNumber(val) ||
isString(val) ||
isBoolean(val) ||
isDate(val) ||
isNull(val) ||
isUndefined(val) ||
isNaN(val) ||
isFunction(val) ||
!isPlainObject(val));
}
function isLeafObject(obj) {
if (!isObject(obj)) {
return false;
}
for (const key in obj) {
const val = obj[key];
if (!isLeafValue(val)) {
return false;
}
}
return true;
}
function isTable(arr) {
if (!isArray(arr)) {
return false;
}
if (arr.length === 0 || !isObject(arr[0])) {
return false;
}
else {
let nonCompliant = arr.find(row => !isLeafObject(row));
if (nonCompliant) {
return false;
}
else {
const cols = Object.keys(arr[0]);
nonCompliant = arr.find((row) => !isEqual(cols, Object.keys(row)));
return !nonCompliant;
}
}
}
function drawTable(arr) {
function drawRow(headers, rowObj) {
return '<td>' + headers.map(header => rowObj[header]).join('</td><td>') + '</td>';
}
const cols = Object.keys(arr[0]);
const content = arr.map(rowObj => drawRow(cols, rowObj));
const headingHtml = '<tr><th>' + cols.join('</th><th>') + '</th></tr>';
const contentHtml = '<tr>' + content.join('</tr><tr>') + '</tr>';
return '<table style="display: table; width:100%; table-layout: fixed;">' + headingHtml + contentHtml + '</table>';
}
function _render(name, data, options, level, altRow) {
const contentClass = getContentClass(name);
if (isArray(data)) {
const title = makeLabelDiv(options, level, `${name}`, 'array');
let subs;
if (isTable(data)) {
subs = drawTable(data);
}
else {
subs =
"<div class='altRows'>" +
data
.map((val, idx) => _render(idx.toString(), val, options, level + 1, idx % 2))
.join("</div><div class='altRows'>") +
'</div>';
}
return `<div class="json-to-html-collapse clearfix ${altRow}">
${title}
<div class="${contentClass}">${subs}</div>
</div>`;
}
else if (isLeafValue(data)) {
const title = makeLabelDiv(options, level, name);
if (isFunction(data)) {
return `${title}<span class='json-to-html-value'>&nbsp;&nbsp;-function() can't _render-</span>`;
}
else if (!isPlainObject(data)) {
if (isFunction(data.toString)) {
return `${title}<span class='json-to-html-value'>&nbsp;&nbsp;${data.toString()}</span>`;
}
else {
return `${title}<span class='json-to-html-value'>&nbsp;&nbsp;-instance object, can't render-</span>`;
}
}
else {
return `${title}<span class='json-to-html-value'>&nbsp;&nbsp;${data}</span>`;
}
}
else {
const title = makeLabelDiv(options, level, name, 'object');
let count = 0;
const subs = '<div>' +
Object.entries(data)
.map(([key, val]) => _render(key, val, options, level + 1, count++ % 2))
.join('</div><div>') +
'</div>';
const inner = `<div class="json-to-html-expand clearfix ${altRow}">
${title}
<div class="${contentClass}">${subs}</div>
</div>`;
return `${level === 0 ? "<div id='json-to-html'>" : ''}
${inner}
${level === 0 ? '</div>' : ''}`;
}
}
export function render(name, json, options) {
return `${_render(name, json, options, 0, 0)}`;
}
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
function numberFix(num, decimalPlaces) {
if (num > 10000 || num < 0.001) {
const [mantissa, exponent] = num.toExponential().split('e');
const formattedMantissa = Number(mantissa).toFixed(decimalPlaces);
return `${formattedMantissa}e${exponent}`;
} else {
return num.toFixed(decimalPlaces);
}
}
const ConsoleColor = {
END: '\x1b[0m',
BOLD: '\x1b[1m',
DIM: '\x1b[2m',
ITALIC: '\x1b[3m',
UNDERLINE: '\x1b[4m',
INVERSE: '\x1b[7m',
STRIKETHROUGH: '\x1b[9m',
NO_BOLD: '\x1b[22m',
NO_ITALIC: '\x1b[23m',
NO_UNDERLINE: '\x1b[24m',
NO_INVERSE: '\x1b[27m',
NO_STRIKETHROUGH: '\x1b[29m',
BLACK: '\x1b[30m',
RED: '\x1b[31m',
GREEN: '\x1b[32m',
YELLOW: '\x1b[33m',
BLUE: '\x1b[34m',
MAGENTA: '\x1b[35m',
GRAY: '\x1b[90m',
CYAN: '\x1b[36m',
WHITE: '\x1b[37m',
BG_BLACK: '\x1b[40m',
BG_RED: '\x1b[41m',
BG_GREEN: '\x1b[42m',
BG_YELLOW: '\x1b[43m',
BG_BLUE: '\x1b[44m',
BG_MAGENTA: '\x1b[45m',
BG_CYAN: '\x1b[46m',
BG_WHITE: '\x1b[47m'
};
const args = process.argv.slice(2);
const { GREEN, BOLD, END, YELLOW, GRAY, CYAN, BG_YELLOW } = ConsoleColor;
const isOnlyOrdered = true;
const runOrder = [
'heap',
'avl-tree',
'rb-tree',
'red-black-tree',
'doubly-linked-list',
'directed-graph',
'queue',
@ -24,6 +278,7 @@ const getRelativePath = file => {
return path.relative(__dirname, file);
};
const coloredLabeled = (label, file) => {
const relativeFilePath = getRelativePath(file);
const directory = path.dirname(relativeFilePath);
const fileName = path.basename(relativeFilePath);
@ -32,7 +287,8 @@ const coloredLabeled = (label, file) => {
const parentDirectory = path.resolve(__dirname, '../..');
const reportDistPath = path.join(parentDirectory, 'benchmark');
const testDir = path.join(__dirname, 'data-structures');
const allFiles = fastGlob.sync(path.join(testDir, '**', '*.test.js'));
let allFiles = fastGlob.sync(path.join(testDir, '**', '*.test.mjs'));
let testFiles;
let isIndividual = false;
if (args.length > 0) {
@ -50,9 +306,9 @@ if (args.length > 0) {
const report = {};
let completedCount = 0;
const performanceTests = [];
testFiles.forEach(file => {
const testName = path.basename(file, '.test.ts');
const testFunction = require(file);
for (const file of testFiles) {
const testName = path.basename(file, '.test.mjs');
const testFunction = await import(file);
const { suite } = testFunction;
if (suite)
performanceTests.push({
@ -60,7 +316,8 @@ testFiles.forEach(file => {
suite,
file
});
});
}
const composeReport = () => {
if (!fs.existsSync(reportDistPath))
fs.mkdirSync(reportDistPath, {

View file

@ -12,7 +12,7 @@ const isOnlyOrdered = true;
const runOrder = [
'heap',
'avl-tree',
'rb-tree',
'red-black-tree',
'doubly-linked-list',
'directed-graph',
'queue',

View file

@ -160,159 +160,5 @@ function _render(name: string, data: any, options: Json2htmlOptions, level: numb
}
export function render(name: string, json: any, options: Json2htmlOptions): string {
// return `${head}${_render('', json, options, 0, 0)}`;
return `${_render(name, json, options, 0, 0)}`;
}
// const head = `<style>
// #json-to-html table {
// border-collapse: collapse;
// }
// #json-to-html th {
// color: #888;
// }
// #json-to-html table,th, td {
// border: 1px solid #DDD;
// padding: 10px 5px;
// }
// #json-to-html th, td {
// text-align: center;
// }
// #json-to-html .content {
// padding-left: 30px;
// font-family: Arial;
// }
//
// #json-to-html .index {
// font-size: 100%;
// color: #999;
// float: left;
// }
// #json-to-html .clearfix:after {
// content: ".";
// display: block;
// height: 0;
// clear: both;
// visibility: hidden;
// }
// #json-to-html .json-to-html-label {
// font-family: Helvetica Neue;
// color: #333;
// }
// #json-to-html .json-to-html-value {
// font-family: Arial;
// color: #777;
// }
// #json-to-html .collapsible > .json-to-html-label:hover {
// text-decoration: underline;
// }
// #json-to-html .collapsible > .json-to-html-label {
// color: #15C;
// }
// #json-to-html .json-to-html-collapse > div.content {
// display: none;
// }
// #json-to-html .json-to-html-collapse > .json-to-html-label {
// font-weight: bold;
// }
//
// #json-to-html .json-to-html-expand > div > .json-to-html-label, #json-to-html .json-to-html-collapse > div > .json-to-html-label {
// background-repeat: no-repeat;
// background-position: left;
// padding-left: 25px;
// margin: 5px 0px 5px 15px;
// display: inline-block;
// }
//
// #json-to-html .json-to-html-expand > div > .json-to-html-label {
// width: 30px;
// height: 30px;
// background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"><polygon points="50,10 10,90 90,90" fill="blue" /></svg>');
// background-size: cover;
// background-position: center;
// }
//
// #json-to-html .json-to-html-collapse > div > .json-to-html-label {
// width: 30px;
// height: 30px;
// background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"><polygon points="50,10 10,90 90,90" fill="blue" /></svg>');
// background-size: cover;
// background-position: center;
// }
//
// #json-to-html .json-to-html-collapse > span.collapsible:before {
// border-radius: 2px;
// border-color: #A44;
// border-style: solid;
// border-width: 1px;
// color: #A44;
// content: '+';
// display: inline-block;
// line-height: 7px;
// margin: 0 2px;
// overflow: hidden;
// padding: 1px;
// font-size: 11px;
// }
//
// #json-to-html .json-to-html-expand > span.collapsible:before {
// border: none;
// color: #A44;
// content: '-';
// display: inline-block;
// line-height: 7px;
// margin: 4px;
// overflow: hidden;
// padding: 1px;
// font-size: 11px;
// }
//
// #json-to-html.level0 {
// font-size: 25px;
// }
// #json-to-html .level1 {
// font-size: 22px;
// }
//
// #json-to-html .leaf {
// color: #666;
// display: inline;
// }
//
// #json-to-html .altRows:nth-child(odd) { background-color:#ddd; }
// #json-to-html .altRows:nth-child(even) { background-color:#fff; }
//
// #json-to-html tr:nth-child(odd) { background-color:#eee; }
// #json-to-html tr:nth-child(even) { background-color:#fff; }
// </style>
// <script type="text/javascript">
// json-to-html = {
// toggleVisibility: function(el, name) {
// json-to-html.toggleClass(el.parentElement,'json-to-html-collapse json-to-html-expand');
// },
// classRe: function(name) {
// return new RegExp('(?:^|\\s)'+name+'(?!\\S)');
// },
// addClass: function(el, name) {
// el.className += " "+name;
// },
// removeClass: function(el, name) {
// var re = json-to-html.classRe(name);
// el.className = el.className.replace(json-to-html.classRe(name) , '' )
// },
// hasClass: function(el, name) {
// var re = json-to-html.classRe(name);
// return json-to-html.classRe(name).exec(el.className);
// },
// toggleClass: function(el, name) {
// var names = name.split(/\s+/);
// for (n in names) {
// if (json-to-html.hasClass(el, names[n])) {
// json-to-html.removeClass(el, names[n]);
// } else {
// json-to-html.addClass(el, names[n]);
// }
// }
// }
// };
// </script>`;