Compare commits

..

4 commits

Author SHA1 Message Date
Revone 9e62968e3d release: v1.52.8 2024-10-30 21:28:20 +13:00
Revone 487f45f6b2 release: v1.52.7 2024-10-30 21:00:03 +13:00
Revone 6428e0f228 fix: Bug fix #103: Fixed an issue where all binary tree clone methods lost constructor parameters. Optimized variable names. Standardized access modifiers for binary tree member variables. 2024-10-30 20:52:23 +13:00
Revone fc0d157295 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.
2024-10-30 15:30:28 +13:00
58 changed files with 3577 additions and 4210 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

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

View file

@ -14,6 +14,8 @@
[//]: # (<p><a href="https://github.com/zrwusa/data-structure-typed/blob/main/README.md">English</a> | <a href="https://github.com/zrwusa/data-structure-typed/blob/main/README_zh-CN.md">简体中文</a></p>)
> ***Our goal is to make every data structure as convenient and efficient as JavaScript's Array.***
## Installation and Usage
### npm
@ -212,6 +214,7 @@ Performance surpasses that of native JS/TS
### Conciseness and uniformity
In [java.utils](), you need to memorize a table for all sequential data structures(Queue, Deque, LinkedList),
<table style="display: table; width:100%; table-layout: fixed;">
@ -710,24 +713,24 @@ bst.print()
const objBST = new BST<number, { height: number, age: number }>();
objBST.add(11, { "name": "Pablo", "age": 15 });
objBST.add(3, { "name": "Kirk", "age": 1 });
objBST.add(11, { "name": "Pablo", "size": 15 });
objBST.add(3, { "name": "Kirk", "size": 1 });
objBST.addMany([15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5], [
{ "name": "Alice", "age": 15 },
{ "name": "Bob", "age": 1 },
{ "name": "Charlie", "age": 8 },
{ "name": "David", "age": 13 },
{ "name": "Emma", "age": 16 },
{ "name": "Frank", "age": 2 },
{ "name": "Grace", "age": 6 },
{ "name": "Hannah", "age": 9 },
{ "name": "Isaac", "age": 12 },
{ "name": "Jack", "age": 14 },
{ "name": "Katie", "age": 4 },
{ "name": "Liam", "age": 7 },
{ "name": "Mia", "age": 10 },
{ "name": "Noah", "age": 5 }
{ "name": "Alice", "size": 15 },
{ "name": "Bob", "size": 1 },
{ "name": "Charlie", "size": 8 },
{ "name": "David", "size": 13 },
{ "name": "Emma", "size": 16 },
{ "name": "Frank", "size": 2 },
{ "name": "Grace", "size": 6 },
{ "name": "Hannah", "size": 9 },
{ "name": "Isaac", "size": 12 },
{ "name": "Jack", "size": 14 },
{ "name": "Katie", "size": 4 },
{ "name": "Liam", "size": 7 },
{ "name": "Mia", "size": 10 },
{ "name": "Noah", "size": 5 }
]
);
@ -823,43 +826,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.49</td><td>154.00</td><td>1.90e-4</td></tr><tr><td>100,000 add & poll</td><td>35.79</td><td>27.94</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="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>85.30</td><td>11.72</td><td>7.38e-4</td></tr><tr><td>100,000 add randomly</td><td>84.77</td><td>11.80</td><td>0.00</td></tr><tr><td>100,000 get</td><td>113.74</td><td>8.79</td><td>0.00</td></tr><tr><td>100,000 iterator</td><td>24.51</td><td>40.80</td><td>0.00</td></tr><tr><td>100,000 add & delete orderly</td><td>152.17</td><td>6.57</td><td>0.01</td></tr><tr><td>100,000 add & delete randomly</td><td>240.78</td><td>4.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>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.16</td><td>22.64</td><td>0.01</td></tr><tr><td>100,000 push & shift</td><td>6.08</td><td>164.58</td><td>0.00</td></tr><tr><td>Native JS Array 100,000 push & shift</td><td>2240.74</td><td>0.45</td><td>0.17</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.75</td><td>48.19</td><td>0.00</td></tr><tr><td>1,000,000 push & pop</td><td>26.85</td><td>37.24</td><td>0.00</td></tr><tr><td>1,000,000 push & shift</td><td>27.56</td><td>36.28</td><td>0.00</td></tr><tr><td>100,000 push & shift</td><td>2.61</td><td>382.75</td><td>4.11e-4</td></tr><tr><td>Native JS Array 100,000 push & shift</td><td>2388.65</td><td>0.42</td><td>0.15</td></tr><tr><td>100,000 unshift & shift</td><td>2.50</td><td>399.53</td><td>3.59e-4</td></tr><tr><td>Native JS Array 100,000 unshift & shift</td><td>4343.52</td><td>0.23</td><td>0.30</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>87.12</td><td>11.48</td><td>0.02</td></tr><tr><td>Native JS Map 1,000,000 set</td><td>211.63</td><td>4.73</td><td>0.03</td></tr><tr><td>Native JS Set 1,000,000 add</td><td>167.62</td><td>5.97</td><td>0.01</td></tr><tr><td>1,000,000 set & get</td><td>78.91</td><td>12.67</td><td>0.02</td></tr><tr><td>Native JS Map 1,000,000 set & get</td><td>295.47</td><td>3.38</td><td>0.03</td></tr><tr><td>Native JS Set 1,000,000 add & has</td><td>267.22</td><td>3.74</td><td>0.07</td></tr><tr><td>1,000,000 ObjKey set & get</td><td>378.26</td><td>2.64</td><td>0.06</td></tr><tr><td>Native JS Map 1,000,000 ObjKey set & get</td><td>344.04</td><td>2.91</td><td>0.06</td></tr><tr><td>Native JS Set 1,000,000 ObjKey add & has</td><td>277.87</td><td>3.60</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'>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>42.67</td><td>23.44</td><td>8.55e-4</td></tr><tr><td>100,000 getWords</td><td>82.51</td><td>12.12</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>307.42</td><td>3.25</td><td>9.13e-4</td></tr><tr><td>100,000 add randomly</td><td>373.75</td><td>2.68</td><td>0.01</td></tr><tr><td>100,000 get</td><td>172.23</td><td>5.81</td><td>0.00</td></tr><tr><td>100,000 iterator</td><td>25.90</td><td>38.61</td><td>0.00</td></tr><tr><td>100,000 add & delete orderly</td><td>509.58</td><td>1.96</td><td>0.00</td></tr><tr><td>100,000 add & delete randomly</td><td>690.44</td><td>1.45</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.45</td><td>134.14</td><td>0.00</td></tr><tr><td>10,000 RBTree get randomly</td><td>13.03</td><td>76.74</td><td>1.43e-4</td></tr><tr><td>10,000 RBTree add & delete randomly</td><td>22.62</td><td>44.21</td><td>1.83e-4</td></tr><tr><td>10,000 AVLTree add randomly</td><td>28.44</td><td>35.16</td><td>2.71e-4</td></tr><tr><td>10,000 AVLTree get randomly</td><td>13.02</td><td>76.81</td><td>1.05e-4</td></tr><tr><td>10,000 AVLTree add & delete randomly</td><td>54.46</td><td>18.36</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'>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.01e+4</td><td>8.01e-7</td></tr><tr><td>1,000 addEdge</td><td>6.06</td><td>165.03</td><td>2.89e-4</td></tr><tr><td>1,000 getVertex</td><td>0.10</td><td>1.05e+4</td><td>9.35e-7</td></tr><tr><td>1,000 getEdge</td><td>23.80</td><td>42.02</td><td>0.00</td></tr><tr><td>tarjan</td><td>193.59</td><td>5.17</td><td>0.01</td></tr><tr><td>topologicalSort</td><td>148.99</td><td>6.71</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.05</td><td>5.23</td><td>0.04</td></tr><tr><td>1,000,000 unshift</td><td>186.38</td><td>5.37</td><td>0.06</td></tr><tr><td>1,000,000 unshift & shift</td><td>151.27</td><td>6.61</td><td>0.00</td></tr><tr><td>1,000,000 addBefore</td><td>267.57</td><td>3.74</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>163.01</td><td>6.13</td><td>0.03</td></tr><tr><td>10,000 push & pop</td><td>246.05</td><td>4.06</td><td>0.04</td></tr><tr><td>10,000 addBefore</td><td>275.54</td><td>3.63</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.54</td><td>32.75</td><td>0.00</td></tr><tr><td>100,000 add & poll</td><td>89.20</td><td>11.21</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.42</td><td>24.74</td><td>0.00</td></tr><tr><td>1,000,000 push & pop</td><td>47.90</td><td>20.88</td><td>0.01</td></tr></table></div>
</div>
[//]: # (No deletion!!! End of Replace Section)
@ -1218,4 +1221,4 @@ const {
AVLTree, MinHeap, SinglyLinkedList, DirectedGraph, TreeMultiMap,
DirectedVertex, AVLTreeNode
} = dataStructureTyped;
```
```

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"],
},
}];

