refactor: Test coverage increased to 95.63%.

Upgraded all dependencies.
Added a toVisual method while retaining the print method.
Replaced all short-circuit evaluations with logical expressions.
This commit is contained in:
Revone 2024-10-30 15:30:28 +13:00
parent aece11bd01
commit fc0d157295
37 changed files with 2448 additions and 3030 deletions

View file

@ -1,64 +0,0 @@
module.exports = {
"parser": "@typescript-eslint/parser",
"plugins": [
"@typescript-eslint",
"eslint-plugin-import"
],
"extends": [
"plugin:@typescript-eslint/recommended",
"prettier"
],
"ignorePatterns": ["lib/", "dist/", "umd/", "coverage/", "docs/"],
"rules": {
"import/no-anonymous-default-export": "off",
"@typescript-eslint/no-unused-vars": "warn",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-var-requires": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"lines-around-comment": [
"warn",
{
"beforeLineComment": false,
"beforeBlockComment": true,
"allowBlockStart": true,
"allowClassStart": true,
"allowObjectStart": true,
"allowArrayStart": true
}
],
"newline-before-return": "off",
"import/newline-after-import": [
"warn",
{
"count": 1
}
],
"@typescript-eslint/ban-types": [
"error",
{
"extendDefaults": true,
"types": {
"{}": false
}
}
],
// "brace-style": ["error", "1tbs", { "allowSingleLine": true }],
"object-curly-spacing": ["warn", "always"]
},
"settings": {
"import/parsers": {
"@typescript-eslint/parser": [
".ts"
]
},
"import/resolver": {
"typescript": {
"alwaysTryTypes": true,
"project": [
"./tsconfig.json"
]
}
}
}
}

View file

@ -823,43 +823,43 @@ Version 11.7.9
[//]: # (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>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 add</td><td>7.51</td><td>133.17</td><td>1.36e-4</td></tr><tr><td>100,000 add & poll</td><td>44.25</td><td>22.60</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>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 add</td><td>6.56</td><td>152.37</td><td>1.86e-4</td></tr><tr><td>100,000 add & poll</td><td>35.15</td><td>28.45</td><td>7.98e-4</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>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 add</td><td>76.98</td><td>12.99</td><td>0.00</td></tr><tr><td>100,000 add randomly</td><td>80.96</td><td>12.35</td><td>0.00</td></tr><tr><td>100,000 get</td><td>111.72</td><td>8.95</td><td>0.00</td></tr><tr><td>100,000 iterator</td><td>29.58</td><td>33.81</td><td>0.00</td></tr><tr><td>100,000 add & delete orderly</td><td>153.21</td><td>6.53</td><td>0.00</td></tr><tr><td>100,000 add & delete randomly</td><td>233.26</td><td>4.29</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>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 add</td><td>83.54</td><td>11.97</td><td>8.43e-4</td></tr><tr><td>100,000 add randomly</td><td>85.53</td><td>11.69</td><td>0.00</td></tr><tr><td>100,000 get</td><td>115.17</td><td>8.68</td><td>0.00</td></tr><tr><td>100,000 iterator</td><td>30.20</td><td>33.11</td><td>0.00</td></tr><tr><td>100,000 add & delete orderly</td><td>151.05</td><td>6.62</td><td>0.00</td></tr><tr><td>100,000 add & delete randomly</td><td>239.32</td><td>4.18</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>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>42.18</td><td>23.71</td><td>0.01</td></tr><tr><td>100,000 push & shift</td><td>5.16</td><td>193.66</td><td>7.47e-4</td></tr><tr><td>Native JS Array 100,000 push & shift</td><td>2386.29</td><td>0.42</td><td>0.30</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>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>44.31</td><td>22.57</td><td>0.01</td></tr><tr><td>100,000 push & shift</td><td>5.50</td><td>181.72</td><td>0.00</td></tr><tr><td>Native JS Array 100,000 push & shift</td><td>2451.35</td><td>0.41</td><td>0.39</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>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>23.59</td><td>42.40</td><td>0.00</td></tr><tr><td>1,000,000 push & pop</td><td>31.93</td><td>31.32</td><td>0.00</td></tr><tr><td>1,000,000 push & shift</td><td>33.12</td><td>30.19</td><td>0.00</td></tr><tr><td>100,000 push & shift</td><td>3.50</td><td>285.57</td><td>9.51e-4</td></tr><tr><td>Native JS Array 100,000 push & shift</td><td>2211.26</td><td>0.45</td><td>0.34</td></tr><tr><td>100,000 unshift & shift</td><td>3.41</td><td>292.89</td><td>5.52e-4</td></tr><tr><td>Native JS Array 100,000 unshift & shift</td><td>4343.81</td><td>0.23</td><td>0.25</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>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>20.56</td><td>48.65</td><td>0.00</td></tr><tr><td>1,000,000 push & pop</td><td>25.77</td><td>38.81</td><td>0.00</td></tr><tr><td>1,000,000 push & shift</td><td>26.35</td><td>37.95</td><td>0.00</td></tr><tr><td>100,000 push & shift</td><td>2.54</td><td>394.25</td><td>4.24e-4</td></tr><tr><td>Native JS Array 100,000 push & shift</td><td>2109.72</td><td>0.47</td><td>0.12</td></tr><tr><td>100,000 unshift & shift</td><td>2.43</td><td>411.24</td><td>3.06e-4</td></tr><tr><td>Native JS Array 100,000 unshift & shift</td><td>4275.22</td><td>0.23</td><td>0.35</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>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 set</td><td>259.74</td><td>3.85</td><td>0.07</td></tr><tr><td>Native JS Map 1,000,000 set</td><td>208.35</td><td>4.80</td><td>0.02</td></tr><tr><td>Native JS Set 1,000,000 add</td><td>167.66</td><td>5.96</td><td>0.01</td></tr><tr><td>1,000,000 set & get</td><td>260.46</td><td>3.84</td><td>0.04</td></tr><tr><td>Native JS Map 1,000,000 set & get</td><td>265.09</td><td>3.77</td><td>0.02</td></tr><tr><td>Native JS Set 1,000,000 add & has</td><td>169.15</td><td>5.91</td><td>0.01</td></tr><tr><td>1,000,000 ObjKey set & get</td><td>317.23</td><td>3.15</td><td>0.04</td></tr><tr><td>Native JS Map 1,000,000 ObjKey set & get</td><td>304.84</td><td>3.28</td><td>0.04</td></tr><tr><td>Native JS Set 1,000,000 ObjKey add & has</td><td>278.30</td><td>3.59</td><td>0.05</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>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 set</td><td>85.09</td><td>11.75</td><td>0.02</td></tr><tr><td>Native JS Map 1,000,000 set</td><td>211.60</td><td>4.73</td><td>0.03</td></tr><tr><td>Native JS Set 1,000,000 add</td><td>165.56</td><td>6.04</td><td>0.01</td></tr><tr><td>1,000,000 set & get</td><td>78.93</td><td>12.67</td><td>0.02</td></tr><tr><td>Native JS Map 1,000,000 set & get</td><td>273.56</td><td>3.66</td><td>0.00</td></tr><tr><td>Native JS Set 1,000,000 add & has</td><td>241.87</td><td>4.13</td><td>0.03</td></tr><tr><td>1,000,000 ObjKey set & get</td><td>339.57</td><td>2.94</td><td>0.04</td></tr><tr><td>Native JS Map 1,000,000 ObjKey set & get</td><td>294.22</td><td>3.40</td><td>0.02</td></tr><tr><td>Native JS Set 1,000,000 ObjKey add & has</td><td>268.41</td><td>3.73</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'>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>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 push</td><td>43.93</td><td>22.76</td><td>5.95e-4</td></tr><tr><td>100,000 getWords</td><td>82.18</td><td>12.17</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>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 push</td><td>43.89</td><td>22.78</td><td>8.04e-4</td></tr><tr><td>100,000 getWords</td><td>82.90</td><td>12.06</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'>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>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 add</td><td>275.72</td><td>3.63</td><td>0.00</td></tr><tr><td>100,000 add randomly</td><td>332.35</td><td>3.01</td><td>0.00</td></tr><tr><td>100,000 get</td><td>129.56</td><td>7.72</td><td>0.00</td></tr><tr><td>100,000 iterator</td><td>32.03</td><td>31.22</td><td>0.01</td></tr><tr><td>100,000 add & delete orderly</td><td>447.87</td><td>2.23</td><td>0.00</td></tr><tr><td>100,000 add & delete randomly</td><td>605.40</td><td>1.65</td><td>0.03</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>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 add</td><td>281.55</td><td>3.55</td><td>0.00</td></tr><tr><td>100,000 add randomly</td><td>353.66</td><td>2.83</td><td>0.02</td></tr><tr><td>100,000 get</td><td>150.33</td><td>6.65</td><td>0.01</td></tr><tr><td>100,000 iterator</td><td>33.26</td><td>30.07</td><td>0.01</td></tr><tr><td>100,000 add & delete orderly</td><td>465.24</td><td>2.15</td><td>0.00</td></tr><tr><td>100,000 add & delete randomly</td><td>634.77</td><td>1.58</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'>binary-tree-overall</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 RBTree add randomly</td><td>6.91</td><td>144.82</td><td>1.13e-4</td></tr><tr><td>10,000 RBTree get randomly</td><td>9.08</td><td>110.14</td><td>7.72e-5</td></tr><tr><td>10,000 RBTree add & delete randomly</td><td>18.97</td><td>52.71</td><td>8.49e-4</td></tr><tr><td>10,000 AVLTree add randomly</td><td>24.97</td><td>40.05</td><td>4.34e-4</td></tr><tr><td>10,000 AVLTree get randomly</td><td>9.95</td><td>100.47</td><td>0.00</td></tr><tr><td>10,000 AVLTree add & delete randomly</td><td>45.96</td><td>21.76</td><td>5.77e-4</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>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 RBTree add randomly</td><td>7.62</td><td>131.29</td><td>8.51e-5</td></tr><tr><td>10,000 RBTree get randomly</td><td>10.50</td><td>95.20</td><td>5.32e-5</td></tr><tr><td>10,000 RBTree add & delete randomly</td><td>20.69</td><td>48.33</td><td>1.32e-4</td></tr><tr><td>10,000 AVLTree add randomly</td><td>25.68</td><td>38.94</td><td>2.47e-4</td></tr><tr><td>10,000 AVLTree get randomly</td><td>10.95</td><td>91.29</td><td>6.68e-5</td></tr><tr><td>10,000 AVLTree add & delete randomly</td><td>48.33</td><td>20.69</td><td>3.14e-4</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>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000 addVertex</td><td>0.10</td><td>9730.42</td><td>1.39e-6</td></tr><tr><td>1,000 addEdge</td><td>6.01</td><td>166.32</td><td>9.47e-5</td></tr><tr><td>1,000 getVertex</td><td>0.04</td><td>2.59e+4</td><td>3.52e-7</td></tr><tr><td>1,000 getEdge</td><td>23.80</td><td>42.03</td><td>0.00</td></tr><tr><td>tarjan</td><td>215.66</td><td>4.64</td><td>0.01</td></tr><tr><td>topologicalSort</td><td>187.85</td><td>5.32</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>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000 addVertex</td><td>0.10</td><td>1.03e+4</td><td>1.01e-6</td></tr><tr><td>1,000 addEdge</td><td>5.95</td><td>168.01</td><td>1.05e-4</td></tr><tr><td>1,000 getVertex</td><td>0.10</td><td>1.05e+4</td><td>1.10e-6</td></tr><tr><td>1,000 getEdge</td><td>23.44</td><td>42.67</td><td>0.00</td></tr><tr><td>tarjan</td><td>194.66</td><td>5.14</td><td>0.00</td></tr><tr><td>topologicalSort</td><td>151.88</td><td>6.58</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'>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>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>197.45</td><td>5.06</td><td>0.03</td></tr><tr><td>1,000,000 unshift</td><td>214.02</td><td>4.67</td><td>0.08</td></tr><tr><td>1,000,000 unshift & shift</td><td>198.97</td><td>5.03</td><td>0.05</td></tr><tr><td>1,000,000 addBefore</td><td>315.44</td><td>3.17</td><td>0.05</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>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>191.43</td><td>5.22</td><td>0.04</td></tr><tr><td>1,000,000 unshift</td><td>171.35</td><td>5.84</td><td>0.01</td></tr><tr><td>1,000,000 unshift & shift</td><td>151.25</td><td>6.61</td><td>0.00</td></tr><tr><td>1,000,000 addBefore</td><td>264.87</td><td>3.78</td><td>0.07</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>singly-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>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push & shift</td><td>196.91</td><td>5.08</td><td>0.04</td></tr><tr><td>10,000 push & pop</td><td>222.29</td><td>4.50</td><td>0.01</td></tr><tr><td>10,000 addBefore</td><td>248.87</td><td>4.02</td><td>0.01</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>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push & shift</td><td>173.29</td><td>5.77</td><td>0.05</td></tr><tr><td>10,000 push & pop</td><td>235.53</td><td>4.25</td><td>0.01</td></tr><tr><td>10,000 addBefore</td><td>278.19</td><td>3.59</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'>priority-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>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 add</td><td>27.69</td><td>36.11</td><td>8.96e-4</td></tr><tr><td>100,000 add & poll</td><td>75.38</td><td>13.27</td><td>6.45e-4</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>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 add</td><td>30.64</td><td>32.64</td><td>0.00</td></tr><tr><td>100,000 add & poll</td><td>89.25</td><td>11.20</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>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>39.19</td><td>25.52</td><td>0.00</td></tr><tr><td>1,000,000 push & pop</td><td>45.24</td><td>22.10</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>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>40.92</td><td>24.44</td><td>0.00</td></tr><tr><td>1,000,000 push & pop</td><td>46.83</td><td>21.35</td><td>0.01</td></tr></table></div>
</div>
[//]: # (No deletion!!! End of Replace Section)

69
eslint.config.mjs Normal file
View file

@ -0,0 +1,69 @@
import typescriptEslint from "@typescript-eslint/eslint-plugin";
import _import from "eslint-plugin-import";
import { fixupPluginRules } from "@eslint/compat";
import tsParser from "@typescript-eslint/parser";
import path from "node:path";
import { fileURLToPath } from "node:url";
import js from "@eslint/js";
import { FlatCompat } from "@eslint/eslintrc";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all
});
export default [{
ignores: ["**/lib/", "**/dist/", "**/umd/", "**/coverage/", "**/docs/"],
}, ...compat.extends("plugin:@typescript-eslint/recommended", "prettier"), {
plugins: {
"@typescript-eslint": typescriptEslint,
import: fixupPluginRules(_import),
},
languageOptions: {
parser: tsParser,
},
settings: {
"import/parsers": {
"@typescript-eslint/parser": [".ts"],
},
"import/resolver": {
typescript: {
alwaysTryTypes: true,
project: ["./tsconfig.json"],
},
},
},
rules: {
"import/no-anonymous-default-export": "off",
"@typescript-eslint/no-unused-vars": "warn",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-var-requires": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-require-imports": "off",
"lines-around-comment": ["warn", {
beforeLineComment: false,
beforeBlockComment: true,
allowBlockStart: true,
allowClassStart: true,
allowObjectStart: true,
allowArrayStart: true,
}],
"newline-before-return": "off",
"import/newline-after-import": ["warn", {
count: 1,
}],
"object-curly-spacing": ["warn", "always"],
},
}];

