Compare commits

..

No commits in common. "37ff9207fe3a749323bd174857f314e78ebdd318" and "6ef4b47b0b14234177e1ef1eb9f14b99b78bb9fb" have entirely different histories.

24 changed files with 796 additions and 1654 deletions

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.9](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

@ -826,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>6.63</td><td>150.92</td><td>3.07e-4</td></tr><tr><td>100,000 add & poll</td><td>35.09</td><td>28.50</td><td>8.68e-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>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>89.65</td><td>11.15</td><td>0.00</td></tr><tr><td>100,000 add randomly</td><td>92.74</td><td>10.78</td><td>0.01</td></tr><tr><td>100,000 get</td><td>1.09</td><td>921.21</td><td>7.98e-5</td></tr><tr><td>100,000 iterator</td><td>25.76</td><td>38.82</td><td>0.00</td></tr><tr><td>100,000 add & delete orderly</td><td>159.43</td><td>6.27</td><td>0.02</td></tr><tr><td>100,000 add & delete randomly</td><td>239.83</td><td>4.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 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>45.01</td><td>22.22</td><td>0.01</td></tr><tr><td>100,000 push & shift</td><td>6.24</td><td>160.17</td><td>0.01</td></tr><tr><td>Native JS Array 100,000 push & shift</td><td>2227.55</td><td>0.45</td><td>0.22</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>20.21</td><td>49.47</td><td>0.00</td></tr><tr><td>1,000,000 push & pop</td><td>26.85</td><td>37.24</td><td>0.01</td></tr><tr><td>1,000,000 push & shift</td><td>27.57</td><td>36.27</td><td>0.00</td></tr><tr><td>100,000 push & shift</td><td>2.61</td><td>382.64</td><td>4.60e-4</td></tr><tr><td>Native JS Array 100,000 push & shift</td><td>2152.90</td><td>0.46</td><td>0.22</td></tr><tr><td>100,000 unshift & shift</td><td>2.51</td><td>398.74</td><td>3.60e-4</td></tr><tr><td>Native JS Array 100,000 unshift & shift</td><td>4376.45</td><td>0.23</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>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>86.79</td><td>11.52</td><td>0.03</td></tr><tr><td>Native JS Map 1,000,000 set</td><td>207.96</td><td>4.81</td><td>0.01</td></tr><tr><td>Native JS Set 1,000,000 add</td><td>169.32</td><td>5.91</td><td>0.02</td></tr><tr><td>1,000,000 set & get</td><td>81.30</td><td>12.30</td><td>0.02</td></tr><tr><td>Native JS Map 1,000,000 set & get</td><td>272.31</td><td>3.67</td><td>0.01</td></tr><tr><td>Native JS Set 1,000,000 add & has</td><td>237.78</td><td>4.21</td><td>0.02</td></tr><tr><td>1,000,000 ObjKey set & get</td><td>374.05</td><td>2.67</td><td>0.06</td></tr><tr><td>Native JS Map 1,000,000 ObjKey set & get</td><td>345.51</td><td>2.89</td><td>0.06</td></tr><tr><td>Native JS Set 1,000,000 ObjKey add & has</td><td>286.45</td><td>3.49</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>41.60</td><td>24.04</td><td>5.38e-4</td></tr><tr><td>100,000 getWords</td><td>81.04</td><td>12.34</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>299.03</td><td>3.34</td><td>0.00</td></tr><tr><td>100,000 add randomly</td><td>364.39</td><td>2.74</td><td>0.02</td></tr><tr><td>100,000 get</td><td>1.08</td><td>921.78</td><td>8.08e-5</td></tr><tr><td>100,000 iterator</td><td>27.60</td><td>36.23</td><td>0.00</td></tr><tr><td>100,000 add & delete orderly</td><td>488.82</td><td>2.05</td><td>0.00</td></tr><tr><td>100,000 add & delete randomly</td><td>649.46</td><td>1.54</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>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>7.76</td><td>128.90</td><td>1.09e-4</td></tr><tr><td>10,000 RBTree get randomly</td><td>0.11</td><td>9328.86</td><td>5.44e-6</td></tr><tr><td>10,000 RBTree add & delete randomly</td><td>21.72</td><td>46.04</td><td>2.07e-4</td></tr><tr><td>10,000 AVLTree add randomly</td><td>27.45</td><td>36.43</td><td>3.65e-4</td></tr><tr><td>10,000 AVLTree get randomly</td><td>0.11</td><td>9432.49</td><td>4.04e-7</td></tr><tr><td>10,000 AVLTree add & delete randomly</td><td>51.03</td><td>19.60</td><td>6.60e-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>1.03e+4</td><td>1.04e-6</td></tr><tr><td>1,000 addEdge</td><td>6.01</td><td>166.29</td><td>1.12e-4</td></tr><tr><td>1,000 getVertex</td><td>0.10</td><td>1.04e+4</td><td>1.71e-6</td></tr><tr><td>1,000 getEdge</td><td>23.72</td><td>42.15</td><td>0.00</td></tr><tr><td>tarjan</td><td>194.37</td><td>5.14</td><td>0.00</td></tr><tr><td>topologicalSort</td><td>152.91</td><td>6.54</td><td>0.02</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>188.44</td><td>5.31</td><td>0.04</td></tr><tr><td>1,000,000 unshift</td><td>177.48</td><td>5.63</td><td>0.02</td></tr><tr><td>1,000,000 unshift & shift</td><td>161.09</td><td>6.21</td><td>0.04</td></tr><tr><td>1,000,000 addBefore</td><td>277.84</td><td>3.60</td><td>0.08</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>193.99</td><td>5.15</td><td>0.05</td></tr><tr><td>10,000 push & pop</td><td>232.82</td><td>4.30</td><td>0.01</td></tr><tr><td>10,000 addBefore</td><td>285.44</td><td>3.50</td><td>0.02</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>30.02</td><td>33.31</td><td>2.68e-4</td></tr><tr><td>100,000 add & poll</td><td>89.21</td><td>11.21</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>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>42.73</td><td>23.40</td><td>0.00</td></tr><tr><td>1,000,000 push & pop</td><td>50.52</td><td>19.79</td><td>0.02</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)

52
package-lock.json generated
View file