4607
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{
"name": "data-structure-typed",
"version": "1.52.6",
"version": "1.52.8",
"description": "Javascript Data Structure. Heap, Binary Tree, Red Black Tree, Linked List, Deque, Trie, HashMap, Directed Graph, Undirected Graph, Binary Search Tree(BST), AVL Tree, Priority Queue, Graph, Queue, Tree Multiset, Singly Linked List, Doubly Linked List, Max Heap, Max Priority Queue, Min Heap, Min Priority Queue, Stack. Benchmark compared with C++ STL. API aligned with ES6 and Java.util. Usability is comparable to Python",
"main": "dist/cjs/index.js",
"module": "dist/mjs/index.js",
@ -9,8 +9,7 @@
"exports": {
".": {
"import": "./dist/mjs/index.js",
"require": "./dist/cjs/index.js",
"types": "./dist/mjs/index.d.ts"
"require": "./dist/cjs/index.js"
}
},
"scripts": {
@ -59,37 +58,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.7",
"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",

4
src/constants/index.ts Normal file
View file

@ -0,0 +1,4 @@
export enum DFSOperation {
VISIT = 0,
PROCESS = 1
}

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

@ -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 {
@ -11,11 +11,11 @@ import type {
AVLTreeMultiMapOptions,
BinaryTreeDeleteResult,
BSTNKeyOrNode,
BTNCallback,
BTNKeyOrNodeOrEntry,
IterationType
BTNPredicate,
IterationType,
BTNEntry
} from '../../types';
import { BTNEntry } from '../../types';
import { IBinaryTree } from '../../interfaces';
import { AVLTree, AVLTreeNode } from './avl-tree';
@ -80,18 +80,18 @@ export class AVLTreeMultiMap<
{
/**
* The constructor initializes a new AVLTreeMultiMap object with optional initial elements.
* @param keysOrNodesOrEntriesOrRawElements - The `keysOrNodesOrEntriesOrRawElements` parameter is an
* @param keysOrNodesOrEntriesOrRaws - The `keysOrNodesOrEntriesOrRaws` parameter is an
* iterable object that can contain either keys, nodes, entries, or raw elements.
* @param [options] - The `options` parameter is an optional object that can be used to customize the
* behavior of the AVLTreeMultiMap. It can include properties such as `compareKeys` and
* `compareValues` functions to define custom comparison logic for keys and values, respectively.
*/
constructor(
keysOrNodesOrEntriesOrRawElements: Iterable<R | BTNKeyOrNodeOrEntry<K, V, NODE>> = [],
keysOrNodesOrEntriesOrRaws: Iterable<R | BTNKeyOrNodeOrEntry<K, V, NODE>> = [],
options?: AVLTreeMultiMapOptions<K, V, R>
) {
super([], options);
if (keysOrNodesOrEntriesOrRawElements) this.addMany(keysOrNodesOrEntriesOrRawElements);
if (keysOrNodesOrEntriesOrRaws) this.addMany(keysOrNodesOrEntriesOrRaws);
}
protected _count = 0;
@ -144,29 +144,28 @@ export class AVLTreeMultiMap<
override createTree(options?: AVLTreeMultiMapOptions<K, V, R>): TREE {
return new AVLTreeMultiMap<K, V, R, NODE, TREE>([], {
iterationType: this.iterationType,
comparator: this.comparator,
comparator: this._comparator,
toEntryFn: this._toEntryFn,
...options
}) as TREE;
}
/**
* The function checks if the input is an instance of AVLTreeMultiMapNode.
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} keyOrNodeOrEntryOrRawElement - The parameter
* `keyOrNodeOrEntryOrRawElement` can be of type `R` or `BTNKeyOrNodeOrEntry<K, V, NODE>`.
* @returns a boolean value indicating whether the input parameter `keyOrNodeOrEntryOrRawElement` is
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - The parameter
* `keyOrNodeOrEntryOrRaw` can be of type `R` or `BTNKeyOrNodeOrEntry<K, V, NODE>`.
* @returns a boolean value indicating whether the input parameter `keyOrNodeOrEntryOrRaw` is
* an instance of the `AVLTreeMultiMapNode` class.
*/
override isNode(
keyOrNodeOrEntryOrRawElement: R | BTNKeyOrNodeOrEntry<K, V, NODE>
): keyOrNodeOrEntryOrRawElement is NODE {
return keyOrNodeOrEntryOrRawElement instanceof AVLTreeMultiMapNode;
override isNode(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R): keyOrNodeOrEntryOrRaw is NODE {
return keyOrNodeOrEntryOrRaw instanceof AVLTreeMultiMapNode;
}
/**
* The function `keyValueOrEntryOrRawElementToNode` converts a key, value, entry, or raw element into
* a node object.
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} keyOrNodeOrEntryOrRawElement - The
* `keyOrNodeOrEntryOrRawElement` parameter can be of type `R` or `BTNKeyOrNodeOrEntry<K, V, NODE>`.
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - The
* `keyOrNodeOrEntryOrRaw` parameter can be of type `R` or `BTNKeyOrNodeOrEntry<K, V, NODE>`.
* @param {V} [value] - The `value` parameter is an optional value that can be passed to the
* `override` function. It represents the value associated with the key in the data structure. If no
* value is provided, it will default to `undefined`.
@ -175,25 +174,25 @@ export class AVLTreeMultiMap<
* @returns either a NODE object or undefined.
*/
override keyValueOrEntryOrRawElementToNode(
keyOrNodeOrEntryOrRawElement: R | BTNKeyOrNodeOrEntry<K, V, NODE>,
keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R,
value?: V,
count = 1
): NODE | undefined {
if (keyOrNodeOrEntryOrRawElement === undefined || keyOrNodeOrEntryOrRawElement === null) return;
if (this.isNode(keyOrNodeOrEntryOrRawElement)) return keyOrNodeOrEntryOrRawElement;
if (keyOrNodeOrEntryOrRaw === undefined || keyOrNodeOrEntryOrRaw === null) return;
if (this.isNode(keyOrNodeOrEntryOrRaw)) return keyOrNodeOrEntryOrRaw;
if (this.isEntry(keyOrNodeOrEntryOrRawElement)) {
const [key, entryValue] = keyOrNodeOrEntryOrRawElement;
if (this.isEntry(keyOrNodeOrEntryOrRaw)) {
const [key, entryValue] = keyOrNodeOrEntryOrRaw;
if (key === undefined || key === null) return;
if (this.isKey(key)) return this.createNode(key, value ?? entryValue, count);
}
if (this.toEntryFn) {
const [key, entryValue] = this.toEntryFn(keyOrNodeOrEntryOrRawElement as R);
if (this._toEntryFn) {
const [key, entryValue] = this._toEntryFn(keyOrNodeOrEntryOrRaw as R);
if (this.isKey(key)) return this.createNode(key, value ?? entryValue, count);
}
if (this.isKey(keyOrNodeOrEntryOrRawElement)) return this.createNode(keyOrNodeOrEntryOrRawElement, value, count);
if (this.isKey(keyOrNodeOrEntryOrRaw)) return this.createNode(keyOrNodeOrEntryOrRaw, value, count);
return;
}
@ -204,8 +203,8 @@ export class AVLTreeMultiMap<
*
* The function overrides the add method of a TypeScript class to add a new node to a data structure
* and update the count.
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} keyOrNodeOrEntryOrRawElement - The
* `keyOrNodeOrEntryOrRawElement` parameter can accept a value of type `R`, which can be any type. It
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - The
* `keyOrNodeOrEntryOrRaw` parameter can accept a value of type `R`, which can be any type. It
* can also accept a value of type `BTNKeyOrNodeOrEntry<K, V, NODE>`, which represents a key, node,
* entry, or raw element
* @param {V} [value] - The `value` parameter represents the value associated with the key in the
@ -215,8 +214,8 @@ export class AVLTreeMultiMap<
* be added once. However, you can specify a different value for `count` if you want to add
* @returns a boolean value.
*/
override add(keyOrNodeOrEntryOrRawElement: R | BTNKeyOrNodeOrEntry<K, V, NODE>, value?: V, count = 1): boolean {
const newNode = this.keyValueOrEntryOrRawElementToNode(keyOrNodeOrEntryOrRawElement, value, count);
override add(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R, value?: V, count = 1): boolean {
const newNode = this.keyValueOrEntryOrRawElementToNode(keyOrNodeOrEntryOrRaw, value, count);
if (newNode === undefined) return false;
const orgNodeCount = newNode?.count || 0;
@ -231,31 +230,29 @@ export class AVLTreeMultiMap<
* Time Complexity: O(log n)
* Space Complexity: O(1)
*
* The `delete` function in a binary tree data structure deletes a node based on its identifier and
* returns the deleted node along with the parent node that needs to be balanced.
* @param identifier - The identifier parameter is the value used to identify the node that needs to
* be deleted from the binary tree. It can be of any type and is the return type of the callback
* function.
* @param {C} callback - The `callback` parameter is a function that is used to determine the
* equality of nodes in the binary tree. It is optional and has a default value of
* `this._DEFAULT_CALLBACK`. The `callback` function takes a single argument, which is the identifier
* of a node, and returns a value that
* @param [ignoreCount=false] - A boolean flag indicating whether to ignore the count of the node
* being deleted. If set to true, the count of the node will not be considered and the node will be
* deleted regardless of its count. If set to false (default), the count of the node will be taken
* into account and the node
* @returns an array of `BinaryTreeDeleteResult<NODE>`.
* The function overrides the delete method in a binary tree data structure, handling deletion of
* nodes and maintaining balance in the tree.
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R | BTNPredicate<NODE>} predicate - The `predicate`
* parameter in the `delete` method is used to specify the condition for deleting a node from the
* binary tree. It can be a key, node, entry, or a custom predicate function that determines which
* node(s) should be deleted.
* @param [ignoreCount=false] - The `ignoreCount` parameter in the `override delete` method is a
* boolean flag that determines whether to ignore the count of the node being deleted. If
* `ignoreCount` is set to `true`, the method will delete the node regardless of its count. If
* `ignoreCount` is set to
* @returns The `delete` method overrides the default delete behavior in a binary tree data
* structure. It takes a predicate or node to be deleted and an optional flag to ignore count. The
* method returns an array of `BinaryTreeDeleteResult` objects, each containing information about the
* deleted node and whether balancing is needed in the tree.
*/
override delete<C extends BTNCallback<NODE>>(
identifier: ReturnType<C>,
callback: C = this._DEFAULT_CALLBACK as C,
override delete(
predicate: BTNKeyOrNodeOrEntry<K, V, NODE> | R | BTNPredicate<NODE>,
ignoreCount = false
): BinaryTreeDeleteResult<NODE>[] {
const deletedResult: BinaryTreeDeleteResult<NODE>[] = [];
if (!this.root) return deletedResult;
callback = this._ensureCallback(identifier, callback);
const curr: NODE | undefined = this.getNode(identifier, callback) ?? undefined;
const curr: NODE | undefined = this.getNode(predicate) ?? undefined;
if (!curr) return deletedResult;
const parent: NODE | undefined = curr?.parent ? curr.parent : undefined;
@ -293,7 +290,7 @@ export class AVLTreeMultiMap<
}
}
}
this._size = this.size - 1;
this._size = this._size - 1;
// TODO How to handle when the count of target node is lesser than current node's count
if (orgCurrent) this._count -= orgCurrent.count;
}

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 { BST, BSTNode } from './bst';
@ -12,10 +12,10 @@ import type {
AVLTreeOptions,
BinaryTreeDeleteResult,
BSTNKeyOrNode,
BTNCallback,
BTNKeyOrNodeOrEntry
BTNKeyOrNodeOrEntry,
BTNPredicate,
BTNEntry
} from '../../types';
import { BTNEntry } from '../../types';
import { IBinaryTree } from '../../interfaces';
export class AVLTreeNode<
@ -78,7 +78,7 @@ export class AVLTree<
/**
* This is a constructor function for an AVLTree class that initializes the tree with keys, nodes,
* entries, or raw elements.
* @param keysOrNodesOrEntriesOrRawElements - The `keysOrNodesOrEntriesOrRawElements` parameter is an
* @param keysOrNodesOrEntriesOrRaws - The `keysOrNodesOrEntriesOrRaws` parameter is an
* iterable object that can contain either keys, nodes, entries, or raw elements. These elements will
* be used to initialize the AVLTree.
* @param [options] - The `options` parameter is an optional object that can be used to customize the
@ -87,11 +87,11 @@ export class AVLTree<
* `nodeBuilder` (
*/
constructor(
keysOrNodesOrEntriesOrRawElements: Iterable<R | BTNKeyOrNodeOrEntry<K, V, NODE>> = [],
keysOrNodesOrEntriesOrRaws: Iterable<R | BTNKeyOrNodeOrEntry<K, V, NODE>> = [],
options?: AVLTreeOptions<K, V, R>
) {
super([], options);
if (keysOrNodesOrEntriesOrRawElements) super.addMany(keysOrNodesOrEntriesOrRawElements);
if (keysOrNodesOrEntriesOrRaws) super.addMany(keysOrNodesOrEntriesOrRaws);
}
/**
@ -117,22 +117,21 @@ export class AVLTree<
override createTree(options?: AVLTreeOptions<K, V, R>): TREE {
return new AVLTree<K, V, R, NODE, TREE>([], {
iterationType: this.iterationType,
comparator: this.comparator,
comparator: this._comparator,
toEntryFn: this._toEntryFn,
...options
}) as TREE;
}
/**
* The function checks if the input is an instance of AVLTreeNode.
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} keyOrNodeOrEntryOrRawElement - The parameter
* `keyOrNodeOrEntryOrRawElement` can be of type `R` or `BTNKeyOrNodeOrEntry<K, V, NODE>`.
* @returns a boolean value indicating whether the input parameter `keyOrNodeOrEntryOrRawElement` is
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - The parameter
* `keyOrNodeOrEntryOrRaw` can be of type `R` or `BTNKeyOrNodeOrEntry<K, V, NODE>`.
* @returns a boolean value indicating whether the input parameter `keyOrNodeOrEntryOrRaw` is
* an instance of the `AVLTreeNode` class.
*/
override isNode(
keyOrNodeOrEntryOrRawElement: R | BTNKeyOrNodeOrEntry<K, V, NODE>
): keyOrNodeOrEntryOrRawElement is NODE {
return keyOrNodeOrEntryOrRawElement instanceof AVLTreeNode;
override isNode(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R): keyOrNodeOrEntryOrRaw is NODE {
return keyOrNodeOrEntryOrRaw instanceof AVLTreeNode;
}
/**
@ -141,17 +140,17 @@ export class AVLTree<
*
* The function overrides the add method of a class and inserts a key-value pair into a data
* structure, then balances the path.
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} keyOrNodeOrEntryOrRawElement - The parameter
* `keyOrNodeOrEntryOrRawElement` can accept values of type `R`, `BTNKeyOrNodeOrEntry<K, V, NODE>`, or
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - The parameter
* `keyOrNodeOrEntryOrRaw` can accept values of type `R`, `BTNKeyOrNodeOrEntry<K, V, NODE>`, or
* `RawElement`.
* @param {V} [value] - The `value` parameter is an optional value that you want to associate with
* the key or node being added to the data structure.
* @returns The method is returning a boolean value.
*/
override add(keyOrNodeOrEntryOrRawElement: R | BTNKeyOrNodeOrEntry<K, V, NODE>, value?: V): boolean {
if (keyOrNodeOrEntryOrRawElement === null) return false;
const inserted = super.add(keyOrNodeOrEntryOrRawElement, value);
if (inserted) this._balancePath(keyOrNodeOrEntryOrRawElement);
override add(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R, value?: V): boolean {
if (keyOrNodeOrEntryOrRaw === null) return false;
const inserted = super.add(keyOrNodeOrEntryOrRaw, value);
if (inserted) this._balancePath(keyOrNodeOrEntryOrRaw);
return inserted;
}
@ -159,20 +158,17 @@ export class AVLTree<
* Time Complexity: O(log n)
* Space Complexity: O(1)
*
* The function overrides the delete method of a binary tree class and performs additional operations
* to balance the tree after deletion.
* @param identifier - The `identifier` parameter is the value or condition used to identify the
* node(s) to be deleted from the binary tree. It can be of any type that is compatible with the
* binary tree's node type.
* @param {C} callback - The `callback` parameter is a function that will be used to determine if a
* node should be deleted or not. It is optional and has a default value of `this._DEFAULT_CALLBACK`.
* @returns The method is returning an array of BinaryTreeDeleteResult<NODE> objects.
* The function overrides the delete method in a TypeScript class, performs deletion, and then
* balances the tree if necessary.
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R | BTNPredicate<NODE>} predicate - The `predicate`
* parameter in the `override delete` method can be one of the following types:
* @returns The `delete` method is being overridden in this code snippet. It first calls the `delete`
* method from the superclass (presumably a parent class) with the provided `predicate`, which could
* be a key, node, entry, or a custom predicate. The result of this deletion operation is stored in
* `deletedResults`, which is an array of `BinaryTreeDeleteResult` objects.
*/
override delete<C extends BTNCallback<NODE>>(
identifier: ReturnType<C>,
callback: C = this._DEFAULT_CALLBACK as C
): BinaryTreeDeleteResult<NODE>[] {
const deletedResults = super.delete(identifier, callback);
override delete(predicate: BTNKeyOrNodeOrEntry<K, V, NODE> | R | BTNPredicate<NODE>): BinaryTreeDeleteResult<NODE>[] {
const deletedResults = super.delete(predicate);
for (const { needBalanced } of deletedResults) {
if (needBalanced) {
this._balancePath(needBalanced);
@ -339,8 +335,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 +374,7 @@ export class AVLTree<
B.left = A;
}
this._updateHeight(A);
B && this._updateHeight(B);
if (B) this._updateHeight(B);
}
/**
@ -427,8 +423,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);
}
/**
@ -437,46 +433,48 @@ export class AVLTree<
*
* The `_balancePath` function is used to update the heights of nodes and perform rotation operations
* to restore balance in an AVL tree after inserting a node.
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} node - The `node` parameter can be of type `R` or
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} node - The `node` parameter can be of type `R` or
* `BTNKeyOrNodeOrEntry<K, V, NODE>`.
*/
protected _balancePath(node: R | BTNKeyOrNodeOrEntry<K, V, NODE>): void {
protected _balancePath(node: BTNKeyOrNodeOrEntry<K, V, NODE> | R): 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

@ -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 { getMSB } from '../../utils';

File diff suppressed because it is too large Load diff

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 {
@ -11,7 +11,9 @@ import type {
BSTNodeNested,
BSTOptions,
BTNCallback,
BTNEntry,
BTNKeyOrNodeOrEntry,
BTNPredicate,
BTNPureKeyOrNodeOrEntry,
Comparator,
CP,
@ -19,7 +21,6 @@ import type {
IterationType,
OptBSTN
} from '../../types';
import { BTNEntry } from '../../types';
import { BinaryTree, BinaryTreeNode } from './binary-tree';
import { IBinaryTree } from '../../interfaces';
import { Queue } from '../queue';
@ -106,14 +107,14 @@ export class BST<
{
/**
* This is the constructor function for a Binary Search Tree class in TypeScript.
* @param keysOrNodesOrEntriesOrRawElements - The `keysOrNodesOrEntriesOrRawElements` parameter is an
* @param keysOrNodesOrEntriesOrRaws - The `keysOrNodesOrEntriesOrRaws` parameter is an
* iterable that can contain either keys, nodes, entries, or raw elements. These elements will be
* added to the binary search tree during the construction of the object.
* @param [options] - An optional object that contains additional options for the Binary Search Tree.
* It can include a comparator function that defines the order of the elements in the tree.
*/
constructor(
keysOrNodesOrEntriesOrRawElements: Iterable<R | BTNKeyOrNodeOrEntry<K, V, NODE>> = [],
keysOrNodesOrEntriesOrRaws: Iterable<R | BTNKeyOrNodeOrEntry<K, V, NODE>> = [],
options?: BSTOptions<K, V, R>
) {
super([], options);
@ -123,7 +124,7 @@ export class BST<
if (comparator) this._comparator = comparator;
}
if (keysOrNodesOrEntriesOrRawElements) this.addMany(keysOrNodesOrEntriesOrRawElements);
if (keysOrNodesOrEntriesOrRaws) this.addMany(keysOrNodesOrEntriesOrRaws);
}
protected override _root?: NODE = undefined;
@ -155,17 +156,18 @@ export class BST<
* following properties:
* @returns a new instance of the BST class with the provided options.
*/
override createTree(options?: Partial<BSTOptions<K, V, R>>): TREE {
override createTree(options?: BSTOptions<K, V, R>): TREE {
return new BST<K, V, R, NODE, TREE>([], {
iterationType: this.iterationType,
comparator: this.comparator,
comparator: this._comparator,
toEntryFn: this._toEntryFn,
...options
}) as TREE;
}
/**
* The function overrides a method and converts a key, value pair or entry or raw element to a node.
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} keyOrNodeOrEntryOrRawElement - A variable that can be of
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - A variable that can be of
* type R or BTNKeyOrNodeOrEntry<K, V, NODE>. It represents either a key, a node, an entry, or a raw
* element.
* @param {V} [value] - The `value` parameter is an optional value of type `V`. It represents the
@ -173,10 +175,10 @@ export class BST<
* @returns either a NODE object or undefined.
*/
override keyValueOrEntryOrRawElementToNode(
keyOrNodeOrEntryOrRawElement: R | BTNKeyOrNodeOrEntry<K, V, NODE>,
keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R,
value?: V
): OptBSTN<NODE> {
return super.keyValueOrEntryOrRawElementToNode(keyOrNodeOrEntryOrRawElement, value) ?? undefined;
return super.keyValueOrEntryOrRawElementToNode(keyOrNodeOrEntryOrRaw, value) ?? undefined;
}
/**
@ -185,8 +187,8 @@ export class BST<
*
* The function ensures the existence of a node in a data structure and returns it, or undefined if
* it doesn't exist.
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} keyOrNodeOrEntryOrRawElement - The parameter
* `keyOrNodeOrEntryOrRawElement` can accept a value of type `R`, which represents the key, node,
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - The parameter
* `keyOrNodeOrEntryOrRaw` can accept a value of type `R`, which represents the key, node,
* entry, or raw element that needs to be ensured in the tree.
* @param {IterationType} [iterationType=ITERATIVE] - The `iterationType` parameter is an optional
* parameter that specifies the type of iteration to be used when ensuring a node. It has a default
@ -195,25 +197,31 @@ export class BST<
* not be ensured.
*/
override ensureNode(
keyOrNodeOrEntryOrRawElement: R | BTNKeyOrNodeOrEntry<K, V, NODE>,
keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R,
iterationType: IterationType = this.iterationType
): OptBSTN<NODE> {
return super.ensureNode(keyOrNodeOrEntryOrRawElement, iterationType) ?? undefined;
return super.ensureNode(keyOrNodeOrEntryOrRaw, iterationType) ?? undefined;
}
/**
* The function checks if the input is an instance of the BSTNode class.
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} keyOrNodeOrEntryOrRawElement - The parameter
* `keyOrNodeOrEntryOrRawElement` can be of type `R` or `BTNKeyOrNodeOrEntry<K, V, NODE>`.
* @returns a boolean value indicating whether the input parameter `keyOrNodeOrEntryOrRawElement` is
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - The parameter
* `keyOrNodeOrEntryOrRaw` can be of type `R` or `BTNKeyOrNodeOrEntry<K, V, NODE>`.
* @returns a boolean value indicating whether the input parameter `keyOrNodeOrEntryOrRaw` is
* an instance of the `BSTNode` class.
*/
override isNode(
keyOrNodeOrEntryOrRawElement: R | BTNKeyOrNodeOrEntry<K, V, NODE>
): keyOrNodeOrEntryOrRawElement is NODE {
return keyOrNodeOrEntryOrRawElement instanceof BSTNode;
override isNode(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R): keyOrNodeOrEntryOrRaw is NODE {
return keyOrNodeOrEntryOrRaw instanceof BSTNode;
}
/**
* The function "override isKey" checks if a key is comparable based on a given comparator.
* @param {any} key - The `key` parameter is a value that will be checked to determine if it is of
* type `K`.
* @returns The `override isKey(key: any): key is K` function is returning a boolean value based on
* the result of the `isComparable` function with the condition `this.comparator !==
* this._DEFAULT_COMPARATOR`.
*/
override isKey(key: any): key is K {
return isComparable(key, this.comparator !== this._DEFAULT_COMPARATOR);
}
@ -223,23 +231,23 @@ export class BST<
* Space Complexity: O(1)
*
* The `add` function in TypeScript adds a new node to a binary search tree based on the key value.
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} keyOrNodeOrEntryOrRawElement - The parameter
* `keyOrNodeOrEntryOrRawElement` can accept a value of type `R` or `BTNKeyOrNodeOrEntry<K, V, NODE>`.
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - The parameter
* `keyOrNodeOrEntryOrRaw` can accept a value of type `R` or `BTNKeyOrNodeOrEntry<K, V, NODE>`.
* @param {V} [value] - The `value` parameter is an optional value that can be associated with the
* key in the binary search tree. If provided, it will be stored in the node along with the key.
* @returns a boolean value.
*/
override add(keyOrNodeOrEntryOrRawElement: R | BTNKeyOrNodeOrEntry<K, V, NODE>, value?: V): boolean {
const newNode = this.keyValueOrEntryOrRawElementToNode(keyOrNodeOrEntryOrRawElement, value);
override add(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R, value?: V): boolean {
const newNode = this.keyValueOrEntryOrRawElementToNode(keyOrNodeOrEntryOrRaw, value);
if (newNode === undefined) return false;
if (this.root === undefined) {
if (this._root === undefined) {
this._setRoot(newNode);
this._size++;
return true;
}
let current = this.root;
let current = this._root;
while (current !== undefined) {
if (this.comparator(current.key, newNode.key) === 0) {
this._replaceNode(current, newNode);
@ -270,7 +278,7 @@ export class BST<
*
* The `addMany` function in TypeScript adds multiple keys or nodes to a data structure and returns
* an array indicating whether each key or node was successfully inserted.
* @param keysOrNodesOrEntriesOrRawElements - An iterable containing keys, nodes, entries, or raw
* @param keysOrNodesOrEntriesOrRaws - An iterable containing keys, nodes, entries, or raw
* elements to be added to the data structure.
* @param [values] - An optional iterable of values to be associated with the keys or nodes being
* added. If provided, the values will be assigned to the corresponding keys or nodes in the same
@ -286,7 +294,7 @@ export class BST<
* successfully inserted into the data structure.
*/
override addMany(
keysOrNodesOrEntriesOrRawElements: Iterable<R | BTNKeyOrNodeOrEntry<K, V, NODE>>,
keysOrNodesOrEntriesOrRaws: Iterable<R | BTNKeyOrNodeOrEntry<K, V, NODE>>,
values?: Iterable<V | undefined>,
isBalanceAdd = true,
iterationType: IterationType = this.iterationType
@ -300,7 +308,7 @@ export class BST<
}
if (!isBalanceAdd) {
for (const kve of keysOrNodesOrEntriesOrRawElements) {
for (const kve of keysOrNodesOrEntriesOrRaws) {
const value = valuesIterator?.next().value;
const nn = this.add(kve, value);
inserted.push(nn);
@ -311,14 +319,14 @@ export class BST<
const realBTNExemplars: (R | BTNPureKeyOrNodeOrEntry<K, V, NODE>)[] = [];
const isRealBTNExemplar = (
kve: R | BTNKeyOrNodeOrEntry<K, V, NODE>
kve: BTNKeyOrNodeOrEntry<K, V, NODE> | R
): kve is BTNPureKeyOrNodeOrEntry<K, V, NODE> => {
if (kve === undefined || kve === null) return false;
return !(this.isEntry(kve) && (kve[0] === undefined || kve[0] === null));
};
for (const kve of keysOrNodesOrEntriesOrRawElements) {
isRealBTNExemplar(kve) && realBTNExemplars.push(kve);
for (const kve of keysOrNodesOrEntriesOrRaws) {
if (isRealBTNExemplar(kve)) realBTNExemplars.push(kve);
}
let sorted: (R | BTNPureKeyOrNodeOrEntry<K, V, NODE>)[] = [];
@ -327,16 +335,16 @@ export class BST<
let keyA: K | undefined | null, keyB: K | undefined | null;
if (this.isEntry(a)) keyA = a[0];
else if (this.isRealNode(a)) keyA = a.key;
else if (this.toEntryFn) {
keyA = this.toEntryFn(a as R)[0];
else if (this._toEntryFn) {
keyA = this._toEntryFn(a as R)[0];
} else {
keyA = a as K;
}
if (this.isEntry(b)) keyB = b[0];
else if (this.isRealNode(b)) keyB = b.key;
else if (this.toEntryFn) {
keyB = this.toEntryFn(b as R)[0];
else if (this._toEntryFn) {
keyB = this._toEntryFn(b as R)[0];
} else {
keyB = b as K;
}
@ -388,54 +396,52 @@ export class BST<
* Time Complexity: O(log n)
* Space Complexity: O(k + log n)
*
* The `getNodes` function in TypeScript retrieves nodes from a binary tree based on a given
* identifier and callback function.
* @param {ReturnType<C> | undefined} identifier - The `identifier` parameter is the value that you
* want to search for in the binary tree. It can be of any type that is returned by the callback
* function.
* @param {C} callback - The `callback` parameter is a function that takes a node as input and
* returns a value. This value is used to identify the nodes that match the given identifier. The
* `callback` function is optional and defaults to `this._DEFAULT_CALLBACK`.
* @param [onlyOne=false] - A boolean value indicating whether to return only the first matching node
* or all matching nodes. If set to true, only the first matching node will be returned. If set to
* false, all matching nodes will be returned. The default value is false.
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} beginRoot - The `beginRoot` parameter is the starting
* point for the search in the binary tree. It can be either a node object, a key-value pair, or an
* entry object. If it is not provided, the `root` of the binary tree is used as the starting point.
* @param {IterationType} iterationType - The `iterationType` parameter determines the type of
* iteration to be performed. It can have two possible values:
* @returns The method `getNodes` returns an array of `NODE` objects.
* The function `getNodes` in TypeScript overrides the base class method to retrieve nodes based on a
* given predicate and iteration type.
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R | BTNPredicate<NODE>} predicate - The `predicate`
* parameter in the `getNodes` method is used to filter the nodes that will be returned. It can be a
* key, a node, an entry, or a custom predicate function that determines whether a node should be
* included in the result.
* @param [onlyOne=false] - The `onlyOne` parameter in the `getNodes` method is a boolean flag that
* determines whether to return only the first node that matches the predicate (`true`) or all nodes
* that match the predicate (`false`). If `onlyOne` is set to `true`, the method will stop iterating
* and
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} beginRoot - The `beginRoot` parameter in the
* `getNodes` method is used to specify the starting point for traversing the tree when searching for
* nodes that match a given predicate. It represents the root node of the subtree where the search
* should begin. If not explicitly provided, the default value for `begin
* @param {IterationType} iterationType - The `iterationType` parameter in the `getNodes` method
* specifies the type of iteration to be performed when traversing the nodes of a binary tree. It can
* have two possible values:
* @returns The `getNodes` method returns an array of nodes that satisfy the given predicate.
*/
override getNodes<C extends BTNCallback<NODE>>(
identifier: ReturnType<C> | undefined,
callback: C = this._DEFAULT_CALLBACK as C,
override getNodes(
predicate: BTNKeyOrNodeOrEntry<K, V, NODE> | R | BTNPredicate<NODE>,
onlyOne = false,
beginRoot: R | BTNKeyOrNodeOrEntry<K, V, NODE> = this.root,
beginRoot: BTNKeyOrNodeOrEntry<K, V, NODE> | R = this._root,
iterationType: IterationType = this.iterationType
): NODE[] {
if (identifier === undefined) return [];
if (identifier === null) return [];
if (predicate === undefined) return [];
if (predicate === null) return [];
beginRoot = this.ensureNode(beginRoot);
if (!beginRoot) return [];
callback = this._ensureCallback(identifier, callback);
const callback = this._ensurePredicate(predicate);
const ans: NODE[] = [];
if (iterationType === 'RECURSIVE') {
const dfs = (cur: NODE) => {
const callbackResult = callback(cur);
if (callbackResult === identifier) {
if (callback(cur)) {
ans.push(cur);
if (onlyOne) return;
}
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return;
// TODO potential bug
if (callback === this._DEFAULT_CALLBACK) {
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);
if (this.isKey(predicate)) {
if (this.isRealNode(cur.left) && this.comparator(cur.key, predicate) > 0) dfs(cur.left);
if (this.isRealNode(cur.right) && this.comparator(cur.key, predicate) < 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);
}
};
@ -444,26 +450,16 @@ export class BST<
const stack = [beginRoot];
while (stack.length > 0) {
const cur = stack.pop()!;
const callbackResult = callback(cur);
if (callbackResult === identifier) {
if (callback(cur)) {
ans.push(cur);
if (onlyOne) return ans;
}
// TODO potential bug
if (callback === this._DEFAULT_CALLBACK) {
if (this.isRealNode(cur.right) && this.comparator(cur.key, identifier as K) < 0) stack.push(cur.right);
if (this.isRealNode(cur.left) && this.comparator(cur.key, identifier as K) > 0) stack.push(cur.left);
// if (this.isRealNode(cur.right) && this._lt(cur.key, identifier as K)) stack.push(cur.right);
// if (this.isRealNode(cur.left) && this._gt(cur.key, identifier as K)) stack.push(cur.left);
// // @ts-ignore
// if (this.isRealNode(cur.right) && cur.key > identifier) stack.push(cur.right);
// // @ts-ignore
// if (this.isRealNode(cur.left) && cur.key < identifier) stack.push(cur.left);
if (this.isKey(predicate)) {
if (this.isRealNode(cur.right) && this.comparator(cur.key, predicate) < 0) stack.push(cur.right);
if (this.isRealNode(cur.left) && this.comparator(cur.key, predicate) > 0) 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);
}
}
}
@ -475,30 +471,28 @@ export class BST<
* Time Complexity: O(log n)
* Space Complexity: O(1)
*
* The function `getNode` returns the first node that matches the given identifier and callback
* function in a binary search tree.
* @param {ReturnType<C> | undefined} identifier - The `identifier` parameter is the value that you
* want to search for in the binary search tree. It can be of any type that is compatible with the
* type returned by the callback function.
* @param {C} callback - The `callback` parameter is a function that will be used to determine if a
* node matches the desired criteria. It should be a function that takes a node as an argument and
* returns a boolean value indicating whether the node matches the criteria or not. If no callback is
* provided, the default callback will be
* @param beginRoot - The `beginRoot` parameter is the starting point for the search in the binary
* search tree. It can be either a key or a node. If it is a key, the search will start from the node
* with that key. If it is a node, the search will start from that node.
* @param {IterationType} iterationType - The `iterationType` parameter is used to specify the type
* of iteration to be performed when searching for nodes in the binary search tree. It can have one
* of the following values:
* @returns The method is returning a NODE object or undefined.
* This function retrieves a node based on a given predicate within a binary search tree structure.
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R | BTNPredicate<NODE>} predicate - The `predicate`
* parameter can be of type `BTNKeyOrNodeOrEntry<K, V, NODE>`, `R`, or `BTNPredicate<NODE>`.
* @param {R | BSTNKeyOrNode<K, NODE>} beginRoot - The `beginRoot` parameter in the `getNode` method
* is used to specify the starting point for searching nodes in the binary search tree. If no
* specific starting point is provided, the default value is set to `this._root`, which is the root
* node of the binary search tree.
* @param {IterationType} iterationType - The `iterationType` parameter in the `getNode` method is a
* parameter that specifies the type of iteration to be used. It has a default value of
* `this.iterationType`, which means it will use the iteration type defined in the class instance if
* no value is provided when calling the method.
* @returns The `getNode` method is returning an optional binary search tree node (`OptBSTN<NODE>`).
* It is using the `getNodes` method to find the node based on the provided predicate, beginning at
* the specified root node (`beginRoot`) and using the specified iteration type. The method then
* returns the first node found or `undefined` if no node is found.
*/
override getNode<C extends BTNCallback<NODE>>(
identifier: ReturnType<C> | undefined,
callback: C = this._DEFAULT_CALLBACK as C,
beginRoot: R | BSTNKeyOrNode<K, NODE> = this.root,
override getNode(
predicate: BTNKeyOrNodeOrEntry<K, V, NODE> | R | BTNPredicate<NODE>,
beginRoot: R | BSTNKeyOrNode<K, NODE> = this._root,
iterationType: IterationType = this.iterationType
): OptBSTN<NODE> {
return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? undefined;
return this.getNodes(predicate, true, beginRoot, iterationType)[0] ?? undefined;
}
/**
@ -515,7 +509,7 @@ export class BST<
* @returns The method is returning a NODE object or undefined.
*/
override getNodeByKey(key: K, iterationType: IterationType = this.iterationType): OptBSTN<NODE> {
return this.getNode(key, this._DEFAULT_CALLBACK, this.root, iterationType);
return this.getNode(key, this._root, iterationType);
}
/**
@ -526,11 +520,11 @@ export class BST<
* the callback function.
* @param {C} callback - The `callback` parameter is a function that will be called for each node
* during the depth-first search traversal. It is an optional parameter and defaults to
* `this._DEFAULT_CALLBACK`. The type `C` represents the type of the callback function.
* `this._DEFAULT_BTN_CALLBACK`. The type `C` represents the type of the callback function.
* @param {DFSOrderPattern} [pattern=IN] - The "pattern" parameter in the code snippet refers to the
* order in which the Depth-First Search (DFS) algorithm visits the nodes in a tree or graph. It can
* take one of the following values:
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} beginRoot - The `beginRoot` parameter is the starting
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} beginRoot - The `beginRoot` parameter is the starting
* point for the depth-first search traversal. It can be either a root node, a key-value pair, or a
* node entry. If not specified, the default value is the root of the tree.
* @param {IterationType} [iterationType=ITERATIVE] - The `iterationType` parameter specifies the
@ -539,9 +533,9 @@ export class BST<
* @returns The method is returning an array of the return type of the callback function.
*/
override dfs<C extends BTNCallback<NODE>>(
callback: C = this._DEFAULT_CALLBACK as C,
callback: C = this._DEFAULT_BTN_CALLBACK as C,
pattern: DFSOrderPattern = 'IN',
beginRoot: R | BTNKeyOrNodeOrEntry<K, V, NODE> = this.root,
beginRoot: BTNKeyOrNodeOrEntry<K, V, NODE> | R = this._root,
iterationType: IterationType = this.iterationType
): ReturnType<C>[] {
return super.dfs(callback, pattern, beginRoot, iterationType);
@ -556,7 +550,7 @@ export class BST<
* @param {C} callback - The `callback` parameter is a function that will be called for each node
* visited during the breadth-first search. It should take a single argument, which is the current
* node being visited, and it can return a value of any type.
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} beginRoot - The `beginRoot` parameter is the starting
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} beginRoot - The `beginRoot` parameter is the starting
* point for the breadth-first search. It can be either a root node, a key-value pair, or an entry
* object. If no value is provided, the default value is the root of the tree.
* @param {IterationType} iterationType - The `iterationType` parameter is used to specify the type
@ -565,8 +559,8 @@ export class BST<
* @returns an array of the return type of the callback function.
*/
override bfs<C extends BTNCallback<NODE>>(
callback: C = this._DEFAULT_CALLBACK as C,
beginRoot: R | BTNKeyOrNodeOrEntry<K, V, NODE> = this.root,
callback: C = this._DEFAULT_BTN_CALLBACK as C,
beginRoot: BTNKeyOrNodeOrEntry<K, V, NODE> | R = this._root,
iterationType: IterationType = this.iterationType
): ReturnType<C>[] {
return super.bfs(callback, beginRoot, iterationType, false);
@ -581,7 +575,7 @@ export class BST<
* @param {C} callback - The `callback` parameter is a generic type `C` that extends
* `BTNCallback<NODE>`. It represents a callback function that will be called for each node in the
* tree during the iteration process.
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} beginRoot - The `beginRoot` parameter is the starting
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} beginRoot - The `beginRoot` parameter is the starting
* point for listing the levels of the binary tree. It can be either a root node of the tree, a
* key-value pair representing a node in the tree, or a key representing a node in the tree. If no
* value is provided, the root of
@ -591,8 +585,8 @@ export class BST<
* function.
*/
override listLevels<C extends BTNCallback<NODE>>(
callback: C = this._DEFAULT_CALLBACK as C,
beginRoot: R | BTNKeyOrNodeOrEntry<K, V, NODE> = this.root,
callback: C = this._DEFAULT_BTN_CALLBACK as C,
beginRoot: BTNKeyOrNodeOrEntry<K, V, NODE> | R = this._root,
iterationType: IterationType = this.iterationType
): ReturnType<C>[][] {
return super.listLevels(callback, beginRoot, iterationType, false);
@ -610,7 +604,7 @@ export class BST<
* @param {CP} lesserOrGreater - The `lesserOrGreater` parameter is used to determine whether to
* traverse nodes that are lesser, greater, or both than the `targetNode`. It accepts the values -1,
* 0, or 1, where:
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} targetNode - The `targetNode` parameter is the node in
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} targetNode - The `targetNode` parameter is the node in
* the binary tree that you want to start traversing from. It can be specified either by providing
* the key of the node, the node itself, or an entry containing the key and value of the node. If no
* `targetNode` is provided,
@ -620,15 +614,15 @@ export class BST<
* `ReturnType<C>`, which is the return type of the callback function passed as an argument.
*/
lesserOrGreaterTraverse<C extends BTNCallback<NODE>>(
callback: C = this._DEFAULT_CALLBACK as C,
callback: C = this._DEFAULT_BTN_CALLBACK as C,
lesserOrGreater: CP = -1,
targetNode: R | BTNKeyOrNodeOrEntry<K, V, NODE> = this.root,
targetNode: BTNKeyOrNodeOrEntry<K, V, NODE> | R = this._root,
iterationType: IterationType = this.iterationType
): ReturnType<C>[] {
const targetNodeEnsured = this.ensureNode(targetNode);
const ans: ReturnType<BTNCallback<NODE>>[] = [];
if (!this._root) return ans;
if (!targetNodeEnsured) return ans;
if (!this.root) return ans;
const targetKey = targetNodeEnsured.key;
@ -641,10 +635,10 @@ export class BST<
if (this.isRealNode(cur.right)) dfs(cur.right);
};
dfs(this.root);
dfs(this._root);
return ans;
} else {
const queue = new Queue<NODE>([this.root]);
const queue = new Queue<NODE>([this._root]);
while (queue.size > 0) {
const cur = queue.shift();
if (this.isRealNode(cur)) {
@ -721,7 +715,7 @@ export class BST<
* @returns a boolean value.
*/
isAVLBalanced(iterationType: IterationType = this.iterationType): boolean {
if (!this.root) return true;
if (!this._root) return true;
let balanced = true;
@ -733,10 +727,10 @@ export class BST<
if (Math.abs(leftHeight - rightHeight) > 1) balanced = false;
return Math.max(leftHeight, rightHeight) + 1;
};
_height(this.root);
_height(this._root);
} else {
const stack: NODE[] = [];
let node: OptBSTN<NODE> = this.root,
let node: OptBSTN<NODE> = this._root,
last: OptBSTN<NODE> = undefined;
const depths: Map<NODE, number> = new Map();
@ -749,8 +743,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

@ -1,14 +1,15 @@
import type {
BinaryTreeDeleteResult,
BTNCallback,
BTNKeyOrNodeOrEntry,
BTNPredicate,
CRUD,
OptBSTN,
RBTNColor,
RBTreeOptions,
RedBlackTreeNested,
RedBlackTreeNodeNested
RedBlackTreeNodeNested,
BTNEntry
} from '../../types';
import { BTNEntry } from '../../types';
import { BST, BSTNode } from './bst';
import { IBinaryTree } from '../../interfaces';
@ -64,7 +65,7 @@ export class RedBlackTree<
{
/**
* This is the constructor function for a Red-Black Tree data structure in TypeScript.
* @param keysOrNodesOrEntriesOrRawElements - The `keysOrNodesOrEntriesOrRawElements` parameter is an
* @param keysOrNodesOrEntriesOrRaws - The `keysOrNodesOrEntriesOrRaws` parameter is an
* iterable object that can contain either keys, nodes, entries, or raw elements. It is used to
* initialize the RBTree with the provided elements.
* @param [options] - The `options` parameter is an optional object that can be passed to the
@ -73,15 +74,15 @@ export class RedBlackTree<
* depend on the implementation
*/
constructor(
keysOrNodesOrEntriesOrRawElements: Iterable<R | BTNKeyOrNodeOrEntry<K, V, NODE>> = [],
keysOrNodesOrEntriesOrRaws: Iterable<R | BTNKeyOrNodeOrEntry<K, V, NODE>> = [],
options?: RBTreeOptions<K, V, R>
) {
super([], options);
this._root = this.NIL;
if (keysOrNodesOrEntriesOrRawElements) {
this.addMany(keysOrNodesOrEntriesOrRawElements);
if (keysOrNodesOrEntriesOrRaws) {
this.addMany(keysOrNodesOrEntriesOrRaws);
}
}
@ -122,6 +123,8 @@ export class RedBlackTree<
override createTree(options?: RBTreeOptions<K, V, R>): TREE {
return new RedBlackTree<K, V, R, NODE, TREE>([], {
iterationType: this.iterationType,
comparator: this._comparator,
toEntryFn: this._toEntryFn,
...options
}) as TREE;
}
@ -131,15 +134,13 @@ export class RedBlackTree<
* Space Complexity: O(1)
*
* The function checks if the input is an instance of the RedBlackTreeNode class.
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} keyOrNodeOrEntryOrRawElement - The parameter
* `keyOrNodeOrEntryOrRawElement` can be of type `R` or `BTNKeyOrNodeOrEntry<K, V, NODE>`.
* @returns a boolean value indicating whether the input parameter `keyOrNodeOrEntryOrRawElement` is
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - The parameter
* `keyOrNodeOrEntryOrRaw` can be of type `R` or `BTNKeyOrNodeOrEntry<K, V, NODE>`.
* @returns a boolean value indicating whether the input parameter `keyOrNodeOrEntryOrRaw` is
* an instance of the `RedBlackTreeNode` class.
*/
override isNode(
keyOrNodeOrEntryOrRawElement: R | BTNKeyOrNodeOrEntry<K, V, NODE>
): keyOrNodeOrEntryOrRawElement is NODE {
return keyOrNodeOrEntryOrRawElement instanceof RedBlackTreeNode;
override isNode(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R): keyOrNodeOrEntryOrRaw is NODE {
return keyOrNodeOrEntryOrRaw instanceof RedBlackTreeNode;
}
// /**
@ -153,27 +154,27 @@ export class RedBlackTree<
// *
// * The function `keyValueOrEntryOrRawElementToNode` takes a key, value, or entry and returns a node if it is
// * valid, otherwise it returns undefined.
// * @param {BTNKeyOrNodeOrEntry<K, V, NODE>} keyOrNodeOrEntryOrRawElement - The key, value, or entry to convert.
// * @param {V} [value] - The value associated with the key (if `keyOrNodeOrEntryOrRawElement` is a key).
// * @param {BTNKeyOrNodeOrEntry<K, V, NODE>} keyOrNodeOrEntryOrRaw - The key, value, or entry to convert.
// * @param {V} [value] - The value associated with the key (if `keyOrNodeOrEntryOrRaw` is a key).
// * @returns {NODE | undefined} - The corresponding Red-Black Tree node, or `undefined` if conversion fails.
// */
// override keyValueOrEntryOrRawElementToNode(keyOrNodeOrEntryOrRawElement: R | BTNKeyOrNodeOrEntry<K, V, NODE>, value?: V): NODE | undefined {
// override keyValueOrEntryOrRawElementToNode(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R, value?: V): NODE | undefined {
//
// if (keyOrNodeOrEntryOrRawElement === null || keyOrNodeOrEntryOrRawElement === undefined) return;
// if (this.isNode(keyOrNodeOrEntryOrRawElement)) return keyOrNodeOrEntryOrRawElement;
// if (keyOrNodeOrEntryOrRaw === null || keyOrNodeOrEntryOrRaw === undefined) return;
// if (this.isNode(keyOrNodeOrEntryOrRaw)) return keyOrNodeOrEntryOrRaw;
//
// if (this.toEntryFn) {
// const [key, entryValue] = this.toEntryFn(keyOrNodeOrEntryOrRawElement as R);
// if (this._toEntryFn) {
// const [key, entryValue] = this._toEntryFn(keyOrNodeOrEntryOrRaw as R);
// if (this.isKey(key)) return this.createNode(key, entryValue ?? value, 'RED');
// }
//
// if (this.isEntry(keyOrNodeOrEntryOrRawElement)) {
// const [key, value] = keyOrNodeOrEntryOrRawElement;
// if (this.isEntry(keyOrNodeOrEntryOrRaw)) {
// const [key, value] = keyOrNodeOrEntryOrRaw;
// if (key === undefined || key === null) return;
// else return this.createNode(key, value, 'RED');
// }
//
// if (this.isKey(keyOrNodeOrEntryOrRawElement)) return this.createNode(keyOrNodeOrEntryOrRawElement, value, 'RED');
// if (this.isKey(keyOrNodeOrEntryOrRaw)) return this.createNode(keyOrNodeOrEntryOrRaw, value, 'RED');
//
// return ;
// }
@ -196,8 +197,8 @@ export class RedBlackTree<
*
* The function adds a new node to a binary search tree and returns true if the node was successfully
* added.
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} keyOrNodeOrEntryOrRawElement - The parameter
* `keyOrNodeOrEntryOrRawElement` can accept a value of type `R` or `BTNKeyOrNodeOrEntry<K, V, NODE>`.
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - The parameter
* `keyOrNodeOrEntryOrRaw` can accept a value of type `R` or `BTNKeyOrNodeOrEntry<K, V, NODE>`.
* @param {V} [value] - The `value` parameter is an optional value that you want to associate with
* the key in the data structure. It represents the value that you want to add or update in the data
* structure.
@ -205,8 +206,8 @@ export class RedBlackTree<
* the method returns true. If the node already exists and its value is updated, the method also
* returns true. If the node cannot be added or updated, the method returns false.
*/
override add(keyOrNodeOrEntryOrRawElement: R | BTNKeyOrNodeOrEntry<K, V, NODE>, value?: V): boolean {
const newNode = this.keyValueOrEntryOrRawElementToNode(keyOrNodeOrEntryOrRawElement, value);
override add(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R, value?: V): boolean {
const newNode = this.keyValueOrEntryOrRawElementToNode(keyOrNodeOrEntryOrRaw, value);
if (!this.isRealNode(newNode)) return false;
const insertStatus = this._insert(newNode);
@ -227,26 +228,23 @@ export class RedBlackTree<
* Time Complexity: O(log n)
* Space Complexity: O(1)
*
* The function overrides the delete method of a binary tree data structure, allowing for the
* deletion of a node and maintaining the balance of the tree.
* @param {ReturnType<C> | null | undefined} identifier - The `identifier` parameter is the value
* that identifies the node to be deleted from the binary tree. It can be of any type that is
* returned by the callback function `C`. It can also be `null` or `undefined` if there is no node to
* delete.
* @param {C} callback - The `callback` parameter is a function that is used to determine the
* equality of nodes in the binary tree. It is optional and has a default value of
* `this._DEFAULT_CALLBACK`. The type of the `callback` parameter is `C`, which is a generic type
* that extends the `BTNCallback
* @returns an array of BinaryTreeDeleteResult<NODE> objects.
* The function overrides the delete method in a binary tree data structure to remove a node based on
* a given predicate and maintain the binary search tree properties.
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R | BTNPredicate<NODE>} predicate - The `predicate`
* parameter in the `override delete` method is used to specify the condition or key based on which a
* node should be deleted from the binary tree. It can be a key, a node, an entry, or a predicate
* function that determines which node(s) should be deleted.
* @returns The `override delete` method is returning an array of `BinaryTreeDeleteResult<NODE>`
* objects. Each object in the array contains information about the deleted node and whether
* balancing is needed.
*/
override delete<C extends BTNCallback<NODE>>(
identifier: ReturnType<C> | null | undefined,
callback: C = this._DEFAULT_CALLBACK as C
): BinaryTreeDeleteResult<NODE>[] {
if (identifier === null) return [];
override delete(predicate: BTNKeyOrNodeOrEntry<K, V, NODE> | R | BTNPredicate<NODE>): BinaryTreeDeleteResult<NODE>[] {
if (predicate === null) return [];
const results: BinaryTreeDeleteResult<NODE>[] = [];
callback = this._ensureCallback(identifier, callback);
const nodeToDelete = this.isRealNode(identifier) ? identifier : this.getNode(identifier, callback);
let nodeToDelete: OptBSTN<NODE>;
if (this._isPredicated(predicate)) nodeToDelete = this.getNode(predicate);
else nodeToDelete = this.isRealNode(predicate) ? predicate : this.getNode(predicate);
if (!nodeToDelete) {
return results;

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
*/

View file

@ -1,22 +1,23 @@
/**
* 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 {
BinaryTreeDeleteResult,
BSTNKeyOrNode,
BTNCallback,
BTNKeyOrNodeOrEntry,
BTNPredicate,
IterationType,
OptBSTN,
RBTNColor,
TreeMultiMapNested,
TreeMultiMapNodeNested,
TreeMultiMapOptions
TreeMultiMapOptions,
BTNEntry
} from '../../types';
import { BTNEntry } from '../../types';
import { IBinaryTree } from '../../interfaces';
import { RedBlackTree, RedBlackTreeNode } from './rb-tree';
@ -74,7 +75,7 @@ export class TreeMultiMap<
{
/**
* The constructor function initializes a TreeMultiMap object with optional initial data.
* @param keysOrNodesOrEntriesOrRawElements - The parameter `keysOrNodesOrEntriesOrRawElements` is an
* @param keysOrNodesOrEntriesOrRaws - The parameter `keysOrNodesOrEntriesOrRaws` is an
* iterable that can contain keys, nodes, entries, or raw elements. It is used to initialize the
* TreeMultiMap with initial data.
* @param [options] - The `options` parameter is an optional object that can be used to customize the
@ -82,11 +83,11 @@ export class TreeMultiMap<
* `compareValues`, which are functions used to compare keys and values respectively.
*/
constructor(
keysOrNodesOrEntriesOrRawElements: Iterable<BTNKeyOrNodeOrEntry<K, V, NODE>> = [],
keysOrNodesOrEntriesOrRaws: Iterable<BTNKeyOrNodeOrEntry<K, V, NODE>> = [],
options?: TreeMultiMapOptions<K, V, R>
) {
super([], options);
if (keysOrNodesOrEntriesOrRawElements) this.addMany(keysOrNodesOrEntriesOrRawElements);
if (keysOrNodesOrEntriesOrRaws) this.addMany(keysOrNodesOrEntriesOrRaws);
}
protected _count = 0;
@ -142,6 +143,8 @@ export class TreeMultiMap<
override createTree(options?: TreeMultiMapOptions<K, V, R>): TREE {
return new TreeMultiMap<K, V, R, NODE, TREE>([], {
iterationType: this.iterationType,
comparator: this._comparator,
toEntryFn: this._toEntryFn,
...options
}) as TREE;
}
@ -149,8 +152,8 @@ export class TreeMultiMap<
/**
* The function `keyValueOrEntryOrRawElementToNode` takes in a key, value, and count and returns a
* node based on the input.
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} keyOrNodeOrEntryOrRawElement - The parameter
* `keyOrNodeOrEntryOrRawElement` can be of type `R` or `BTNKeyOrNodeOrEntry<K, V, NODE>`.
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - The parameter
* `keyOrNodeOrEntryOrRaw` can be of type `R` or `BTNKeyOrNodeOrEntry<K, V, NODE>`.
* @param {V} [value] - The `value` parameter is an optional value that represents the value
* associated with the key in the node. It is used when creating a new node or updating the value of
* an existing node.
@ -159,42 +162,39 @@ export class TreeMultiMap<
* @returns either a NODE object or undefined.
*/
override keyValueOrEntryOrRawElementToNode(
keyOrNodeOrEntryOrRawElement: R | BTNKeyOrNodeOrEntry<K, V, NODE>,
keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R,
value?: V,
count = 1
): NODE | undefined {
if (keyOrNodeOrEntryOrRawElement === undefined || keyOrNodeOrEntryOrRawElement === null) return;
if (keyOrNodeOrEntryOrRaw === undefined || keyOrNodeOrEntryOrRaw === null) return;
if (this.isNode(keyOrNodeOrEntryOrRawElement)) return keyOrNodeOrEntryOrRawElement;
if (this.isNode(keyOrNodeOrEntryOrRaw)) return keyOrNodeOrEntryOrRaw;
if (this.isEntry(keyOrNodeOrEntryOrRawElement)) {
const [key, entryValue] = keyOrNodeOrEntryOrRawElement;
if (this.isEntry(keyOrNodeOrEntryOrRaw)) {
const [key, entryValue] = keyOrNodeOrEntryOrRaw;
if (key === undefined || key === null) return;
if (this.isKey(key)) return this.createNode(key, value ?? entryValue, 'BLACK', count);
}
if (this.toEntryFn) {
const [key, entryValue] = this.toEntryFn(keyOrNodeOrEntryOrRawElement as R);
if (this._toEntryFn) {
const [key, entryValue] = this._toEntryFn(keyOrNodeOrEntryOrRaw as R);
if (this.isKey(key)) return this.createNode(key, value ?? entryValue, 'BLACK', count);
}
if (this.isKey(keyOrNodeOrEntryOrRawElement))
return this.createNode(keyOrNodeOrEntryOrRawElement, value, 'BLACK', count);
if (this.isKey(keyOrNodeOrEntryOrRaw)) return this.createNode(keyOrNodeOrEntryOrRaw, value, 'BLACK', count);
return;
}
/**
* The function checks if the input is an instance of the TreeMultiMapNode class.
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} keyOrNodeOrEntryOrRawElement - The parameter
* `keyOrNodeOrEntryOrRawElement` can be of type `R` or `BTNKeyOrNodeOrEntry<K, V, NODE>`.
* @returns a boolean value indicating whether the input parameter `keyOrNodeOrEntryOrRawElement` is
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - The parameter
* `keyOrNodeOrEntryOrRaw` can be of type `R` or `BTNKeyOrNodeOrEntry<K, V, NODE>`.
* @returns a boolean value indicating whether the input parameter `keyOrNodeOrEntryOrRaw` is
* an instance of the `TreeMultiMapNode` class.
*/
override isNode(
keyOrNodeOrEntryOrRawElement: R | BTNKeyOrNodeOrEntry<K, V, NODE>
): keyOrNodeOrEntryOrRawElement is NODE {
return keyOrNodeOrEntryOrRawElement instanceof TreeMultiMapNode;
override isNode(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R): keyOrNodeOrEntryOrRaw is NODE {
return keyOrNodeOrEntryOrRaw instanceof TreeMultiMapNode;
}
/**
@ -203,8 +203,8 @@ export class TreeMultiMap<
*
* The function overrides the add method of a class and adds a new node to a data structure, updating
* the count and returning a boolean indicating success.
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} keyOrNodeOrEntryOrRawElement - The
* `keyOrNodeOrEntryOrRawElement` parameter can accept one of the following types:
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - The
* `keyOrNodeOrEntryOrRaw` parameter can accept one of the following types:
* @param {V} [value] - The `value` parameter represents the value associated with the key in the
* data structure. It is an optional parameter, so it can be omitted if not needed.
* @param [count=1] - The `count` parameter represents the number of times the key-value pair should
@ -213,8 +213,8 @@ export class TreeMultiMap<
* @returns The method is returning a boolean value. It returns true if the addition of the new node
* was successful, and false otherwise.
*/
override add(keyOrNodeOrEntryOrRawElement: R | BTNKeyOrNodeOrEntry<K, V, NODE>, value?: V, count = 1): boolean {
const newNode = this.keyValueOrEntryOrRawElementToNode(keyOrNodeOrEntryOrRawElement, value, count);
override add(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R, value?: V, count = 1): boolean {
const newNode = this.keyValueOrEntryOrRawElementToNode(keyOrNodeOrEntryOrRaw, value, count);
const orgCount = newNode?.count || 0;
const isSuccessAdded = super.add(newNode);
@ -230,30 +230,29 @@ export class TreeMultiMap<
* Time Complexity: O(log n)
* Space Complexity: O(1)
*
* The function `delete` is used to remove a node from a binary tree and fix the tree if necessary.
* @param {ReturnType<C> | null | undefined} identifier - The `identifier` parameter is the value or
* key that is used to identify the node that needs to be deleted from the binary tree. It can be of
* any type that is returned by the callback function `C`. It can also be `null` or `undefined` if
* the node to be deleted
* @param {C} callback - The `callback` parameter is a function that is used to determine the
* equality of nodes in the binary tree. It is optional and has a default value of
* `this._DEFAULT_CALLBACK`. The `callback` function is used to compare nodes when searching for a
* specific node or when performing other operations on the
* @param [ignoreCount=false] - A boolean flag indicating whether to ignore the count of the node
* being deleted. If set to true, the count of the node will not be taken into account when deleting
* it. If set to false, the count of the node will be decremented by 1 before deleting it.
* @returns an array of BinaryTreeDeleteResult<NODE> objects.
* The function `delete` in TypeScript overrides the deletion operation in a binary tree data
* structure, handling cases where nodes have children and maintaining balance in the tree.
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R | BTNPredicate<NODE>} predicate - The `predicate`
* parameter in the `delete` method is used to specify the condition or key based on which a node
* should be deleted from the binary tree. It can be a key, a node, an entry, or a predicate
* function.
* @param [ignoreCount=false] - The `ignoreCount` parameter in the `override delete` method is a
* boolean flag that determines whether to ignore the count of nodes when performing deletion. If
* `ignoreCount` is set to `true`, the method will delete the node regardless of its count. If
* `ignoreCount` is `false
* @returns The `override delete` method returns an array of `BinaryTreeDeleteResult<NODE>` objects.
*/
override delete<C extends BTNCallback<NODE>>(
identifier: ReturnType<C> | null | undefined,
callback: C = this._DEFAULT_CALLBACK as C,
override delete(
predicate: BTNKeyOrNodeOrEntry<K, V, NODE> | R | BTNPredicate<NODE>,
ignoreCount = false
): BinaryTreeDeleteResult<NODE>[] {
if (identifier === null) return [];
const results: BinaryTreeDeleteResult<NODE>[] = [];
callback = this._ensureCallback(identifier, callback);
if (predicate === null) return [];
const nodeToDelete = this.isRealNode(identifier) ? identifier : this.getNode(identifier, callback);
const results: BinaryTreeDeleteResult<NODE>[] = [];
let nodeToDelete: OptBSTN<NODE>;
if (this._isPredicated(predicate)) nodeToDelete = this.getNode(predicate);
else nodeToDelete = this.isRealNode(predicate) ? predicate : this.getNode(predicate);
if (!nodeToDelete) {
return results;

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 { DijkstraResult, EntryCallback, VertexKey } from '../../types';
@ -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

@ -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 { TopologicalStatus, VertexKey } from '../../types';
@ -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

@ -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 { VertexKey } from '../../types';

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 {
@ -111,7 +111,7 @@ export class HashMap<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
* @returns A boolean value indicating whether the size of the object is 0 or not.
*/
isEmpty(): boolean {
return this.size === 0;
return this._size === 0;
}
/**

View file

@ -626,7 +626,7 @@ export class FibonacciHeap<E> {
* @returns The top element or undefined if the heap is empty.
*/
pop(): E | undefined {
if (this.size === 0) return undefined;
if (this._size === 0) return undefined;
const z = this.min!;
if (z.child) {
@ -770,7 +770,7 @@ export class FibonacciHeap<E> {
* @protected
*/
protected _consolidate(): void {
const A: (FibonacciHeapNode<E> | undefined)[] = new Array(this.size);
const A: (FibonacciHeapNode<E> | undefined)[] = new Array(this._size);
const elements = this.consumeLinkedList(this.root);
let x: FibonacciHeapNode<E> | undefined,
y: FibonacciHeapNode<E> | undefined,
@ -798,7 +798,7 @@ export class FibonacciHeap<E> {
A[d] = x;
}
for (let i = 0; i < this.size; i++) {
for (let i = 0; i < this._size; i++) {
if (A[i] && this.comparator(A[i]!.element, this.min!.element) <= 0) {
this._min = A[i]!;
}

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 { DoublyLinkedListOptions, ElementCallback } from '../../types';
@ -267,7 +267,7 @@ export class DoublyLinkedList<E = any, R = any> extends IterableElementBase<E, R
* or the linked list is empty, it will return undefined.
*/
at(index: number): E | undefined {
if (index < 0 || index >= this.size) return undefined;
if (index < 0 || index >= this._size) return undefined;
let current = this.head;
for (let i = 0; i < index; i++) {
current = current!.next;
@ -287,7 +287,7 @@ export class DoublyLinkedList<E = any, R = any> extends IterableElementBase<E, R
* valid range of the linked list, otherwise it returns `undefined`.
*/
getNodeAt(index: number): DoublyLinkedListNode<E> | undefined {
if (index < 0 || index >= this.size) return undefined;
if (index < 0 || index >= this._size) return undefined;
let current = this.head;
for (let i = 0; i < index; i++) {
current = current!.next;
@ -331,12 +331,12 @@ export class DoublyLinkedList<E = any, R = any> extends IterableElementBase<E, R
* if the index is out of bounds.
*/
addAt(index: number, value: E): boolean {
if (index < 0 || index > this.size) return false;
if (index < 0 || index > this._size) return false;
if (index === 0) {
this.unshift(value);
return true;
}
if (index === this.size) {
if (index === this._size) {
this.push(value);
return true;
}
@ -442,12 +442,12 @@ export class DoublyLinkedList<E = any, R = any> extends IterableElementBase<E, R
* bounds.
*/
deleteAt(index: number): boolean {
if (index < 0 || index >= this.size) return false;
if (index < 0 || index >= this._size) return false;
if (index === 0) {
this.shift();
return true;
}
if (index === this.size - 1) {
if (index === this._size - 1) {
this.pop();
return true;
}
@ -505,7 +505,7 @@ export class DoublyLinkedList<E = any, R = any> extends IterableElementBase<E, R
* @returns A boolean value is being returned.
*/
isEmpty(): boolean {
return this.size === 0;
return this._size === 0;
}
/**

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 { ElementCallback, SinglyLinkedListOptions } from '../../types';
@ -237,7 +237,7 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
* `undefined` if the index is out of bounds.
*/
at(index: number): E | undefined {
if (index < 0 || index >= this.size) return undefined;
if (index < 0 || index >= this._size) return undefined;
let current = this.head;
for (let i = 0; i < index; i++) {
current = current!.next;
@ -274,12 +274,12 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
* bounds.
*/
deleteAt(index: number): boolean {
if (index < 0 || index >= this.size) return false;
if (index < 0 || index >= this._size) return false;
if (index === 0) {
this.shift();
return true;
}
if (index === this.size - 1) {
if (index === this._size - 1) {
this.pop();
return true;
}
@ -348,12 +348,12 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
* if the index is out of bounds.
*/
addAt(index: number, value: E): boolean {
if (index < 0 || index > this.size) return false;
if (index < 0 || index > this._size) return false;
if (index === 0) {
this.unshift(value);
return true;
}
if (index === this.size) {
if (index === this._size) {
this.push(value);
return true;
}
@ -372,7 +372,7 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
* @returns A boolean value indicating whether the length of the object is equal to 0.
*/
isEmpty(): boolean {
return this.size === 0;
return this._size === 0;
}
/**

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 { SkipLinkedListOptions } from '../../types';

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 { MatrixOptions } from '../../types';

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 { Direction, NavigatorParams, Turning } from '../../types';
@ -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,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 { DequeOptions, ElementCallback, IterableWithSizeOrLength } from '../../types';
@ -163,7 +163,7 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
* @returns The first element of the collection, of type E, is being returned.
*/
get first(): E | undefined {
if (this.size === 0) return;
if (this._size === 0) return;
return this._buckets[this._bucketFirst][this._firstInBucket];
}
@ -172,7 +172,7 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
* @return The last element in the array
*/
get last(): E | undefined {
if (this.size === 0) return;
if (this._size === 0) return;
return this._buckets[this._bucketLast][this._lastInBucket];
}
@ -186,7 +186,7 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
* @returns The size of the data structure after the element has been pushed.
*/
push(element: E): boolean {
if (this.size) {
if (this._size) {
if (this._lastInBucket < this._bucketSize - 1) {
this._lastInBucket += 1;
} else if (this._bucketLast < this._bucketCount - 1) {
@ -213,9 +213,9 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
* @returns The element that was removed from the data structure is being returned.
*/
pop(): E | undefined {
if (this.size === 0) return;
if (this._size === 0) return;
const element = this._buckets[this._bucketLast][this._lastInBucket];
if (this.size !== 1) {
if (this._size !== 1) {
if (this._lastInBucket > 0) {
this._lastInBucket -= 1;
} else if (this._bucketLast > 0) {
@ -241,7 +241,7 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
* @returns The size of the data structure after the element has been added.
*/
unshift(element: E): boolean {
if (this.size) {
if (this._size) {
if (this._firstInBucket > 0) {
this._firstInBucket -= 1;
} else if (this._bucketFirst > 0) {
@ -269,9 +269,9 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
* returned.
*/
shift(): E | undefined {
if (this.size === 0) return;
if (this._size === 0) return;
const element = this._buckets[this._bucketFirst][this._firstInBucket];
if (this.size !== 1) {
if (this._size !== 1) {
if (this._firstInBucket < this._bucketSize - 1) {
this._firstInBucket += 1;
} else if (this._bucketFirst < this._bucketCount - 1) {
@ -294,7 +294,7 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
* @returns A boolean value indicating whether the size of the object is 0 or not.
*/
isEmpty(): boolean {
return this.size === 0;
return this._size === 0;
}
/**
@ -316,7 +316,7 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
*/
*begin(): Generator<E> {
let index = 0;
while (index < this.size) {
while (index < this._size) {
yield this.at(index);
index++;
}
@ -327,7 +327,7 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
* the last element.
*/
*reverseBegin(): Generator<E> {
let index = this.size - 1;
let index = this._size - 1;
while (index >= 0) {
yield this.at(index);
index--;
@ -345,7 +345,7 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
* @returns The element at the specified position in the data structure is being returned.
*/
at(pos: number): E {
rangeCheck(pos, 0, this.size - 1);
rangeCheck(pos, 0, this._size - 1);
const { bucketIndex, indexInBucket } = this._getBucketAndPosition(pos);
return this._buckets[bucketIndex][indexInBucket]!;
}
@ -361,7 +361,7 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
* position in the data structure.
*/
setAt(pos: number, element: E): boolean {
rangeCheck(pos, 0, this.size - 1);
rangeCheck(pos, 0, this._size - 1);
const { bucketIndex, indexInBucket } = this._getBucketAndPosition(pos);
this._buckets[bucketIndex][indexInBucket] = element;
return true;
@ -383,15 +383,15 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
* @returns The size of the array after the insertion is being returned.
*/
addAt(pos: number, element: E, num = 1): boolean {
const length = this.size;
const length = this._size;
rangeCheck(pos, 0, length);
if (pos === 0) {
while (num--) this.unshift(element);
} else if (pos === this.size) {
} else if (pos === this._size) {
while (num--) this.push(element);
} else {
const arr: E[] = [];
for (let i = pos; i < this.size; ++i) {
for (let i = pos; i < this._size; ++i) {
arr.push(this.at(i));
}
this.cut(pos - 1, true);
@ -462,7 +462,7 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
} else {
const newDeque = new Deque<E>([], { bucketSize: this._bucketSize });
if (pos < 0) pos = 0;
for (let i = pos; i < this.size; i++) {
for (let i = pos; i < this._size; i++) {
newDeque.push(this.at(i));
}
@ -482,11 +482,11 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
* @returns The size of the data structure after the deletion operation is performed.
*/
deleteAt(pos: number): boolean {
rangeCheck(pos, 0, this.size - 1);
rangeCheck(pos, 0, this._size - 1);
if (pos === 0) this.shift();
else if (pos === this.size - 1) this.pop();
else if (pos === this._size - 1) this.pop();
else {
const length = this.size - 1;
const length = this._size - 1;
let { bucketIndex: curBucket, indexInBucket: curPointer } = this._getBucketAndPosition(pos);
for (let i = pos; i < length; ++i) {
const { bucketIndex: nextBucket, indexInBucket: nextPointer } = this._getBucketAndPosition(pos + 1);
@ -510,7 +510,7 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
* @returns The size of the data structure after the element has been deleted.
*/
delete(element: E): boolean {
const size = this.size;
const size = this._size;
if (size === 0) return false;
let i = 0;
let index = 0;
@ -556,12 +556,12 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
* @returns The size of the modified array is being returned.
*/
unique(): this {
if (this.size <= 1) {
if (this._size <= 1) {
return this;
}
let index = 1;
let prev = this.at(0);
for (let i = 1; i < this.size; ++i) {
for (let i = 1; i < this._size; ++i) {
const cur = this.at(i);
if (cur !== prev) {
prev = cur;
@ -584,11 +584,11 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
*/
sort(comparator?: (x: E, y: E) => number): this {
const arr: E[] = [];
for (let i = 0; i < this.size; ++i) {
for (let i = 0; i < this._size; ++i) {
arr.push(this.at(i));
}
arr.sort(comparator);
for (let i = 0; i < this.size; ++i) {
for (let i = 0; i < this._size; ++i) {
this.setAt(i, arr[i]);
}
return this;
@ -601,10 +601,10 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
* The `shrinkToFit` function reorganizes the elements in an array-like data structure to minimize
* memory usage.
* @returns Nothing is being returned. The function is using the `return` statement to exit early if
* `this.size` is 0, but it does not return any value.
* `this._size` is 0, but it does not return any value.
*/
shrinkToFit(): void {
if (this.size === 0) return;
if (this._size === 0) return;
const newBuckets = [];
if (this._bucketFirst === this._bucketLast) return;
else if (this._bucketFirst < this._bucketLast) {
@ -636,7 +636,7 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
* in the data structure. If the element is not found, it returns -1.
*/
indexOf(element: E): number {
for (let i = 0; i < this.size; ++i) {
for (let i = 0; i < this._size; ++i) {
if (this.at(i) === element) {
return i;
}
@ -736,7 +736,7 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
* object to be iterated over using a for...of loop.
*/
protected *_getIterator(): IterableIterator<E> {
for (let i = 0; i < this.size; ++i) {
for (let i = 0; i < this._size; ++i) {
yield this.at(i);
}
}

View file

@ -1,6 +1,6 @@
/**
* @license MIT
* @copyright Tyler Zeng <zrwusa@gmail.com>
* @copyright Pablo Zeng <zrwusa@gmail.com>
* @class
*/
import type { ElementCallback, QueueOptions } from '../../types';

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 { ElementCallback, StackOptions } from '../../types';

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 { ElementCallback, TrieOptions } from '../../types';
@ -202,7 +202,7 @@ export class Trie<R = any> extends IterableElementBase<string, R, Trie<R>> {
* @return True if the size of the queue is 0
*/
isEmpty(): boolean {
return this.size === 0;
return this._size === 0;
}
/**

View file

@ -2,3 +2,4 @@ export * from './data-structures';
export * from './utils';
export * from './interfaces';
export * from './types';
export * from './constants';

View file

@ -4,8 +4,8 @@ import type {
BinaryTreeNested,
BinaryTreeNodeNested,
BinaryTreeOptions,
BTNCallback,
BTNKeyOrNodeOrEntry
BTNKeyOrNodeOrEntry,
BTNPredicate
} from '../types';
export interface IBinaryTree<
@ -23,5 +23,5 @@ export interface IBinaryTree<
addMany(nodes: Iterable<BTNKeyOrNodeOrEntry<K, V, NODE>>, values?: Iterable<V | undefined>): boolean[];
delete<C extends BTNCallback<NODE>>(identifier: ReturnType<C> | null, callback: C): BinaryTreeDeleteResult<NODE>[];
delete(predicate: R | BTNKeyOrNodeOrEntry<K, V, NODE> | BTNPredicate<NODE>): BinaryTreeDeleteResult<NODE>[];
}

View file

@ -1,5 +1,6 @@
import { BinaryTree, BinaryTreeNode } from '../../../data-structures';
import { IterationType, OptValue } from '../../common';
import { DFSOperation } from '../../../constants';
export type BinaryTreeNodeNested<K, V> = BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, BinaryTreeNode<K, V, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
@ -30,9 +31,6 @@ export type BinaryTreeDeleteResult<NODE> = { deleted: OptBTNOrNull<NODE>; needBa
export type BTNCallback<NODE, D = any> = (node: NODE) => D;
export enum DFSOperation {
VISIT = 0,
PROCESS = 1,
}
export type BTNPredicate<NODE> = (node: NODE) => boolean;
export type DFSStackItem<NODE> = { opt: DFSOperation; node: OptBTNOrNull<NODE> }
export type DFSStackItem<NODE> = { opt: DFSOperation; node: OptBTNOrNull<NODE> }

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

@ -75,13 +75,13 @@ describe('AVLTreeMultiMap operations test1', () => {
const nodeId10 = treeMultimap.getNode(10);
expect(nodeId10?.key).toBe(10);
const nodeVal9 = treeMultimap.getNode(9, node => node.value);
const nodeVal9 = treeMultimap.getNode(node => node.value === 9);
expect(nodeVal9?.key).toBe(9);
const nodesByCount1 = treeMultimap.getNodes(1, node => node.count);
const nodesByCount1 = treeMultimap.getNodes(node => node.count === 1);
expect(nodesByCount1.length).toBe(14);
const nodesByCount2 = treeMultimap.getNodes(2, node => node.count);
const nodesByCount2 = treeMultimap.getNodes(node => node.count === 2);
expect(nodesByCount2.length).toBe(2);
const leftMost = treeMultimap.getLeftMost();
expect(leftMost).toBe(1);
@ -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);
@ -123,7 +123,7 @@ describe('AVLTreeMultiMap operations test1', () => {
expect(bfsNodesAfterBalanced[0].key).toBe(8);
expect(bfsNodesAfterBalanced[bfsNodesAfterBalanced.length - 1].key).toBe(16);
const removed11 = treeMultimap.delete(11, undefined, true);
const removed11 = treeMultimap.delete(11, true);
expect(removed11 instanceof Array);
expect(removed11[0]);
expect(removed11[0].deleted);
@ -134,7 +134,7 @@ describe('AVLTreeMultiMap operations test1', () => {
expect(treeMultimap.getHeight(15)).toBe(1);
const removed1 = treeMultimap.delete(1, undefined, true);
const removed1 = treeMultimap.delete(1, true);
expect(removed1 instanceof Array);
expect(removed1[0]);
expect(removed1[0].deleted);
@ -144,7 +144,7 @@ describe('AVLTreeMultiMap operations test1', () => {
expect(treeMultimap.getHeight()).toBe(4);
const removed4 = treeMultimap.delete(4, undefined, true);
const removed4 = treeMultimap.delete(4, true);
expect(removed4 instanceof Array);
expect(removed4[0]);
expect(removed4[0].deleted);
@ -153,7 +153,7 @@ describe('AVLTreeMultiMap operations test1', () => {
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(4);
const removed10 = treeMultimap.delete(10, undefined, true);
const removed10 = treeMultimap.delete(10, true);
expect(removed10 instanceof Array);
expect(removed10[0]);
expect(removed10[0].deleted);
@ -162,7 +162,7 @@ describe('AVLTreeMultiMap operations test1', () => {
expect(treeMultimap.getHeight()).toBe(3);
const removed15 = treeMultimap.delete(15, undefined, true);
const removed15 = treeMultimap.delete(15, true);
expect(removed15 instanceof Array);
expect(removed15[0]);
expect(removed15[0].deleted);
@ -171,7 +171,7 @@ describe('AVLTreeMultiMap operations test1', () => {
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(3);
const removed5 = treeMultimap.delete(5, undefined, true);
const removed5 = treeMultimap.delete(5, true);
expect(removed5 instanceof Array);
expect(removed5[0]);
expect(removed5[0].deleted);
@ -180,7 +180,7 @@ describe('AVLTreeMultiMap operations test1', () => {
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(3);
const removed13 = treeMultimap.delete(13, undefined, true);
const removed13 = treeMultimap.delete(13, true);
expect(removed13 instanceof Array);
expect(removed13[0]);
expect(removed13[0].deleted);
@ -188,7 +188,7 @@ describe('AVLTreeMultiMap operations test1', () => {
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(3);
const removed3 = treeMultimap.delete(3, undefined, true);
const removed3 = treeMultimap.delete(3, true);
expect(removed3 instanceof Array);
expect(removed3[0]);
expect(removed3[0].deleted);
@ -196,7 +196,7 @@ describe('AVLTreeMultiMap operations test1', () => {
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(3);
const removed8 = treeMultimap.delete(8, undefined, true);
const removed8 = treeMultimap.delete(8, true);
expect(removed8 instanceof Array);
expect(removed8[0]);
expect(removed8[0].deleted);
@ -204,17 +204,17 @@ describe('AVLTreeMultiMap operations test1', () => {
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(3);
const removed6 = treeMultimap.delete(6, undefined, true);
const removed6 = treeMultimap.delete(6, true);
expect(removed6 instanceof Array);
expect(removed6[0]);
expect(removed6[0].deleted);
if (removed6[0].deleted) expect(removed6[0].deleted.key).toBe(6);
expect(treeMultimap.delete(6, undefined, true).length).toBe(0);
expect(treeMultimap.delete(6, true).length).toBe(0);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(2);
const removed7 = treeMultimap.delete(7, undefined, true);
const removed7 = treeMultimap.delete(7, true);
expect(removed7 instanceof Array);
expect(removed7[0]);
expect(removed7[0].deleted);
@ -222,7 +222,7 @@ describe('AVLTreeMultiMap operations test1', () => {
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(2);
const removed9 = treeMultimap.delete(9, undefined, true);
const removed9 = treeMultimap.delete(9, true);
expect(removed9 instanceof Array);
expect(removed9[0]);
expect(removed9[0].deleted);
@ -230,7 +230,7 @@ describe('AVLTreeMultiMap operations test1', () => {
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(2);
const removed14 = treeMultimap.delete(14, undefined, true);
const removed14 = treeMultimap.delete(14, true);
expect(removed14 instanceof Array);
expect(removed14[0]);
expect(removed14[0].deleted);
@ -331,13 +331,13 @@ describe('AVLTreeMultiMap operations test recursively1', () => {
const nodeId10 = treeMultimap.getNode(10);
expect(nodeId10?.key).toBe(10);
const nodeVal9 = treeMultimap.getNode(9, node => node.value);
const nodeVal9 = treeMultimap.getNode(node => node.value === 9);
expect(nodeVal9?.key).toBe(9);
const nodesByCount1 = treeMultimap.getNodes(1, node => node.count);
const nodesByCount1 = treeMultimap.getNodes(node => node.count === 1);
expect(nodesByCount1.length).toBe(14);
const nodesByCount2 = treeMultimap.getNodes(2, node => node.count);
const nodesByCount2 = treeMultimap.getNodes(node => node.count === 2);
expect(nodesByCount2.length).toBe(2);
const leftMost = treeMultimap.getLeftMost();
expect(leftMost).toBe(1);
@ -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);
@ -379,7 +379,7 @@ describe('AVLTreeMultiMap operations test recursively1', () => {
expect(bfsNodesAfterBalanced[0].key).toBe(8);
expect(bfsNodesAfterBalanced[bfsNodesAfterBalanced.length - 1].key).toBe(16);
const removed11 = treeMultimap.delete(11, undefined, true);
const removed11 = treeMultimap.delete(11, true);
expect(removed11 instanceof Array);
expect(removed11[0]);
expect(removed11[0].deleted);
@ -390,7 +390,7 @@ describe('AVLTreeMultiMap operations test recursively1', () => {
expect(treeMultimap.getHeight(15)).toBe(1);
const removed1 = treeMultimap.delete(1, undefined, true);
const removed1 = treeMultimap.delete(1, true);
expect(removed1 instanceof Array);
expect(removed1[0]);
expect(removed1[0].deleted);
@ -400,7 +400,7 @@ describe('AVLTreeMultiMap operations test recursively1', () => {
expect(treeMultimap.getHeight()).toBe(4);
const removed4 = treeMultimap.delete(4, undefined, true);
const removed4 = treeMultimap.delete(4, true);
expect(removed4 instanceof Array);
expect(removed4[0]);
expect(removed4[0].deleted);
@ -409,7 +409,7 @@ describe('AVLTreeMultiMap operations test recursively1', () => {
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(4);
const removed10 = treeMultimap.delete(10, undefined, true);
const removed10 = treeMultimap.delete(10, true);
expect(removed10 instanceof Array);
expect(removed10[0]);
expect(removed10[0].deleted);
@ -418,7 +418,7 @@ describe('AVLTreeMultiMap operations test recursively1', () => {
expect(treeMultimap.getHeight()).toBe(3);
const removed15 = treeMultimap.delete(15, undefined, true);
const removed15 = treeMultimap.delete(15, true);
expect(removed15 instanceof Array);
expect(removed15[0]);
expect(removed15[0].deleted);
@ -427,7 +427,7 @@ describe('AVLTreeMultiMap operations test recursively1', () => {
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(3);
const removed5 = treeMultimap.delete(5, undefined, true);
const removed5 = treeMultimap.delete(5, true);
expect(removed5 instanceof Array);
expect(removed5[0]);
expect(removed5[0].deleted);
@ -436,7 +436,7 @@ describe('AVLTreeMultiMap operations test recursively1', () => {
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(3);
const removed13 = treeMultimap.delete(13, undefined, true);
const removed13 = treeMultimap.delete(13, true);
expect(removed13 instanceof Array);
expect(removed13[0]);
expect(removed13[0].deleted);
@ -444,7 +444,7 @@ describe('AVLTreeMultiMap operations test recursively1', () => {
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(3);
const removed3 = treeMultimap.delete(3, undefined, true);
const removed3 = treeMultimap.delete(3, true);
expect(removed3 instanceof Array);
expect(removed3[0]);
expect(removed3[0].deleted);
@ -452,7 +452,7 @@ describe('AVLTreeMultiMap operations test recursively1', () => {
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(3);
const removed8 = treeMultimap.delete(8, undefined, true);
const removed8 = treeMultimap.delete(8, true);
expect(removed8 instanceof Array);
expect(removed8[0]);
expect(removed8[0].deleted);
@ -460,17 +460,17 @@ describe('AVLTreeMultiMap operations test recursively1', () => {
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(3);
const removed6 = treeMultimap.delete(6, undefined, true);
const removed6 = treeMultimap.delete(6, true);
expect(removed6 instanceof Array);
expect(removed6[0]);
expect(removed6[0].deleted);
if (removed6[0].deleted) expect(removed6[0].deleted.key).toBe(6);
expect(treeMultimap.delete(6, undefined, true).length).toBe(0);
expect(treeMultimap.delete(6, true).length).toBe(0);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(2);
const removed7 = treeMultimap.delete(7, undefined, true);
const removed7 = treeMultimap.delete(7, true);
expect(removed7 instanceof Array);
expect(removed7[0]);
expect(removed7[0].deleted);
@ -478,7 +478,7 @@ describe('AVLTreeMultiMap operations test recursively1', () => {
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(2);
const removed9 = treeMultimap.delete(9, undefined, true);
const removed9 = treeMultimap.delete(9, true);
expect(removed9 instanceof Array);
expect(removed9[0]);
expect(removed9[0].deleted);
@ -486,7 +486,7 @@ describe('AVLTreeMultiMap operations test recursively1', () => {
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(2);
const removed14 = treeMultimap.delete(14, undefined, true);
const removed14 = treeMultimap.delete(14, true);
expect(removed14 instanceof Array);
expect(removed14[0]);
expect(removed14[0].deleted);
@ -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

@ -169,8 +169,8 @@ describe('BinaryTree', () => {
expect(tree.has(4)).toBe(false);
const node4 = tree.getNode(4);
expect(tree.has(node4)).toBe(false);
expect(tree.has(node4, node => node)).toBe(false);
expect(tree.has('3', node => node.value?.toString())).toBe(true);
expect(tree.has(node => node === node4)).toBe(false);
expect(tree.has(node => node.value?.toString() === '3')).toBe(true);
});
it('should the clone method work fine', () => {
@ -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,12 +306,26 @@ 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);
expect(tree.getNodes(2, undefined, false, null)).toEqual([]);
expect(tree.getNodes(2, false, null)).toEqual([]);
expect(tree.getNodes(undefined)).toEqual([]);
expect(tree.getNodes(tree.getNodeByKey(2), undefined, false, tree.root)).toEqual([tree.getNodeByKey(2)]);
expect(tree.getNodes(tree.getNodeByKey(2), false, tree.root)).toEqual([tree.getNodeByKey(2)]);
});
describe('should isKey', () => {
@ -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']);
@ -1095,17 +1130,17 @@ describe('BinaryTree', () => {
tree.add([2, 'B']);
tree.add([null, 'null']);
const nodes = tree.getNodes('B', node => node.value);
const nodes = tree.getNodes(node => node.value === 'B');
expect(nodes.length).toBe(1);
expect(nodes[0].key).toBe(2);
const nodesRec = tree.getNodes('B', node => node.value, false, tree.root, 'RECURSIVE');
const nodesRec = tree.getNodes(node => node.value === 'B', false, tree.root, 'RECURSIVE');
expect(nodesRec.length).toBe(1);
expect(nodesRec[0].key).toBe(2);
const nodesItr = tree.getNodes('B', node => node.value, false, tree.root, 'ITERATIVE');
const nodesItr = tree.getNodes(node => node.value === 'B', false, tree.root, 'ITERATIVE');
expect(nodesItr.length).toBe(1);
expect(nodesItr[0].key).toBe(2);
@ -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

@ -69,7 +69,7 @@ describe('BST operations test', () => {
const nodeId10 = bst.getNode(10);
expect(nodeId10?.key).toBe(10);
const nodeVal9 = bst.getNode(9, node => node.value);
const nodeVal9 = bst.getNode(node => node.value === 9);
expect(nodeVal9?.key).toBe(9);
const leftMost = bst.getLeftMost();
@ -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(node => node.value === 15);
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;
@ -484,7 +490,7 @@ describe('BST operations test recursively', () => {
expect(bst.get(10)).toBe(undefined);
expect(nodeId10?.key).toBe(10);
const nodeVal9 = bst.getNode(9, node => node.value);
const nodeVal9 = bst.getNode(node => node.value === 9);
expect(nodeVal9?.key).toBe(undefined);
const leftMost = bst.getLeftMost();
@ -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

@ -87,7 +87,7 @@ describe('TreeMultiMap operations test1', () => {
tmm.delete(11);
expect(tmm.count).toBe(17);
expect(tmm.getComputedCount()).toBe(17);
tmm.delete(3, undefined, true);
tmm.delete(3, true);
expect(tmm.count).toBe(15);
expect(tmm.getComputedCount()).toBe(15);
});
@ -127,19 +127,19 @@ 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);
expect(nodeId10?.key).toBe(10);
const nodeVal9 = tmm.getNode(9, node => node.value);
const nodeVal9 = tmm.getNode(node => node.value === 9);
expect(nodeVal9?.key).toBe(9);
const nodesByCount1 = tmm.getNodes(1, node => node.count);
const nodesByCount1 = tmm.getNodes(node => node.count === 1);
expect(nodesByCount1.length).toBe(14);
const nodesByCount2 = tmm.getNodes(2, node => node.count);
const nodesByCount2 = tmm.getNodes(node => node.count === 2);
expect(nodesByCount2.length).toBe(2);
const leftMost = tmm.getLeftMost();
expect(leftMost).toBe(1);
@ -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);
@ -180,7 +180,7 @@ describe('TreeMultiMap operations test1', () => {
expect(bfsNodesAfterBalanced[0].key).toBe(6);
expect(bfsNodesAfterBalanced[bfsNodesAfterBalanced.length - 1].key).toBe(16);
const removed11 = tmm.delete(11, undefined, true);
const removed11 = tmm.delete(11, true);
expect(removed11 instanceof Array);
expect(removed11[0]);
expect(removed11[0].deleted);
@ -191,7 +191,7 @@ describe('TreeMultiMap operations test1', () => {
expect(tmm.getHeight(15)).toBe(1);
const removed1 = tmm.delete(1, undefined, true);
const removed1 = tmm.delete(1, true);
expect(removed1 instanceof Array);
expect(removed1[0]);
expect(removed1[0].deleted);
@ -201,7 +201,7 @@ describe('TreeMultiMap operations test1', () => {
expect(tmm.getHeight()).toBe(5);
const removed4 = tmm.delete(4, undefined, true);
const removed4 = tmm.delete(4, true);
expect(removed4 instanceof Array);
expect(removed4[0]);
expect(removed4[0].deleted);
@ -210,7 +210,7 @@ describe('TreeMultiMap operations test1', () => {
expect(tmm.isAVLBalanced()).toBe(false);
expect(tmm.getHeight()).toBe(5);
const removed10 = tmm.delete(10, undefined, true);
const removed10 = tmm.delete(10, true);
expect(removed10 instanceof Array);
expect(removed10[0]);
expect(removed10[0].deleted);
@ -219,7 +219,7 @@ describe('TreeMultiMap operations test1', () => {
expect(tmm.getHeight()).toBe(4);
const removed15 = tmm.delete(15, undefined, true);
const removed15 = tmm.delete(15, true);
expect(removed15 instanceof Array);
expect(removed15[0]);
expect(removed15[0].deleted);
@ -228,7 +228,7 @@ describe('TreeMultiMap operations test1', () => {
expect(tmm.isAVLBalanced()).toBe(false);
expect(tmm.getHeight()).toBe(3);
const removed5 = tmm.delete(5, undefined, true);
const removed5 = tmm.delete(5, true);
expect(removed5 instanceof Array);
expect(removed5[0]);
expect(removed5[0].deleted);
@ -237,7 +237,7 @@ describe('TreeMultiMap operations test1', () => {
expect(tmm.isAVLBalanced()).toBe(true);
expect(tmm.getHeight()).toBe(3);
const removed13 = tmm.delete(13, undefined, true);
const removed13 = tmm.delete(13, true);
expect(removed13 instanceof Array);
expect(removed13[0]);
expect(removed13[0].deleted);
@ -245,7 +245,7 @@ describe('TreeMultiMap operations test1', () => {
expect(tmm.isAVLBalanced()).toBe(true);
expect(tmm.getHeight()).toBe(3);
const removed3 = tmm.delete(3, undefined, true);
const removed3 = tmm.delete(3, true);
expect(removed3 instanceof Array);
expect(removed3[0]);
expect(removed3[0].deleted);
@ -253,7 +253,7 @@ describe('TreeMultiMap operations test1', () => {
expect(tmm.isAVLBalanced()).toBe(false);
expect(tmm.getHeight()).toBe(3);
const removed8 = tmm.delete(8, undefined, true);
const removed8 = tmm.delete(8, true);
expect(removed8 instanceof Array);
expect(removed8[0]);
expect(removed8[0].deleted);
@ -261,17 +261,17 @@ describe('TreeMultiMap operations test1', () => {
expect(tmm.isAVLBalanced()).toBe(false);
expect(tmm.getHeight()).toBe(3);
const removed6 = tmm.delete(6, undefined, true);
const removed6 = tmm.delete(6, true);
expect(removed6 instanceof Array);
expect(removed6[0]);
expect(removed6[0].deleted);
if (removed6[0].deleted) expect(removed6[0].deleted.key).toBe(6);
expect(tmm.delete(6, undefined, true).length).toBe(0);
expect(tmm.delete(6, true).length).toBe(0);
expect(tmm.isAVLBalanced()).toBe(false);
expect(tmm.getHeight()).toBe(3);
const removed7 = tmm.delete(7, undefined, true);
const removed7 = tmm.delete(7, true);
expect(removed7 instanceof Array);
expect(removed7[0]);
expect(removed7[0].deleted);
@ -279,7 +279,7 @@ describe('TreeMultiMap operations test1', () => {
expect(tmm.isAVLBalanced()).toBe(false);
expect(tmm.getHeight()).toBe(3);
const removed9 = tmm.delete(9, undefined, true);
const removed9 = tmm.delete(9, true);
expect(removed9 instanceof Array);
expect(removed9[0]);
expect(removed9[0].deleted);
@ -287,7 +287,7 @@ describe('TreeMultiMap operations test1', () => {
expect(tmm.isAVLBalanced()).toBe(true);
expect(tmm.getHeight()).toBe(2);
const removed14 = tmm.delete(14, undefined, true);
const removed14 = tmm.delete(14, true);
expect(removed14 instanceof Array);
expect(removed14[0]);
expect(removed14[0].deleted);
@ -391,13 +391,13 @@ describe('TreeMultiMap operations test recursively1', () => {
const nodeId10 = tmm.getNode(10);
expect(nodeId10?.key).toBe(10);
const nodeVal9 = tmm.getNode(9, node => node.value);
const nodeVal9 = tmm.getNode(node => node.value === 9);
expect(nodeVal9?.key).toBe(9);
const nodesByCount1 = tmm.getNodes(1, node => node.count);
const nodesByCount1 = tmm.getNodes(node => node.count === 1);
expect(nodesByCount1.length).toBe(14);
const nodesByCount2 = tmm.getNodes(2, node => node.count);
const nodesByCount2 = tmm.getNodes(node => node.count === 2);
expect(nodesByCount2.length).toBe(2);
const leftMost = tmm.getLeftMost();
expect(leftMost).toBe(1);
@ -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);
@ -447,7 +447,7 @@ describe('TreeMultiMap operations test recursively1', () => {
expect(bfsNodesAfterBalanced[0].key).toBe(6);
expect(bfsNodesAfterBalanced[bfsNodesAfterBalanced.length - 1].key).toBe(16);
const removed11 = tmm.delete(11, undefined, true);
const removed11 = tmm.delete(11, true);
expect(removed11 instanceof Array);
expect(removed11[0]);
expect(removed11[0].deleted);
@ -458,7 +458,7 @@ describe('TreeMultiMap operations test recursively1', () => {
expect(tmm.getHeight(15)).toBe(1);
const removed1 = tmm.delete(1, undefined, true);
const removed1 = tmm.delete(1, true);
expect(removed1 instanceof Array);
expect(removed1[0]);
expect(removed1[0].deleted);
@ -468,7 +468,7 @@ describe('TreeMultiMap operations test recursively1', () => {
expect(tmm.getHeight()).toBe(5);
const removed4 = tmm.delete(4, undefined, true);
const removed4 = tmm.delete(4, true);
expect(removed4 instanceof Array);
expect(removed4[0]);
expect(removed4[0].deleted);
@ -477,7 +477,7 @@ describe('TreeMultiMap operations test recursively1', () => {
expect(tmm.isAVLBalanced()).toBe(false);
expect(tmm.getHeight()).toBe(5);
const removed10 = tmm.delete(10, undefined, true);
const removed10 = tmm.delete(10, true);
expect(removed10 instanceof Array);
expect(removed10[0]);
expect(removed10[0].deleted);
@ -486,7 +486,7 @@ describe('TreeMultiMap operations test recursively1', () => {
expect(tmm.getHeight()).toBe(4);
const removed15 = tmm.delete(15, undefined, true);
const removed15 = tmm.delete(15, true);
expect(removed15 instanceof Array);
expect(removed15[0]);
expect(removed15[0].deleted);
@ -495,7 +495,7 @@ describe('TreeMultiMap operations test recursively1', () => {
expect(tmm.isAVLBalanced()).toBe(false);
expect(tmm.getHeight()).toBe(3);
const removed5 = tmm.delete(5, undefined, true);
const removed5 = tmm.delete(5, true);
expect(removed5 instanceof Array);
expect(removed5[0]);
expect(removed5[0].deleted);
@ -504,7 +504,7 @@ describe('TreeMultiMap operations test recursively1', () => {
expect(tmm.isAVLBalanced()).toBe(true);
expect(tmm.getHeight()).toBe(3);
const removed13 = tmm.delete(13, undefined, true);
const removed13 = tmm.delete(13, true);
expect(removed13 instanceof Array);
expect(removed13[0]);
expect(removed13[0].deleted);
@ -512,7 +512,7 @@ describe('TreeMultiMap operations test recursively1', () => {
expect(tmm.isAVLBalanced()).toBe(true);
expect(tmm.getHeight()).toBe(3);
const removed3 = tmm.delete(3, undefined, true);
const removed3 = tmm.delete(3, true);
expect(removed3 instanceof Array);
expect(removed3[0]);
expect(removed3[0].deleted);
@ -520,7 +520,7 @@ describe('TreeMultiMap operations test recursively1', () => {
expect(tmm.isAVLBalanced()).toBe(false);
expect(tmm.getHeight()).toBe(3);
const removed8 = tmm.delete(8, undefined, true);
const removed8 = tmm.delete(8, true);
expect(removed8 instanceof Array);
expect(removed8[0]);
expect(removed8[0].deleted);
@ -528,17 +528,17 @@ describe('TreeMultiMap operations test recursively1', () => {
expect(tmm.isAVLBalanced()).toBe(false);
expect(tmm.getHeight()).toBe(3);
const removed6 = tmm.delete(6, undefined, true);
const removed6 = tmm.delete(6, true);
expect(removed6 instanceof Array);
expect(removed6[0]);
expect(removed6[0].deleted);
if (removed6[0].deleted) expect(removed6[0].deleted.key).toBe(6);
expect(tmm.delete(6, undefined, true).length).toBe(0);
expect(tmm.delete(6, true).length).toBe(0);
expect(tmm.isAVLBalanced()).toBe(false);
expect(tmm.getHeight()).toBe(3);
const removed7 = tmm.delete(7, undefined, true);
const removed7 = tmm.delete(7, true);
expect(removed7 instanceof Array);
expect(removed7[0]);
expect(removed7[0].deleted);
@ -546,7 +546,7 @@ describe('TreeMultiMap operations test recursively1', () => {
expect(tmm.isAVLBalanced()).toBe(false);
expect(tmm.getHeight()).toBe(3);
const removed9 = tmm.delete(9, undefined, true);
const removed9 = tmm.delete(9, true);
expect(removed9 instanceof Array);
expect(removed9[0]);
expect(removed9[0].deleted);
@ -554,7 +554,7 @@ describe('TreeMultiMap operations test recursively1', () => {
expect(tmm.isAVLBalanced()).toBe(true);
expect(tmm.getHeight()).toBe(2);
const removed14 = tmm.delete(14, undefined, true);
const removed14 = tmm.delete(14, true);
expect(removed14 instanceof Array);
expect(removed14[0]);
expect(removed14[0].deleted);
@ -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 () {
@ -664,7 +664,7 @@ describe('TreeMultiMap delete test', function () {
}
for (let i = 0; i < inputSize; i++) {
tmm.delete(i, undefined, true);
tmm.delete(i, true);
}
let nilCount = 0;
@ -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', () => {
@ -39,6 +44,8 @@ describe('UndirectedGraph Operation Test', () => {
expect(graph.hasEdge('A', 'B')).toBe(true);
expect(graph.hasEdge('B', 'A')).toBe(true);
expect(graph.has('A')).toBe(true);
expect(graph.get('A')).toBe(undefined);
});
it('should delete edges', () => {
@ -577,7 +584,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 +598,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);
}
}