4603
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -9,11 +9,11 @@
"exports": {
".": {
"import": "./dist/mjs/index.js",
"require": "./dist/cjs/index.js",
"types": "./dist/mjs/index.d.ts"
"require": "./dist/cjs/index.js"
}
},
"scripts": {
"install:all-packages": "npm install @swc/core @types/benchmark @types/jest @types/node @typescript-eslint/eslint-plugin @typescript-eslint/parser auto-changelog avl-tree-typed benchmark binary-tree-typed bst-typed data-structure-typed dependency-cruiser doctoc eslint eslint-config-prettier eslint-import-resolver-alias eslint-import-resolver-typescript eslint-plugin-import fast-glob heap-typed istanbul-badges-readme jest js-sdsl prettier ts-jest ts-loader ts-node tsup typedoc typescript --save-dev",
"build": "npm run build:mjs && npm run build:cjs && npm run build:umd && npm run build:docs-class",
"build:mjs": "rm -rf dist/mjs && tsc -p tsconfig-mjs.json",
"build:cjs": "rm -rf dist/cjs && tsc -p tsconfig-cjs.json",
@ -59,37 +59,40 @@
"@zrwusa:registry": "https://npm.pkg.github.com"
},
"devDependencies": {
"@swc/core": "^1.3.96",
"@types/benchmark": "^2.1.3",
"@types/jest": "^29.5.5",
"@types/node": "^20.8.2",
"@typescript-eslint/eslint-plugin": "^6.7.4",
"@typescript-eslint/parser": "^6.7.4",
"auto-changelog": "^2.4.0",
"avl-tree-typed": "^1.52.5",
"@eslint/compat": "^1.2.2",
"@eslint/eslintrc": "^3.1.0",
"@eslint/js": "^9.13.0",
"@swc/core": "^1.7.40",
"@types/benchmark": "^2.1.5",
"@types/jest": "^29.5.14",
"@types/node": "^22.8.2",
"@typescript-eslint/eslint-plugin": "^8.12.1",
"@typescript-eslint/parser": "^8.12.1",
"auto-changelog": "^2.5.0",
"avl-tree-typed": "^1.52.6",
"benchmark": "^2.1.4",
"binary-tree-typed": "^1.52.5",
"bst-typed": "^1.52.5",
"data-structure-typed": "^1.52.5",
"dependency-cruiser": "^14.1.0",
"binary-tree-typed": "^1.52.6",
"bst-typed": "^1.52.6",
"data-structure-typed": "^1.52.6",
"dependency-cruiser": "^16.5.0",
"doctoc": "^2.2.1",
"eslint": "^8.50.0",
"eslint-config-prettier": "^9.0.0",
"eslint": "^9.13.0",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-alias": "^1.1.2",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.28.1",
"fast-glob": "^3.3.1",
"heap-typed": "^1.52.5",
"istanbul-badges-readme": "^1.8.5",
"eslint-import-resolver-typescript": "^3.6.3",
"eslint-plugin-import": "^2.31.0",
"fast-glob": "^3.3.2",
"heap-typed": "^1.52.6",
"istanbul-badges-readme": "^1.9.0",
"jest": "^29.7.0",
"js-sdsl": "^4.4.2",
"prettier": "^3.3.3",
"ts-jest": "^29.1.1",
"ts-loader": "^9.4.4",
"ts-node": "^10.9.1",
"tsup": "^7.2.0",
"typedoc": "^0.26.5",
"typescript": "^5.3.2"
"ts-jest": "^29.2.5",
"ts-loader": "^9.5.1",
"ts-node": "^10.9.2",
"tsup": "^8.3.5",
"typedoc": "^0.26.10",
"typescript": "^5.6.3"
},
"keywords": [
"data",

View file

@ -192,10 +192,20 @@ export abstract class IterableElementBase<E, R, C> {
*
* The print function logs the elements of an array to the console.
*/
print(): E[] {
toVisual(): E[] {
return [...this];
}
/**
* Time Complexity: O(n)
* Space Complexity: O(n)
*
* The print function logs the elements of an array to the console.
*/
print(): void {
console.log(this.toVisual());
}
abstract isEmpty(): boolean;
abstract clear(): void;

View file

@ -1,26 +1,8 @@
import { EntryCallback, ReduceEntryCallback } from '../../types';
export abstract class IterableEntryBase<K = any, V = any> {
// protected constructor(options?: IterableEntryBaseOptions<K, V, R>) {
// if (options) {
// const { toEntryFn } = options;
// if (typeof toEntryFn === 'function') this._toEntryFn = toEntryFn
// else throw new TypeError('toEntryFn must be a function type');
// }
// }
abstract get size(): number;
// protected _toEntryFn?: (rawElement: R) => BTNEntry<K, V>;
//
// /**
// * The function returns the value of the _toEntryFn property.
// * @returns The function being returned is `this._toEntryFn`.
// */
// get toEntryFn() {
// return this._toEntryFn;
// }
/**
* Time Complexity: O(n)
* Space Complexity: O(1)
@ -251,10 +233,20 @@ export abstract class IterableEntryBase<K = any, V = any> {
*
* The print function logs the elements of an array to the console.
*/
print(): [K, V][] | string {
toVisual(): [K, V][] | string {
return [...this];
}
/**
* Time Complexity: O(n)
* Space Complexity: O(n)
*
* The print function logs the elements of an array to the console.
*/
print(): void {
console.log(this.toVisual());
}
abstract isEmpty(): boolean;
abstract clear(): void;

View file

@ -339,8 +339,8 @@ export class AVLTree<
}
this._updateHeight(A);
B && this._updateHeight(B);
C && this._updateHeight(C);
if (B) this._updateHeight(B);
if (C) this._updateHeight(C);
}
/**
@ -378,7 +378,7 @@ export class AVLTree<
B.left = A;
}
this._updateHeight(A);
B && this._updateHeight(B);
if (B) this._updateHeight(B);
}
/**
@ -427,8 +427,8 @@ export class AVLTree<
if (C) C.right = B;
this._updateHeight(A);
B && this._updateHeight(B);
C && this._updateHeight(C);
if (B) this._updateHeight(B);
if (C) this._updateHeight(C);
}
/**
@ -442,41 +442,43 @@ export class AVLTree<
*/
protected _balancePath(node: R | BTNKeyOrNodeOrEntry<K, V, NODE>): void {
node = this.ensureNode(node);
const path = this.getPathToRoot(node, false); // first O(log n) + O(log n)
const path = this.getPathToRoot(node => node, node, false); // first O(log n) + O(log n)
for (let i = 0; i < path.length; i++) {
// second O(log n)
const A = path[i];
// Update Heights: After inserting a node, backtrack from the insertion point to the root node, updating the height of each node along the way.
this._updateHeight(A); // first O(1)
// Check Balance: Simultaneously with height updates, check if each node violates the balance property of an AVL tree.
// Balance Restoration: If a balance issue is discovered after inserting a node, it requires balance restoration operations. Balance restoration includes four basic cases where rotation operations need to be performed to fix the balance:
switch (
this._balanceFactor(A) // second O(1)
) {
case -2:
if (A && A.left) {
if (this._balanceFactor(A.left) <= 0) {
// second O(1)
// Left Rotation (LL Rotation): When the inserted node is in the left subtree of the left subtree, causing an imbalance.
this._balanceLL(A);
} else {
// Left-Right Rotation (LR Rotation): When the inserted node is in the right subtree of the left subtree, causing an imbalance.
this._balanceLR(A);
if (A) {
// Update Heights: After inserting a node, backtrack from the insertion point to the root node, updating the height of each node along the way.
this._updateHeight(A); // first O(1)
// Check Balance: Simultaneously with height updates, check if each node violates the balance property of an AVL tree.
// Balance Restoration: If a balance issue is discovered after inserting a node, it requires balance restoration operations. Balance restoration includes four basic cases where rotation operations need to be performed to fix the balance:
switch (
this._balanceFactor(A) // second O(1)
) {
case -2:
if (A && A.left) {
if (this._balanceFactor(A.left) <= 0) {
// second O(1)
// Left Rotation (LL Rotation): When the inserted node is in the left subtree of the left subtree, causing an imbalance.
this._balanceLL(A);
} else {
// Left-Right Rotation (LR Rotation): When the inserted node is in the right subtree of the left subtree, causing an imbalance.
this._balanceLR(A);
}
}
}
break;
case +2:
if (A && A.right) {
if (this._balanceFactor(A.right) >= 0) {
// Right Rotation (RR Rotation): When the inserted node is in the right subtree of the right subtree, causing an imbalance.
this._balanceRR(A);
} else {
// Right-Left Rotation (RL Rotation): When the inserted node is in the left subtree of the right subtree, causing an imbalance.
this._balanceRL(A);
break;
case +2:
if (A && A.right) {
if (this._balanceFactor(A.right) >= 0) {
// Right Rotation (RR Rotation): When the inserted node is in the right subtree of the right subtree, causing an imbalance.
this._balanceRR(A);
} else {
// Right-Left Rotation (RL Rotation): When the inserted node is in the left subtree of the right subtree, causing an imbalance.
this._balanceRL(A);
}
}
}
}
// TODO So far, no sure if this is necessary that Recursive Repair: Once rotation operations are executed, it may cause imbalance issues at higher levels of the tree. Therefore, you need to recursively check and repair imbalance problems upwards until you reach the root node.
}
// TODO So far, no sure if this is necessary that Recursive Repair: Once rotation operations are executed, it may cause imbalance issues at higher levels of the tree. Therefore, you need to recursively check and repair imbalance problems upwards until you reach the root node.
}
}

View file

@ -415,7 +415,7 @@ export class BinaryTree<
// If the tree is empty, directly set the new node as the root node
if (!this.root) {
this._root = newNode;
this._setRoot(newNode);
this._size = 1;
return true;
}
@ -441,10 +441,10 @@ export class BinaryTree<
// Continue traversing the left and right subtrees
if (cur.left !== null) {
cur.left && queue.push(cur.left);
if (cur.left) queue.push(cur.left);
}
if (cur.right !== null) {
cur.right && queue.push(cur.right);
if (cur.right) queue.push(cur.right);
}
}
@ -665,8 +665,8 @@ export class BinaryTree<
if (onlyOne) return;
}
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return;
this.isRealNode(cur.left) && dfs(cur.left);
this.isRealNode(cur.right) && dfs(cur.right);
if (this.isRealNode(cur.left)) dfs(cur.left);
if (this.isRealNode(cur.right)) dfs(cur.right);
};
dfs(beginRoot);
@ -679,8 +679,8 @@ export class BinaryTree<
ans.push(cur);
if (onlyOne) return ans;
}
this.isRealNode(cur.left) && stack.push(cur.left);
this.isRealNode(cur.right) && stack.push(cur.right);
if (this.isRealNode(cur.left)) stack.push(cur.left);
if (this.isRealNode(cur.right)) stack.push(cur.right);
}
}
}
@ -1076,8 +1076,8 @@ export class BinaryTree<
if (!this.isRealNode(node.right) || last === node.right) {
node = stack.pop();
if (this.isRealNode(node)) {
const leftMinHeight = this.isRealNode(node.left) ? (depths.get(node.left) ?? -1) : -1;
const rightMinHeight = this.isRealNode(node.right) ? (depths.get(node.right) ?? -1) : -1;
const leftMinHeight = this.isRealNode(node.left) ? depths.get(node.left)! : -1;
const rightMinHeight = this.isRealNode(node.right) ? depths.get(node.right)! : -1;
depths.set(node, 1 + Math.min(leftMinHeight, rightMinHeight));
last = node;
node = null;
@ -1086,7 +1086,7 @@ export class BinaryTree<
}
}
return depths.get(beginRoot) ?? -1;
return depths.get(beginRoot)!;
}
}
@ -1094,27 +1094,39 @@ export class BinaryTree<
* Time Complexity: O(log n)
* Space Complexity: O(log n)
*
* The function `getPathToRoot` returns an array of nodes starting from a given node and traversing
* up to the root node, with an option to reverse the order of the nodes.
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} beginNode - The `beginNode` parameter can be either of
* type `R` or `BTNKeyOrNodeOrEntry<K, V, NODE>`.
* @param [isReverse=true] - The `isReverse` parameter is a boolean flag that determines whether the
* resulting path should be reversed or not. If `isReverse` is set to `true`, the path will be
* reversed before returning it. If `isReverse` is set to `false` or not provided, the path will
* @returns The function `getPathToRoot` returns an array of `NODE` objects.
* The function `getPathToRoot` in TypeScript retrieves the path from a given node to the root node
* in a tree structure, applying a specified callback function along the way.
* @param {C} callback - The `callback` parameter is a function that is expected to be of type
* `BTNCallback<OptBTNOrNull<NODE>>`. It is used to process each node as the function traverses up
* the tree from the `beginNode`.
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} beginNode - The `beginNode` parameter in the
* `getPathToRoot` function represents the starting node from which you want to traverse up to the
* root node in a tree structure. It can be either a reference to a node (`NODE`), a key-value pair
* (`K, V`), or an entry
* @param [isReverse=true] - The `isReverse` parameter in the `getPathToRoot` function determines
* whether the resulting path from the given node to the root should be reversed before returning it.
* If `isReverse` is set to `true`, the path will be reversed; otherwise, it will be returned as is.
* @returns The function `getPathToRoot` returns an array of the return type of the callback function
* `C`. The array contains the results of invoking the callback function on each node starting from
* the `beginNode` up to the root node in the tree structure. The order of nodes in the array can be
* reversed based on the `isReverse` parameter.
*/
getPathToRoot(beginNode: R | BTNKeyOrNodeOrEntry<K, V, NODE>, isReverse = true): NODE[] {
const result: NODE[] = [];
getPathToRoot<C extends BTNCallback<OptBTNOrNull<NODE>>>(
callback: C = this._DEFAULT_CALLBACK as C,
beginNode: R | BTNKeyOrNodeOrEntry<K, V, NODE>,
isReverse = true
): ReturnType<C>[] {
const result: ReturnType<C>[] = [];
let beginNodeEnsured = this.ensureNode(beginNode);
if (!beginNodeEnsured) return result;
while (beginNodeEnsured.parent) {
// Array.push + Array.reverse is more efficient than Array.unshift
result.push(beginNodeEnsured);
result.push(callback(beginNodeEnsured));
beginNodeEnsured = beginNodeEnsured.parent;
}
result.push(beginNodeEnsured);
result.push(callback(beginNodeEnsured));
return isReverse ? result.reverse() : result;
}
@ -1431,17 +1443,16 @@ export class BinaryTree<
): ReturnType<C>[] {
beginRoot = this.ensureNode(beginRoot);
const leaves: ReturnType<BTNCallback<NODE>>[] = [];
if (!this.isRealNode(beginRoot)) {
return [];
}
if (!this.isRealNode(beginRoot)) return [];
if (iterationType === 'RECURSIVE') {
const dfs = (cur: NODE) => {
if (this.isLeaf(cur)) {
leaves.push(callback(cur));
}
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return;
this.isRealNode(cur.left) && dfs(cur.left);
this.isRealNode(cur.right) && dfs(cur.right);
if (this.isRealNode(cur.left)) dfs(cur.left);
if (this.isRealNode(cur.right)) dfs(cur.right);
};
dfs(beginRoot);
@ -1453,8 +1464,8 @@ export class BinaryTree<
if (this.isLeaf(cur)) {
leaves.push(callback(cur));
}
this.isRealNode(cur.left) && queue.push(cur.left);
this.isRealNode(cur.right) && queue.push(cur.right);
if (this.isRealNode(cur.left)) queue.push(cur.left);
if (this.isRealNode(cur.right)) queue.push(cur.right);
}
}
}
@ -1569,7 +1580,7 @@ export class BinaryTree<
beginRoot: R | BTNKeyOrNodeOrEntry<K, V, NODE> = this.root
): ReturnType<C>[] {
beginRoot = this.ensureNode(beginRoot);
if (beginRoot === null) return [];
if (!beginRoot) return [];
const ans: ReturnType<BTNCallback<NODE>>[] = [];
let cur: OptBTNOrNull<NODE> = beginRoot;
@ -1734,7 +1745,7 @@ export class BinaryTree<
* Time Complexity: O(n)
* Space Complexity: O(n)
*
* The `print` function in TypeScript prints the binary tree structure with customizable options.
* The `toVisual` function in TypeScript prints the binary tree structure with customizable options.
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} beginRoot - The `beginRoot` parameter is the starting
* point for printing the binary tree. It can be either a node of the binary tree or a key or entry
* that exists in the binary tree. If no value is provided, the root of the binary tree will be used
@ -1744,7 +1755,10 @@ export class BinaryTree<
* @returns Nothing is being returned. The function has a return type of `void`, which means it does
* not return any value.
*/
override print(beginRoot: R | BTNKeyOrNodeOrEntry<K, V, NODE> = this.root, options?: BinaryTreePrintOptions): string {
override toVisual(
beginRoot: R | BTNKeyOrNodeOrEntry<K, V, NODE> = this.root,
options?: BinaryTreePrintOptions
): string {
const opts = { isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false, ...options };
beginRoot = this.ensureNode(beginRoot);
let output = '';
@ -2113,7 +2127,7 @@ export class BinaryTree<
newNode.right = oldNode.right;
newNode.parent = oldNode.parent;
if (this.root === oldNode) {
this._root = newNode;
this._setRoot(newNode);
}
return newNode;

View file

@ -318,7 +318,7 @@ export class BST<
};
for (const kve of keysOrNodesOrEntriesOrRawElements) {
isRealBTNExemplar(kve) && realBTNExemplars.push(kve);
if (isRealBTNExemplar(kve)) realBTNExemplars.push(kve);
}
let sorted: (R | BTNPureKeyOrNodeOrEntry<K, V, NODE>)[] = [];
@ -434,8 +434,8 @@ export class BST<
if (this.isRealNode(cur.left) && this.comparator(cur.key, identifier as K) > 0) dfs(cur.left);
if (this.isRealNode(cur.right) && this.comparator(cur.key, identifier as K) < 0) dfs(cur.right);
} else {
this.isRealNode(cur.left) && dfs(cur.left);
this.isRealNode(cur.right) && dfs(cur.right);
if (this.isRealNode(cur.left)) dfs(cur.left);
if (this.isRealNode(cur.right)) dfs(cur.right);
}
};
@ -462,8 +462,8 @@ export class BST<
// // @ts-ignore
// if (this.isRealNode(cur.left) && cur.key < identifier) stack.push(cur.left);
} else {
this.isRealNode(cur.right) && stack.push(cur.right);
this.isRealNode(cur.left) && stack.push(cur.left);
if (this.isRealNode(cur.right)) stack.push(cur.right);
if (this.isRealNode(cur.left)) stack.push(cur.left);
}
}
}
@ -627,8 +627,8 @@ export class BST<
): ReturnType<C>[] {
const targetNodeEnsured = this.ensureNode(targetNode);
const ans: ReturnType<BTNCallback<NODE>>[] = [];
if (!targetNodeEnsured) return ans;
if (!this.root) return ans;
if (!targetNodeEnsured) return ans;
const targetKey = targetNodeEnsured.key;
@ -749,8 +749,8 @@ export class BST<
if (!node.right || last === node.right) {
node = stack.pop();
if (node) {
const left = node.left ? (depths.get(node.left) ?? -1) : -1;
const right = node.right ? (depths.get(node.right) ?? -1) : -1;
const left = node.left ? depths.get(node.left)! : -1;
const right = node.right ? depths.get(node.right)! : -1;
if (Math.abs(left - right) > 1) return false;
depths.set(node, 1 + Math.max(left, right));
last = node;

View file

@ -564,7 +564,7 @@ export abstract class AbstractGraph<
}
}
getMinDist &&
if (getMinDist)
distMap.forEach((d, v) => {
if (v !== srcVertex) {
if (d < minDist) {
@ -574,7 +574,7 @@ export abstract class AbstractGraph<
}
});
genPaths && getPaths(minDest);
if (genPaths) getPaths(minDest);
return { distMap, preMap, seen, paths, minDist, minPath };
}
@ -761,7 +761,7 @@ export abstract class AbstractGraph<
if (sWeight !== undefined && dWeight !== undefined) {
if (distMap.get(s) !== Infinity && sWeight + weight < dWeight) {
distMap.set(d, sWeight + weight);
genPath && preMap.set(d, s);
if (genPath) preMap.set(d, s);
}
}
}
@ -900,7 +900,7 @@ export abstract class AbstractGraph<
currentPath.push(vertex.key);
for (const neighbor of this.getNeighbors(vertex)) {
neighbor && dfs(neighbor, currentPath, visited);
if (neighbor) dfs(neighbor, currentPath, visited);
}
visited.delete(vertex);