@ -1,12 +1,12 @@
{
"name": "data-structure-typed",
"version": "1.52.9",
"version": "1.52.8",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "data-structure-typed",
"version": "1.52.9",
"version": "1.52.8",
"license": "MIT",
"devDependencies": {
"@eslint/compat": "^1.2.2",
@ -19,11 +19,11 @@
"@typescript-eslint/eslint-plugin": "^8.12.1",
"@typescript-eslint/parser": "^8.12.1",
"auto-changelog": "^2.5.0",
"avl-tree-typed": "^1.52.9",
"avl-tree-typed": "^1.52.8",
"benchmark": "^2.1.4",
"binary-tree-typed": "^1.52.9",
"bst-typed": "^1.52.9",
"data-structure-typed": "^1.52.9",
"binary-tree-typed": "^1.52.8",
"bst-typed": "^1.52.8",
"data-structure-typed": "^1.52.8",
"dependency-cruiser": "^16.5.0",
"doctoc": "^2.2.1",
"eslint": "^9.13.0",
@ -32,7 +32,7 @@
"eslint-import-resolver-typescript": "^3.6.3",
"eslint-plugin-import": "^2.31.0",
"fast-glob": "^3.3.2",
"heap-typed": "^1.52.9",
"heap-typed": "^1.52.8",
"istanbul-badges-readme": "^1.9.0",
"jest": "^29.7.0",
"js-sdsl": "^4.4.2",
@ -3437,13 +3437,13 @@
}
},
"node_modules/avl-tree-typed": {
"version": "1.52.9",
"resolved": "https://registry.npmjs.org/avl-tree-typed/-/avl-tree-typed-1.52.9.tgz",
"integrity": "sha512-TfapTNrlIquhf1iwrzhc5pEejEhE0CogxiNlaI0nqkv2Qz2OkhvfmAtJOG5ndiFBp4btNZYFGHb+S/zXkEX82A==",
"version": "1.52.8",
"resolved": "https://registry.npmjs.org/avl-tree-typed/-/avl-tree-typed-1.52.8.tgz",
"integrity": "sha512-8oU+KjIVtzF9U12NudYuQNBX/If1DL1bKrbqLtKk5RjEq1Jsl56/GIvuzbvKHnGgv9h7DpXHyJUCLjAz3zjhbg==",
"dev": true,
"license": "MIT",
"dependencies": {
"data-structure-typed": "^1.52.9"
"data-structure-typed": "^1.52.8"
}
},
"node_modules/babel-jest": {
@ -3602,13 +3602,13 @@
}
},
"node_modules/binary-tree-typed": {
"version": "1.52.9",
"resolved": "https://registry.npmjs.org/binary-tree-typed/-/binary-tree-typed-1.52.9.tgz",
"integrity": "sha512-/q5l3wftn485Px+L40NKjKBPukL1XjotSQVCYB+wmz1S3P4H8FobBlEFo5j0UqaW9+TgzhSwecoBbIPsvshXAQ==",
"version": "1.52.8",
"resolved": "https://registry.npmjs.org/binary-tree-typed/-/binary-tree-typed-1.52.8.tgz",
"integrity": "sha512-tjUcMufU41Tmp+/6/cBHdSonA+gjhMUpfJqspJ06xp8A3gfWQpf9TjHdY9FxpeeTLPnREpU4SGGZqqIk372XVA==",
"dev": true,
"license": "MIT",
"dependencies": {
"data-structure-typed": "^1.52.9"
"data-structure-typed": "^1.52.8"
}
},
"node_modules/brace-expansion": {
@ -3691,13 +3691,13 @@
}
},
"node_modules/bst-typed": {
"version": "1.52.9",
"resolved": "https://registry.npmjs.org/bst-typed/-/bst-typed-1.52.9.tgz",
"integrity": "sha512-7jgOhrYST+HBZRGvmKx3UZRt6ddBr9Ib807gfJ9+jRVuXQIK9m3hW1MSwXMovWs8tKpF0JZMCqj+uk+S8B85qg==",
"version": "1.52.8",
"resolved": "https://registry.npmjs.org/bst-typed/-/bst-typed-1.52.8.tgz",
"integrity": "sha512-YMRUaz8jNxSymvKNNyeJR8HozHRgDWUw8PO0QLSvaW/c4Ed/KhpDSyBth52NClFnbJnNV2lTsd01k/VwuerimA==",
"dev": true,
"license": "MIT",
"dependencies": {
"data-structure-typed": "^1.52.9"
"data-structure-typed": "^1.52.8"
}
},
"node_modules/buffer-from": {
@ -4069,9 +4069,9 @@
}
},
"node_modules/data-structure-typed": {
"version": "1.52.9",
"resolved": "https://registry.npmjs.org/data-structure-typed/-/data-structure-typed-1.52.9.tgz",
"integrity": "sha512-tIAf4CqOdDz5XJZBtTjWwhOgLOwiMS+1kH9dN44x12klBcKavpUDUjncvrcAqLsVP5xTZSeehJ5teNa6YNgWQQ==",
"version": "1.52.8",
"resolved": "https://registry.npmjs.org/data-structure-typed/-/data-structure-typed-1.52.8.tgz",
"integrity": "sha512-2YNk0YSjwK0IA8b+g68bmbWtc82M4IzIqo/VUSY16lO3LZ+AajxPkBK68VHPP07ckNNLhdLbh04RoQd3dMNNiw==",
"dev": true,
"license": "MIT"
},
@ -5946,13 +5946,13 @@
}
},
"node_modules/heap-typed": {
"version": "1.52.9",
"resolved": "https://registry.npmjs.org/heap-typed/-/heap-typed-1.52.9.tgz",
"integrity": "sha512-YdCJFzKob73n5sDovGkL2Y/jqVe+vY9dXcDyx4ToZoneJqJ83IMVDl/qlGb/ujDMlTXqJR4/jiIT5s00jxS7jQ==",
"version": "1.52.8",
"resolved": "https://registry.npmjs.org/heap-typed/-/heap-typed-1.52.8.tgz",
"integrity": "sha512-Zzq+V9IQMf8o2FrIeqc0kRxRyDxOyUPX5dXRi095LnpOFRzUXZoSl2hggbHfsjKEaKwLDRoJuS9t77alqmK4NQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"data-structure-typed": "^1.52.9"
"data-structure-typed": "^1.52.8"
}
},
"node_modules/html-escaper": {

View file

@ -1,6 +1,6 @@
{
"name": "data-structure-typed",
"version": "1.53.0",
"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",
@ -68,11 +68,11 @@
"@typescript-eslint/eslint-plugin": "^8.12.1",
"@typescript-eslint/parser": "^8.12.1",
"auto-changelog": "^2.5.0",
"avl-tree-typed": "^1.52.9",
"avl-tree-typed": "^1.52.8",
"benchmark": "^2.1.4",
"binary-tree-typed": "^1.52.9",
"bst-typed": "^1.52.9",
"data-structure-typed": "^1.52.9",
"binary-tree-typed": "^1.52.8",
"bst-typed": "^1.52.8",
"data-structure-typed": "^1.52.8",
"dependency-cruiser": "^16.5.0",
"doctoc": "^2.2.1",
"eslint": "^9.13.0",
@ -81,7 +81,7 @@
"eslint-import-resolver-typescript": "^3.6.3",
"eslint-plugin-import": "^2.31.0",
"fast-glob": "^3.3.2",
"heap-typed": "^1.52.9",
"heap-typed": "^1.52.8",
"istanbul-badges-readme": "^1.9.0",
"jest": "^29.7.0",
"js-sdsl": "^4.4.2",

View file

@ -10,9 +10,11 @@ import type {
AVLTreeMultiMapNodeNested,
AVLTreeMultiMapOptions,
BinaryTreeDeleteResult,
BSTNOptKeyOrNode,
BTNRep,
IterationType
BSTNKeyOrNode,
BTNKeyOrNodeOrEntry,
BTNPredicate,
IterationType,
BTNEntry
} from '../../types';
import { IBinaryTree } from '../../interfaces';
import { AVLTree, AVLTreeNode } from './avl-tree';
@ -63,7 +65,7 @@ export class AVLTreeMultiMapNode<
export class AVLTreeMultiMap<
K = any,
V = any,
R = object,
R = BTNEntry<K, V>,
NODE extends AVLTreeMultiMapNode<K, V, NODE> = AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNodeNested<K, V>>,
TREE extends AVLTreeMultiMap<K, V, R, NODE, TREE> = AVLTreeMultiMap<
K,
@ -78,18 +80,18 @@ export class AVLTreeMultiMap<
{
/**
* The constructor initializes a new AVLTreeMultiMap object with optional initial elements.
* @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` 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(
keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V, NODE>> = [],
keysOrNodesOrEntriesOrRaws: Iterable<R | BTNKeyOrNodeOrEntry<K, V, NODE>> = [],
options?: AVLTreeMultiMapOptions<K, V, R>
) {
super([], options);
if (keysNodesEntriesOrRaws) this.addMany(keysNodesEntriesOrRaws);
if (keysOrNodesOrEntriesOrRaws) this.addMany(keysOrNodesOrEntriesOrRaws);
}
protected _count = 0;
@ -142,7 +144,6 @@ export class AVLTreeMultiMap<
override createTree(options?: AVLTreeMultiMapOptions<K, V, R>): TREE {
return new AVLTreeMultiMap<K, V, R, NODE, TREE>([], {
iterationType: this.iterationType,
isMapMode: this._isMapMode,
comparator: this._comparator,
toEntryFn: this._toEntryFn,
...options
@ -151,20 +152,20 @@ export class AVLTreeMultiMap<
/**
* The function checks if the input is an instance of AVLTreeMultiMapNode.
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
* `keyNodeEntryOrRaw` can be of type `R` or `BTNRep<K, V, NODE>`.
* @returns a boolean value indicating whether the input parameter `keyNodeEntryOrRaw` 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(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R): keyNodeEntryOrRaw is NODE {
return keyNodeEntryOrRaw instanceof AVLTreeMultiMapNode;
override isNode(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R): keyOrNodeOrEntryOrRaw is NODE {
return keyOrNodeOrEntryOrRaw instanceof AVLTreeMultiMapNode;
}
/**
* The function `keyValueNodeEntryRawToNodeAndValue` converts a key, value, entry, or raw element into
* The function `keyValueOrEntryOrRawElementToNode` converts a key, value, entry, or raw element into
* a node object.
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The
* `keyNodeEntryOrRaw` parameter can be of type `R` or `BTNRep<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`.
@ -172,33 +173,28 @@ export class AVLTreeMultiMap<
* times the key-value pair should be added to the data structure. If not provided, it defaults to 1.
* @returns either a NODE object or undefined.
*/
override keyValueNodeEntryRawToNodeAndValue(
keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R,
override keyValueOrEntryOrRawElementToNode(
keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R,
value?: V,
count = 1
): [NODE | undefined, V | undefined] {
if (keyNodeEntryOrRaw === undefined || keyNodeEntryOrRaw === null) return [undefined, undefined];
if (this.isNode(keyNodeEntryOrRaw)) return [keyNodeEntryOrRaw, value];
): NODE | undefined {
if (keyOrNodeOrEntryOrRaw === undefined || keyOrNodeOrEntryOrRaw === null) return;
if (this.isNode(keyOrNodeOrEntryOrRaw)) return keyOrNodeOrEntryOrRaw;
if (this.isEntry(keyNodeEntryOrRaw)) {
const [key, entryValue] = keyNodeEntryOrRaw;
if (key === undefined || key === null) return [undefined, undefined];
const finalValue = value ?? entryValue;
return [this.createNode(key, finalValue, count), finalValue];
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.isKey(keyNodeEntryOrRaw)) return [this.createNode(keyNodeEntryOrRaw, value, count), value];
if (this.isRaw(keyNodeEntryOrRaw)) {
if (this._toEntryFn) {
const [key, entryValue] = this._toEntryFn(keyNodeEntryOrRaw as R);
const finalValue = value ?? entryValue;
if (this.isKey(key)) return [this.createNode(key, finalValue, count), finalValue];
}
return [undefined, undefined];
if (this._toEntryFn) {
const [key, entryValue] = this._toEntryFn(keyOrNodeOrEntryOrRaw as R);
if (this.isKey(key)) return this.createNode(key, value ?? entryValue, count);
}
return [undefined, undefined];
if (this.isKey(keyOrNodeOrEntryOrRaw)) return this.createNode(keyOrNodeOrEntryOrRaw, value, count);
return;
}
/**
@ -207,9 +203,9 @@ 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 {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The
* `keyNodeEntryOrRaw` parameter can accept a value of type `R`, which can be any type. It
* can also accept a value of type `BTNRep<K, V, NODE>`, which represents a key, node,
* @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
* data structure. It is an optional parameter, so it can be omitted if not needed.
@ -218,12 +214,12 @@ 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(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R, value?: V, count = 1): boolean {
const [newNode, newValue] = this.keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, 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;
const inserted = super.add(newNode, newValue);
const inserted = super.add(newNode);
if (inserted) {
this._count += orgNodeCount;
}
@ -236,7 +232,7 @@ export class AVLTreeMultiMap<
*
* The function overrides the delete method in a binary tree data structure, handling deletion of
* nodes and maintaining balance in the tree.
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The `predicate`
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - 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, or entry that determines which
* node(s) should be deleted.
@ -249,11 +245,14 @@ export class AVLTreeMultiMap<
* method returns an array of `BinaryTreeDeleteResult` objects, each containing information about the
* deleted node and whether balancing is needed in the tree.
*/
override delete(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R, ignoreCount = false): BinaryTreeDeleteResult<NODE>[] {
override delete(
keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R,
ignoreCount = false
): BinaryTreeDeleteResult<NODE>[] {
const deletedResult: BinaryTreeDeleteResult<NODE>[] = [];
if (!this.root) return deletedResult;
const curr: NODE | undefined = this.getNode(keyNodeEntryOrRaw) ?? undefined;
const curr: NODE | undefined = this.getNode(keyOrNodeOrEntryOrRaw) ?? undefined;
if (!curr) return deletedResult;
const parent: NODE | undefined = curr?.parent ? curr.parent : undefined;
@ -341,8 +340,7 @@ export class AVLTreeMultiMap<
if (l > r) return;
const m = l + Math.floor((r - l) / 2);
const midNode = sorted[m];
if (this._isMapMode) this.add(midNode.key, undefined, midNode.count);
else this.add(midNode.key, midNode.value, midNode.count);
this.add(midNode.key, midNode.value, midNode.count);
buildBalanceBST(l, m - 1);
buildBalanceBST(m + 1, r);
};
@ -358,8 +356,7 @@ export class AVLTreeMultiMap<
if (l <= r) {
const m = l + Math.floor((r - l) / 2);
const midNode = sorted[m];
if (this._isMapMode) this.add(midNode.key, undefined, midNode.count);
else this.add(midNode.key, midNode.value, midNode.count);
this.add(midNode.key, midNode.value, midNode.count);
stack.push([m + 1, r]);
stack.push([l, m - 1]);
}
@ -378,9 +375,7 @@ export class AVLTreeMultiMap<
*/
override clone(): TREE {
const cloned = this.createTree();
if (this._isMapMode) this.bfs(node => cloned.add(node.key, undefined, node.count));
else this.bfs(node => cloned.add(node.key, node.value, node.count));
if (this._isMapMode) cloned._store = this._store;
this.bfs(node => cloned.add(node.key, node.value, node.count));
return cloned;
}
@ -390,16 +385,16 @@ export class AVLTreeMultiMap<
*
* The `_swapProperties` function swaps the properties (key, value, count, height) between two nodes
* in a binary search tree.
* @param {R | BSTNOptKeyOrNode<K, NODE>} srcNode - The `srcNode` parameter represents the source node
* @param {R | BSTNKeyOrNode<K, NODE>} srcNode - The `srcNode` parameter represents the source node
* that will be swapped with the `destNode`.
* @param {R | BSTNOptKeyOrNode<K, NODE>} destNode - The `destNode` parameter represents the destination
* @param {R | BSTNKeyOrNode<K, NODE>} destNode - The `destNode` parameter represents the destination
* node where the properties will be swapped with the source node.
* @returns The method is returning the `destNode` after swapping its properties with the `srcNode`.
* If either `srcNode` or `destNode` is undefined, it returns `undefined`.
*/
protected override _swapProperties(
srcNode: R | BSTNOptKeyOrNode<K, NODE>,
destNode: R | BSTNOptKeyOrNode<K, NODE>
srcNode: R | BSTNKeyOrNode<K, NODE>,
destNode: R | BSTNKeyOrNode<K, NODE>
): NODE | undefined {
srcNode = this.ensureNode(srcNode);
destNode = this.ensureNode(destNode);
@ -410,12 +405,12 @@ export class AVLTreeMultiMap<
tempNode.height = height;
destNode.key = srcNode.key;
if (!this._isMapMode) destNode.value = srcNode.value;
destNode.value = srcNode.value;
destNode.count = srcNode.count;
destNode.height = srcNode.height;
srcNode.key = tempNode.key;
if (!this._isMapMode) srcNode.value = tempNode.value;
srcNode.value = tempNode.value;
srcNode.count = tempNode.count;
srcNode.height = tempNode.height;
}

View file

@ -11,8 +11,10 @@ import type {
AVLTreeNodeNested,
AVLTreeOptions,
BinaryTreeDeleteResult,
BSTNOptKeyOrNode,
BTNRep
BSTNKeyOrNode,
BTNKeyOrNodeOrEntry,
BTNPredicate,
BTNEntry
} from '../../types';
import { IBinaryTree } from '../../interfaces';
@ -66,7 +68,7 @@ export class AVLTreeNode<
export class AVLTree<
K = any,
V = any,
R = object,
R = BTNEntry<K, V>,
NODE extends AVLTreeNode<K, V, NODE> = AVLTreeNode<K, V, AVLTreeNodeNested<K, V>>,
TREE extends AVLTree<K, V, R, NODE, TREE> = AVLTree<K, V, R, NODE, AVLTreeNested<K, V, R, NODE>>
>
@ -76,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 keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` 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
@ -84,9 +86,12 @@ export class AVLTree<
* keys), `allowDuplicates` (a boolean indicating whether duplicate keys are allowed), and
* `nodeBuilder` (
*/
constructor(keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V, NODE>> = [], options?: AVLTreeOptions<K, V, R>) {
constructor(
keysOrNodesOrEntriesOrRaws: Iterable<R | BTNKeyOrNodeOrEntry<K, V, NODE>> = [],
options?: AVLTreeOptions<K, V, R>
) {
super([], options);
if (keysNodesEntriesOrRaws) super.addMany(keysNodesEntriesOrRaws);
if (keysOrNodesOrEntriesOrRaws) super.addMany(keysOrNodesOrEntriesOrRaws);
}
/**
@ -112,7 +117,6 @@ export class AVLTree<
override createTree(options?: AVLTreeOptions<K, V, R>): TREE {
return new AVLTree<K, V, R, NODE, TREE>([], {
iterationType: this.iterationType,
isMapMode: this._isMapMode,
comparator: this._comparator,
toEntryFn: this._toEntryFn,
...options
@ -121,13 +125,13 @@ export class AVLTree<
/**
* The function checks if the input is an instance of AVLTreeNode.
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
* `keyNodeEntryOrRaw` can be of type `R` or `BTNRep<K, V, NODE>`.
* @returns a boolean value indicating whether the input parameter `keyNodeEntryOrRaw` 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(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R): keyNodeEntryOrRaw is NODE {
return keyNodeEntryOrRaw instanceof AVLTreeNode;
override isNode(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R): keyOrNodeOrEntryOrRaw is NODE {
return keyOrNodeOrEntryOrRaw instanceof AVLTreeNode;
}
/**
@ -136,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 {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
* `keyNodeEntryOrRaw` can accept values of type `R`, `BTNRep<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(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R, value?: V): boolean {
if (keyNodeEntryOrRaw === null) return false;
const inserted = super.add(keyNodeEntryOrRaw, value);
if (inserted) this._balancePath(keyNodeEntryOrRaw);
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;
}
@ -156,15 +160,15 @@ export class AVLTree<
*
* The function overrides the delete method in a TypeScript class, performs deletion, and then
* balances the tree if necessary.
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The `keyNodeEntryOrRaw`
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - The `keyOrNodeOrEntryOrRaw`
* 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(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R): BinaryTreeDeleteResult<NODE>[] {
const deletedResults = super.delete(keyNodeEntryOrRaw);
override delete(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R): BinaryTreeDeleteResult<NODE>[] {
const deletedResults = super.delete(keyOrNodeOrEntryOrRaw);
for (const { needBalanced } of deletedResults) {
if (needBalanced) {
this._balancePath(needBalanced);
@ -179,16 +183,16 @@ export class AVLTree<
*
* The `_swapProperties` function swaps the key, value, and height properties between two nodes in a
* binary search tree.
* @param {R | BSTNOptKeyOrNode<K, NODE>} srcNode - The `srcNode` parameter represents either a node
* @param {R | BSTNKeyOrNode<K, NODE>} srcNode - The `srcNode` parameter represents either a node
* object (`NODE`) or a key-value pair (`R`) that is being swapped with another node.
* @param {R | BSTNOptKeyOrNode<K, NODE>} destNode - The `destNode` parameter is either an instance of
* `R` or an instance of `BSTNOptKeyOrNode<K, NODE>`.
* @param {R | BSTNKeyOrNode<K, NODE>} destNode - The `destNode` parameter is either an instance of
* `R` or an instance of `BSTNKeyOrNode<K, NODE>`.
* @returns The method is returning the `destNodeEnsured` object if both `srcNodeEnsured` and
* `destNodeEnsured` are truthy. Otherwise, it returns `undefined`.
*/
protected override _swapProperties(
srcNode: R | BSTNOptKeyOrNode<K, NODE>,
destNode: R | BSTNOptKeyOrNode<K, NODE>
srcNode: R | BSTNKeyOrNode<K, NODE>,
destNode: R | BSTNKeyOrNode<K, NODE>
): NODE | undefined {
const srcNodeEnsured = this.ensureNode(srcNode);
const destNodeEnsured = this.ensureNode(destNode);
@ -201,11 +205,11 @@ export class AVLTree<
tempNode.height = height;
destNodeEnsured.key = srcNodeEnsured.key;
if (!this._isMapMode) destNodeEnsured.value = srcNodeEnsured.value;
destNodeEnsured.value = srcNodeEnsured.value;
destNodeEnsured.height = srcNodeEnsured.height;
srcNodeEnsured.key = tempNode.key;
if (!this._isMapMode) srcNodeEnsured.value = tempNode.value;
srcNodeEnsured.value = tempNode.value;
srcNodeEnsured.height = tempNode.height;
}
@ -429,10 +433,10 @@ 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 {BTNRep<K, V, NODE> | R} node - The `node` parameter can be of type `R` or
* `BTNRep<K, V, NODE>`.
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} node - The `node` parameter can be of type `R` or
* `BTNKeyOrNodeOrEntry<K, V, NODE>`.
*/
protected _balancePath(node: BTNRep<K, V, NODE> | R): void {
protected _balancePath(node: BTNKeyOrNodeOrEntry<K, V, NODE> | R): void {
node = this.ensureNode(node);
const path = this.getPathToRoot(node => node, node, false); // first O(log n) + O(log n)
for (let i = 0; i < path.length; i++) {

File diff suppressed because it is too large Load diff

View file

@ -7,17 +7,19 @@
*/
import type {
BSTNested,
BSTNKeyOrNode,
BSTNodeNested,
BSTNOptKeyOrNode,
BSTOptions,
BTNRep,
BTNCallback,
BTNEntry,
BTNKeyOrNodeOrEntry,
BTNPredicate,
BTNPureKeyOrNodeOrEntry,
Comparator,
CP,
DFSOrderPattern,
IterationType,
NodeCallback,
NodePredicate,
OptNode
OptBSTN
} from '../../types';
import { BinaryTree, BinaryTreeNode } from './binary-tree';
import { IBinaryTree } from '../../interfaces';
@ -44,16 +46,16 @@ export class BSTNode<K = any, V = any, NODE extends BSTNode<K, V, NODE> = BSTNod
* The function returns the value of the `_left` property.
* @returns The `_left` property of the current object is being returned.
*/
override get left(): OptNode<NODE> {
override get left(): OptBSTN<NODE> {
return this._left;
}
/**
* The function sets the left child of a node and updates the parent reference of the child.
* @param {OptNode<NODE>} v - The parameter `v` is of type `OptNode<NODE>`. It can either be an
* @param {OptBSTN<NODE>} v - The parameter `v` is of type `OptBSTN<NODE>`. It can either be an
* instance of the `NODE` class or `undefined`.
*/
override set left(v: OptNode<NODE>) {
override set left(v: OptBSTN<NODE>) {
if (v) {
v.parent = this as unknown as NODE;
}
@ -67,16 +69,16 @@ export class BSTNode<K = any, V = any, NODE extends BSTNode<K, V, NODE> = BSTNod
* @returns The method is returning the value of the `_right` property, which is of type `NODE` or
* `undefined`.
*/
override get right(): OptNode<NODE> {
override get right(): OptBSTN<NODE> {
return this._right;
}
/**
* The function sets the right child of a node and updates the parent reference of the child.
* @param {OptNode<NODE>} v - The parameter `v` is of type `OptNode<NODE>`. It can either be a
* @param {OptBSTN<NODE>} v - The parameter `v` is of type `OptBSTN<NODE>`. It can either be a
* `NODE` object or `undefined`.
*/
override set right(v: OptNode<NODE>) {
override set right(v: OptBSTN<NODE>) {
if (v) {
v.parent = this as unknown as NODE;
}
@ -96,7 +98,7 @@ export class BSTNode<K = any, V = any, NODE extends BSTNode<K, V, NODE> = BSTNod
export class BST<
K = any,
V = any,
R = object,
R = BTNEntry<K, V>,
NODE extends BSTNode<K, V, NODE> = BSTNode<K, V, BSTNodeNested<K, V>>,
TREE extends BST<K, V, R, NODE, TREE> = BST<K, V, R, NODE, BSTNested<K, V, R, NODE>>
>
@ -105,13 +107,16 @@ export class BST<
{
/**
* This is the constructor function for a Binary Search Tree class in TypeScript.
* @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` 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(keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V, NODE>> = [], options?: BSTOptions<K, V, R>) {
constructor(
keysOrNodesOrEntriesOrRaws: Iterable<R | BTNKeyOrNodeOrEntry<K, V, NODE>> = [],
options?: BSTOptions<K, V, R>
) {
super([], options);
if (options) {
@ -119,7 +124,7 @@ export class BST<
if (comparator) this._comparator = comparator;
}
if (keysNodesEntriesOrRaws) this.addMany(keysNodesEntriesOrRaws);
if (keysOrNodesOrEntriesOrRaws) this.addMany(keysOrNodesOrEntriesOrRaws);
}
protected override _root?: NODE = undefined;
@ -128,7 +133,7 @@ export class BST<
* The function returns the root node of a tree structure.
* @returns The `_root` property of the object, which is of type `NODE` or `undefined`.
*/
override get root(): OptNode<NODE> {
override get root(): OptBSTN<NODE> {
return this._root;
}
@ -154,7 +159,6 @@ export class BST<
override createTree(options?: BSTOptions<K, V, R>): TREE {
return new BST<K, V, R, NODE, TREE>([], {
iterationType: this.iterationType,
isMapMode: this._isMapMode,
comparator: this._comparator,
toEntryFn: this._toEntryFn,
...options
@ -163,20 +167,18 @@ export class BST<
/**
* The function overrides a method and converts a key, value pair or entry or raw element to a node.
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - A variable that can be of
* type R or BTNRep<K, V, NODE>. It represents either a key, a node, an entry, or a raw
* @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
* value associated with a key in a key-value pair.
* @returns either a NODE object or undefined.
*/
override keyValueNodeEntryRawToNodeAndValue(
keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R,
override keyValueOrEntryOrRawElementToNode(
keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R,
value?: V
): [OptNode<NODE>, V | undefined] {
const [node, tValue] = super.keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value);
if (node === null) return [undefined, undefined];
return [node, tValue ?? value];
): OptBSTN<NODE> {
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 {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
* `keyNodeEntryOrRaw` 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,21 +197,21 @@ export class BST<
* not be ensured.
*/
override ensureNode(
keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R,
keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R,
iterationType: IterationType = this.iterationType
): OptNode<NODE> {
return super.ensureNode(keyNodeEntryOrRaw, iterationType) ?? undefined;
): OptBSTN<NODE> {
return super.ensureNode(keyOrNodeOrEntryOrRaw, iterationType) ?? undefined;
}
/**
* The function checks if the input is an instance of the BSTNode class.
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
* `keyNodeEntryOrRaw` can be of type `R` or `BTNRep<K, V, NODE>`.
* @returns a boolean value indicating whether the input parameter `keyNodeEntryOrRaw` 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(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R): keyNodeEntryOrRaw is NODE {
return keyNodeEntryOrRaw instanceof BSTNode;
override isNode(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R): keyOrNodeOrEntryOrRaw is NODE {
return keyOrNodeOrEntryOrRaw instanceof BSTNode;
}
/**
@ -229,19 +231,18 @@ 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 {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
* `keyNodeEntryOrRaw` can accept a value of type `R` or `BTNRep<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(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R, value?: V): boolean {
const [newNode, newValue] = this.keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, 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) {
this._setRoot(newNode);
if (this._isMapMode) this._setValue(newNode?.key, newValue);
this._size++;
return true;
}
@ -254,7 +255,6 @@ export class BST<
} else if (this.comparator(current.key, newNode.key) > 0) {
if (current.left === undefined) {
current.left = newNode;
if (this._isMapMode) this._setValue(newNode?.key, newValue);
this._size++;
return true;
}
@ -262,7 +262,6 @@ export class BST<
} else {
if (current.right === undefined) {
current.right = newNode;
if (this._isMapMode) this._setValue(newNode?.key, newValue);
this._size++;
return true;
}
@ -279,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 keysNodesEntriesOrRaws - 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
@ -295,7 +294,7 @@ export class BST<
* successfully inserted into the data structure.
*/
override addMany(
keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V, NODE>>,
keysOrNodesOrEntriesOrRaws: Iterable<R | BTNKeyOrNodeOrEntry<K, V, NODE>>,
values?: Iterable<V | undefined>,
isBalanceAdd = true,
iterationType: IterationType = this.iterationType
@ -309,7 +308,7 @@ export class BST<
}
if (!isBalanceAdd) {
for (const kve of keysNodesEntriesOrRaws) {
for (const kve of keysOrNodesOrEntriesOrRaws) {
const value = valuesIterator?.next().value;
inserted.push(this.add(kve, value));
}
@ -317,18 +316,18 @@ export class BST<
}
const realBTNExemplars: {
key: R | BTNRep<K, V, NODE>;
key: R | BTNKeyOrNodeOrEntry<K, V, NODE>;
value: V | undefined;
orgIndex: number;
}[] = [];
let i = 0;
for (const kve of keysNodesEntriesOrRaws) {
for (const kve of keysOrNodesOrEntriesOrRaws) {
realBTNExemplars.push({ key: kve, value: valuesIterator?.next().value, orgIndex: i });
i++;
}
let sorted: { key: R | BTNRep<K, V, NODE>; value: V | undefined; orgIndex: number }[] = [];
let sorted: { key: R | BTNKeyOrNodeOrEntry<K, V, NODE>; value: V | undefined; orgIndex: number }[] = [];
sorted = realBTNExemplars.sort(({ key: a }, { key: b }) => {
let keyA: K | undefined | null, keyB: K | undefined | null;
@ -354,7 +353,7 @@ export class BST<
return 0;
});
const _dfs = (arr: { key: R | BTNRep<K, V, NODE>; value: V | undefined; orgIndex: number }[]) => {
const _dfs = (arr: { key: R | BTNKeyOrNodeOrEntry<K, V, NODE>; value: V | undefined; orgIndex: number }[]) => {
if (arr.length === 0) return;
const mid = Math.floor((arr.length - 1) / 2);
@ -396,35 +395,35 @@ export class BST<
* Space Complexity: O(k + log n)
*
* The function `getNodes` in TypeScript overrides the base class method to retrieve nodes based on a
* given keyNodeEntryRawOrPredicate and iteration type.
* @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate - The `keyNodeEntryRawOrPredicate`
* 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 keyNodeEntryRawOrPredicate function that determines whether a node should be
* 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 keyNodeEntryRawOrPredicate (`true`) or all nodes
* that match the keyNodeEntryRawOrPredicate (`false`). If `onlyOne` is set to `true`, the method will stop iterating
* 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 {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
* @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 keyNodeEntryRawOrPredicate. It represents the root node of the subtree where the search
* 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 keyNodeEntryRawOrPredicate.
* @returns The `getNodes` method returns an array of nodes that satisfy the given predicate.
*/
override getNodes(
keyNodeEntryRawOrPredicate: BTNRep<K, V, NODE> | R | NodePredicate<NODE>,
predicate: BTNKeyOrNodeOrEntry<K, V, NODE> | R | BTNPredicate<NODE>,
onlyOne = false,
startNode: BTNRep<K, V, NODE> | R = this._root,
beginRoot: BTNKeyOrNodeOrEntry<K, V, NODE> | R = this._root,
iterationType: IterationType = this.iterationType
): NODE[] {
if (keyNodeEntryRawOrPredicate === undefined) return [];
if (keyNodeEntryRawOrPredicate === null) return [];
startNode = this.ensureNode(startNode);
if (!startNode) return [];
const callback = this._ensurePredicate(keyNodeEntryRawOrPredicate);
if (predicate === undefined) return [];
if (predicate === null) return [];
beginRoot = this.ensureNode(beginRoot);
if (!beginRoot) return [];
const callback = this._ensurePredicate(predicate);
const ans: NODE[] = [];
if (iterationType === 'RECURSIVE') {
@ -435,53 +434,27 @@ export class BST<
}
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return;
if (!this._isPredicate(keyNodeEntryRawOrPredicate)) {
const benchmarkKey = this._getKey(keyNodeEntryRawOrPredicate);
if (
this.isRealNode(cur.left) &&
benchmarkKey !== null &&
benchmarkKey !== undefined &&
this.comparator(cur.key, benchmarkKey) > 0
)
dfs(cur.left);
if (
this.isRealNode(cur.right) &&
benchmarkKey !== null &&
benchmarkKey !== undefined &&
this.comparator(cur.key, benchmarkKey) < 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 {
if (this.isRealNode(cur.left)) dfs(cur.left);
if (this.isRealNode(cur.right)) dfs(cur.right);
}
};
dfs(startNode);
dfs(beginRoot);
} else {
const stack = [startNode];
const stack = [beginRoot];
while (stack.length > 0) {
const cur = stack.pop()!;
if (callback(cur)) {
ans.push(cur);
if (onlyOne) return ans;
}
if (!this._isPredicate(keyNodeEntryRawOrPredicate)) {
const benchmarkKey = this._getKey(keyNodeEntryRawOrPredicate);
if (
this.isRealNode(cur.right) &&
benchmarkKey !== null &&
benchmarkKey !== undefined &&
this.comparator(cur.key, benchmarkKey) < 0
)
stack.push(cur.right);
if (
this.isRealNode(cur.left) &&
benchmarkKey !== null &&
benchmarkKey !== undefined &&
this.comparator(cur.key, benchmarkKey) > 0
)
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 {
if (this.isRealNode(cur.right)) stack.push(cur.right);
if (this.isRealNode(cur.left)) stack.push(cur.left);
@ -496,10 +469,10 @@ export class BST<
* Time Complexity: O(log n)
* Space Complexity: O(1)
*
* This function retrieves a node based on a given keyNodeEntryRawOrPredicate within a binary search tree structure.
* @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate - The `keyNodeEntryRawOrPredicate`
* parameter can be of type `BTNRep<K, V, NODE>`, `R`, or `NodePredicate<NODE>`.
* @param {R | BSTNOptKeyOrNode<K, NODE>} startNode - The `startNode` parameter in the `getNode` method
* 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.
@ -507,17 +480,17 @@ export class BST<
* 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 (`OptNode<NODE>`).
* It is using the `getNodes` method to find the node based on the provided keyNodeEntryRawOrPredicate, beginning at
* the specified root node (`startNode`) and using the specified iteration type. The method then
* @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(
keyNodeEntryRawOrPredicate: BTNRep<K, V, NODE> | R | NodePredicate<NODE>,
startNode: R | BSTNOptKeyOrNode<K, NODE> = this._root,
predicate: BTNKeyOrNodeOrEntry<K, V, NODE> | R | BTNPredicate<NODE>,
beginRoot: R | BSTNKeyOrNode<K, NODE> = this._root,
iterationType: IterationType = this.iterationType
): OptNode<NODE> {
return this.getNodes(keyNodeEntryRawOrPredicate, true, startNode, iterationType)[0] ?? undefined;
): OptBSTN<NODE> {
return this.getNodes(predicate, true, beginRoot, iterationType)[0] ?? undefined;
}
/**
@ -533,7 +506,7 @@ export class BST<
* It has a default value of `'ITERATIVE'`.
* @returns The method is returning a NODE object or undefined.
*/
override getNodeByKey(key: K, iterationType: IterationType = this.iterationType): OptNode<NODE> {
override getNodeByKey(key: K, iterationType: IterationType = this.iterationType): OptBSTN<NODE> {
return this.getNode(key, this._root, iterationType);
}
@ -545,11 +518,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_NODE_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 {BTNRep<K, V, NODE> | R} startNode - The `startNode` 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
@ -557,13 +530,13 @@ export class BST<
* following values:
* @returns The method is returning an array of the return type of the callback function.
*/
override dfs<C extends NodeCallback<NODE>>(
callback: C = this._DEFAULT_NODE_CALLBACK as C,
override dfs<C extends BTNCallback<NODE>>(
callback: C = this._DEFAULT_BTN_CALLBACK as C,
pattern: DFSOrderPattern = 'IN',
startNode: BTNRep<K, V, NODE> | R = this._root,
beginRoot: BTNKeyOrNodeOrEntry<K, V, NODE> | R = this._root,
iterationType: IterationType = this.iterationType
): ReturnType<C>[] {
return super.dfs(callback, pattern, startNode, iterationType);
return super.dfs(callback, pattern, beginRoot, iterationType);
}
/**
@ -575,7 +548,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 {BTNRep<K, V, NODE> | R} startNode - The `startNode` 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
@ -583,12 +556,12 @@ export class BST<
* the following values:
* @returns an array of the return type of the callback function.
*/
override bfs<C extends NodeCallback<NODE>>(
callback: C = this._DEFAULT_NODE_CALLBACK as C,
startNode: BTNRep<K, V, NODE> | R = this._root,
override bfs<C extends BTNCallback<NODE>>(
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, startNode, iterationType, false);
return super.bfs(callback, beginRoot, iterationType, false);
}
/**
@ -598,9 +571,9 @@ export class BST<
* The function overrides the listLevels method from the superclass and returns an array of arrays
* containing the results of the callback function applied to each level of the tree.
* @param {C} callback - The `callback` parameter is a generic type `C` that extends
* `NodeCallback<NODE>`. It represents a callback function that will be called for each node in the
* `BTNCallback<NODE>`. It represents a callback function that will be called for each node in the
* tree during the iteration process.
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` 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
@ -609,12 +582,12 @@ export class BST<
* @returns The method is returning a two-dimensional array of the return type of the callback
* function.
*/
override listLevels<C extends NodeCallback<NODE>>(
callback: C = this._DEFAULT_NODE_CALLBACK as C,
startNode: BTNRep<K, V, NODE> | R = this._root,
override listLevels<C extends BTNCallback<NODE>>(
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, startNode, iterationType, false);
return super.listLevels(callback, beginRoot, iterationType, false);
}
/**
@ -629,7 +602,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 {BTNRep<K, V, NODE> | R} 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,
@ -638,14 +611,14 @@ export class BST<
* @returns The function `lesserOrGreaterTraverse` returns an array of values of type
* `ReturnType<C>`, which is the return type of the callback function passed as an argument.
*/
lesserOrGreaterTraverse<C extends NodeCallback<NODE>>(
callback: C = this._DEFAULT_NODE_CALLBACK as C,
lesserOrGreaterTraverse<C extends BTNCallback<NODE>>(
callback: C = this._DEFAULT_BTN_CALLBACK as C,
lesserOrGreater: CP = -1,
targetNode: BTNRep<K, V, NODE> | R = this._root,
targetNode: BTNKeyOrNodeOrEntry<K, V, NODE> | R = this._root,
iterationType: IterationType = this.iterationType
): ReturnType<C>[] {
const targetNodeEnsured = this.ensureNode(targetNode);
const ans: ReturnType<NodeCallback<NODE>>[] = [];
const ans: ReturnType<BTNCallback<NODE>>[] = [];
if (!this._root) return ans;
if (!targetNodeEnsured) return ans;
@ -693,7 +666,7 @@ export class BST<
perfectlyBalance(iterationType: IterationType = this.iterationType): boolean {
const sorted = this.dfs(node => node, 'IN'),
n = sorted.length;
this._clearNodes();
this.clear();
if (sorted.length < 1) return false;
if (iterationType === 'RECURSIVE') {
@ -701,8 +674,7 @@ export class BST<
if (l > r) return;
const m = l + Math.floor((r - l) / 2);
const midNode = sorted[m];
if (this._isMapMode) this.add(midNode.key);
else this.add([midNode.key, midNode.value]);
this.add([midNode.key, midNode.value]);
buildBalanceBST(l, m - 1);
buildBalanceBST(m + 1, r);
};
@ -718,8 +690,7 @@ export class BST<
if (l <= r) {
const m = l + Math.floor((r - l) / 2);
const midNode = sorted[m];
if (this._isMapMode) this.add(midNode.key);
else this.add([midNode.key, midNode.value]);
this.add([midNode.key, midNode.value]);
stack.push([m + 1, r]);
stack.push([l, m - 1]);
}
@ -747,7 +718,7 @@ export class BST<
let balanced = true;
if (iterationType === 'RECURSIVE') {
const _height = (cur: OptNode<NODE>): number => {
const _height = (cur: OptBSTN<NODE>): number => {
if (!cur) return 0;
const leftHeight = _height(cur.left),
rightHeight = _height(cur.right);
@ -757,8 +728,8 @@ export class BST<
_height(this._root);
} else {
const stack: NODE[] = [];
let node: OptNode<NODE> = this._root,
last: OptNode<NODE> = undefined;
let node: OptBSTN<NODE> = this._root,
last: OptBSTN<NODE> = undefined;
const depths: Map<NODE, number> = new Map();
while (stack.length > 0 || node) {
@ -809,9 +780,9 @@ export class BST<
/**
* The function sets the root of a tree-like structure and updates the parent property of the new
* root.
* @param {OptNode<NODE>} v - v is a parameter of type NODE or undefined.
* @param {OptBSTN<NODE>} v - v is a parameter of type NODE or undefined.
*/
protected override _setRoot(v: OptNode<NODE>) {
protected override _setRoot(v: OptBSTN<NODE>) {
if (v) {
v.parent = undefined;
}

View file

@ -1,12 +1,14 @@
import type {
BinaryTreeDeleteResult,
BTNRep,
BTNKeyOrNodeOrEntry,
BTNPredicate,
CRUD,
OptNode,
OptBSTN,
RBTNColor,
RBTreeOptions,
RedBlackTreeNested,
RedBlackTreeNodeNested
RedBlackTreeNodeNested,
BTNEntry
} from '../../types';
import { BST, BSTNode } from './bst';
import { IBinaryTree } from '../../interfaces';
@ -54,7 +56,7 @@ export class RedBlackTreeNode<
export class RedBlackTree<
K = any,
V = any,
R = object,
R = BTNEntry<K, V>,
NODE extends RedBlackTreeNode<K, V, NODE> = RedBlackTreeNode<K, V, RedBlackTreeNodeNested<K, V>>,
TREE extends RedBlackTree<K, V, R, NODE, TREE> = RedBlackTree<K, V, R, NODE, RedBlackTreeNested<K, V, R, NODE>>
>
@ -63,7 +65,7 @@ export class RedBlackTree<
{
/**
* This is the constructor function for a Red-Black Tree data structure in TypeScript.
* @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` 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
@ -71,13 +73,16 @@ export class RedBlackTree<
* configuring the behavior of the Red-Black Tree. The specific properties and their meanings would
* depend on the implementation
*/
constructor(keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V, NODE>> = [], options?: RBTreeOptions<K, V, R>) {
constructor(
keysOrNodesOrEntriesOrRaws: Iterable<R | BTNKeyOrNodeOrEntry<K, V, NODE>> = [],
options?: RBTreeOptions<K, V, R>
) {
super([], options);
this._root = this.NIL;
if (keysNodesEntriesOrRaws) {
this.addMany(keysNodesEntriesOrRaws);
if (keysOrNodesOrEntriesOrRaws) {
this.addMany(keysOrNodesOrEntriesOrRaws);
}
}
@ -118,7 +123,6 @@ export class RedBlackTree<
override createTree(options?: RBTreeOptions<K, V, R>): TREE {
return new RedBlackTree<K, V, R, NODE, TREE>([], {
iterationType: this.iterationType,
isMapMode: this._isMapMode,
comparator: this._comparator,
toEntryFn: this._toEntryFn,
...options
@ -130,13 +134,13 @@ export class RedBlackTree<
* Space Complexity: O(1)
*
* The function checks if the input is an instance of the RedBlackTreeNode class.
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
* `keyNodeEntryOrRaw` can be of type `R` or `BTNRep<K, V, NODE>`.
* @returns a boolean value indicating whether the input parameter `keyNodeEntryOrRaw` 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(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R): keyNodeEntryOrRaw is NODE {
return keyNodeEntryOrRaw instanceof RedBlackTreeNode;
override isNode(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R): keyOrNodeOrEntryOrRaw is NODE {
return keyOrNodeOrEntryOrRaw instanceof RedBlackTreeNode;
}
// /**
@ -148,29 +152,29 @@ export class RedBlackTree<
// * Time Complexity: O(1)
// * Space Complexity: O(1)
// *
// * The function `keyValueNodeEntryRawToNodeAndValue` takes a key, value, or entry and returns a node if it is
// * The function `keyValueOrEntryOrRawElementToNode` takes a key, value, or entry and returns a node if it is
// * valid, otherwise it returns undefined.
// * @param {BTNRep<K, V, NODE>} keyNodeEntryOrRaw - The key, value, or entry to convert.
// * @param {V} [value] - The value associated with the key (if `keyNodeEntryOrRaw` 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 keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R, value?: V): NODE | undefined {
// override keyValueOrEntryOrRawElementToNode(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R, value?: V): NODE | undefined {
//
// if (keyNodeEntryOrRaw === null || keyNodeEntryOrRaw === undefined) return;
// if (this.isNode(keyNodeEntryOrRaw)) return keyNodeEntryOrRaw;
// if (keyOrNodeOrEntryOrRaw === null || keyOrNodeOrEntryOrRaw === undefined) return;
// if (this.isNode(keyOrNodeOrEntryOrRaw)) return keyOrNodeOrEntryOrRaw;
//
// if (this._toEntryFn) {
// const [key, entryValue] = this._toEntryFn(keyNodeEntryOrRaw as R);
// if (this.isKey(key)) return this.createNode(key, value ?? entryValue, 'RED');
// const [key, entryValue] = this._toEntryFn(keyOrNodeOrEntryOrRaw as R);
// if (this.isKey(key)) return this.createNode(key, entryValue ?? value, 'RED');
// }
//
// if (this.isEntry(keyNodeEntryOrRaw)) {
// const [key, value] = keyNodeEntryOrRaw;
// if (this.isEntry(keyOrNodeOrEntryOrRaw)) {
// const [key, value] = keyOrNodeOrEntryOrRaw;
// if (key === undefined || key === null) return;
// else return this.createNode(key, value, 'RED');
// }
//
// if (this.isKey(keyNodeEntryOrRaw)) return this.createNode(keyNodeEntryOrRaw, value, 'RED');
// if (this.isKey(keyOrNodeOrEntryOrRaw)) return this.createNode(keyOrNodeOrEntryOrRaw, value, 'RED');
//
// return ;
// }
@ -193,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 {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
* `keyNodeEntryOrRaw` can accept a value of type `R` or `BTNRep<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.
@ -202,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(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R, value?: V): boolean {
const [newNode, newValue] = this.keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, 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);
@ -215,7 +219,6 @@ export class RedBlackTree<
} else {
return false;
}
if (this._isMapMode) this._setValue(newNode.key, newValue);
this._size++;
return true;
} else return insertStatus === 'UPDATED';
@ -227,7 +230,7 @@ export class RedBlackTree<
*
* 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 {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The `keyNodeEntryOrRaw`
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - The `keyOrNodeOrEntryOrRaw`
* 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.
@ -235,13 +238,16 @@ export class RedBlackTree<
* objects. Each object in the array contains information about the deleted node and whether
* balancing is needed.
*/
override delete(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R): BinaryTreeDeleteResult<NODE>[] {
if (keyNodeEntryOrRaw === null) return [];
override delete(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R): BinaryTreeDeleteResult<NODE>[] {
if (keyOrNodeOrEntryOrRaw === null) return [];
const results: BinaryTreeDeleteResult<NODE>[] = [];
let nodeToDelete: OptNode<NODE>;
if (this._isPredicate(keyNodeEntryOrRaw)) nodeToDelete = this.getNode(keyNodeEntryOrRaw);
else nodeToDelete = this.isRealNode(keyNodeEntryOrRaw) ? keyNodeEntryOrRaw : this.getNode(keyNodeEntryOrRaw);
let nodeToDelete: OptBSTN<NODE>;
if (this._isPredicated(keyOrNodeOrEntryOrRaw)) nodeToDelete = this.getNode(keyOrNodeOrEntryOrRaw);
else
nodeToDelete = this.isRealNode(keyOrNodeOrEntryOrRaw)
? keyOrNodeOrEntryOrRaw
: this.getNode(keyOrNodeOrEntryOrRaw);
if (!nodeToDelete) {
return results;
@ -282,7 +288,6 @@ export class RedBlackTree<
successor.color = nodeToDelete.color;
}
}
if (this._isMapMode) this._store.delete(nodeToDelete.key);
this._size--;
// If the original color was black, fix the tree

View file

@ -7,14 +7,16 @@
*/
import type {
BinaryTreeDeleteResult,
BSTNOptKeyOrNode,
BTNRep,
BSTNKeyOrNode,
BTNKeyOrNodeOrEntry,
BTNPredicate,
IterationType,
OptNode,
OptBSTN,
RBTNColor,
TreeMultiMapNested,
TreeMultiMapNodeNested,
TreeMultiMapOptions
TreeMultiMapOptions,
BTNEntry
} from '../../types';
import { IBinaryTree } from '../../interfaces';
import { RedBlackTree, RedBlackTreeNode } from './rb-tree';
@ -64,7 +66,7 @@ export class TreeMultiMapNode<
export class TreeMultiMap<
K = any,
V = any,
R = object,
R = BTNEntry<K, V>,
NODE extends TreeMultiMapNode<K, V, NODE> = TreeMultiMapNode<K, V, TreeMultiMapNodeNested<K, V>>,
TREE extends TreeMultiMap<K, V, R, NODE, TREE> = TreeMultiMap<K, V, R, NODE, TreeMultiMapNested<K, V, R, NODE>>
>
@ -73,16 +75,19 @@ export class TreeMultiMap<
{
/**
* The constructor function initializes a TreeMultiMap object with optional initial data.
* @param keysNodesEntriesOrRaws - The parameter `keysNodesEntriesOrRaws` 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
* behavior of the `TreeMultiMap` constructor. It can include properties such as `compareKeys` and
* `compareValues`, which are functions used to compare keys and values respectively.
*/
constructor(keysNodesEntriesOrRaws: Iterable<BTNRep<K, V, NODE>> = [], options?: TreeMultiMapOptions<K, V, R>) {
constructor(
keysOrNodesOrEntriesOrRaws: Iterable<BTNKeyOrNodeOrEntry<K, V, NODE>> = [],
options?: TreeMultiMapOptions<K, V, R>
) {
super([], options);
if (keysNodesEntriesOrRaws) this.addMany(keysNodesEntriesOrRaws);
if (keysOrNodesOrEntriesOrRaws) this.addMany(keysOrNodesOrEntriesOrRaws);
}
protected _count = 0;
@ -138,7 +143,6 @@ export class TreeMultiMap<
override createTree(options?: TreeMultiMapOptions<K, V, R>): TREE {
return new TreeMultiMap<K, V, R, NODE, TREE>([], {
iterationType: this.iterationType,
isMapMode: this._isMapMode,
comparator: this._comparator,
toEntryFn: this._toEntryFn,
...options
@ -146,10 +150,10 @@ export class TreeMultiMap<
}
/**
* The function `keyValueNodeEntryRawToNodeAndValue` takes in a key, value, and count and returns a
* The function `keyValueOrEntryOrRawElementToNode` takes in a key, value, and count and returns a
* node based on the input.
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
* `keyNodeEntryOrRaw` can be of type `R` or `BTNRep<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.
@ -157,42 +161,40 @@ export class TreeMultiMap<
* times the key-value pair should be added to the data structure. If not provided, it defaults to 1.
* @returns either a NODE object or undefined.
*/
override keyValueNodeEntryRawToNodeAndValue(
keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R,
override keyValueOrEntryOrRawElementToNode(
keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R,
value?: V,
count = 1
): [NODE | undefined, V | undefined] {
if (keyNodeEntryOrRaw === undefined || keyNodeEntryOrRaw === null) return [undefined, undefined];
): NODE | undefined {
if (keyOrNodeOrEntryOrRaw === undefined || keyOrNodeOrEntryOrRaw === null) return;
if (this.isNode(keyNodeEntryOrRaw)) return [keyNodeEntryOrRaw, value];
if (this.isNode(keyOrNodeOrEntryOrRaw)) return keyOrNodeOrEntryOrRaw;
if (this.isEntry(keyNodeEntryOrRaw)) {
const [key, entryValue] = keyNodeEntryOrRaw;
if (key === undefined || key === null) return [undefined, undefined];
const finalValue = value ?? entryValue;
if (this.isKey(key)) return [this.createNode(key, finalValue, 'BLACK', count), finalValue];
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(keyNodeEntryOrRaw as R);
const finalValue = value ?? entryValue;
if (this.isKey(key)) return [this.createNode(key, finalValue, 'BLACK', count), finalValue];
const [key, entryValue] = this._toEntryFn(keyOrNodeOrEntryOrRaw as R);
if (this.isKey(key)) return this.createNode(key, value ?? entryValue, 'BLACK', count);
}
if (this.isKey(keyNodeEntryOrRaw)) return [this.createNode(keyNodeEntryOrRaw, value, 'BLACK', count), value];
if (this.isKey(keyOrNodeOrEntryOrRaw)) return this.createNode(keyOrNodeOrEntryOrRaw, value, 'BLACK', count);
return [undefined, undefined];
return;
}
/**
* The function checks if the input is an instance of the TreeMultiMapNode class.
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
* `keyNodeEntryOrRaw` can be of type `R` or `BTNRep<K, V, NODE>`.
* @returns a boolean value indicating whether the input parameter `keyNodeEntryOrRaw` 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(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R): keyNodeEntryOrRaw is NODE {
return keyNodeEntryOrRaw instanceof TreeMultiMapNode;
override isNode(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R): keyOrNodeOrEntryOrRaw is NODE {
return keyOrNodeOrEntryOrRaw instanceof TreeMultiMapNode;
}
/**
@ -201,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 {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The
* `keyNodeEntryOrRaw` 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
@ -211,10 +213,10 @@ 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(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R, value?: V, count = 1): boolean {
const [newNode, newValue] = this.keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, 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, newValue);
const isSuccessAdded = super.add(newNode);
if (isSuccessAdded) {
this._count += orgCount;
@ -230,7 +232,7 @@ export class TreeMultiMap<
*
* 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 {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The `predicate`
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - 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, or an entry.
* @param [ignoreCount=false] - The `ignoreCount` parameter in the `override delete` method is a
@ -239,14 +241,20 @@ export class TreeMultiMap<
* `ignoreCount` is `false
* @returns The `override delete` method returns an array of `BinaryTreeDeleteResult<NODE>` objects.
*/
override delete(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R, ignoreCount = false): BinaryTreeDeleteResult<NODE>[] {
if (keyNodeEntryOrRaw === null) return [];
override delete(
keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R,
ignoreCount = false
): BinaryTreeDeleteResult<NODE>[] {
if (keyOrNodeOrEntryOrRaw === null) return [];
const results: BinaryTreeDeleteResult<NODE>[] = [];
let nodeToDelete: OptNode<NODE>;
if (this._isPredicate(keyNodeEntryOrRaw)) nodeToDelete = this.getNode(keyNodeEntryOrRaw);
else nodeToDelete = this.isRealNode(keyNodeEntryOrRaw) ? keyNodeEntryOrRaw : this.getNode(keyNodeEntryOrRaw);
let nodeToDelete: OptBSTN<NODE>;
if (this._isPredicated(keyOrNodeOrEntryOrRaw)) nodeToDelete = this.getNode(keyOrNodeOrEntryOrRaw);
else
nodeToDelete = this.isRealNode(keyOrNodeOrEntryOrRaw)
? keyOrNodeOrEntryOrRaw
: this.getNode(keyOrNodeOrEntryOrRaw);
if (!nodeToDelete) {
return results;
@ -367,8 +375,7 @@ export class TreeMultiMap<
if (l > r) return;
const m = l + Math.floor((r - l) / 2);
const midNode = sorted[m];
if (this._isMapMode) this.add(midNode.key, undefined, midNode.count);
else this.add(midNode.key, midNode.value, midNode.count);
this.add(midNode.key, midNode.value, midNode.count);
buildBalanceBST(l, m - 1);
buildBalanceBST(m + 1, r);
};
@ -384,8 +391,7 @@ export class TreeMultiMap<
if (l <= r) {
const m = l + Math.floor((r - l) / 2);
const midNode = sorted[m];
if (this._isMapMode) this.add(midNode.key, undefined, midNode.count);
else this.add(midNode.key, midNode.value, midNode.count);
this.add(midNode.key, midNode.value, midNode.count);
stack.push([m + 1, r]);
stack.push([l, m - 1]);
}
@ -404,8 +410,7 @@ export class TreeMultiMap<
*/
override clone(): TREE {
const cloned = this.createTree();
this.bfs(node => cloned.add(node.key, undefined, node.count));
if (this._isMapMode) cloned._store = this._store;
this.bfs(node => cloned.add(node.key, node.value, node.count));
return cloned;
}
@ -415,17 +420,17 @@ export class TreeMultiMap<
*
* The `_swapProperties` function swaps the properties (key, value, count, color) between two nodes
* in a binary search tree.
* @param {R | BSTNOptKeyOrNode<K, NODE>} srcNode - The `srcNode` parameter represents the source node
* @param {R | BSTNKeyOrNode<K, NODE>} srcNode - The `srcNode` parameter represents the source node
* that will be swapped with the `destNode`. It can be either an instance of the `R` class or an
* instance of the `BSTNOptKeyOrNode<K, NODE>` class.
* @param {R | BSTNOptKeyOrNode<K, NODE>} destNode - The `destNode` parameter represents the destination
* instance of the `BSTNKeyOrNode<K, NODE>` class.
* @param {R | BSTNKeyOrNode<K, NODE>} destNode - The `destNode` parameter represents the destination
* node where the properties will be swapped with the source node.
* @returns The method is returning the `destNode` after swapping its properties with the `srcNode`.
* If either `srcNode` or `destNode` is undefined, it returns undefined.
*/
protected override _swapProperties(
srcNode: R | BSTNOptKeyOrNode<K, NODE>,
destNode: R | BSTNOptKeyOrNode<K, NODE>
srcNode: R | BSTNKeyOrNode<K, NODE>,
destNode: R | BSTNKeyOrNode<K, NODE>
): NODE | undefined {
srcNode = this.ensureNode(srcNode);
destNode = this.ensureNode(destNode);
@ -436,12 +441,12 @@ export class TreeMultiMap<
tempNode.color = color;
destNode.key = srcNode.key;
if (!this._isMapMode) destNode.value = srcNode.value;
destNode.value = srcNode.value;
destNode.count = srcNode.count;
destNode.color = srcNode.color;
srcNode.key = tempNode.key;
if (!this._isMapMode) srcNode.value = tempNode.value;
srcNode.value = tempNode.value;
srcNode.count = tempNode.count;
srcNode.color = tempNode.color;
}

View file

@ -266,9 +266,9 @@ export class Trie<R = any> extends IterableElementBase<string, R, Trie<R>> {
*
*/
getHeight(): number {
const startNode = this.root;
const beginRoot = this.root;
let maxDepth = 0;
if (startNode) {
if (beginRoot) {
const bfs = (node: TrieNode, level: number) => {
if (level > maxDepth) {
maxDepth = level;
@ -280,7 +280,7 @@ export class Trie<R = any> extends IterableElementBase<string, R, Trie<R>> {
}
}
};
bfs(startNode, 0);
bfs(beginRoot, 0);
}
return maxDepth;
}

View file

@ -4,14 +4,14 @@ import type {
BinaryTreeNested,
BinaryTreeNodeNested,
BinaryTreeOptions,
BTNRep,
NodePredicate
BTNKeyOrNodeOrEntry,
BTNPredicate
} from '../types';
export interface IBinaryTree<
K = any,
V = any,
R = object,
R = [K, V],
NODE extends BinaryTreeNode<K, V, NODE> = BinaryTreeNodeNested<K, V>,
TREE extends BinaryTree<K, V, R, NODE, TREE> = BinaryTreeNested<K, V, R, NODE>
> {
@ -19,9 +19,9 @@ export interface IBinaryTree<
createTree(options?: Partial<BinaryTreeOptions<K, V, R>>): TREE;
add(keyOrNodeOrEntryOrRawElement: BTNRep<K, V, NODE>, value?: V, count?: number): boolean;
add(keyOrNodeOrEntryOrRawElement: BTNKeyOrNodeOrEntry<K, V, NODE>, value?: V, count?: number): boolean;
addMany(nodes: Iterable<BTNRep<K, V, NODE>>, values?: Iterable<V | undefined>): boolean[];
addMany(nodes: Iterable<BTNKeyOrNodeOrEntry<K, V, NODE>>, values?: Iterable<V | undefined>): boolean[];
delete(predicate: R | BTNRep<K, V, NODE> | NodePredicate<NODE>): BinaryTreeDeleteResult<NODE>[];
delete(predicate: R | BTNKeyOrNodeOrEntry<K, V, NODE> | BTNPredicate<NODE>): BinaryTreeDeleteResult<NODE>[];
}

View file

@ -6,30 +6,31 @@ export type BinaryTreeNodeNested<K, V> = BinaryTreeNode<K, V, BinaryTreeNode<K,
export type BinaryTreeNested<K, V, R, NODE extends BinaryTreeNode<K, V, NODE>> = BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, BinaryTree<K, V, R, NODE, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
export type ToEntryFn<K, V, R> = (rawElement: R) => BTNEntry<K, V>;
export type BinaryTreeOptions<K, V, R> = {
iterationType?: IterationType;
toEntryFn?: ToEntryFn<K, V, R>;
isMapMode?: boolean;
iterationType?: IterationType;
toEntryFn?: (rawElement: R) => BTNEntry<K, V>;
}
export type BinaryTreePrintOptions = { isShowUndefined?: boolean; isShowNull?: boolean; isShowRedBlackNIL?: boolean };
export type OptNodeOrNull<NODE> = NODE | null | undefined;
export type OptBTNOrNull<NODE> = NODE | null | undefined;
export type BTNOptKeyOrNull<K> = K | null | undefined;
export type OptBTNKeyOrNull<K> = K | null | undefined;
export type BTNEntry<K, V> = [BTNOptKeyOrNull<K>, OptValue<V>];
export type BTNEntry<K, V> = [OptBTNKeyOrNull<K>, OptValue<V>];
export type BTNOptKeyNodeOrNull<K, NODE> = BTNOptKeyOrNull<K> | NODE;
export type BTNKeyOrNode<K, NODE> = OptBTNKeyOrNull<K> | NODE;
export type BTNRep<K, V, NODE> = BTNEntry<K, V> | BTNOptKeyNodeOrNull<K, NODE>;
export type BTNKeyOrNodeOrEntry<K, V, NODE> = BTNEntry<K, V> | BTNKeyOrNode<K, NODE>;
export type BinaryTreeDeleteResult<NODE> = { deleted: OptNodeOrNull<NODE>; needBalanced: OptNodeOrNull<NODE> };
export type BTNPureKeyOrNode<K, NODE> = K | NODE;
export type NodeCallback<NODE, D = any> = (node: NODE) => D;
export type BTNPureKeyOrNodeOrEntry<K, V, NODE> = [K, OptValue<V>] | BTNPureKeyOrNode<K, NODE>;
export type NodePredicate<NODE> = (node: NODE) => boolean;
export type BinaryTreeDeleteResult<NODE> = { deleted: OptBTNOrNull<NODE>; needBalanced: OptBTNOrNull<NODE> };
export type DFSStackItem<NODE> = { opt: DFSOperation; node: OptNodeOrNull<NODE> }
export type BTNCallback<NODE, D = any> = (node: NODE) => D;
export type BTNPredicate<NODE> = (node: NODE) => boolean;
export type DFSStackItem<NODE> = { opt: DFSOperation; node: OptBTNOrNull<NODE> }

View file

@ -7,12 +7,12 @@ export type BSTNodeNested<K, V> = BSTNode<K, V, BSTNode<K, V, BSTNode<K, V, BSTN
export type BSTNested<K, V, R, NODE extends BSTNode<K, V, NODE>> = BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, BST<K, V, R, NODE, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
export type BSTOptions<K, V, R> = BinaryTreeOptions<K, V, R> & {
comparator?: Comparator<K>
comparator?: Comparator<K>
}
export type BSTNOptKey<K> = K | undefined;
export type OptBSTNKey<K> = K | undefined;
export type OptNode<NODE> = NODE | undefined;
export type OptBSTN<NODE> = NODE | undefined;
export type BSTNOptKeyOrNode<K, NODE> = BSTNOptKey<K> | NODE;
export type BSTNKeyOrNode<K, NODE> = OptBSTNKey<K> | NODE;

View file

@ -3,7 +3,7 @@ import * as Benchmark from 'benchmark';
import { getRandomIntArray, magnitude } from '../../../utils';
const suite = new Benchmark.Suite();
const avlTree = new AVLTree<number>([], { isMapMode: true });
const avlTree = new AVLTree<number>();
const { HUNDRED_THOUSAND } = magnitude;
const randomArray = getRandomIntArray(HUNDRED_THOUSAND, 0, HUNDRED_THOUSAND - 1, true);

View file

@ -3,8 +3,8 @@ import * as Benchmark from 'benchmark';
import { getRandomIntArray, magnitude } from '../../../utils';
const suite = new Benchmark.Suite();
const rbTree = new RedBlackTree<number>([], { isMapMode: true });
const avlTree = new AVLTree<number>([], { isMapMode: true });
const rbTree = new RedBlackTree();
const avlTree = new AVLTree();
const { TEN_THOUSAND } = magnitude;
const arr = getRandomIntArray(TEN_THOUSAND, 0, TEN_THOUSAND - 1, true);

View file

@ -3,7 +3,7 @@ import * as Benchmark from 'benchmark';
import { getRandomIntArray, magnitude } from '../../../utils';
const suite = new Benchmark.Suite();
const biTree = new BinaryTree<number>([], { isMapMode: true });
const biTree = new BinaryTree<number>();
const { THOUSAND } = magnitude;
const arr = getRandomIntArray(THOUSAND, 0, THOUSAND, true);

View file

@ -3,7 +3,7 @@ import * as Benchmark from 'benchmark';
import { getRandomIntArray, magnitude } from '../../../utils';
const suite = new Benchmark.Suite();
const bst = new BST<number>([], { isMapMode: true });
const bst = new BST<number>();
const { TEN_THOUSAND } = magnitude;
const arr = getRandomIntArray(TEN_THOUSAND, 0, TEN_THOUSAND, true);

View file

@ -5,7 +5,7 @@ import { OrderedMap } from 'js-sdsl';
import { isCompetitor } from '../../../config';
const suite = new Benchmark.Suite();
const rbTree = new RedBlackTree<number>([], { isMapMode: true });
const rbTree = new RedBlackTree();
const { HUNDRED_THOUSAND } = magnitude;
const randomArray = getRandomIntArray(HUNDRED_THOUSAND, 0, HUNDRED_THOUSAND - 1, true);
const cOrderedMap = new OrderedMap<number, number>();

View file

@ -678,7 +678,7 @@ describe('AVLTreeMultiMap iterative methods test', () => {
expect(treeMM.count).toBe(21);
const cloned = treeMM.clone();
expect(cloned.root?.left?.key).toBe(1);
expect(cloned.get(cloned.root?.right)).toBe('c');
expect(cloned.root?.right?.value).toBe('c');
});
it('should keys', () => {
@ -761,115 +761,3 @@ describe('AVLTree toEntryFn', () => {
expect(tree.dfs(node => node.key, 'IN', tree.root, 'RECURSIVE')).toEqual(expected);
});
});
describe('AVLTreeMultiMap map mode count', () => {
let tm: AVLTreeMultiMap<number>;
beforeEach(() => {
tm = new AVLTreeMultiMap<number>([], { isMapMode: true });
});
it('Should added isolated node count ', () => {
tm.addMany([
[1, 1],
[2, 2],
[3, 3],
[4, 4],
[5, 5]
]);
const newNode = new AVLTreeMultiMapNode(3, undefined, 10);
tm.add(newNode, 33);
expect(tm.count).toBe(15);
});
});
describe('AVLTreeMultiMap map mode operations test1', () => {
it('should perform various operations on a Binary Search Tree with numeric values1', () => {
const treeMultimap = new AVLTreeMultiMap<number>([], { isMapMode: true });
expect(treeMultimap instanceof AVLTreeMultiMap);
treeMultimap.add([11, 11]);
treeMultimap.add([3, 3]);
const idAndValues: [number, number][] = [
[11, 11],
[3, 3],
[15, 15],
[1, 1],
[8, 8],
[13, 13],
[16, 16],
[2, 2],
[6, 6],
[9, 9],
[12, 12],
[14, 14],
[4, 4],
[7, 7],
[10, 10],
[5, 5]
];
treeMultimap.addMany(idAndValues);
expect(treeMultimap.root instanceof AVLTreeMultiMapNode);
if (treeMultimap.root) expect(treeMultimap.root.key == 11);
expect(treeMultimap.size).toBe(16);
expect(treeMultimap.count).toBe(18);
expect(treeMultimap.has(6));
expect(treeMultimap.getHeight(6)).toBe(4);
expect(treeMultimap.getDepth(6)).toBe(0);
const nodeId10 = treeMultimap.getNode(10);
expect(nodeId10?.key).toBe(10);
const nodeVal9 = treeMultimap.getNode(node => node.key === 9);
expect(nodeVal9?.key).toBe(9);
});
});
describe('AVLTreeMultiMap map mode operations test recursively1', () => {
it('should perform various operations on a Binary Search Tree with numeric values1', () => {
const treeMultimap = new AVLTreeMultiMap<number>([], {
iterationType: 'RECURSIVE',
isMapMode: true
});
expect(treeMultimap instanceof AVLTreeMultiMap);
treeMultimap.add([11, 11]);
treeMultimap.add([3, 3]);
const idAndValues: [number, number][] = [
[11, 11],
[3, 3],
[15, 15],
[1, 1],
[8, 8],
[13, 13],
[16, 16],
[2, 2],
[6, 6],
[9, 9],
[12, 12],
[14, 14],
[4, 4],
[7, 7],
[10, 10],
[5, 5]
];
treeMultimap.addMany(idAndValues);
expect(treeMultimap.root).toBeInstanceOf(AVLTreeMultiMapNode);
if (treeMultimap.root) expect(treeMultimap.root.key).toBe(6);
expect(treeMultimap.size).toBe(16);
expect(treeMultimap.count).toBe(18);
expect(treeMultimap.has(6));
expect(treeMultimap.getHeight(6)).toBe(4);
expect(treeMultimap.getDepth(6)).toBe(0);
const nodeId10 = treeMultimap.getNode(10);
expect(nodeId10?.key).toBe(10);
const nodeVal9 = treeMultimap.getNode(node => node.key === 9);
expect(nodeVal9?.key).toBe(9);
});
});

View file

@ -33,6 +33,7 @@ describe('AVL Tree Test', () => {
// node15 has type problem. After the uniform design, the generics of containers (DirectedGraph, BST) are based on the type of value. However, this design has a drawback: when I attempt to inherit from the Vertex or BSTNode classes, the types of the results obtained by all methods are those of the parent class.
expect(node15?.value).toBe(15);
const dfs = tree.dfs(node => node, 'IN');
expect(dfs[0].key).toBe(1);
expect(dfs[dfs.length - 1].key).toBe(16);
@ -436,90 +437,3 @@ describe('AVLTree iterative methods test', () => {
expect(leaves).toEqual([1, 3]);
});
});
describe('AVL Tree map mode', () => {
it('should perform various operations on a AVL Tree', () => {
const arr = [11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5];
const tree = new AVLTree<number>([], { isMapMode: true });
for (const i of arr) tree.add([i, i]);
tree.add(null);
const node6 = tree.getNode(6);
expect(node6 && tree.getHeight(node6)).toBe(3);
expect(node6 && tree.getDepth(node6)).toBe(1);
const getNodeById = tree.getNode(10);
expect(getNodeById?.key).toBe(10);
const getMinNodeByRoot = tree.getLeftMost();
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;
if (node15) tree.dfs(node => (subTreeSum += node.key), 'PRE', node15);
expect(subTreeSum).toBe(70);
let lesserSum = 0;
tree.lesserOrGreaterTraverse(node => (lesserSum += node.key), -1, 10);
expect(lesserSum).toBe(45);
// node15 has type problem. After the uniform design, the generics of containers (DirectedGraph, BST) are based on the type of value. However, this design has a drawback: when I attempt to inherit from the Vertex or BSTNode classes, the types of the results obtained by all methods are those of the parent class.
expect(tree.get(node15)).toBe(15);
});
});
describe('AVL Tree map mode test recursively', () => {
it('should perform various operations on a AVL Tree', () => {
const arr = [11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5];
const tree = new AVLTree<number>([], { iterationType: 'RECURSIVE', isMapMode: true });
for (const i of arr) tree.add([i, i]);
const node6 = tree.getNode(6);
expect(node6 && tree.getHeight(node6)).toBe(3);
expect(node6 && tree.getDepth(node6)).toBe(1);
const getNodeById = tree.getNode(10);
expect(getNodeById?.key).toBe(10);
const getMinNodeByRoot = tree.getLeftMost();
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;
if (node15) tree.dfs(node => (subTreeSum += node.key), 'PRE', node15);
expect(subTreeSum).toBe(70);
let lesserSum = 0;
tree.lesserOrGreaterTraverse(node => (lesserSum += node.key), -1, 10);
expect(lesserSum).toBe(45);
// node15 has type problem. After the uniform design, the generics of containers (DirectedGraph, BST) are based on the type of value. However, this design has a drawback: when I attempt to inherit from the Vertex or BSTNode classes, the types of the results obtained by all methods are those of the parent class.
expect(tree.get(node15)).toBe(15);
});
});
describe('AVLTree iterative methods map mode', () => {
let avl: AVLTree<number, string>;
beforeEach(() => {
avl = new AVLTree<number, string>([], { isMapMode: true });
avl.add([1, 'a']);
avl.add([2, 'b']);
avl.add([3, 'c']);
});
it('should clone work well', () => {
const cloned = avl.clone();
expect(cloned.root?.left?.key).toBe(1);
expect(cloned.get(cloned.root?.right?.key)).toBe('c');
});
});

View file

@ -20,8 +20,6 @@ describe('BinaryTreeNode', () => {
it('should set and get the value correctly', () => {
const node: BinaryTreeNode<number> = new BinaryTreeNode<number>(1, 42);
expect(node.key).toBe(1);
expect(node.value).toBe(42);
node.value = 55;
@ -321,28 +319,26 @@ describe('BinaryTree', () => {
it('should isSubtreeBST', () => {
expect(tree.toVisual()).toBe('');
tree.addMany([4, 2, 6, 1, 3, 5, 7, 4]);
expect(tree.toVisual()).toBe(
'N for null\n' +
' ___4___ \n' +
' / \\ \n' +
' _2_ _6_ \n' +
' / \\ / \\ \n' +
' 1 3 5 7 \n' +
' \n'
);
expect(tree.toVisual()).toBe('N for null\n' +
' ___4___ \n' +
' / \\ \n' +
' _2_ _6_ \n' +
' / \\ / \\ \n' +
' 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'
'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);
@ -733,40 +729,34 @@ describe('BinaryTree', () => {
]);
});
it('should keyValueNodeEntryRawToNodeAndValue', () => {
it('should keyValueOrEntryOrRawElementToNode', () => {
const tree = new BinaryTree<number>();
const node0 = tree.keyValueNodeEntryRawToNodeAndValue(0);
expect(node0).toEqual([
{
_left: undefined,
_right: undefined,
key: 0,
parent: undefined,
value: undefined
},
undefined
]);
const node0 = tree.keyValueOrEntryOrRawElementToNode(0);
expect(node0).toEqual({
_left: undefined,
_right: undefined,
key: 0,
parent: undefined,
value: undefined
});
const nodeUndefined = tree.keyValueNodeEntryRawToNodeAndValue(undefined);
expect(nodeUndefined).toEqual([undefined, undefined]);
const nodeUndefined = tree.keyValueOrEntryOrRawElementToNode(undefined);
expect(nodeUndefined).toBe(undefined);
const nodeNull = tree.keyValueNodeEntryRawToNodeAndValue(null);
expect(nodeNull).toEqual([null, undefined]);
const nodeNull = tree.keyValueOrEntryOrRawElementToNode(null);
expect(nodeNull).toBe(null);
const [, nodeWithSeparateValue] = tree.keyValueNodeEntryRawToNodeAndValue(7, 77);
expect(nodeWithSeparateValue).toBe(77);
const nodeWithSeparateValue = tree.keyValueOrEntryOrRawElementToNode(7, 77);
expect(nodeWithSeparateValue?.value).toBe(77);
expect(tree.keyValueNodeEntryRawToNodeAndValue([undefined, 2])).toEqual([undefined, undefined]);
expect(tree.keyValueOrEntryOrRawElementToNode([undefined, 2])).toBe(undefined);
expect(tree.keyValueNodeEntryRawToNodeAndValue(Symbol('test') as unknown as number)).toEqual([
undefined,
undefined
]);
expect(tree.keyValueOrEntryOrRawElementToNode(Symbol('test') as unknown as number)).toBe(undefined);
const bTree = new BinaryTree<number, number, { obj: { id: number } }>([], {
toEntryFn: (ele: { obj: { id: number } }) => [Symbol('test') as unknown as number, ele.obj.id]
});
expect(bTree.keyValueNodeEntryRawToNodeAndValue({ obj: { id: 1 } })).toEqual([undefined, undefined]);
expect(bTree.keyValueOrEntryOrRawElementToNode({ obj: { id: 1 } })).toBe(undefined);
});
});
@ -1160,21 +1150,17 @@ describe('BinaryTree', () => {
tree.add([2, 'B']);
tree.add([null, 'null']);
const nodes = tree.isMapMode ? tree.getNodes(node => node.key === 2) : tree.getNodes(node => node.value === 'B');
const nodes = tree.getNodes(node => node.value === 'B');
expect(nodes.length).toBe(1);
expect(nodes[0].key).toBe(2);
const nodesRec = tree.isMapMode
? tree.getNodes(node => node.key === 2, false, tree.root, 'RECURSIVE')
: tree.getNodes(node => node.value === 'B', 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.isMapMode
? tree.getNodes(node => node.key === 2, false, tree.root, 'ITERATIVE')
: tree.getNodes(node => node.value === 'B', 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);
@ -1220,98 +1206,6 @@ describe('BinaryTree', () => {
});
});
describe('BinaryTree map mode', () => {
let tree: BinaryTree<number, string>;
beforeEach(() => {
tree = new BinaryTree<number, string>([], {
iterationType: 'RECURSIVE',
isMapMode: true
});
});
afterEach(() => {
tree.clear();
});
it('should add and find nodes', () => {
tree.add([1, 1]);
tree.add(undefined);
tree.add([2, 2]);
tree.add([3, 3]);
expect(tree.has(1)).toBe(true);
expect(tree.has(2)).toBe(true);
expect(tree.has(3)).toBe(true);
expect(tree.has(4)).toBe(false);
const node4 = tree.getNode(4);
expect(tree.has(node4)).toBe(false);
expect(tree.has(node => node === node4)).toBe(false);
if (tree.isMapMode) expect(tree.has(node => node.key?.toString() === '3')).toBe(true);
else expect(tree.has(node => node.value?.toString() === '3')).toBe(true);
});
it('should isSubtreeBST', () => {
tree.addMany([
new BinaryTreeNode(4),
new BinaryTreeNode(2),
new BinaryTreeNode(6),
new BinaryTreeNode(1),
new BinaryTreeNode(3),
new BinaryTreeNode(5),
new BinaryTreeNode(7),
new BinaryTreeNode(4)
]);
expect(tree.isBST(tree.getNode(4), 'RECURSIVE')).toBe(true);
expect(tree.isBST(tree.getNode(4), 'ITERATIVE')).toBe(true);
});
it('should get nodes by key', () => {
tree.add([5, 'A']);
tree.add([3, 'B']);
tree.add([7, 'C']);
const nodeA = tree.getNode(5);
const nodeB = tree.getNode(3);
expect(nodeA?.key).toBe(5);
expect(tree.get(nodeA)).toBe('A');
expect(nodeB?.key).toBe(3);
expect(tree.get(nodeB)).toBe('B');
});
it('should get nodes by a custom callback', () => {
tree.add([5, 'E']);
tree.add([4, 'D']);
tree.add([3, 'C']);
tree.add([7, 'G']);
tree.add([null, 'null']);
tree.add([1, 'A']);
tree.add([6, 'F']);
tree.add([null, 'null']);
tree.add([2, 'B']);
tree.add([null, 'null']);
const nodes = tree.getNodes(node => node.key === 2);
expect(nodes.length).toBe(1);
expect(nodes[0].key).toBe(2);
const nodesRec = tree.getNodes(node => node.key === 2, false, tree.root, 'RECURSIVE');
expect(nodesRec.length).toBe(1);
expect(nodesRec[0].key).toBe(2);
const nodesItr = tree.getNodes(node => node.key === 2, false, tree.root, 'ITERATIVE');
expect(nodesItr.length).toBe(1);
expect(nodesItr[0].key).toBe(2);
expect(nodesItr).toEqual(nodesRec);
});
});
describe('BinaryTree iterative methods test', () => {
let binaryTree: BinaryTree<number, string>;
beforeEach(() => {
@ -1379,8 +1273,7 @@ describe('BinaryTree iterative methods test', () => {
it('should clone work well', () => {
const cloned = binaryTree.clone();
expect(cloned.root?.left?.key).toBe(2);
if (cloned.isMapMode) expect(cloned.get(cloned.root?.right)).toBe('c');
else expect(cloned.root?.right?.value).toBe('c');
expect(cloned.root?.right?.value).toBe('c');
});
it('should keys', () => {
@ -1422,19 +1315,3 @@ describe('BinaryTree iterative methods test', () => {
]);
});
});
describe('BinaryTree map mode iterative methods test', () => {
let binaryTree: BinaryTree<number, string>;
beforeEach(() => {
binaryTree = new BinaryTree<number, string>([], { isMapMode: true });
binaryTree.add([1, 'a']);
binaryTree.add(2, 'b');
binaryTree.add([3, 'c']);
});
it('should clone work well', () => {
const cloned = binaryTree.clone();
expect(cloned.root?.left?.key).toBe(2);
expect(cloned.get(cloned.root?.right)).toBe('c');
});
});

View file

@ -1,5 +1,5 @@
import { BinaryTreeNode, BST, BSTNode } from '../../../../src';
import { isDebugTest, isTestStackOverflow, SYSTEM_MAX_CALL_STACK } from '../../../config';
import { isDebugTest, SYSTEM_MAX_CALL_STACK, isTestStackOverflow } from '../../../config';
const isDebug = isDebugTest;
@ -450,25 +450,22 @@ describe('BST operations test', () => {
expect(bfsNodes[2].key).toBe(16);
});
it('should keyValueNodeEntryRawToNodeAndValue', () => {
it('should keyValueOrEntryOrRawElementToNode', () => {
const bst = new BST<number>();
const node0 = bst.keyValueNodeEntryRawToNodeAndValue(0);
expect(node0).toEqual([
{
_left: undefined,
_right: undefined,
key: 0,
parent: undefined,
value: undefined
},
undefined
]);
const node0 = bst.keyValueOrEntryOrRawElementToNode(0);
expect(node0).toEqual({
_left: undefined,
_right: undefined,
key: 0,
parent: undefined,
value: undefined
});
const nodeUndefined = bst.keyValueNodeEntryRawToNodeAndValue(undefined);
expect(nodeUndefined).toEqual([undefined, undefined]);
const nodeUndefined = bst.keyValueOrEntryOrRawElementToNode(undefined);
expect(nodeUndefined).toBe(undefined);
const nodeNull = bst.keyValueNodeEntryRawToNodeAndValue(null);
expect(nodeNull).toEqual([undefined, undefined]);
const nodeNull = bst.keyValueOrEntryOrRawElementToNode(null);
expect(nodeNull).toBe(undefined);
});
});
@ -499,7 +496,7 @@ describe('BST operations test recursively', () => {
expect(nodeId10?.key).toBe(10);
const nodeVal9 = bst.getNode(node => node.value === 9);
expect(bst.get(nodeVal9?.key)).toBe(undefined);
expect(nodeVal9?.key).toBe(undefined);
const leftMost = bst.getLeftMost();
expect(leftMost).toBe(1);
@ -1213,300 +1210,3 @@ describe('BST iterative methods test', () => {
expect(balanced.leaves(node => node?.value)).toEqual(['a', 'f', 'd', 'i']);
});
});
describe('BST operations map mode test', () => {
it('should perform various operations on a Binary Search Tree with numeric values', () => {
const bst = new BST<number, number>([], { isMapMode: true });
expect(bst).toBeInstanceOf(BST);
bst.add([11, 11]);
bst.add([3, 3]);
const idsAndValues: [number, number][] = [
[15, 15],
[1, 1],
[8, 8],
[13, 13],
[16, 16],
[2, 2],
[6, 6],
[9, 9],
[12, 12],
[14, 14],
[4, 4],
[7, 7],
[10, 10],
[5, 5]
];
bst.addMany(idsAndValues, undefined, false);
expect(bst.root).toBeInstanceOf(BSTNode);
if (bst.root) expect(bst.root.key).toBe(11);
expect(bst.size).toBe(16);
expect(bst.has(6)).toBe(true);
const node6 = bst.getNode(6);
expect(node6 && bst.getHeight(6)).toBe(2);
expect(node6 && bst.getDepth(6)).toBe(3);
const nodeId10 = bst.getNode(10);
expect(nodeId10?.key).toBe(10);
const nodeVal9 = bst.getNode(node => node.key === 9);
expect(nodeVal9?.key).toBe(9);
const leftMost = bst.getLeftMost();
expect(leftMost).toBe(1);
expect(bst.isBST()).toBe(true);
const node15 = bst.getNode(15);
const minNodeBySpecificNode = node15 && bst.getLeftMost(node => node, node15);
expect(minNodeBySpecificNode?.key).toBe(12);
const nodes = bst.getNodes(node => node.key === 15);
expect(nodes.map(node => node.key)).toEqual([15]);
});
it('should perform various operations on a Binary Search Tree with object values', () => {
const objBST = new BST<number, { name: string; age: number }>([], { isMapMode: true });
expect(objBST).toBeInstanceOf(BST);
objBST.add([11, { name: '11', age: 11 }]);
objBST.add([3, { name: '3', age: 3 }]);
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 }
],
false
);
expect(objBST.root).toBeInstanceOf(BSTNode);
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);
const nodeId10 = objBST.getNode(10);
expect(nodeId10?.key).toBe(10);
const nodeVal9 = objBST.getNode(9);
expect(nodeVal9?.key).toBe(9);
const leftMost = objBST.getLeftMost();
expect(leftMost).toBe(1);
const node15 = objBST.getNode(15);
expect(objBST.get(node15)).toEqual({
name: 'Alice',
age: 15
});
});
it('should keyValueNodeEntryRawToNodeAndValue', () => {
const bst = new BST<number>([], { isMapMode: true });
const node0 = bst.keyValueNodeEntryRawToNodeAndValue(0);
expect(node0).toEqual([
{
_left: undefined,
_right: undefined,
key: 0,
parent: undefined,
value: undefined
},
undefined
]);
const nodeUndefined = bst.keyValueNodeEntryRawToNodeAndValue(undefined);
expect(nodeUndefined).toEqual([undefined, undefined]);
const nodeNull = bst.keyValueNodeEntryRawToNodeAndValue(null);
expect(nodeNull).toEqual([undefined, undefined]);
});
});
describe('BST operations map mode test recursively', () => {
it('should perform various operations on a Binary Search Tree with numeric values', () => {
const bst = new BST<number>([], {
iterationType: 'RECURSIVE',
isMapMode: true
});
expect(bst).toBeInstanceOf(BST);
bst.add([11, 11]);
bst.add([3, 3]);
const idsAndValues = [15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5];
bst.addMany(idsAndValues, undefined, false);
expect(bst.root).toBeInstanceOf(BSTNode);
if (bst.root) expect(bst.root.key).toBe(11);
expect(bst.size).toBe(16);
expect(bst.has(6)).toBe(true);
const node6 = bst.getNode(6);
expect(node6 && bst.getHeight(6)).toBe(2);
expect(node6 && bst.getDepth(6)).toBe(3);
const nodeId10 = bst.getNode(10);
expect(bst.get(10)).toBe(undefined);
expect(nodeId10?.key).toBe(10);
const nodeVal9 = bst.getNode(node => node.key === 9);
expect(bst.get(nodeVal9?.key)).toBe(undefined);
});
it('should perform various operations on a Binary Search Tree with object values', () => {
const objBST = new BST<number, { key: number; keyA: number }>([], { isMapMode: true });
expect(objBST).toBeInstanceOf(BST);
objBST.add([11, { key: 11, keyA: 11 }]);
objBST.add([3, { key: 3, keyA: 3 }]);
const entries: [number, { key: number; keyA: number }][] = [
[15, { key: 15, keyA: 15 }],
[1, { key: 1, keyA: 1 }],
[8, { key: 8, keyA: 8 }],
[13, { key: 13, keyA: 13 }],
[16, { key: 16, keyA: 16 }],
[2, { key: 2, keyA: 2 }],
[6, { key: 6, keyA: 6 }],
[9, { key: 9, keyA: 9 }],
[12, { key: 12, keyA: 12 }],
[14, { key: 14, keyA: 14 }],
[4, { key: 4, keyA: 4 }],
[7, { key: 7, keyA: 7 }],
[10, { key: 10, keyA: 10 }],
[5, { key: 5, keyA: 5 }]
];
objBST.addMany(entries, undefined, false);
expect(objBST.root).toBeInstanceOf(BSTNode);
if (objBST.root) expect(objBST.root.key).toBe(11);
expect(objBST.has(6)).toBe(true);
const node6 = objBST.getNode(6);
expect(objBST.get(6)).toEqual({
key: 6,
keyA: 6
});
expect(node6 && objBST.getHeight(node6)).toBe(2);
expect(node6 && objBST.getDepth(node6)).toBe(3);
const nodeId10 = objBST.getNode(10);
expect(nodeId10?.key).toBe(10);
const nodeVal9 = objBST.getNode(9);
expect(nodeVal9?.key).toBe(9);
const leftMost = objBST.getLeftMost();
expect(leftMost).toBe(1);
const node15 = objBST.getNode(15);
expect(objBST.get(node15)).toEqual({
key: 15,
keyA: 15
});
});
});
describe('BST iterative methods map mode test', () => {
let bst: BST<number, string>;
beforeEach(() => {
bst = new BST();
bst.addMany(
[
[1, 'a'],
[2, 'b'],
[3, 'c']
],
[],
false
);
});
it('should clone work well', () => {
const cloned = bst.clone();
expect(cloned.root?.left).toBe(undefined);
expect(cloned.get(cloned.root?.right)).toBe('b');
});
it('should collapsed, unbalanced, balanced bst leaves', () => {
const collapsedToLinkedList = new BST();
collapsedToLinkedList.addMany(
[
[1, 'a'],
[2, 'b'],
[3, 'c'],
[4, 'd'],
[5, 'e'],
[6, 'f'],
[7, 'g'],
[8, 'h'],
[9, 'i']
],
[],
false
);
expect(collapsedToLinkedList.leaves()).toEqual([9]);
const unbalanced = new BST();
unbalanced.addMany(
[
[2, 'b'],
[1, 'a'],
[3, 'c'],
[4, 'd'],
[5, 'e'],
[6, 'f'],
[7, 'g'],
[8, 'h'],
[9, 'i']
],
[],
false
);
expect(unbalanced.leaves()).toEqual([1, 9]);
const balanced = new BST();
balanced.addMany(
[
[2, 'b'],
[1, 'a'],
[3, 'c'],
[4, 'd'],
[5, 'e'],
[6, 'f'],
[7, 'g'],
[8, 'h'],
[9, 'i']
],
[],
true
);
expect(balanced.leaves()).toEqual([1, 6, 4, 9]);
expect(balanced.leaves(node => balanced.get(node?.key))).toEqual(['a', 'f', 'd', 'i']);
});
});

View file

@ -817,8 +817,7 @@ describe('TreeMultiMap iterative methods test', () => {
expect(treeMM.getComputedCount()).toBe(21);
const cloned = treeMM.clone();
expect(cloned.root?.left?.key).toBe(1);
if (cloned.isMapMode) expect(cloned.get(cloned.root?.right)).toBe('c');
else expect(cloned.root?.right?.value).toBe(undefined);
expect(cloned.root?.right?.value).toBe('c');
});
it('should keys', () => {
@ -836,140 +835,3 @@ describe('TreeMultiMap iterative methods test', () => {
expect(leaves).toEqual([1, 3]);
});
});
describe('TreeMultiMap count map mode', () => {
let tmm: TreeMultiMap<number>;
beforeEach(() => {
tmm = new TreeMultiMap<number>([], { isMapMode: true });
});
it('Should added node count ', () => {
tmm.addMany([
[1, 1],
[2, 2],
[3, 3],
[4, 4],
[5, 5]
]);
const newNode = new TreeMultiMapNode(3, undefined, 10);
tmm.add(newNode, 33, 20);
// TODO expect(tmm.count).toBe(25);
expect(tmm.count).toBe(15);
expect(tmm.getComputedCount()).toBe(15);
expect(tmm.getNode(3)?.count).toBe(11);
});
});
describe('TreeMultiMap operations test1 map mode', () => {
it('should perform various operations on a Binary Search Tree with numeric values1', () => {
const tmm = new TreeMultiMap<number, number>([], { isMapMode: true });
expect(tmm instanceof TreeMultiMap);
tmm.add([11, 11]);
tmm.add([3, 3]);
const idAndValues: [number, number][] = [
[11, 11],
[3, 3],
[15, 15],
[1, 1],
[8, 8],
[13, 13],
[16, 16],
[2, 2],
[6, 6],
[9, 9],
[12, 12],
[14, 14],
[4, 4],
[7, 7],
[10, 10],
[5, 5]
];
tmm.addMany(idAndValues);
expect(tmm.root instanceof TreeMultiMapNode);
if (tmm.root) expect(tmm.root.key == 11);
expect(tmm.size).toBe(16);
expect(tmm.count).toBe(18);
expect(tmm.getComputedCount()).toBe(18);
expect(tmm.has(6));
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(node => node.key === 9);
expect(nodeVal9?.key).toBe(9);
});
});
describe('TreeMultiMap operations test recursively1 map mode', () => {
it('should perform various operations on a Binary Search Tree with numeric values1', () => {
const tmm = new TreeMultiMap<number>([], {
iterationType: 'RECURSIVE',
isMapMode: true
});
expect(tmm instanceof TreeMultiMap);
tmm.add([11, 11]);
tmm.add([3, 3]);
const idAndValues: [number, number][] = [
[11, 11],
[3, 3],
[15, 15],
[1, 1],
[8, 8],
[13, 13],
[16, 16],
[2, 2],
[6, 6],
[9, 9],
[12, 12],
[14, 14],
[4, 4],
[7, 7],
[10, 10],
[5, 5]
];
tmm.addMany(idAndValues);
expect(tmm.root).toBeInstanceOf(TreeMultiMapNode);
if (tmm.root) expect(tmm.root.key).toBe(5);
expect(tmm.size).toBe(16);
expect(tmm.count).toBe(18);
expect(tmm.getComputedCount()).toBe(18);
expect(tmm.has(6));
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(node => node.key === 9);
expect(nodeVal9?.key).toBe(9);
});
});
describe('TreeMultiMap iterative methods testm ap mode', () => {
let treeMM: TreeMultiMap<number, string>;
beforeEach(() => {
treeMM = new TreeMultiMap<number, string>([], { isMapMode: true });
treeMM.add(1, 'a', 10);
treeMM.add([2, 'b'], undefined, 10);
treeMM.add([3, 'c'], undefined, 1);
});
it('should clone work well', () => {
expect(treeMM.count).toBe(21);
expect(treeMM.getComputedCount()).toBe(21);
const cloned = treeMM.clone();
expect(cloned.root?.left?.key).toBe(1);
expect(cloned.get(cloned.root?.right)).toBe('c');
});
});