View file

@ -260,8 +260,8 @@ export class DirectedGraph<
const v1ToV2 = this.deleteEdgeSrcToDest(v1, v2);
const v2ToV1 = this.deleteEdgeSrcToDest(v2, v1);
v1ToV2 && removed.push(v1ToV2);
v2ToV1 && removed.push(v2ToV1);
if (v1ToV2) removed.push(v1ToV2);
if (v2ToV1) removed.push(v2ToV1);
}
return removed;

View file

@ -42,7 +42,7 @@ export class Navigator<T = number> {
this._cur = cur;
this._character = new Character(charDir, turning);
this.onMove = onMove;
this.onMove && this.onMove(this._cur);
if (this.onMove) this.onMove(this._cur);
this._VISITED = VISITED;
this._matrix[this._cur[0]][this._cur[1]] = this._VISITED;
}
@ -116,6 +116,6 @@ export class Navigator<T = number> {
const [i, j] = this._cur;
this._matrix[i][j] = this._VISITED;
this.onMove && this.onMove(this._cur);
if (this.onMove) this.onMove(this._cur);
}
}

View file

@ -1,10 +1,4 @@
export const isDebugTest: boolean = false;
export const isCompetitor: boolean = false;
export const isTestStackOverflow = false;
export const SYSTEM_MAX_CALL_STACK = (function getMaxStackDepth(depth = 0) {
try {
return getMaxStackDepth(depth + 1);
} catch (e) {
return depth + 3000;
}
})();
export const SYSTEM_MAX_CALL_STACK = 12000;

View file

@ -16,14 +16,14 @@ describe('AVL Tree Test from data-structure-typed', () => {
expect(getValueById).toBe(10);
const getMinNodeByRoot = tree.getLeftMost();
expect(getMinNodeByRoot?.key).toBe(1);
expect(getMinNodeByRoot).toBe(1);
const node15 = tree.getNode(15);
const getMinNodeBySpecificNode = node15 && tree.getLeftMost(node => node, node15);
expect(getMinNodeBySpecificNode?.key).toBe(12);
let subTreeSum = 0;
node15 && tree.dfs(node => (subTreeSum += node.key), 'PRE', 15);
if (node15) tree.dfs(node => (subTreeSum += node.key), 'PRE', 15);
expect(subTreeSum).toBe(70);
let lesserSum = 0;

View file

@ -33,14 +33,14 @@ describe('AVL Tree Test', () => {
expect(getValueById).toBe(10);
const getMinNodeByRoot = tree.getLeftMost();
expect(getMinNodeByRoot?.key).toBe(1);
expect(getMinNodeByRoot).toBe(1);
const node15 = tree.getNode(15);
const getMinNodeBySpecificNode = node15 && tree.getLeftMost(node => node, node15);
expect(getMinNodeBySpecificNode?.key).toBe(12);
let subTreeSum = 0;
node15 && tree.dfs(node => (subTreeSum += node.key), 'IN', 15);
if (node15) tree.dfs(node => (subTreeSum += node.key), 'IN', 15);
expect(subTreeSum).toBe(70);
let lesserSum = 0;

View file

@ -17,25 +17,28 @@ describe('Individual package BST operations test', () => {
expect(bst.has(6)).toBe(true);
const node6 = bst.get(6);
expect(node6 && bst.getHeight(6)).toBe(2);
expect(node6 && bst.getDepth(6)).toBe(3);
expect(bst.getHeight(node6)).toBe(5);
expect(bst.getDepth(6)).toBe(4);
const nodeId10 = bst.getNode(10);
expect(nodeId10?.key).toBe(10);
const nodeVal9 = bst.getNode(9, node => node.value);
expect(nodeVal9?.key).toBe(9);
expect(nodeVal9?.key).toBe(undefined);
const leftMost = bst.getLeftMost();
const nodeVal11 = bst.getNode(11, node => node.value);
expect(nodeVal11?.key).toBe(11);
const leftMost = bst.getLeftMost(node => node);
expect(leftMost?.key).toBe(1);
const node15 = bst.getNode(15);
const minNodeBySpecificNode = node15 && bst.getLeftMost(node => node, node15);
expect(minNodeBySpecificNode?.key).toBe(12);
expect(minNodeBySpecificNode?.key).toBe(14);
let subTreeSum = 0;
node15 && bst.dfs(node => (subTreeSum += node.key), 'IN', 15);
expect(subTreeSum).toBe(70);
if (node15) bst.dfs(node => (subTreeSum += node.key), 'IN', 15);
expect(subTreeSum).toBe(45);
let lesserSum = 0;
bst.lesserOrGreaterTraverse(node => (lesserSum += node.key), -1, 10);
@ -211,10 +214,9 @@ describe('Individual package BST operations test', () => {
if (objBST.root) expect(objBST.root.key).toBe(11);
expect(objBST.has(6)).toBe(true);
const node6 = objBST.getNode(6);
expect(node6 && objBST.getHeight(node6)).toBe(2);
expect(node6 && objBST.getDepth(node6)).toBe(3);
expect(objBST.getHeight(node6)).toBe(1);
expect(objBST.getDepth(node6)).toBe(4);
const nodeId10 = objBST.get(10);
expect(nodeId10?.key).toBe(10);
@ -223,7 +225,7 @@ describe('Individual package BST operations test', () => {
expect(nodeVal9?.key).toBe(9);
const leftMost = objBST.getLeftMost();
expect(leftMost?.key).toBe(1);
expect(leftMost).toBe(1);
const node15 = objBST.getNode(15);
expect(node15?.value).toEqual({
@ -231,11 +233,11 @@ describe('Individual package BST operations test', () => {
keyA: 15
});
const minNodeBySpecificNode = node15 && objBST.getLeftMost(node => node, node15);
expect(minNodeBySpecificNode?.key).toBe(12);
expect(minNodeBySpecificNode?.key).toBe(14);
let subTreeSum = 0;
node15 && objBST.dfs(node => (subTreeSum += node.key), 'IN', node15);
expect(subTreeSum).toBe(70);
if (node15) objBST.dfs(node => (subTreeSum += node.key), 'IN', node15);
expect(subTreeSum).toBe(45);
let lesserSum = 0;
objBST.lesserOrGreaterTraverse(node => (lesserSum += node.key), -1, 10);
@ -265,8 +267,7 @@ describe('Individual package BST operations test', () => {
if (removed11[0].deleted) expect(removed11[0].deleted.key).toBe(11);
expect(objBST.isAVLBalanced()).toBe(true);
expect(node15 && objBST.getHeight(node15)).toBe(2);
expect(node15 && objBST.getHeight(node15)).toBe(1);
const removed1 = objBST.delete(1);
expect(removed1).toBeInstanceOf(Array);

View file

@ -3,7 +3,12 @@ const { MinHeap } = require('heap-typed');
describe('JS Heap Operation Test', () => {
it('should numeric heap work well', function () {
const minNumHeap = new MinHeap();
minNumHeap.add(1).add(6).add(2).add(0).add(5).add(9);
minNumHeap.add(1);
minNumHeap.add(6);
minNumHeap.add(2);
minNumHeap.add(0);
minNumHeap.add(5);
minNumHeap.add(9);
expect(minNumHeap.poll()).toBe(0);
expect(minNumHeap.poll()).toBe(1);
expect(minNumHeap.peek()).toBe(2);

View file

@ -91,7 +91,7 @@ describe('AVLTreeMultiMap operations test1', () => {
expect(minNodeBySpecificNode?.key).toBe(15);
let subTreeSum = 0;
node15 && treeMultimap.dfs(node => (subTreeSum += node.key), 'PRE', 15);
if (node15) treeMultimap.dfs(node => (subTreeSum += node.key), 'PRE', 15);
expect(subTreeSum).toBe(31);
let lesserSum = 0;
treeMultimap.lesserOrGreaterTraverse((node: AVLTreeMultiMapNode<number>) => (lesserSum += node.key), -1, 10);
@ -347,7 +347,7 @@ describe('AVLTreeMultiMap operations test recursively1', () => {
expect(minNodeBySpecificNode?.key).toBe(15);
let subTreeSum = 0;
node15 && treeMultimap.dfs(node => (subTreeSum += node.key), 'PRE', 15);
if (node15) treeMultimap.dfs(node => (subTreeSum += node.key), 'PRE', 15);
expect(subTreeSum).toBe(31);
let lesserSum = 0;
treeMultimap.lesserOrGreaterTraverse((node: AVLTreeMultiMapNode<number>) => (lesserSum += node.key), -1, 10);
@ -556,7 +556,7 @@ describe('AVLTreeMultiMap Performance test', function () {
it(`Observe the time consumption of AVLTreeMultiMap.dfs be good`, function () {
const startDFS = performance.now();
const dfs = treeMS.dfs(node => node);
isDebug && console.log('---bfs', performance.now() - startDFS, dfs.length);
if (isDebug) console.log('---bfs', performance.now() - startDFS, dfs.length);
});
it('Should the time consumption of lesserOrGreaterTraverse fitting O(n log n)', function () {
@ -564,10 +564,10 @@ describe('AVLTreeMultiMap Performance test', function () {
for (let i = 0; i < inputSize; i++) {
treeMS.add(i);
}
isDebug && console.log('---add', performance.now() - start);
if (isDebug) console.log('---add', performance.now() - start);
const startL = performance.now();
treeMS.lesserOrGreaterTraverse(node => (node.count += 1), -1, inputSize / 2);
isDebug && console.log('---lesserOrGreaterTraverse', performance.now() - startL);
if (isDebug) console.log('---lesserOrGreaterTraverse', performance.now() - startL);
});
it('should the clone method', () => {

View file

@ -24,7 +24,7 @@ describe('AVL Tree Test', () => {
expect(getMinNodeBySpecificNode?.key).toBe(12);
let subTreeSum = 0;
node15 && tree.dfs(node => (subTreeSum += node.key), 'PRE', node15);
if (node15) tree.dfs(node => (subTreeSum += node.key), 'PRE', node15);
expect(subTreeSum).toBe(70);
let lesserSum = 0;
@ -132,7 +132,7 @@ describe('AVL Tree Test recursively', () => {
expect(getMinNodeBySpecificNode?.key).toBe(12);
let subTreeSum = 0;
node15 && tree.dfs(node => (subTreeSum += node.key), 'PRE', node15);
if (node15) tree.dfs(node => (subTreeSum += node.key), 'PRE', node15);
expect(subTreeSum).toBe(70);
let lesserSum = 0;

View file

@ -296,8 +296,9 @@ describe('BinaryTree', () => {
});
it('should isSubtreeBST', () => {
expect(tree.toVisual()).toBe('');
tree.addMany([4, 2, 6, 1, 3, 5, 7, 4]);
expect(tree.print()).toBe(
expect(tree.toVisual()).toBe(
' ___4___ \n' +
' / \\ \n' +
' _2_ _6_ \n' +
@ -305,6 +306,20 @@ describe('BinaryTree', () => {
' 1 3 5 7 \n' +
' \n'
);
const visualized = tree.toVisual(undefined, { isShowUndefined: true, isShowNull: true, isShowRedBlackNIL: true });
expect(visualized).toBe(
'U for undefined\n' +
' N for null\n' +
' S for Sentinel Node(NIL)\n' +
' _______4_______ \n' +
' / \\ \n' +
' ___2___ ___6___ \n' +
' / \\ / \\ \n' +
' _1_ _3_ _5_ _7_ \n' +
' / \\ / \\ / \\ / \\ \n' +
' U U U U U U U U \n' +
' \n'
);
expect(tree.isBST(tree.getNode(4), 'RECURSIVE')).toBe(true);
expect(tree.isBST(tree.getNode(4), 'ITERATIVE')).toBe(true);
@ -472,13 +487,20 @@ describe('BinaryTree', () => {
});
it('should isLeaf', () => {
expect(tree.getLeftMost()).toBe(undefined);
expect(tree.getRightMost()).toBe(undefined);
tree.addMany([4, 2, 6, 1, 3, 5, 7, 4]);
const leftMost = tree.getLeftMost();
expect(tree.isLeaf(leftMost)).toBe(true);
expect(tree.isLeaf(null)).toBe(true);
const rightMost = tree.getRightMost();
expect(tree.isLeaf(rightMost)).toBe(true);
expect(tree.isLeaf(null)).toBe(true);
});
it('should tree traverse', () => {
expect(tree.dfs()).toEqual([]);
expect([...tree.values()]).toEqual([]);
tree.addMany([4, 2, 6, null, 1, 3, null, 5, null, 7]);
expect(tree.dfs(node => node.key, 'PRE', undefined, 'ITERATIVE')).toEqual([4, 2, 1, 5, 6, 3, 7]);
expect(tree.dfs(node => (node !== null ? node.key : null), 'PRE', undefined, 'ITERATIVE', false)).toEqual([
@ -666,6 +688,7 @@ describe('BinaryTree', () => {
it('should duplicated nodes just replace the node exists', function () {
tree.clear();
expect(tree.bfs()).toEqual([]);
tree.addMany([-10, -10, -10, 9, 9, 20, null, null, 15, 7, 8, null, 2, null, 6, null, null, 8, 8, 8]);
expect(tree.bfs(node => (node ? node.key : null), undefined, undefined, true)).toEqual([
@ -941,6 +964,8 @@ describe('BinaryTree traversals', () => {
[15, 29, null, 50],
[null, 16, 28, 30, 45, 55]
]);
tree.clear();
expect(tree.listLevels()).toEqual([]);
});
});
@ -1017,6 +1042,7 @@ describe('BinaryTree', () => {
});
it('should get the height of the tree', () => {
expect(tree.getMinHeight()).toBe(-1);
tree.add([5, 'A']);
tree.add(3, 'B');
tree.add([7, 'C']);
@ -1075,6 +1101,15 @@ describe('BinaryTree', () => {
expect(tree.getNode(3)).toBe(null);
});
it('should getPathToRoot', () => {
tree.add([5, 'A']);
tree.add([3, 'B']);
tree.add([7, 'C']);
expect(tree.getPathToRoot(undefined, 7)).toEqual([5, 7]);
expect(tree.getPathToRoot(undefined, 1)).toEqual([]);
});
it('should check if the tree is perfectly balanced', () => {
tree.add([5, 'A']);
tree.add([3, 'B']);
@ -1134,7 +1169,8 @@ describe('BinaryTree', () => {
const result = tree.morris();
expect(result).toEqual([3, 5, 7]);
// Add assertions for the result of Morris traversal
tree.clear();
expect(tree.morris()).toEqual([]);
});
it('should perform delete all', () => {
@ -1233,6 +1269,8 @@ describe('BinaryTree iterative methods test', () => {
it('should leaves', () => {
const leaves = binaryTree.leaves();
expect(leaves).toEqual([2, 3]);
binaryTree.clear();
expect(binaryTree.leaves()).toEqual([]);
});
it('should iterative method return undefined when the node is null', () => {

View file

@ -81,8 +81,11 @@ describe('BST operations test', () => {
const minNodeBySpecificNode = node15 && bst.getLeftMost(node => node, node15);
expect(minNodeBySpecificNode?.key).toBe(12);
const nodes = bst.getNodes(15, node => node.value);
expect(nodes.map(node => node.key)).toEqual([15]);
let subTreeSum = 0;
node15 && bst.dfs(node => (subTreeSum += node.key), 'PRE', 15);
if (node15) bst.dfs(node => (subTreeSum += node.key), 'PRE', 15);
expect(subTreeSum).toBe(70);
let lesserSum = 0;
@ -231,6 +234,9 @@ describe('BST operations test', () => {
expect(bfsNodes[0].key).toBe(2);
expect(bfsNodes[1].key).toBe(12);
expect(bfsNodes[2].key).toBe(16);
bst.clear();
expect(bst.perfectlyBalance()).toBe(false);
expect(bst.isAVLBalanced()).toBe(true);
});
it('should perform various operations on a Binary Search Tree with object values', () => {
@ -288,7 +294,7 @@ describe('BST operations test', () => {
expect(minNodeBySpecificNode?.key).toBe(12);
let subTreeSum = 0;
node15 && objBST.dfs(node => (subTreeSum += node.key), 'PRE', node15);
if (node15) objBST.dfs(node => (subTreeSum += node.key), 'PRE', node15);
expect(subTreeSum).toBe(70);
let lesserSum = 0;
@ -495,7 +501,7 @@ describe('BST operations test recursively', () => {
expect(minNodeBySpecificNode?.key).toBe(12);
let subTreeSum = 0;
node15 && bst.dfs(node => (subTreeSum += node.key), 'PRE', 15);
if (node15) bst.dfs(node => (subTreeSum += node.key), 'PRE', 15);
expect(subTreeSum).toBe(70);
let lesserSum = 0;
@ -702,7 +708,7 @@ describe('BST operations test recursively', () => {
expect(minNodeBySpecificNode?.key).toBe(12);
let subTreeSum = 0;
node15 && objBST.dfs(node => (subTreeSum += node.key), 'PRE', node15);
if (node15) objBST.dfs(node => (subTreeSum += node.key), 'PRE', node15);
expect(subTreeSum).toBe(70);
let lesserSum = 0;
@ -869,6 +875,28 @@ describe('BST operations test recursively', () => {
expect(numBST.size).toBe(0);
});
it('should listLevels', () => {
const bst = new BST<number>();
bst.addMany([2, 4, 5, 3, 1]);
expect(bst.size).toBe(5);
bst.delete(1);
bst.delete(5);
const levelKeys = bst.listLevels();
expect(levelKeys).toEqual([[3], [2, 4]]);
});
it('should lesserOrGreaterTraverse', () => {
const bst = new BST<number>();
const levelKeys = bst.lesserOrGreaterTraverse();
expect(levelKeys).toEqual([]);
bst.addMany([2, 4, 5, 3, 1]);
expect(bst.size).toBe(5);
bst.delete(1);
bst.delete(5);
const levelKeys1 = bst.lesserOrGreaterTraverse();
expect(levelKeys1).toEqual([2]);
});
it('should the clone method', () => {
function checkTreeStructure(bst: BST<string, number>) {
expect(bst.size).toBe(4);
@ -972,7 +1000,7 @@ describe('BST Performance test', function () {
it(`Observe the time consumption of BST.dfs be good`, function () {
const startDFS = performance.now();
const dfs = bst.dfs(node => node);
isDebug && console.log('---bfs', performance.now() - startDFS, dfs.length);
if (isDebug) console.log('---bfs', performance.now() - startDFS, dfs.length);
});
it('Should the time consumption of lesserOrGreaterTraverse fitting O(n log n)', function () {
@ -982,16 +1010,16 @@ describe('BST Performance test', function () {
}
const start = performance.now();
bst.addMany(nodes);
isDebug && console.log('---add', performance.now() - start);
if (isDebug) console.log('---add', performance.now() - start);
const startL = performance.now();
bst.lesserOrGreaterTraverse(
node => {
node.key - 1;
node.key -= 1;
},
-1,
inputSize / 2
);
isDebug && console.log('---lesserOrGreaterTraverse', performance.now() - startL);
if (isDebug) console.log('---lesserOrGreaterTraverse', performance.now() - startL);
});
it('Should the time consumption of listLevels fitting well', function () {
@ -1001,11 +1029,11 @@ describe('BST Performance test', function () {
}
const start = performance.now();
bst.addMany(nodes);
isDebug && console.log('---add', performance.now() - start);
if (isDebug) console.log('---add', performance.now() - start);
const startL = performance.now();
const arr: number[][] = bst.listLevels(node => node.key);
isDebug && console.log('---listLevels', arr);
isDebug && console.log('---listLevels', performance.now() - startL);
if (isDebug) console.log('---listLevels', arr);
if (isDebug) console.log('---listLevels', performance.now() - startL);
});
it('should the lastKey of a BST to be the largest key', function () {

View file

@ -6,18 +6,13 @@ describe('Overall BinaryTree Test', () => {
bst.add(11);
bst.add(3);
bst.addMany([15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5], undefined, false);
bst.size === 16; // true
expect(bst.size).toBe(16); // true
bst.has(6); // true
expect(bst.has(6)).toBe(true); // true
bst.getHeight(6) === 2; // true
bst.getHeight() === 5; // true
bst.getDepth(6) === 3; // true
expect(bst.getHeight(6)).toBe(2); // true
expect(bst.getHeight()).toBe(5); // true
expect(bst.getDepth(6)).toBe(3); // true
const leftMost = bst.getLeftMost();
leftMost?.key === 1; // true
expect(leftMost).toBe(1);
bst.delete(6);
bst.getNode(6); // undefined
@ -26,7 +21,6 @@ describe('Overall BinaryTree Test', () => {
expect(bst.isAVLBalanced()).toBe(true);
const bfsIDs: number[] = [];
bst.bfs(node => bfsIDs.push(node.key));
bfsIDs[0] === 11; // true
expect(bfsIDs[0]).toBe(11);
const objBST = new BST<number, { key: number; keyA: number }>();

View file

@ -414,7 +414,7 @@ describe('RedBlackTree 2', () => {
expect(node225F?.right).toBe(rbTree.NIL);
expect(node225F?.parent?.key).toBe(155);
rbTree.add(7);
isDebug && rbTree.print();
if (isDebug) rbTree.print();
const node15S = rbTree.getNode(15);
expect(node15S?.left?.key).toBe(10);
@ -463,7 +463,7 @@ describe('RedBlackTree 2', () => {
rbTree.add(19);
rbTree.add(110);
isDebug && rbTree.print();
if (isDebug) rbTree.print();
expect(rbTree.dfs()).toEqual([
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 22, 23, 25, 28, 33, 50, 110, 111, 155, 225
@ -525,19 +525,19 @@ describe('RedBlackTree 2', () => {
for (let i = 0; i < arr.length; i++) {
rbTree.add(arr[i]);
}
isDebug && console.log(performance.now() - tS);
if (isDebug) console.log(performance.now() - tS);
const cS = performance.now();
for (let i = 0; i < arr.length; i++) {
competitor.setElement(arr[i], arr[i]);
}
isDebug && console.log(performance.now() - cS);
if (isDebug) console.log(performance.now() - cS);
});
it('duplicates', () => {
rbTree.addMany([9, 8, 7, 8, 8, 8, 2, 3, 6, 5, 5, 4]);
isDebug && rbTree.print();
if (isDebug) rbTree.print();
expect(rbTree.size).toBe(8);
expect(rbTree.isBST()).toBe(true);
@ -606,7 +606,7 @@ describe('RedBlackTree 2', () => {
expect(rbTree.getHeight()).toBe(-1);
expect(nanCount).toBeLessThanOrEqual(inputSize);
isDebug && rbTree.print();
if (isDebug) rbTree.print();
});
});

View file

@ -1,50 +1,104 @@
import { SegmentTree } from '../../../../src';
import { SegmentTree, SegmentTreeNode } from '../../../../src';
describe('SegmentTree', () => {
let segmentTree: SegmentTree;
beforeEach(() => {
// Create an example SegmentTree for testing
const values = [1, 2, 3, 4, 5];
segmentTree = new SegmentTree(values);
describe('SegmentTreeNode', () => {
it('should initialize with correct start, end, sum, and optional value', () => {
const node = new SegmentTreeNode(0, 1, 10, 2);
expect(node.start).toBe(0);
expect(node.end).toBe(1);
expect(node.sum).toBe(10);
expect(node.value).toBe(2);
});
it('should build a valid segment tree', () => {
// Check if the root node's sum is correct
expect(segmentTree.root?.sum).toBe(15);
});
it('should allow setting start, end, sum, value, left, and right', () => {
const node = new SegmentTreeNode(0, 1, 10);
node.start = 2;
node.end = 3;
node.sum = 15;
node.value = 2;
it('should update a node in the segment tree', () => {
// Update a node value
segmentTree.updateNode(2, 10);
const leftNode = new SegmentTreeNode(0, 1, 5);
const rightNode = new SegmentTreeNode(2, 3, 10);
// Check if the sum of the root node is correct after the update
expect(segmentTree.root?.sum).toBe(22);
});
node.left = leftNode;
node.right = rightNode;
it('should query sum by range correctly', () => {
// Check if the sum within a specific range is correct
expect(segmentTree.querySumByRange(1, 3)).toBe(9); // 2 + 3 + 4 = 9
});
it('should handle edge cases for querySumByRange', () => {
// Check behavior when the range goes beyond boundaries
expect(segmentTree.querySumByRange(0, 4)).toBe(15); // Valid range, should return sum of the specified range
expect(segmentTree.querySumByRange(3, 2)).toBe(NaN); // End index is less than start index, should return NaN
expect(segmentTree.querySumByRange(0, 10)).toBe(NaN); // Beyond upper bound, should return NaN
});
it('should handle an empty input array', () => {
// Check behavior when dealing with an empty input array
const emptySegmentTree = new SegmentTree([]);
expect(emptySegmentTree.root).toBe(undefined);
expect(emptySegmentTree.querySumByRange(0, 2)).toBe(0); // Sum of an empty array should be 0
});
it('should handle a single-element input array', () => {
// Check behavior when the input array contains a single element
const singleElementSegmentTree = new SegmentTree([42]);
expect(singleElementSegmentTree.root?.sum).toBe(42);
expect(singleElementSegmentTree.querySumByRange(0, 0)).toBe(42); // Range covering the only element should return that element's value
expect(node.start).toBe(2);
expect(node.end).toBe(3);
expect(node.sum).toBe(15);
expect(node.value).toBe(2);
expect(node.left).toBe(leftNode);
expect(node.right).toBe(rightNode);
});
});
describe('SegmentTree', () => {
it('should initialize with correct values, start, end, and root', () => {
const values = [1, 2, 3, 4];
const tree = new SegmentTree(values);
expect(tree.values).toEqual(values);
expect(tree.start).toBe(0);
expect(tree.end).toBe(3);
expect(tree.root).toBeDefined();
});
it('should correctly build segment tree with sum of values', () => {
const values = [1, 2, 3, 4];
const tree = new SegmentTree(values);
expect(tree.root?.sum).toBe(10); // 1 + 2 + 3 + 4
});
it('should handle empty values array gracefully', () => {
const tree = new SegmentTree([]);
expect(tree.values).toEqual([]);
expect(tree.root).toBeUndefined();
});
describe('updateNode', () => {
it('should update node value and sum correctly', () => {
const values = [1, 2, 3, 4];
const tree = new SegmentTree(values);
tree.updateNode(1, 5, 2);
expect(tree.root?.sum).toBe(13); // 1 + 5 + 3 + 4
expect(tree.root?.left?.right?.sum).toBe(5);
expect(tree.root?.left?.right?.value).toBe(2);
});
it('should do nothing if root is undefined', () => {
const tree = new SegmentTree([]);
tree.updateNode(0, 10);
expect(tree.root).toBeUndefined();
});
});
describe('querySumByRange', () => {
it('should return sum for a given range', () => {
const values = [1, 2, 3, 4, 5];
const tree = new SegmentTree(values);
const result = tree.querySumByRange(1, 3); // 2 + 3 + 4 = 9
expect(result).toBe(9);
});
it('should return NaN for an invalid range', () => {
const values = [1, 2, 3, 4, 5];
const tree = new SegmentTree(values);
const result = tree.querySumByRange(3, 1); // Invalid range
expect(result).toBeNaN();
});
it('should return 0 if root is undefined', () => {
const tree = new SegmentTree([]);
const result = tree.querySumByRange(0, 1);
expect(result).toBe(0);
});
it('should return NaN if range is out of bounds', () => {
const values = [1, 2, 3, 4];
const tree = new SegmentTree(values);
const result = tree.querySumByRange(-1, 10);
expect(result).toBeNaN();
});
});
});

View file

@ -127,7 +127,7 @@ describe('TreeMultiMap operations test1', () => {
expect(tmm.getComputedCount()).toBe(18);
expect(tmm.has(6));
isDebug && tmm.print();
if (isDebug) tmm.print();
expect(tmm.getHeight(6)).toBe(1);
expect(tmm.getDepth(6)).toBe(3);
const nodeId10 = tmm.getNode(10);
@ -149,7 +149,7 @@ describe('TreeMultiMap operations test1', () => {
expect(minNodeBySpecificNode?.key).toBe(14);
let subTreeSum = 0;
node15 && tmm.dfs(node => (subTreeSum += node.key), 'PRE', 15);
if (node15) tmm.dfs(node => (subTreeSum += node.key), 'PRE', 15);
expect(subTreeSum).toBe(45);
let lesserSum = 0;
tmm.lesserOrGreaterTraverse(node => (lesserSum += node.key), -1, 10);
@ -407,7 +407,7 @@ describe('TreeMultiMap operations test recursively1', () => {
expect(minNodeBySpecificNode?.key).toBe(14);
let subTreeSum = 0;
node15 && tmm.dfs(node => (subTreeSum += node.key), 'PRE', 15);
if (node15) tmm.dfs(node => (subTreeSum += node.key), 'PRE', 15);
expect(subTreeSum).toBe(45);
let lesserSum = 0;
expect(tmm.has(9)).toBe(true);
@ -626,7 +626,7 @@ describe('TreeMultiMap delete test', function () {
it(`Observe the time consumption of TreeMultiMap.dfs be good`, function () {
const startDFS = performance.now();
const dfs = tmm.dfs(node => node);
isDebug && console.log('---bfs', performance.now() - startDFS, dfs.length);
if (isDebug) console.log('---bfs', performance.now() - startDFS, dfs.length);
});
it('The structure remains normal after random deletion', function () {
@ -679,7 +679,7 @@ describe('TreeMultiMap delete test', function () {
expect(tmm.getHeight()).toBe(-1);
expect(nilCount).toBe(tmm.size + 1);
isDebug && tmm.print();
if (isDebug) tmm.print();
});
it(`Random additions, count deletions of structures are normal`, function () {
@ -705,7 +705,7 @@ describe('TreeMultiMap delete test', function () {
expect(tmm.getHeight()).toBeGreaterThanOrEqual(0);
expect(nanCount).toBeLessThanOrEqual(inputSize);
isDebug && tmm.print();
if (isDebug) tmm.print();
});
it('should the clone method', () => {

View file

@ -45,7 +45,7 @@ class MyGraph<
}
degreeOf(vertexOrKey: VO | VertexKey): number {
return 1 ?? Number(vertexOrKey);
return Number(vertexOrKey);
}
edgeSet(): EO[] {

View file

@ -209,8 +209,8 @@ describe('Inherit from DirectedGraph and perform operations', () => {
expect(removedEdge).toBeInstanceOf(MyEdge);
if (removedEdge) {
removedEdge && expect(removedEdge.value).toBe('edge-data1-2');
removedEdge && expect(removedEdge.src).toBe(1);
if (removedEdge) expect(removedEdge.value).toBe('edge-data1-2');
if (removedEdge) expect(removedEdge.src).toBe(1);
}
expect(edgeAfterRemoval).toBe(undefined);
});
@ -241,8 +241,8 @@ describe('Inherit from DirectedGraph and perform operations', () => {
if (sorted && sorted.length > 0) {
expect(sorted.length).toBe(9);
if (sorted[0] instanceof MyVertex) expect(sorted[0].data).toBe('data9');
sorted[3] instanceof MyVertex && expect(sorted[3].data).toBe('data6');
sorted[8] instanceof MyVertex && expect(sorted[8].key).toBe(1);
if (sorted[3] instanceof MyVertex) expect(sorted[3].data).toBe('data6');
if (sorted[8] instanceof MyVertex) expect(sorted[8].key).toBe(1);
}
});

View file

@ -18,14 +18,19 @@ describe('UndirectedGraph Operation Test', () => {
});
it('should add vertices', () => {
expect(graph.isEmpty()).toBe(true);
const vertex1 = new UndirectedVertex('A');
const vertex2 = new UndirectedVertex('B');
graph.addVertex(vertex1);
expect(graph.isEmpty()).toBe(false);
graph.addVertex(vertex2);
expect(graph.hasVertex(vertex1)).toBe(true);
expect(graph.hasVertex(vertex2)).toBe(true);
expect(graph.isEmpty()).toBe(false);
graph.clear();
expect(graph.isEmpty()).toBe(true);
});
it('should add edges', () => {
@ -577,7 +582,7 @@ describe('UndirectedGraph tarjan', () => {
const graph = createExampleGraph5();
const cycles = graph.getCycles();
expect(cycles.length).toBe(13);
expect(cycles).toEqual([
const expectedCycles = [
['A', 'B', 'C', 'D', 'I', 'H', 'F', 'E'],
['A', 'B', 'C', 'D', 'I', 'H', 'F', 'G', 'E'],
['A', 'B', 'C', 'H', 'F', 'E'],
@ -591,7 +596,12 @@ describe('UndirectedGraph tarjan', () => {
['C', 'D', 'I', 'H'],
['E', 'F', 'G'],
['H', 'J', 'K']
]);
];
expect(cycles).toEqual(expectedCycles);
const cloned = graph.clone();
const clonedCycles = cloned.getCycles();
expect(clonedCycles.length).toBe(13);
expect(clonedCycles).toEqual(expectedCycles);
});
// it('should uncuttable graph tarjan SCCs return correct result', () => {

View file

@ -303,7 +303,7 @@ describe('HashMap', () => {
});
it('print', () => {
expect(hm.print()).toEqual([
expect(hm.toVisual()).toEqual([
[2, 2],
[3, 3],
[4, 4],

View file

@ -65,7 +65,7 @@ describe('DoublyLinkedList Operation Test', () => {
dList.delete('5');
expect([...dList]).toEqual(['1', '6', '0', '9']);
expect([...cloned]).toEqual(['1', '6', '0', '5', '9']);
expect(cloned.print()).toEqual(['1', '6', '0', '5', '9']);
expect(cloned.toVisual()).toEqual(['1', '6', '0', '5', '9']);
});
it('should find undefined', () => {

View file

@ -176,7 +176,7 @@ describe('Navigator', () => {
navigator.start();
// The character should not move
isDebug && console.log(visitedCells);
if (isDebug) console.log(visitedCells);
expect(visitedCells).toEqual([
[0, 1],
[1, 1],
@ -226,7 +226,7 @@ describe('Navigator', () => {
navigator.start();
// The character should have navigated the grid, handled turns, and edge cases
isDebug && console.log(visitedCells);
if (isDebug) console.log(visitedCells);
expect(visitedCells).toEqual([
[0, 1],
[0, 2],

View file

@ -76,6 +76,6 @@ describe('MinPriorityQueue Operation Test', () => {
);
expect(mapped instanceof MinPriorityQueue).toBe(true);
expect([...mapped]).toEqual([{ key: 1 }, { key: 5 }, { key: 7 }]);
expect(mapped.print()).toEqual([{ key: 1 }, { key: 5 }, { key: 7 }]);
expect(mapped.toVisual()).toEqual([{ key: 1 }, { key: 5 }, { key: 7 }]);
});
});

View file

@ -86,8 +86,8 @@ describe('Priority Queue Performance Test', () => {
// for (let i = 0; i < 10000; i++) {
// pq.pop();
// }
isDebug && console.log(performance.now() - tS);
isDebug && console.log(pq.size);
if (isDebug) console.log(performance.now() - tS);
if (isDebug) console.log(pq.size);
const cS = performance.now();
const cpq = new CPriorityQueue();
@ -98,7 +98,7 @@ describe('Priority Queue Performance Test', () => {
// for (let i = 0; i < 10000; i++) {
// cpq.pop();
// }
isDebug && console.log(performance.now() - cS);
isDebug && console.log(cpq.size());
if (isDebug) console.log(performance.now() - cS);
if (isDebug) console.log(cpq.size());
});
});

View file

@ -18,6 +18,12 @@ describe('Stack', () => {
expect(stack.size).toBe(3);
});
it('should has and get', () => {
const stack = new Stack<number, { id: number; name: string }>([], { toElementFn: rawElement => rawElement.id });
expect(stack.has(1)).toBe(false);
expect(stack.size).toBe(0);
});
it('should peek at the top element without removing it', () => {
expect(stack.peek()).toBe(undefined);
stack.push(1);

View file

@ -48,61 +48,61 @@ const entries: [number, string][] = [
describe('conversions', () => {
it('Array to Queue', () => {
const q = new Queue<number>(orgArr);
isDebug && q.print();
if (isDebug) q.print();
expect([...q]).toEqual([6, 1, 2, 7, 5, 3, 4, 9, 8]);
});
it('Array to Deque', () => {
const dq = new Deque<number>(orgArr);
isDebug && dq.print();
if (isDebug) dq.print();
expect([...dq]).toEqual([6, 1, 2, 7, 5, 3, 4, 9, 8]);
});
it('Array to SinglyLinkedList', () => {
const sl = new SinglyLinkedList<number>(orgArr);
isDebug && sl.print();
if (isDebug) sl.print();
expect([...sl]).toEqual([6, 1, 2, 7, 5, 3, 4, 9, 8]);
});
it('Array to DoublyLinkedList', () => {
const dl = new DoublyLinkedList<number>(orgArr);
isDebug && dl.print();
if (isDebug) dl.print();
expect([...dl]).toEqual([6, 1, 2, 7, 5, 3, 4, 9, 8]);
});
it('Array to Stack', () => {
const stack = new Stack<number>(orgArr);
isDebug && stack.print();
if (isDebug) stack.print();
expect([...stack]).toEqual([6, 1, 2, 7, 5, 3, 4, 9, 8]);
});
it('Array to MinHeap', () => {
const minHeap = new MinHeap<number>(orgArr);
isDebug && minHeap.print();
if (isDebug) minHeap.print();
expect([...minHeap]).toEqual([1, 5, 2, 7, 6, 3, 4, 9, 8]);
});
it('Array to MaxHeap', () => {
const maxHeap = new MaxHeap<number>(orgArr);
isDebug && maxHeap.print();
if (isDebug) maxHeap.print();
expect([...maxHeap]).toEqual([9, 8, 4, 7, 5, 2, 3, 1, 6]);
});
it('Array to MinPriorityQueue', () => {
const minPQ = new MinPriorityQueue<number>(orgArr);
isDebug && minPQ.print();
if (isDebug) minPQ.print();
expect([...minPQ]).toEqual([1, 5, 2, 7, 6, 3, 4, 9, 8]);
});
it('Array to MaxPriorityQueue', () => {
const maxPQ = new MaxPriorityQueue<number>(orgArr);
isDebug && maxPQ.print();
if (isDebug) maxPQ.print();
expect([...maxPQ]).toEqual([9, 8, 4, 7, 5, 2, 3, 1, 6]);
});
it('Entry Array to BinaryTree', () => {
const biTree = new BinaryTree<number>(entries);
isDebug && biTree.print();
if (isDebug) biTree.print();
expect([...biTree]).toEqual([
[9, '9'],
[7, '7'],
@ -119,7 +119,7 @@ describe('conversions', () => {
it('Entry Array to BST', () => {
const bst = new BST<number>(entries);
expect(bst.size).toBe(9);
isDebug && bst.print();
if (isDebug) bst.print();
expect([...bst]).toEqual([
[1, '1'],
[2, '2'],
@ -136,7 +136,7 @@ describe('conversions', () => {
it('Entry Array to RedBlackTree', () => {
const rbTree = new RedBlackTree<number>(entries);
expect(rbTree.size).toBe(9);
isDebug && rbTree.print();
if (isDebug) rbTree.print();
expect([...rbTree]).toEqual([
[1, '1'],
[2, '2'],
@ -153,7 +153,7 @@ describe('conversions', () => {
it('Entry Array to AVLTree', () => {
const avl = new AVLTree<number>(entries);
expect(avl.size).toBe(9);
isDebug && avl.print();
if (isDebug) avl.print();
expect([...avl]).toEqual([
[1, '1'],
[2, '2'],
@ -170,7 +170,7 @@ describe('conversions', () => {
it('Entry Array to TreeMultiMap', () => {
const treeMulti = new TreeMultiMap<number>(entries);
expect(treeMulti.size).toBe(9);
isDebug && treeMulti.print();
if (isDebug) treeMulti.print();
expect([...treeMulti]).toEqual([
[1, '1'],
[2, '2'],
@ -186,10 +186,10 @@ describe('conversions', () => {
it('HashMap to RedBlackTree', () => {
const hm = new HashMap(entries);
isDebug && hm.print();
if (isDebug) hm.print();
const rbTree = new RedBlackTree<number>(hm);
expect(rbTree.size).toBe(9);
isDebug && rbTree.print();
if (isDebug) rbTree.print();
expect([...rbTree]).toEqual([
[1, '1'],
[2, '2'],
@ -205,10 +205,10 @@ describe('conversions', () => {
it('PriorityQueue to BST', () => {
const pq = new MinPriorityQueue(orgArr);
isDebug && pq.print();
if (isDebug) pq.print();
const bst = new BST<number>(pq);
expect(bst.size).toBe(9);
isDebug && bst.print();
if (isDebug) bst.print();
expect([...bst]).toEqual([
[1, undefined],
[2, undefined],
@ -224,10 +224,10 @@ describe('conversions', () => {
it('Deque to RedBlackTree', () => {
const dq = new Deque(orgArr);
isDebug && dq.print();
if (isDebug) dq.print();
const rbTree = new RedBlackTree<number>(dq);
expect(rbTree.size).toBe(9);
isDebug && rbTree.print();
if (isDebug) rbTree.print();
expect([...rbTree]).toEqual([
[1, undefined],
[2, undefined],
@ -244,12 +244,12 @@ describe('conversions', () => {
it('Trie to Heap to Deque', () => {
const trie = new Trie(orgStrArr);
expect(trie.size).toBe(10);
isDebug && trie.print();
if (isDebug) trie.print();
const heap = new Heap<string>(trie, {
comparator: (a, b) => Number(a) - Number(b)
});
expect(heap.size).toBe(10);
isDebug && heap.print();
if (isDebug) heap.print();
expect([...heap]).toEqual([
'transmit',
'trace',
@ -264,7 +264,7 @@ describe('conversions', () => {
]);
const dq = new Deque<string>(heap);
expect(dq.size).toBe(10);
isDebug && dq.print();
if (isDebug) dq.print();
expect([...dq]).toEqual([
'transmit',
'trace',
@ -280,7 +280,7 @@ describe('conversions', () => {
const entries = dq.map((el, i) => <[number, string]>[i, el]);
const avl = new AVLTree<number, string>(entries);
expect(avl.size).toBe(10);
isDebug && avl.print();
if (isDebug) avl.print();
expect([...avl]).toEqual([
[0, 'transmit'],
[1, 'trace'],

View file

@ -158,12 +158,12 @@ export function logBigOMetricsWrap<F extends AnyFunction>(fn: F, args: Parameter
methodLog.push([runTime, maxDataSize]);
if (methodLog.length >= 20) {
isDebug && console.log('triggered', methodName, methodLog);
if (isDebug) console.log('triggered', methodName, methodLog);
const bigO = estimateBigO(
methodLog.map(([runTime]) => runTime),
methodLog.map(([runTime]) => runTime)
);
isDebug && console.log(`Estimated Big O: ${bigO}`);
if (isDebug) console.log(`Estimated Big O: ${bigO}`);
methodLogs.delete(methodName);
}
}
@ -192,12 +192,13 @@ export function logBigOMetrics(target: any, propertyKey: string, descriptor: Pro
methodLog.push([runTime, maxDataSize]);
if (methodLog.length >= 20) {
isDebug && console.log('triggered', methodName, methodLog);
if (isDebug) console.log('triggered', methodName, methodLog);
const bigO = estimateBigO(
methodLog.map(([runTime]) => runTime),
methodLog.map(([runTime]) => runTime)
);
isDebug && console.log(`Estimated Big O: ${bigO}`);
if (isDebug) console.log(`Estimated Big O: ${bigO}`);
methodLogs.delete(methodName);
}
}