refactor: Replace all enumerations with union types for significant performance improvements in BST, AVLTree, and RedBlackTree.

This commit is contained in:
Revone 2024-01-14 03:04:07 +08:00
parent d0b3fcf164
commit a11c104dff
20 changed files with 334 additions and 295 deletions

View file

@ -996,43 +996,45 @@ Intel UHD Graphics 630 1536 MB
[//]: # (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.34</td><td>157.68</td><td>1.57e-4</td></tr><tr><td>100,000 add & poll</td><td>31.54</td><td>31.70</td><td>9.20e-4</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<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.46</td><td>154.91</td><td>3.36e-4</td></tr><tr><td>100,000 add & poll</td><td>31.62</td><td>31.62</td><td>8.04e-4</td></tr></table></div>
</div><div id="json-to-html"><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 orderly</td><td>57.90</td><td>17.27</td><td>0.00</td></tr><tr><td>100,000 delete orderly</td><td>10.65</td><td>93.90</td><td>9.11e-5</td></tr><tr><td>100,000 add randomly</td><td>114.65</td><td>8.72</td><td>0.00</td></tr><tr><td>100,000 delete randomly</td><td>10.24</td><td>97.62</td><td>5.53e-5</td></tr><tr><td>100,000 add orderly</td><td>58.51</td><td>17.09</td><td>0.00</td></tr><tr><td>100,000 delete randomly</td><td>10.25</td><td>97.56</td><td>6.25e-5</td></tr><tr><td>100,000 getNode randomly</td><td>9.53</td><td>104.98</td><td>6.20e-5</td></tr><tr><td>100,000 add & iterator</td><td>146.46</td><td>6.83</td><td>0.02</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<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 orderly</td><td>92.78</td><td>10.78</td><td>0.00</td></tr><tr><td>100,000 add & delete orderly</td><td>164.95</td><td>6.06</td><td>0.00</td></tr><tr><td>100,000 add randomly</td><td>96.14</td><td>10.40</td><td>0.00</td></tr><tr><td>100,000 add & delete randomly</td><td>268.32</td><td>3.73</td><td>0.02</td></tr><tr><td>100,000 add & get randomly</td><td>221.23</td><td>4.52</td><td>0.00</td></tr><tr><td>100,000 add & iterator</td><td>130.01</td><td>7.69</td><td>0.01</td></tr></table></div>
</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>41.59</td><td>24.05</td><td>0.01</td></tr><tr><td>100,000 push & shift</td><td>4.54</td><td>220.29</td><td>1.10e-4</td></tr><tr><td>Native JS Array 100,000 push & shift</td><td>2243.54</td><td>0.45</td><td>0.10</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.07</td><td>22.69</td><td>0.01</td></tr><tr><td>100,000 push & shift</td><td>4.89</td><td>204.65</td><td>5.60e-4</td></tr><tr><td>Native JS Array 100,000 push & shift</td><td>2305.44</td><td>0.43</td><td>0.31</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>deque</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>23.20</td><td>43.10</td><td>0.00</td></tr><tr><td>1,000,000 push & pop</td><td>30.14</td><td>33.18</td><td>0.00</td></tr><tr><td>1,000,000 push & shift</td><td>29.94</td><td>33.40</td><td>0.00</td></tr><tr><td>100,000 push & shift</td><td>3.18</td><td>314.70</td><td>3.27e-4</td></tr><tr><td>Native JS Array 100,000 push & shift</td><td>2238.52</td><td>0.45</td><td>0.09</td></tr><tr><td>100,000 unshift & shift</td><td>2.85</td><td>350.27</td><td>2.85e-4</td></tr><tr><td>Native JS Array 100,000 unshift & shift</td><td>4149.34</td><td>0.24</td><td>0.10</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>24.69</td><td>40.50</td><td>0.00</td></tr><tr><td>1,000,000 push & pop</td><td>31.59</td><td>31.66</td><td>0.00</td></tr><tr><td>1,000,000 push & shift</td><td>31.17</td><td>32.09</td><td>0.00</td></tr><tr><td>100,000 push & shift</td><td>3.27</td><td>305.75</td><td>2.76e-4</td></tr><tr><td>Native JS Array 100,000 push & shift</td><td>2511.34</td><td>0.40</td><td>0.37</td></tr><tr><td>100,000 unshift & shift</td><td>2.97</td><td>336.26</td><td>2.53e-4</td></tr><tr><td>Native JS Array 100,000 unshift & shift</td><td>4097.31</td><td>0.24</td><td>0.34</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>113.24</td><td>8.83</td><td>0.03</td></tr><tr><td>Native JS Map 1,000,000 set</td><td>205.14</td><td>4.87</td><td>0.00</td></tr><tr><td>Native JS Set 1,000,000 add</td><td>174.38</td><td>5.73</td><td>0.01</td></tr><tr><td>1,000,000 set & get</td><td>114.96</td><td>8.70</td><td>0.03</td></tr><tr><td>Native JS Map 1,000,000 set & get</td><td>267.57</td><td>3.74</td><td>0.00</td></tr><tr><td>Native JS Set 1,000,000 add & has</td><td>172.94</td><td>5.78</td><td>0.01</td></tr><tr><td>1,000,000 ObjKey set & get</td><td>327.38</td><td>3.05</td><td>0.03</td></tr><tr><td>Native JS Map 1,000,000 ObjKey set & get</td><td>297.64</td><td>3.36</td><td>0.03</td></tr><tr><td>Native JS Set 1,000,000 ObjKey add & has</td><td>263.30</td><td>3.80</td><td>0.04</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>114.37</td><td>8.74</td><td>0.02</td></tr><tr><td>Native JS Map 1,000,000 set</td><td>202.67</td><td>4.93</td><td>0.00</td></tr><tr><td>Native JS Set 1,000,000 add</td><td>168.24</td><td>5.94</td><td>0.00</td></tr><tr><td>1,000,000 set & get</td><td>124.10</td><td>8.06</td><td>0.03</td></tr><tr><td>Native JS Map 1,000,000 set & get</td><td>266.46</td><td>3.75</td><td>0.01</td></tr><tr><td>Native JS Set 1,000,000 add & has</td><td>175.14</td><td>5.71</td><td>0.02</td></tr><tr><td>1,000,000 ObjKey set & get</td><td>341.26</td><td>2.93</td><td>0.05</td></tr><tr><td>Native JS Map 1,000,000 ObjKey set & get</td><td>311.60</td><td>3.21</td><td>0.04</td></tr><tr><td>Native JS Set 1,000,000 ObjKey add & has</td><td>274.81</td><td>3.64</td><td>0.03</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>trie</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 push</td><td>43.65</td><td>22.91</td><td>0.00</td></tr><tr><td>100,000 getWords</td><td>82.64</td><td>12.10</td><td>0.00</td></tr></table></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 push</td><td>59.08</td><td>16.93</td><td>0.00</td></tr><tr><td>100,000 getWords</td><td>82.92</td><td>12.06</td><td>0.00</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>avl-tree</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 add randomly</td><td>133.02</td><td>7.52</td><td>0.00</td></tr><tr><td>10,000 get</td><td>61.42</td><td>16.28</td><td>5.07e-4</td></tr><tr><td>10,000 add & delete randomly</td><td>204.19</td><td>4.90</td><td>0.00</td></tr><tr><td>10,000 addMany</td><td>142.69</td><td>7.01</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>10,000 add randomly</td><td>48.66</td><td>20.55</td><td>0.01</td></tr><tr><td>10,000 get</td><td>19.36</td><td>51.64</td><td>2.95e-4</td></tr><tr><td>10,000 add & delete randomly</td><td>77.68</td><td>12.87</td><td>0.00</td></tr><tr><td>10,000 addMany</td><td>52.04</td><td>19.22</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'>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</td><td>9.28</td><td>107.79</td><td>1.15e-4</td></tr><tr><td>10,000 RBTree add & delete randomly</td><td>60.56</td><td>16.51</td><td>6.63e-4</td></tr><tr><td>10,000 RBTree get</td><td>1.11</td><td>902.48</td><td>8.41e-6</td></tr><tr><td>10,000 AVLTree add</td><td>134.17</td><td>7.45</td><td>0.01</td></tr><tr><td>10,000 AVLTree get</td><td>60.97</td><td>16.40</td><td>4.05e-4</td></tr><tr><td>10,000 AVLTree add & delete randomly</td><td>201.72</td><td>4.96</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>10,000 RBTree add</td><td>8.07</td><td>123.87</td><td>8.53e-5</td></tr><tr><td>10,000 RBTree add & delete randomly</td><td>22.38</td><td>44.68</td><td>5.81e-4</td></tr><tr><td>10,000 RBTree get</td><td>0.62</td><td>1602.15</td><td>7.37e-6</td></tr><tr><td>10,000 AVLTree add</td><td>46.27</td><td>21.61</td><td>8.12e-4</td></tr><tr><td>10,000 AVLTree get</td><td>20.02</td><td>49.95</td><td>4.21e-4</td></tr><tr><td>10,000 AVLTree add & delete randomly</td><td>75.96</td><td>13.16</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.00e+4</td><td>7.24e-7</td></tr><tr><td>1,000 addEdge</td><td>6.20</td><td>161.25</td><td>8.47e-4</td></tr><tr><td>1,000 getVertex</td><td>0.05</td><td>2.17e+4</td><td>3.59e-7</td></tr><tr><td>1,000 getEdge</td><td>22.60</td><td>44.24</td><td>0.00</td></tr><tr><td>tarjan</td><td>207.15</td><td>4.83</td><td>0.02</td></tr><tr><td>topologicalSort</td><td>175.86</td><td>5.69</td><td>0.00</td></tr></table></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000 addVertex</td><td>0.10</td><td>9647.19</td><td>9.43e-7</td></tr><tr><td>1,000 addEdge</td><td>6.06</td><td>164.98</td><td>1.09e-4</td></tr><tr><td>1,000 getVertex</td><td>0.05</td><td>2.17e+4</td><td>2.85e-7</td></tr><tr><td>1,000 getEdge</td><td>23.47</td><td>42.60</td><td>0.00</td></tr><tr><td>tarjan</td><td>208.86</td><td>4.79</td><td>0.01</td></tr><tr><td>topologicalSort</td><td>186.70</td><td>5.36</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'>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>235.16</td><td>4.25</td><td>0.06</td></tr><tr><td>1,000,000 unshift</td><td>225.37</td><td>4.44</td><td>0.04</td></tr><tr><td>1,000,000 unshift & shift</td><td>170.75</td><td>5.86</td><td>0.03</td></tr><tr><td>1,000,000 addBefore</td><td>324.45</td><td>3.08</td><td>0.07</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>209.57</td><td>4.77</td><td>0.06</td></tr><tr><td>1,000,000 unshift</td><td>203.85</td><td>4.91</td><td>0.03</td></tr><tr><td>1,000,000 unshift & shift</td><td>172.64</td><td>5.79</td><td>0.02</td></tr><tr><td>1,000,000 addBefore</td><td>315.26</td><td>3.17</td><td>0.08</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>215.08</td><td>4.65</td><td>0.07</td></tr><tr><td>10,000 push & pop</td><td>212.54</td><td>4.71</td><td>0.01</td></tr><tr><td>10,000 addBefore</td><td>250.10</td><td>4.00</td><td>0.01</td></tr></table></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push & shift</td><td>218.01</td><td>4.59</td><td>0.06</td></tr><tr><td>10,000 push & pop</td><td>216.06</td><td>4.63</td><td>0.01</td></tr><tr><td>10,000 addBefore</td><td>248.62</td><td>4.02</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>26.71</td><td>37.44</td><td>2.40e-4</td></tr><tr><td>100,000 add & poll</td><td>74.78</td><td>13.37</td><td>5.52e-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>27.52</td><td>36.34</td><td>0.00</td></tr><tr><td>100,000 add & poll</td><td>75.49</td><td>13.25</td><td>5.41e-4</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>37.19</td><td>26.89</td><td>0.00</td></tr><tr><td>1,000,000 push & pop</td><td>46.11</td><td>21.69</td><td>0.00</td></tr></table></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>41.24</td><td>24.25</td><td>0.01</td></tr><tr><td>1,000,000 push & pop</td><td>49.67</td><td>20.13</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.49.4",
"version": "1.50.7",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "data-structure-typed",
"version": "1.49.4",
"version": "1.50.7",
"license": "MIT",
"devDependencies": {
"@swc/core": "^1.3.96",
@ -16,11 +16,11 @@
"@typescript-eslint/eslint-plugin": "^6.7.4",
"@typescript-eslint/parser": "^6.7.4",
"auto-changelog": "^2.4.0",
"avl-tree-typed": "^1.44.0",
"avl-tree-typed": "^1.50.7",
"benchmark": "^2.1.4",
"binary-tree-typed": "^1.44.0",
"bst-typed": "^1.44.0",
"data-structure-typed": "^1.44.0",
"binary-tree-typed": "^1.50.7",
"bst-typed": "^1.50.7",
"data-structure-typed": "^1.50.7",
"dependency-cruiser": "^14.1.0",
"doctoc": "^2.2.1",
"eslint": "^8.50.0",
@ -29,7 +29,7 @@
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.28.1",
"fast-glob": "^3.3.1",
"heap-typed": "^1.44.0",
"heap-typed": "^1.50.7",
"istanbul-badges-readme": "^1.8.5",
"jest": "^29.7.0",
"js-sdsl": "^4.4.2",
@ -3097,12 +3097,12 @@
}
},
"node_modules/avl-tree-typed": {
"version": "1.49.4",
"resolved": "https://registry.npmjs.org/avl-tree-typed/-/avl-tree-typed-1.49.4.tgz",
"integrity": "sha512-koGMepnQ6vmZND5plmUMojmvUSJrbmcFev8uO9XxuJKVKYzcjfWIG3m3Hylantwzi6XAUURFHobmjNgLvsUmaw==",
"version": "1.50.7",
"resolved": "https://registry.npmjs.org/avl-tree-typed/-/avl-tree-typed-1.50.7.tgz",
"integrity": "sha512-zYo8Oa4IrM5i3evHGO0FhELFHpDITUOpa2d8cGd06LHR74I9JL0OX7X0J+yuy6RBSuiIiNieJ99EKmhuggGbTg==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.49.4"
"data-structure-typed": "^1.50.7"
}
},
"node_modules/babel-jest": {
@ -3306,12 +3306,12 @@
}
},
"node_modules/binary-tree-typed": {
"version": "1.49.4",
"resolved": "https://registry.npmjs.org/binary-tree-typed/-/binary-tree-typed-1.49.4.tgz",
"integrity": "sha512-6f0J37Ab6zb3W1YYlQZ7PIeQp/Nabpc03U93ZGAIZo+mSyIzzXgWZkK0XTvarY5vpv8Pd4u1eDeQjV+n6EHHvQ==",
"version": "1.50.7",
"resolved": "https://registry.npmjs.org/binary-tree-typed/-/binary-tree-typed-1.50.7.tgz",
"integrity": "sha512-L1kVL9q+1jsXyTNuZ/PJrBD1HUK4MyWFOwQmH4coy7WmOlTg2z2+ZuXCgmT8X/ADYFoKc9hq94niS/Yvy6RpOg==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.49.4"
"data-structure-typed": "^1.50.7"
}
},
"node_modules/brace-expansion": {
@ -3390,12 +3390,12 @@
}
},
"node_modules/bst-typed": {
"version": "1.49.4",
"resolved": "https://registry.npmjs.org/bst-typed/-/bst-typed-1.49.4.tgz",
"integrity": "sha512-qWuWrC5eGm7Czxc5PPXyGP4kRkkz7FOJ4MlwPwo8JQapJwXrxFLj/ix79pqBvQVUZ4AKXPg8vBsqm/hE4M1mkA==",
"version": "1.50.7",
"resolved": "https://registry.npmjs.org/bst-typed/-/bst-typed-1.50.7.tgz",
"integrity": "sha512-grhnOajT8DBZYivgT5Q+qVQKpBbUPIyMJ2KVOx2EBH68l1pFA78zlf/BJWhEL+UcLwDqIJ6DpbvqcyTAjcfE9A==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.49.4"
"data-structure-typed": "^1.50.7"
}
},
"node_modules/buffer-from": {
@ -3838,9 +3838,9 @@
}
},
"node_modules/data-structure-typed": {
"version": "1.49.4",
"resolved": "https://registry.npmjs.org/data-structure-typed/-/data-structure-typed-1.49.4.tgz",
"integrity": "sha512-Xsb/cHHSFc7x7Rr2ppehqZ+fOI5xykqCZ65rt7tS4n3v0AcNZn1nz9elSwiP7mTHGXCLbOeNQdwLtsmcC32wIw==",
"version": "1.50.7",
"resolved": "https://registry.npmjs.org/data-structure-typed/-/data-structure-typed-1.50.7.tgz",
"integrity": "sha512-TPLHMD4yxQFp4YbigA7i4zAVsQwZEarmYah2KXMmhczzasDXt+bbYLg7/BlRkq58N55Qr8UZuI5MAlH2YKaibQ==",
"dev": true
},
"node_modules/debug": {
@ -5363,12 +5363,12 @@
}
},
"node_modules/heap-typed": {
"version": "1.49.4",
"resolved": "https://registry.npmjs.org/heap-typed/-/heap-typed-1.49.4.tgz",
"integrity": "sha512-ykm0Bs7iYFF16uZ21tnCt+WPBYkLFxWh2HLObZiQmxEgozczcfJpc6IxWfRyvECJkIYrnh2Im9ej4ERWca7+aQ==",
"version": "1.50.7",
"resolved": "https://registry.npmjs.org/heap-typed/-/heap-typed-1.50.7.tgz",
"integrity": "sha512-124SW17qSl+7aVp0d4gdFVTusW/Lq+x8S89yvyTUfSj6YadqUjP0EKblDx4oShiYC91g3YRPKqKV5juN2SDx5w==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.49.4"
"data-structure-typed": "^1.50.7"
}
},
"node_modules/html-escaper": {

View file

@ -66,11 +66,11 @@
"@typescript-eslint/eslint-plugin": "^6.7.4",
"@typescript-eslint/parser": "^6.7.4",
"auto-changelog": "^2.4.0",
"avl-tree-typed": "^1.44.0",
"avl-tree-typed": "^1.50.7",
"benchmark": "^2.1.4",
"binary-tree-typed": "^1.44.0",
"bst-typed": "^1.44.0",
"data-structure-typed": "^1.44.0",
"binary-tree-typed": "^1.50.7",
"bst-typed": "^1.50.7",
"data-structure-typed": "^1.50.7",
"dependency-cruiser": "^14.1.0",
"doctoc": "^2.2.1",
"eslint": "^8.50.0",
@ -79,7 +79,7 @@
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.28.1",
"fast-glob": "^3.3.1",
"heap-typed": "^1.44.0",
"heap-typed": "^1.50.7",
"istanbul-badges-readme": "^1.8.5",
"jest": "^29.7.0",
"js-sdsl": "^4.4.2",

View file

@ -14,7 +14,6 @@ import type {
BTNCallback,
KeyOrNodeOrEntry
} from '../../types';
import { FamilyPosition, IterationType } from '../../types';
import { IBinaryTree } from '../../interfaces';
import { AVLTree, AVLTreeNode } from './avl-tree';
@ -249,9 +248,9 @@ export class AVLTreeMultiMap<
if (curr.right !== undefined) this._setRoot(curr.right);
} else {
const { familyPosition: fp } = curr;
if (fp === FamilyPosition.LEFT || fp === FamilyPosition.ROOT_LEFT) {
if (fp === 'LEFT' || fp === 'ROOT_LEFT') {
parent.left = curr.right;
} else if (fp === FamilyPosition.RIGHT || fp === FamilyPosition.ROOT_RIGHT) {
} else if (fp === 'RIGHT' || fp === 'ROOT_RIGHT') {
parent.right = curr.right;
}
needBalanced = parent;
@ -324,7 +323,7 @@ export class AVLTreeMultiMap<
this.clear();
if (iterationType === IterationType.RECURSIVE) {
if (iterationType === 'RECURSIVE') {
const buildBalanceBST = (l: number, r: number) => {
if (l > r) return;
const m = l + Math.floor((r - l) / 2);

View file

@ -107,16 +107,16 @@ export class BinaryTreeNode<
get familyPosition(): FamilyPosition {
const that = this as unknown as NODE;
if (!this.parent) {
return this.left || this.right ? FamilyPosition.ROOT : FamilyPosition.ISOLATED;
return this.left || this.right ? 'ROOT' : 'ISOLATED';
}
if (this.parent.left === that) {
return this.left || this.right ? FamilyPosition.ROOT_LEFT : FamilyPosition.LEFT;
return this.left || this.right ? 'ROOT_LEFT' : 'LEFT';
} else if (this.parent.right === that) {
return this.left || this.right ? FamilyPosition.ROOT_RIGHT : FamilyPosition.RIGHT;
return this.left || this.right ? 'ROOT_RIGHT' : 'RIGHT';
}
return FamilyPosition.MAL_NODE;
return 'MAL_NODE';
}
}
@ -136,7 +136,7 @@ export class BinaryTree<
>
extends IterableEntryBase<K, V | undefined>
implements IBinaryTree<K, V, NODE, TREE> {
iterationType = IterationType.ITERATIVE;
iterationType: IterationType = 'ITERATIVE';
/**
* The constructor function initializes a binary tree object with optional keysOrNodesOrEntries and options.
@ -160,7 +160,7 @@ export class BinaryTree<
if (keysOrNodesOrEntries) this.addMany(keysOrNodesOrEntries);
}
protected _extractor = (key: K) => Number(key);
protected _extractor = (key: K) => (typeof key === 'number' ? key : Number(key));
/**
* The function returns the value of the `_extractor` property.
@ -260,14 +260,11 @@ export class BinaryTree<
* `null`, or `undefined`. It represents a key used to identify a node in a binary tree.
* @param iterationType - The `iterationType` parameter is an optional parameter that specifies the
* type of iteration to be used when searching for a node by key. It has a default value of
* `IterationType.ITERATIVE`.
* `'ITERATIVE'`.
* @returns either the node corresponding to the given key if it is a valid node key, or the key
* itself if it is not a valid node key.
*/
ensureNode(
keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>,
iterationType = IterationType.ITERATIVE
): NODE | null | undefined {
ensureNode(keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>, iterationType = 'ITERATIVE'): NODE | null | undefined {
let res: NODE | null | undefined;
if (this.isRealNode(keyOrNodeOrEntry)) {
res = keyOrNodeOrEntry;
@ -521,9 +518,9 @@ export class BinaryTree<
}
} else if (parent) {
const { familyPosition: fp } = curr;
if (fp === FamilyPosition.LEFT || fp === FamilyPosition.ROOT_LEFT) {
if (fp === 'LEFT' || fp === 'ROOT_LEFT') {
parent.left = curr.right;
} else if (fp === FamilyPosition.RIGHT || fp === FamilyPosition.ROOT_RIGHT) {
} else if (fp === 'RIGHT' || fp === 'ROOT_RIGHT') {
parent.right = curr.right;
}
needBalanced = parent;
@ -606,7 +603,7 @@ export class BinaryTree<
const ans: NODE[] = [];
if (iterationType === IterationType.RECURSIVE) {
if (iterationType === 'RECURSIVE') {
const _traverse = (cur: NODE) => {
if (callback(cur) === identifier) {
ans.push(cur);
@ -714,9 +711,9 @@ export class BinaryTree<
* @returns The function `getNodeByKey` returns a node (`NODE`) if a node with the specified key is
* found in the binary tree. If no node is found, it returns `undefined`.
*/
getNodeByKey(key: K, iterationType = IterationType.ITERATIVE): NODE | undefined {
getNodeByKey(key: K, iterationType = 'ITERATIVE'): NODE | undefined {
if (!this.root) return undefined;
if (iterationType === IterationType.RECURSIVE) {
if (iterationType === 'RECURSIVE') {
const _dfs = (cur: NODE): NODE | undefined => {
if (cur.key === key) return cur;
@ -932,7 +929,7 @@ export class BinaryTree<
beginRoot = this.ensureNode(beginRoot);
if (!beginRoot) return true;
if (iterationType === IterationType.RECURSIVE) {
if (iterationType === 'RECURSIVE') {
const dfs = (cur: NODE | null | undefined, min: number, max: number): boolean => {
if (!this.isRealNode(cur)) return true;
const numKey = this.extractor(cur.key);
@ -1023,7 +1020,7 @@ export class BinaryTree<
beginRoot = this.ensureNode(beginRoot);
if (!this.isRealNode(beginRoot)) return -1;
if (iterationType === IterationType.RECURSIVE) {
if (iterationType === 'RECURSIVE') {
const _getMaxHeight = (cur: NODE | null | undefined): number => {
if (!this.isRealNode(cur)) return -1;
const leftHeight = _getMaxHeight(cur.left);
@ -1071,7 +1068,7 @@ export class BinaryTree<
beginRoot = this.ensureNode(beginRoot);
if (!beginRoot) return -1;
if (iterationType === IterationType.RECURSIVE) {
if (iterationType === 'RECURSIVE') {
const _getMinHeight = (cur: NODE | null | undefined): number => {
if (!this.isRealNode(cur)) return 0;
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return 0;
@ -1174,7 +1171,7 @@ export class BinaryTree<
if (!this.isRealNode(beginRoot)) return beginRoot;
if (iterationType === IterationType.RECURSIVE) {
if (iterationType === 'RECURSIVE') {
const _traverse = (cur: NODE): NODE => {
if (!this.isRealNode(cur.left)) return cur;
return _traverse(cur.left);
@ -1221,7 +1218,7 @@ export class BinaryTree<
beginRoot = this.ensureNode(beginRoot);
if (!beginRoot) return beginRoot;
if (iterationType === IterationType.RECURSIVE) {
if (iterationType === 'RECURSIVE') {
const _traverse = (cur: NODE): NODE => {
if (!this.isRealNode(cur.right)) return cur;
return _traverse(cur.right);
@ -1345,13 +1342,13 @@ export class BinaryTree<
callback: C = this._defaultOneParamCallback as C,
pattern: DFSOrderPattern = 'in',
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
iterationType: IterationType = IterationType.ITERATIVE,
iterationType: IterationType = 'ITERATIVE',
includeNull = false
): ReturnType<C>[] {
beginRoot = this.ensureNode(beginRoot);
if (!beginRoot) return [];
const ans: ReturnType<C>[] = [];
if (iterationType === IterationType.RECURSIVE) {
if (iterationType === 'RECURSIVE') {
const _traverse = (node: NODE | null | undefined) => {
switch (pattern) {
case 'in':
@ -1487,7 +1484,7 @@ export class BinaryTree<
const ans: ReturnType<BTNCallback<NODE>>[] = [];
if (iterationType === IterationType.RECURSIVE) {
if (iterationType === 'RECURSIVE') {
const queue: Queue<NODE | null | undefined> = new Queue<NODE | null | undefined>([beginRoot]);
const traverse = (level: number) => {
@ -1580,7 +1577,7 @@ export class BinaryTree<
const levelsNodes: ReturnType<C>[][] = [];
if (!beginRoot) return levelsNodes;
if (iterationType === IterationType.RECURSIVE) {
if (iterationType === 'RECURSIVE') {
const _recursive = (node: NODE | null, level: number) => {
if (!levelsNodes[level]) levelsNodes[level] = [];
levelsNodes[level].push(callback(node));
@ -1876,7 +1873,7 @@ export class BinaryTree<
protected* _getIterator(node = this.root): IterableIterator<[K, V | undefined]> {
if (!node) return;
if (this.iterationType === IterationType.ITERATIVE) {
if (this.iterationType === 'ITERATIVE') {
const stack: (NODE | null | undefined)[] = [];
let current: NODE | null | undefined = node;

View file

@ -126,7 +126,7 @@ export class BST<
return this._root;
}
protected _variant = BSTVariant.STANDARD;
protected _variant: BSTVariant = 'STANDARD';
/**
* The function returns the value of the _variant property.
@ -207,13 +207,10 @@ export class BST<
* @param {K | NODE | undefined} keyOrNodeOrEntry - The `key` parameter can be of type `K`, `NODE`, or
* `undefined`.
* @param iterationType - The `iterationType` parameter is an optional parameter that specifies the
* type of iteration to be performed. It has a default value of `IterationType.ITERATIVE`.
* type of iteration to be performed. It has a default value of `'ITERATIVE'`.
* @returns either a node object (NODE) or undefined.
*/
override ensureNode(
keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>,
iterationType = IterationType.ITERATIVE
): NODE | undefined {
override ensureNode(keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>, iterationType = 'ITERATIVE'): NODE | undefined {
let res: NODE | undefined;
if (this.isRealNode(keyOrNodeOrEntry)) {
res = keyOrNodeOrEntry;
@ -263,7 +260,7 @@ export class BST<
let current = this.root;
while (current !== undefined) {
if (this._compare(current.key, newNode.key) === CP.eq) {
if (this._compare(current.key, newNode.key) === 'EQ') {
// if (current !== newNode) {
// The key value is the same but the reference is different, update the value of the existing node
this._replaceNode(current, newNode);
@ -275,7 +272,7 @@ export class BST<
// return;
// }
} else if (this._compare(current.key, newNode.key) === CP.gt) {
} else if (this._compare(current.key, newNode.key) === 'GT') {
if (current.left === undefined) {
current.left = newNode;
this._size++;
@ -397,7 +394,7 @@ export class BST<
}
};
if (iterationType === IterationType.RECURSIVE) {
if (iterationType === 'RECURSIVE') {
_dfs(sorted);
} else {
_iterate();
@ -425,15 +422,15 @@ export class BST<
* @returns The function `getNodeByKey` returns a node (`NODE`) if a node with the specified key is
* found in the binary tree. If no node is found, it returns `undefined`.
*/
override getNodeByKey(key: K, iterationType = IterationType.ITERATIVE): NODE | undefined {
override getNodeByKey(key: K, iterationType = 'ITERATIVE'): NODE | undefined {
if (!this.isRealNode(this.root)) return undefined;
if (iterationType === IterationType.RECURSIVE) {
if (iterationType === 'RECURSIVE') {
const _dfs = (cur: NODE): NODE | undefined => {
if (cur.key === key) return cur;
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return;
if (this._compare(cur.key, key) === CP.gt && this.isRealNode(cur.left)) return _dfs(cur.left);
if (this._compare(cur.key, key) === CP.lt && this.isRealNode(cur.right)) return _dfs(cur.right);
if (this._compare(cur.key, key) === 'GT' && this.isRealNode(cur.left)) return _dfs(cur.left);
if (this._compare(cur.key, key) === 'LT' && this.isRealNode(cur.right)) return _dfs(cur.right);
};
return _dfs(this.root);
@ -442,9 +439,9 @@ export class BST<
while (queue.size > 0) {
const cur = queue.shift();
if (this.isRealNode(cur)) {
if (this._compare(cur.key, key) === CP.eq) return cur;
if (this._compare(cur.key, key) === CP.gt) this.isRealNode(cur.left) && queue.push(cur.left);
if (this._compare(cur.key, key) === CP.lt) this.isRealNode(cur.right) && queue.push(cur.right);
if (this._compare(cur.key, key) === 'EQ') return cur;
if (this._compare(cur.key, key) === 'GT') this.isRealNode(cur.left) && queue.push(cur.left);
if (this._compare(cur.key, key) === 'LT') this.isRealNode(cur.right) && queue.push(cur.right);
}
}
}
@ -489,7 +486,7 @@ export class BST<
if (!beginRoot) return [];
const ans: NODE[] = [];
if (iterationType === IterationType.RECURSIVE) {
if (iterationType === 'RECURSIVE') {
const _traverse = (cur: NODE) => {
const callbackResult = callback(cur);
if (callbackResult === identifier) {
@ -500,8 +497,8 @@ export class BST<
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return;
// TODO potential bug
if (callback === this._defaultOneParamCallback) {
if (this._compare(cur.key, identifier as K) === CP.gt) this.isRealNode(cur.left) && _traverse(cur.left);
if (this._compare(cur.key, identifier as K) === CP.lt) this.isRealNode(cur.right) && _traverse(cur.right);
if (this.isRealNode(cur.left) && this._compare(cur.key, identifier as K) === 'GT') _traverse(cur.left);
if (this.isRealNode(cur.right) && this._compare(cur.key, identifier as K) === 'LT') _traverse(cur.right);
} else {
this.isRealNode(cur.left) && _traverse(cur.left);
this.isRealNode(cur.right) && _traverse(cur.right);
@ -510,9 +507,9 @@ export class BST<
_traverse(beginRoot);
} else {
const queue = new Queue<NODE>([beginRoot]);
while (queue.size > 0) {
const cur = queue.shift();
const stack = [beginRoot];
while (stack.length > 0) {
const cur = stack.pop();
if (this.isRealNode(cur)) {
const callbackResult = callback(cur);
if (callbackResult === identifier) {
@ -521,11 +518,19 @@ export class BST<
}
// TODO potential bug
if (callback === this._defaultOneParamCallback) {
if (this._compare(cur.key, identifier as K) === CP.gt) this.isRealNode(cur.left) && queue.push(cur.left);
if (this._compare(cur.key, identifier as K) === CP.lt) this.isRealNode(cur.right) && queue.push(cur.right);
if (this.isRealNode(cur.right) && this._compare(cur.key, identifier as K) === 'LT') stack.push(cur.right);
if (this.isRealNode(cur.left) && this._compare(cur.key, identifier as K) === 'GT') stack.push(cur.left);
// if (this.isRealNode(cur.right) && this._lt(cur.key, identifier as K)) stack.push(cur.right);
// if (this.isRealNode(cur.left) && this._gt(cur.key, identifier as K)) stack.push(cur.left);
// // @ts-ignore
// if (this.isRealNode(cur.right) && cur.key > identifier) stack.push(cur.right);
// // @ts-ignore
// if (this.isRealNode(cur.left) && cur.key < identifier) stack.push(cur.left);
} else {
this.isRealNode(cur.left) && queue.push(cur.left);
this.isRealNode(cur.right) && queue.push(cur.right);
this.isRealNode(cur.right) && stack.push(cur.right);
this.isRealNode(cur.left) && stack.push(cur.left);
}
}
}
@ -562,7 +567,7 @@ export class BST<
callback: C = this._defaultOneParamCallback as C,
pattern: DFSOrderPattern = 'in',
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
iterationType: IterationType = IterationType.ITERATIVE
iterationType: IterationType = 'ITERATIVE'
): ReturnType<C>[] {
return super.dfs(callback, pattern, beginRoot, iterationType, false);
}
@ -650,7 +655,7 @@ export class BST<
let current = this.ensureNode(beginRoot);
if (!current) return undefined;
if (this._variant === BSTVariant.STANDARD) {
if (this._variant === 'STANDARD') {
// For BSTVariant.MIN, find the rightmost node
while (current.right !== undefined) {
current = current.right;
@ -692,7 +697,7 @@ export class BST<
*/
lesserOrGreaterTraverse<C extends BTNCallback<NODE>>(
callback: C = this._defaultOneParamCallback as C,
lesserOrGreater: CP = CP.lt,
lesserOrGreater: CP = 'LT',
targetNode: KeyOrNodeOrEntry<K, V, NODE> = this.root,
iterationType = this.iterationType
): ReturnType<C>[] {
@ -703,7 +708,7 @@ export class BST<
const targetKey = targetNode.key;
if (iterationType === IterationType.RECURSIVE) {
if (iterationType === 'RECURSIVE') {
const _traverse = (cur: NODE) => {
const compared = this._compare(cur.key, targetKey);
if (compared === lesserOrGreater) ans.push(callback(cur));
@ -752,7 +757,7 @@ export class BST<
this.clear();
if (sorted.length < 1) return false;
if (iterationType === IterationType.RECURSIVE) {
if (iterationType === 'RECURSIVE') {
const buildBalanceBST = (l: number, r: number) => {
if (l > r) return;
const m = l + Math.floor((r - l) / 2);
@ -812,7 +817,7 @@ export class BST<
let balanced = true;
if (iterationType === IterationType.RECURSIVE) {
if (iterationType === 'RECURSIVE') {
const _height = (cur: NODE | undefined): number => {
if (!cur) return 0;
const leftHeight = _height(cur.left),
@ -868,14 +873,32 @@ export class BST<
* is greater than, less than, or equal to the second value.
* @param {K} a - The parameter "a" is of type K.
* @param {K} b - The parameter "b" in the above code represents a K.
* @returns a value of type CP (ComparisonResult). The possible return values are CP.gt (greater
* than), CP.lt (less than), or CP.eq (equal).
* @returns a value of type CP (ComparisonResult). The possible return values are 'GT' (greater
* than), 'LT' (less than), or 'EQ' (equal).
*/
protected _compare(a: K, b: K): CP {
const extractedA = this.extractor(a);
const extractedB = this.extractor(b);
const compared = this.variant === BSTVariant.STANDARD ? extractedA - extractedB : extractedB - extractedA;
const compared = this.variant === 'STANDARD' ? extractedA - extractedB : extractedB - extractedA;
return compared > 0 ? CP.gt : compared < 0 ? CP.lt : CP.eq;
return compared > 0 ? 'GT' : compared < 0 ? 'LT' : 'EQ';
}
protected _lt(a: K, b: K): boolean {
const extractedA = this.extractor(a);
const extractedB = this.extractor(b);
// return this.variant === BSTVariant.STANDARD ? extractedA < extractedB : extractedA > extractedB;
return this.variant === 'STANDARD' ? extractedA < extractedB : extractedA > extractedB;
// return extractedA < extractedB;
// return a < b;
}
protected _gt(a: K, b: K): boolean {
const extractedA = this.extractor(a);
const extractedB = this.extractor(b);
// return this.variant === BSTVariant.STANDARD ? extractedA > extractedB : extractedA < extractedB;
return this.variant === 'STANDARD' ? extractedA > extractedB : extractedA < extractedB;
// return extractedA > extractedB;
// return a > b;
}
}

View file

@ -234,8 +234,8 @@ export class RedBlackTree<
beginRoot: BSTNKeyOrNode<K, NODE> = this.root,
iterationType = this.iterationType
): NODE | null | undefined {
if ((identifier as any) instanceof RedBlackTreeNode) callback = (node => node) as C;
return super.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? undefined;
// if ((identifier as any) instanceof RedBlackTreeNode) callback = (node => node) as C;
return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? undefined;
}
/**
@ -279,7 +279,7 @@ export class RedBlackTree<
const insertStatus = this._insert(newNode);
if (insertStatus === CRUD.CREATED) {
if (insertStatus === 'CREATED') {
// Ensure the root is black
if (this.isRealNode(this._root)) {
this._root.color = RBTNColor.BLACK;
@ -288,7 +288,7 @@ export class RedBlackTree<
}
this._size++;
return true;
} else return insertStatus === CRUD.UPDATED;
} else return insertStatus === 'UPDATED';
}
/**
@ -435,7 +435,7 @@ export class RedBlackTree<
current = current.right ?? this.SENTINEL;
} else {
this._replaceNode(current, node);
return CRUD.UPDATED;
return 'UPDATED';
}
}
@ -454,7 +454,7 @@ export class RedBlackTree<
node.color = RBTNColor.RED;
this._insertFixup(node);
return CRUD.CREATED;
return 'CREATED';
}
/**

View file

@ -14,7 +14,7 @@ import type {
TreeMultiMapNodeNested,
TreeMultiMapOptions
} from '../../types';
import { IterationType, RBTNColor } from '../../types';
import { RBTNColor } from '../../types';
import { IBinaryTree } from '../../interfaces';
import { RedBlackTree, RedBlackTreeNode } from './rb-tree';
@ -363,7 +363,7 @@ export class TreeMultiMap<
this.clear();
if (iterationType === IterationType.RECURSIVE) {
if (iterationType === 'RECURSIVE') {
const buildBalanceBST = (l: number, r: number) => {
if (l > r) return;
const m = l + Math.floor((r - l) / 2);

View file

@ -1,13 +1,5 @@
export enum BSTVariant {
STANDARD = 'STANDARD',
INVERSE = 'INVERSE'
}
export enum CP {
lt = 'lt',
eq = 'eq',
gt = 'gt'
}
export type BSTVariant = 'STANDARD' | 'INVERSE';
export type CP = 'LT' | 'EQ' | 'GT';
/**
* Enum representing different loop types.
@ -15,20 +7,9 @@ export enum CP {
* - `iterative`: Indicates the iterative loop type (with loops that use iterations).
* - `recursive`: Indicates the recursive loop type (with loops that call themselves).
*/
export enum IterationType {
ITERATIVE = 'ITERATIVE',
RECURSIVE = 'RECURSIVE'
}
export type IterationType = 'ITERATIVE' | 'RECURSIVE';
export enum FamilyPosition {
ROOT = 'ROOT',
LEFT = 'LEFT',
RIGHT = 'RIGHT',
ROOT_LEFT = 'ROOT_LEFT',
ROOT_RIGHT = 'ROOT_RIGHT',
ISOLATED = 'ISOLATED',
MAL_NODE = 'MAL_NODE'
}
export type FamilyPosition = 'ROOT' | 'LEFT' | 'RIGHT' | 'ROOT_LEFT' | 'ROOT_RIGHT' | 'ISOLATED' | 'MAL_NODE';
export type Comparator<K> = (a: K, b: K) => number;
@ -64,9 +45,4 @@ export type BSTNKeyOrNode<K, N> = K | undefined | N;
export type BinaryTreeDeleteResult<N> = { deleted: N | null | undefined; needBalanced: N | null | undefined };
export enum CRUD {
CREATED = 'CREATED',
READ = 'READ',
UPDATED = 'UPDATED',
DELETED = 'DELETED'
}
export type CRUD = 'CREATED' | 'READ' | 'UPDATED' | 'DELETED';

View file

@ -1,4 +1,4 @@
import { AVLTree, CP } from 'data-structure-typed';
import { AVLTree } from 'data-structure-typed';
describe('AVL Tree Test from data-structure-typed', () => {
it('should perform various operations on a AVL Tree from data-structure-typed', () => {
@ -27,7 +27,7 @@ describe('AVL Tree Test from data-structure-typed', () => {
expect(subTreeSum).toBe(70);
let lesserSum = 0;
tree.lesserOrGreaterTraverse(node => (lesserSum += node.key), CP.lt, 10);
tree.lesserOrGreaterTraverse(node => (lesserSum += node.key), 'LT', 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.

View file

@ -40,7 +40,7 @@ describe('AVL Tree Test', () => {
expect(getMinNodeBySpecificNode?.key).toBe(12);
let subTreeSum = 0;
node15 && tree.subTreeTraverse(node => (subTreeSum += node.key), 15);
node15 && tree.dfs(node => (subTreeSum += node.key), 'in', 15);
expect(subTreeSum).toBe(70);
let lesserSum = 0;

View file

@ -34,7 +34,7 @@ describe('Individual package BST operations test', () => {
expect(minNodeBySpecificNode?.key).toBe(12);
let subTreeSum = 0;
node15 && bst.subTreeTraverse(node => (subTreeSum += node.key), 15);
node15 && bst.dfs(node => (subTreeSum += node.key), 'in', 15);
expect(subTreeSum).toBe(70);
let lesserSum = 0;
@ -231,7 +231,7 @@ describe('Individual package BST operations test', () => {
expect(minNodeBySpecificNode?.key).toBe(12);
let subTreeSum = 0;
node15 && objBST.subTreeTraverse(node => (subTreeSum += node.key), node15);
node15 && objBST.dfs(node => (subTreeSum += node.key), 'in', node15);
expect(subTreeSum).toBe(70);
let lesserSum = 0;

View file

@ -12,35 +12,29 @@ const cOrderedMap = new OrderedMap<number, number>();
suite
.add(`${HUNDRED_THOUSAND.toLocaleString()} add orderly`, () => {
rbTree.clear();
for (let i = 0; i < randomArray.length; i++) rbTree.add(i);
})
.add(`${HUNDRED_THOUSAND.toLocaleString()} delete orderly`, () => {
.add(`${HUNDRED_THOUSAND.toLocaleString()} add & delete orderly`, () => {
rbTree.clear();
for (let i = 0; i < randomArray.length; i++) rbTree.add(i);
for (let i = 0; i < randomArray.length; i++) rbTree.delete(i);
})
.add(`${HUNDRED_THOUSAND.toLocaleString()} add randomly`, () => {
rbTree.clear();
for (let i = 0; i < randomArray.length; i++) rbTree.add(randomArray[i]);
})
.add(`${HUNDRED_THOUSAND.toLocaleString()} delete randomly`, () => {
.add(`${HUNDRED_THOUSAND.toLocaleString()} add & delete randomly`, () => {
rbTree.clear();
for (let i = 0; i < randomArray.length; i++) rbTree.add(randomArray[i]);
for (let i = 0; i < randomArray.length; i++) rbTree.delete(randomArray[i]);
})
.add(`${HUNDRED_THOUSAND.toLocaleString()} add orderly`, () => {
for (let i = 0; i < randomArray.length; i++) rbTree.add(i);
})
.add(`${HUNDRED_THOUSAND.toLocaleString()} delete randomly`, () => {
for (let i = 0; i < randomArray.length; i++) rbTree.delete(randomArray[i]);
.add(`${HUNDRED_THOUSAND.toLocaleString()} add & get randomly`, () => {
rbTree.clear();
for (let i = 0; i < randomArray.length; i++) rbTree.add(randomArray[i]);
for (let i = 0; i < randomArray.length; i++) rbTree.get(randomArray[i]);
});
if (isCompetitor) {
suite.add(`CPT ${HUNDRED_THOUSAND.toLocaleString()} add`, () => {
for (let i = 0; i < randomArray.length; i++) cOrderedMap.setElement(randomArray[i], randomArray[i]);
});
}
suite.add(`${HUNDRED_THOUSAND.toLocaleString()} getNode randomly`, () => {
for (let i = 0; i < randomArray.length; i++) rbTree.getNode(randomArray[i]);
});
suite.add(`${HUNDRED_THOUSAND.toLocaleString()} add & iterator`, () => {
rbTree.clear();
for (let i = 0; i < randomArray.length; i++) rbTree.add(randomArray[i]);
@ -48,4 +42,10 @@ suite.add(`${HUNDRED_THOUSAND.toLocaleString()} add & iterator`, () => {
return entries.length === HUNDRED_THOUSAND;
});
if (isCompetitor) {
suite.add(`CPT ${HUNDRED_THOUSAND.toLocaleString()} add`, () => {
for (let i = 0; i < randomArray.length; i++) cOrderedMap.setElement(randomArray[i], randomArray[i]);
});
}
export { suite };

View file

@ -1,12 +1,4 @@
import {
AVLTreeMultiMap,
AVLTreeMultiMapNode,
AVLTreeNode,
BinaryTreeNode,
BSTNode,
CP,
IterationType
} from '../../../../src';
import { AVLTreeMultiMap, AVLTreeMultiMapNode, AVLTreeNode, BinaryTreeNode, BSTNode } from '../../../../src';
import { isDebugTest } from '../../../config';
const isDebug = isDebugTest;
@ -36,7 +28,7 @@ describe('AVLTreeMultiMap count', () => {
[3, 3]
]);
tm.add([2, 2], undefined, 10);
tm.lesserOrGreaterTraverse(node => (node.count += 2), CP.gt, 1);
tm.lesserOrGreaterTraverse(node => (node.count += 2), 'GT', 1);
tm.delete(2);
expect(tm.count).toBe(12);
expect(tm.getMutableCount()).toBe(16);
@ -102,7 +94,7 @@ describe('AVLTreeMultiMap operations test1', () => {
node15 && treeMultimap.dfs(node => (subTreeSum += node.key), 'pre', 15);
expect(subTreeSum).toBe(31);
let lesserSum = 0;
treeMultimap.lesserOrGreaterTraverse((node: AVLTreeMultiMapNode<number>) => (lesserSum += node.key), CP.lt, 10);
treeMultimap.lesserOrGreaterTraverse((node: AVLTreeMultiMapNode<number>) => (lesserSum += node.key), 'LT', 10);
expect(lesserSum).toBe(45);
expect(node15 instanceof AVLTreeMultiMapNode);
@ -113,7 +105,7 @@ describe('AVLTreeMultiMap operations test1', () => {
const node11 = treeMultimap.getNode(11);
expect(node11 instanceof AVLTreeMultiMapNode);
if (node11 instanceof AVLTreeMultiMapNode) {
const allGreaterNodesAdded = treeMultimap.lesserOrGreaterTraverse(node => (node.count += 2), CP.gt, 11);
const allGreaterNodesAdded = treeMultimap.lesserOrGreaterTraverse(node => (node.count += 2), 'GT', 11);
expect(allGreaterNodesAdded);
}
@ -299,7 +291,7 @@ describe('AVLTreeMultiMap operations test1', () => {
describe('AVLTreeMultiMap operations test recursively1', () => {
it('should perform various operations on a Binary Search Tree with numeric values1', () => {
const treeMultimap = new AVLTreeMultiMap<number>([], { iterationType: IterationType.RECURSIVE });
const treeMultimap = new AVLTreeMultiMap<number>([], { iterationType: 'RECURSIVE' });
expect(treeMultimap instanceof AVLTreeMultiMap);
treeMultimap.add([11, 11]);
@ -356,7 +348,7 @@ describe('AVLTreeMultiMap operations test recursively1', () => {
node15 && treeMultimap.dfs(node => (subTreeSum += node.key), 'pre', 15);
expect(subTreeSum).toBe(31);
let lesserSum = 0;
treeMultimap.lesserOrGreaterTraverse((node: AVLTreeMultiMapNode<number>) => (lesserSum += node.key), CP.lt, 10);
treeMultimap.lesserOrGreaterTraverse((node: AVLTreeMultiMapNode<number>) => (lesserSum += node.key), 'LT', 10);
expect(lesserSum).toBe(45);
expect(node15 instanceof AVLTreeMultiMapNode);
@ -367,7 +359,7 @@ describe('AVLTreeMultiMap operations test recursively1', () => {
const node11 = treeMultimap.getNode(11);
expect(node11 instanceof AVLTreeMultiMapNode);
if (node11 instanceof AVLTreeMultiMapNode) {
const allGreaterNodesAdded = treeMultimap.lesserOrGreaterTraverse(node => (node.count += 2), CP.gt, 11);
const allGreaterNodesAdded = treeMultimap.lesserOrGreaterTraverse(node => (node.count += 2), 'GT', 11);
expect(allGreaterNodesAdded);
}
@ -572,7 +564,7 @@ describe('AVLTreeMultiMap Performance test', function () {
}
isDebug && console.log('---add', performance.now() - start);
const startL = performance.now();
treeMS.lesserOrGreaterTraverse(node => (node.count += 1), CP.lt, inputSize / 2);
treeMS.lesserOrGreaterTraverse(node => (node.count += 1), 'LT', inputSize / 2);
isDebug && console.log('---lesserOrGreaterTraverse', performance.now() - startL);
});

View file

@ -1,4 +1,4 @@
import { AVLTree, AVLTreeNode, BinaryTreeNode, BSTNode, CP, IterationType } from '../../../../src';
import { AVLTree, AVLTreeNode, BinaryTreeNode, BSTNode } from '../../../../src';
describe('AVL Tree Test', () => {
it('should perform various operations on a AVL Tree', () => {
@ -28,7 +28,7 @@ describe('AVL Tree Test', () => {
expect(subTreeSum).toBe(70);
let lesserSum = 0;
tree.lesserOrGreaterTraverse(node => (lesserSum += node.key), CP.lt, 10);
tree.lesserOrGreaterTraverse(node => (lesserSum += node.key), 'LT', 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.
@ -112,7 +112,7 @@ describe('AVL Tree Test', () => {
describe('AVL Tree 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: IterationType.RECURSIVE });
const tree = new AVLTree<number>([], { iterationType: 'RECURSIVE' });
for (const i of arr) tree.add([i, i]);
@ -136,7 +136,7 @@ describe('AVL Tree Test recursively', () => {
expect(subTreeSum).toBe(70);
let lesserSum = 0;
tree.lesserOrGreaterTraverse(node => (lesserSum += node.key), CP.lt, 10);
tree.lesserOrGreaterTraverse(node => (lesserSum += node.key), 'LT', 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.

View file

@ -1,4 +1,4 @@
import { BinaryTree, BinaryTreeNode, FamilyPosition, IterationType } from '../../../../src';
import { BinaryTree, BinaryTreeNode } from '../../../../src';
import { getRandomIntArray } from '../../../utils';
// import { isDebugTest } from '../../../config';
@ -81,7 +81,7 @@ describe('BinaryTreeNode', () => {
root.right = rightChild;
expect(rightChild.familyPosition).toBe('RIGHT');
expect(isolated.familyPosition).toBe(FamilyPosition.ISOLATED);
expect(isolated.familyPosition).toBe('ISOLATED');
expect(root.familyPosition).toBe('ROOT');
});
});
@ -104,7 +104,7 @@ describe('BinaryTree', () => {
});
it('should delete nodes', () => {
expect(tree.getHeight(tree.root, IterationType.ITERATIVE)).toBe(-1);
expect(tree.getHeight(tree.root, 'ITERATIVE')).toBe(-1);
expect(tree.getMinHeight()).toBe(-1);
const node1 = tree.createNode(1);
tree.add(node1);
@ -132,7 +132,7 @@ describe('BinaryTree', () => {
const result = tree.delete(node1);
expect(result).toHaveLength(1);
expect(tree.size).toBe(4);
expect(tree.getMinHeight(tree.root, IterationType.RECURSIVE)).toBe(1);
expect(tree.getMinHeight(tree.root, 'RECURSIVE')).toBe(1);
}
});
@ -171,16 +171,25 @@ describe('BinaryTree', () => {
expect(cloned.root?.right?.key).toBe(6);
expect(cloned.root?.right?.left?.key).toBe(3);
expect(cloned.root?.right?.right).toBe(null);
expect(cloned.dfs(node => node.key, 'pre', cloned.getNode(6), IterationType.ITERATIVE)).toEqual([6, 3, 7]);
expect(
cloned.dfs(node => (node ? node.key : null), 'pre', cloned.getNode(6), IterationType.ITERATIVE, true)
).toEqual([6, 3, 7, null]);
expect(
cloned.dfs(node => (node ? node.key : node), 'pre', cloned.getNode(6), IterationType.ITERATIVE, true)
).toEqual([6, 3, 7, null]);
expect(
cloned.dfs(node => (node ? node.key : null), 'pre', cloned.getNode(6), IterationType.RECURSIVE, true)
).toEqual([6, 3, 7, null]);
expect(cloned.dfs(node => node.key, 'pre', cloned.getNode(6), 'ITERATIVE')).toEqual([6, 3, 7]);
expect(cloned.dfs(node => (node ? node.key : null), 'pre', cloned.getNode(6), 'ITERATIVE', true)).toEqual([
6,
3,
7,
null
]);
expect(cloned.dfs(node => (node ? node.key : node), 'pre', cloned.getNode(6), 'ITERATIVE', true)).toEqual([
6,
3,
7,
null
]);
expect(cloned.dfs(node => (node ? node.key : null), 'pre', cloned.getNode(6), 'RECURSIVE', true)).toEqual([
6,
3,
7,
null
]);
cloned.delete(6);
cloned.delete(3);
cloned.delete(7);
@ -234,9 +243,9 @@ describe('BinaryTree', () => {
tree.add(4);
tree.add(2);
expect(tree.getHeight()).toBe(1);
tree.iterationType = IterationType.RECURSIVE;
tree.iterationType = 'RECURSIVE';
expect(tree.getHeight()).toBe(1);
tree.iterationType = IterationType.ITERATIVE;
tree.iterationType = 'ITERATIVE';
tree.add(6);
tree.add(1);
@ -252,9 +261,9 @@ describe('BinaryTree', () => {
it('should getLeftMost', () => {
tree.addMany([4, 2, 6, 1, 3, 5, 7]);
const leftMost = tree.getLeftMost(tree.root, IterationType.RECURSIVE);
const leftMost = tree.getLeftMost(tree.root, 'RECURSIVE');
expect(leftMost?.key).toEqual(1);
const rightMost = tree.getRightMost(tree.root, IterationType.RECURSIVE);
const rightMost = tree.getRightMost(tree.root, 'RECURSIVE');
expect(rightMost?.key).toEqual(7);
});
@ -270,37 +279,37 @@ describe('BinaryTree', () => {
new BinaryTreeNode(4, 4)
]);
expect(tree.isBST(tree.getNode(4), IterationType.RECURSIVE)).toBe(true);
expect(tree.isBST(tree.getNode(4), IterationType.ITERATIVE)).toBe(true);
expect(tree.isBST(tree.getNode(4), 'RECURSIVE')).toBe(true);
expect(tree.isBST(tree.getNode(4), 'ITERATIVE')).toBe(true);
});
it('should isSubtreeBST', () => {
tree.addMany([4, 2, 6, 1, 3, 5, 7, 4]);
expect(tree.isBST(tree.getNode(4), IterationType.RECURSIVE)).toBe(true);
expect(tree.isBST(tree.getNode(4), IterationType.ITERATIVE)).toBe(true);
expect(tree.isBST(tree.getNode(4), 'RECURSIVE')).toBe(true);
expect(tree.isBST(tree.getNode(4), 'ITERATIVE')).toBe(true);
expect(tree.getNodes(2, undefined, false, null)).toEqual([]);
expect(tree.getNodes(tree.getNodeByKey(2), undefined, false, tree.root)).toEqual([tree.getNodeByKey(2)]);
});
it('should sub tree traverse', () => {
tree.addMany([4, 2, 6, null, 1, 3, null, 5, null, 7]);
expect(tree.dfs(node => node.key, 'pre', tree.getNode(6), IterationType.ITERATIVE)).toEqual([6, 3, 7]);
expect(tree.dfs(node => node.key, 'pre', tree.getNode(6), IterationType.ITERATIVE, false)).toEqual([6, 3, 7]);
expect(tree.dfs(node => node.key, 'pre', tree.getNode(6), IterationType.RECURSIVE)).toEqual([6, 3, 7]);
expect(tree.dfs(node => (node ? node.key : null), 'pre', tree.getNode(6), IterationType.ITERATIVE, true)).toEqual([
expect(tree.dfs(node => node.key, 'pre', tree.getNode(6), 'ITERATIVE')).toEqual([6, 3, 7]);
expect(tree.dfs(node => node.key, 'pre', tree.getNode(6), 'ITERATIVE', false)).toEqual([6, 3, 7]);
expect(tree.dfs(node => node.key, 'pre', tree.getNode(6), 'RECURSIVE')).toEqual([6, 3, 7]);
expect(tree.dfs(node => (node ? node.key : null), 'pre', tree.getNode(6), 'ITERATIVE', true)).toEqual([
6,
3,
7,
null
]);
expect(tree.dfs(node => (node ? node.key : node), 'pre', tree.getNode(6), IterationType.ITERATIVE, true)).toEqual([
expect(tree.dfs(node => (node ? node.key : node), 'pre', tree.getNode(6), 'ITERATIVE', true)).toEqual([
6,
3,
7,
null
]);
expect(tree.dfs(node => (node ? node.key : null), 'pre', tree.getNode(6), IterationType.RECURSIVE, true)).toEqual([
expect(tree.dfs(node => (node ? node.key : null), 'pre', tree.getNode(6), 'RECURSIVE', true)).toEqual([
6,
3,
7,
@ -360,7 +369,7 @@ describe('BinaryTree Morris Traversal', () => {
expect(result).toEqual(expected);
expect(tree.dfs(node => node.key, 'in')).toEqual(expected);
expect(tree.dfs(node => node.key, 'in', tree.root, IterationType.RECURSIVE)).toEqual(expected);
expect(tree.dfs(node => node.key, 'in', tree.root, 'RECURSIVE')).toEqual(expected);
});
it('should perform pre-order Morris traversal correctly as dfs traversal', () => {
@ -399,57 +408,101 @@ describe('BinaryTree traversals', () => {
const arr = [35, 20, 40, 15, 29, null, 50, null, 16, 28, 30, 45, 55];
tree.refill(arr);
expect(
tree.bfs(node => node, tree.root, IterationType.ITERATIVE, true).map(node => (node ? node.key : null))
).toEqual([35, 20, 40, 15, 29, null, 50, null, 16, 28, 30, 45, 55]);
expect(
tree.bfs(node => node, tree.root, IterationType.RECURSIVE, true).map(node => (node ? node.key : null))
).toEqual([35, 20, 40, 15, 29, null, 50, null, 16, 28, 30, 45, 55]);
expect(
tree.bfs(node => node, tree.root, IterationType.ITERATIVE).map(node => (node === null ? null : node.key))
).toEqual([35, 20, 40, 15, 29, 50, 16, 28, 30, 45, 55]);
expect(
tree.bfs(node => node, tree.root, IterationType.RECURSIVE).map(node => (node === null ? null : node.key))
).toEqual([35, 20, 40, 15, 29, 50, 16, 28, 30, 45, 55]);
expect(tree.bfs(node => node, tree.root, 'ITERATIVE', true).map(node => (node ? node.key : null))).toEqual([
35,
20,
40,
15,
29,
null,
50,
null,
16,
28,
30,
45,
55
]);
expect(tree.bfs(node => node, tree.root, 'RECURSIVE', true).map(node => (node ? node.key : null))).toEqual([
35,
20,
40,
15,
29,
null,
50,
null,
16,
28,
30,
45,
55
]);
expect(tree.bfs(node => node, tree.root, 'ITERATIVE').map(node => (node === null ? null : node.key))).toEqual([
35, 20, 40, 15, 29, 50, 16, 28, 30, 45, 55
]);
expect(tree.bfs(node => node, tree.root, 'RECURSIVE').map(node => (node === null ? null : node.key))).toEqual([
35, 20, 40, 15, 29, 50, 16, 28, 30, 45, 55
]);
expect(tree.dfs(node => node.key, 'pre')).toEqual([35, 20, 15, 16, 29, 28, 30, 40, 50, 45, 55]);
expect(tree.dfs(node => node.key, 'pre', tree.root, IterationType.RECURSIVE)).toEqual([
expect(tree.dfs(node => node.key, 'pre', tree.root, 'RECURSIVE')).toEqual([
35, 20, 15, 16, 29, 28, 30, 40, 50, 45, 55
]);
expect(
tree.dfs(node => node, 'pre', tree.root, IterationType.ITERATIVE, true).map(node => (node ? node.key : null))
).toEqual([35, 20, 15, null, 16, 29, 28, 30, 40, null, 50, 45, 55]);
expect(
tree.dfs(node => node, 'pre', tree.root, IterationType.RECURSIVE, true).map(node => (node ? node.key : null))
).toEqual([35, 20, 15, null, 16, 29, 28, 30, 40, null, 50, 45, 55]);
expect(tree.dfs(node => node, 'pre', tree.root, 'ITERATIVE', true).map(node => (node ? node.key : null))).toEqual([
35,
20,
15,
null,
16,
29,
28,
30,
40,
null,
50,
45,
55
]);
expect(tree.dfs(node => node, 'pre', tree.root, 'RECURSIVE', true).map(node => (node ? node.key : null))).toEqual([
35,
20,
15,
null,
16,
29,
28,
30,
40,
null,
50,
45,
55
]);
expect(tree.dfs(node => node.key, 'in')).toEqual([15, 16, 20, 28, 29, 30, 35, 40, 45, 50, 55]);
expect(tree.dfs(node => node.key, 'post')).toEqual([16, 15, 28, 30, 29, 20, 45, 55, 50, 40, 35]);
expect(tree.dfs(node => node.key, 'post', tree.root, IterationType.RECURSIVE)).toEqual([
expect(tree.dfs(node => node.key, 'post', tree.root, 'RECURSIVE')).toEqual([
16, 15, 28, 30, 29, 20, 45, 55, 50, 40, 35
]);
expect(tree.bfs(node => node.key, tree.root, IterationType.RECURSIVE)).toEqual([
35, 20, 40, 15, 29, 50, 16, 28, 30, 45, 55
]);
expect(tree.bfs(node => node.key, tree.root, IterationType.ITERATIVE)).toEqual([
35, 20, 40, 15, 29, 50, 16, 28, 30, 45, 55
]);
expect(tree.bfs(node => node.key, tree.root, 'RECURSIVE')).toEqual([35, 20, 40, 15, 29, 50, 16, 28, 30, 45, 55]);
expect(tree.bfs(node => node.key, tree.root, 'ITERATIVE')).toEqual([35, 20, 40, 15, 29, 50, 16, 28, 30, 45, 55]);
expect(tree.listLevels(node => node.key)).toEqual([[35], [20, 40], [15, 29, 50], [16, 28, 30, 45, 55]]);
expect(tree.listLevels(node => node.key, tree.root, IterationType.RECURSIVE)).toEqual([
expect(tree.listLevels(node => node.key, tree.root, 'RECURSIVE')).toEqual([
[35],
[20, 40],
[15, 29, 50],
[16, 28, 30, 45, 55]
]);
expect(tree.listLevels(node => (node ? node.key : null), tree.root, IterationType.ITERATIVE, true)).toEqual([
expect(tree.listLevels(node => (node ? node.key : null), tree.root, 'ITERATIVE', true)).toEqual([
[35],
[20, 40],
[15, 29, null, 50],
[null, 16, 28, 30, 45, 55]
]);
expect(tree.listLevels(node => (node ? node.key : null), tree.root, IterationType.RECURSIVE, true)).toEqual([
expect(tree.listLevels(node => (node ? node.key : null), tree.root, 'RECURSIVE', true)).toEqual([
[35],
[20, 40],
[15, 29, null, 50],
@ -461,7 +514,7 @@ describe('BinaryTree', () => {
let tree: BinaryTree<number, string>;
beforeEach(() => {
tree = new BinaryTree<number, string>([], { iterationType: IterationType.RECURSIVE });
tree = new BinaryTree<number, string>([], { iterationType: 'RECURSIVE' });
});
afterEach(() => {
@ -533,8 +586,8 @@ describe('BinaryTree', () => {
tree.add([7, 'C']);
expect(tree.getHeight()).toBe(1);
expect(tree.getHeight(undefined, IterationType.RECURSIVE)).toBe(1);
expect(tree.getMinHeight(undefined, IterationType.RECURSIVE)).toBe(1);
expect(tree.getHeight(undefined, 'RECURSIVE')).toBe(1);
expect(tree.getMinHeight(undefined, 'RECURSIVE')).toBe(1);
});
it('should check if the tree is a binary search tree', () => {
@ -604,7 +657,7 @@ describe('BinaryTree', () => {
expect(nodes.length).toBe(1);
expect(nodes[0].key).toBe(3);
const nodesRec = tree.getNodes('B', node => node.value, false, tree.root, IterationType.RECURSIVE);
const nodesRec = tree.getNodes('B', node => node.value, false, tree.root, 'RECURSIVE');
expect(nodesRec.length).toBe(1);
expect(nodesRec[0].key).toBe(3);
@ -615,19 +668,19 @@ describe('BinaryTree', () => {
tree.add([3, 'B']);
tree.add([7, 'C']);
tree.iterationType = IterationType.ITERATIVE;
tree.iterationType = 'ITERATIVE';
expect([...tree]).toEqual([
[3, 'B'],
[5, 'A'],
[7, 'C']
]);
tree.iterationType = IterationType.RECURSIVE;
tree.iterationType = 'RECURSIVE';
expect([...tree]).toEqual([
[3, 'B'],
[5, 'A'],
[7, 'C']
]);
tree.iterationType = IterationType.ITERATIVE;
tree.iterationType = 'ITERATIVE';
const result = tree.morris();
expect(result).toEqual([3, 5, 7]);

View file

@ -1,4 +1,4 @@
import { BinaryTreeNode, BST, BSTNode, BSTVariant, CP, IterationType } from '../../../../src';
import { BinaryTreeNode, BST, BSTNode } from '../../../../src';
import { isDebugTest } from '../../../config';
const isDebug = isDebugTest;
@ -58,7 +58,7 @@ describe('BST operations test', () => {
expect(subTreeSum).toBe(70);
let lesserSum = 0;
bst.lesserOrGreaterTraverse(node => (lesserSum += node.key), CP.lt, 10);
bst.lesserOrGreaterTraverse(node => (lesserSum += node.key), 'LT', 10);
expect(lesserSum).toBe(45);
expect(node15).toBeInstanceOf(BSTNode);
@ -261,7 +261,7 @@ describe('BST operations test', () => {
expect(subTreeSum).toBe(70);
let lesserSum = 0;
objBST.lesserOrGreaterTraverse(node => (lesserSum += node.key), CP.lt, 10);
objBST.lesserOrGreaterTraverse(node => (lesserSum += node.key), 'LT', 10);
expect(lesserSum).toBe(45);
expect(node15).toBeInstanceOf(BSTNode);
@ -411,7 +411,7 @@ describe('BST operations test', () => {
describe('BST operations test recursively', () => {
it('should perform various operations on a Binary Search Tree with numeric values', () => {
const bst = new BST<number>([], { iterationType: IterationType.RECURSIVE });
const bst = new BST<number>([], { iterationType: 'RECURSIVE' });
expect(bst).toBeInstanceOf(BST);
bst.add([11, 11]);
bst.add([3, 3]);
@ -448,7 +448,7 @@ describe('BST operations test recursively', () => {
expect(subTreeSum).toBe(70);
let lesserSum = 0;
bst.lesserOrGreaterTraverse(node => (lesserSum += node.key), CP.lt, 10);
bst.lesserOrGreaterTraverse(node => (lesserSum += node.key), 'LT', 10);
expect(lesserSum).toBe(45);
expect(node15).toBeInstanceOf(BSTNode);
@ -649,7 +649,7 @@ describe('BST operations test recursively', () => {
expect(subTreeSum).toBe(70);
let lesserSum = 0;
objBST.lesserOrGreaterTraverse(node => (lesserSum += node.key), CP.lt, 10);
objBST.lesserOrGreaterTraverse(node => (lesserSum += node.key), 'LT', 10);
expect(lesserSum).toBe(45);
expect(node15).toBeInstanceOf(BSTNode);
@ -869,7 +869,7 @@ describe('BST isBST', function () {
});
test('isBST when variant is Max', () => {
const bst = new BST<number, number>([1, 2, 3, 9, 8, 5, 6, 7, 4], { variant: BSTVariant.INVERSE });
const bst = new BST<number, number>([1, 2, 3, 9, 8, 5, 6, 7, 4], { variant: 'INVERSE' });
bst.addMany([1, 2, 3, 9, 8, 5, 6, 7, 4]);
expect(bst.isBST()).toBe(true);
});
@ -902,7 +902,7 @@ describe('BST Performance test', function () {
node => {
node.key - 1;
},
CP.lt,
'LT',
inputSize / 2
);
isDebug && console.log('---lesserOrGreaterTraverse', performance.now() - startL);
@ -932,10 +932,10 @@ describe('BST Performance test', function () {
it('should dfs as sub tree traversal, null should be ignored', () => {
const bst = new BST();
bst.addMany([4, 2, 6, 1, 3, 5, 7]);
expect(bst.dfs(node => node.key, 'pre', bst.getNode(6), IterationType.ITERATIVE)).toEqual([6, 5, 7]);
expect(bst.dfs(node => node.key, 'pre', bst.getNode(6), IterationType.RECURSIVE)).toEqual([6, 5, 7]);
expect(bst.dfs(node => node?.key ?? undefined, 'pre', bst.getNode(6), IterationType.ITERATIVE)).toEqual([6, 5, 7]);
expect(bst.dfs(node => node?.key ?? undefined, 'pre', bst.getNode(6), IterationType.RECURSIVE)).toEqual([6, 5, 7]);
expect(bst.dfs(node => node.key, 'pre', bst.getNode(6), 'ITERATIVE')).toEqual([6, 5, 7]);
expect(bst.dfs(node => node.key, 'pre', bst.getNode(6), 'RECURSIVE')).toEqual([6, 5, 7]);
expect(bst.dfs(node => node?.key ?? undefined, 'pre', bst.getNode(6), 'ITERATIVE')).toEqual([6, 5, 7]);
expect(bst.dfs(node => node?.key ?? undefined, 'pre', bst.getNode(6), 'RECURSIVE')).toEqual([6, 5, 7]);
});
});

View file

@ -1,4 +1,4 @@
import { AVLTree, BST, BSTVariant, IterationType, RedBlackTree, TreeMultiMap } from '../../../../src';
import { AVLTree, BST, RedBlackTree, TreeMultiMap } from '../../../../src';
describe('Overall BinaryTree Test', () => {
it('should perform various operations on BinaryTree', () => {
@ -63,8 +63,8 @@ describe('Overall BinaryTree Test', () => {
it('Should clone a BST works fine', () => {
const bst = new BST<number>([3, 6, 7, 1, 9], {
iterationType: IterationType.RECURSIVE,
variant: BSTVariant.INVERSE,
iterationType: 'RECURSIVE',
variant: 'INVERSE',
extractor: key => key
});
expect(bst.size).toBe(5);
@ -104,8 +104,8 @@ describe('Overall BinaryTree Test', () => {
it('Should clone a AVLTree works fine', () => {
const avl = new AVLTree<number>([3, 6, 7, 1, 9], {
iterationType: IterationType.RECURSIVE,
variant: BSTVariant.INVERSE,
iterationType: 'RECURSIVE',
variant: 'INVERSE',
extractor: key => key
});
expect(avl.size).toBe(5);
@ -148,7 +148,7 @@ describe('Overall BinaryTree Test', () => {
it('Should clone a TreeMultiMap works fine', () => {
const tmm = new TreeMultiMap<number>([3, 6, 7, 1, 9], {
iterationType: IterationType.RECURSIVE,
iterationType: 'RECURSIVE',
extractor: key => key
});
expect(tmm.size).toBe(5);
@ -197,7 +197,7 @@ describe('Overall BinaryTree Test', () => {
it('Should clone a RedBlackTree works fine', () => {
const rbTree = new RedBlackTree<number>([3, 6, 7, 1, 9], {
iterationType: IterationType.RECURSIVE,
iterationType: 'RECURSIVE',
extractor: key => key
});
expect(rbTree.size).toBe(5);

View file

@ -1,4 +1,4 @@
import { BinaryTreeNode, BSTNode, IterationType, RBTNColor, RedBlackTree, RedBlackTreeNode } from '../../../../src';
import { BinaryTreeNode, BSTNode, RBTNColor, RedBlackTree, RedBlackTreeNode } from '../../../../src';
import { getRandomInt, getRandomIntArray, magnitude } from '../../../utils';
import { OrderedMap } from 'js-sdsl';
@ -53,6 +53,11 @@ describe('RedBlackTree 1', () => {
expect(rbTree.getNode(15)).toBe(undefined);
});
it('should getNode performance O(log n)', () => {
for (let i = 0; i < 10; i++) rbTree.add(i);
rbTree.getNode(6);
});
});
describe('minimum', () => {
@ -477,13 +482,13 @@ describe('RedBlackTree 2', () => {
expect(rbTree.size).toBe(51);
expect(rbTree.isBST()).toBe(true);
expect(rbTree.isBST(rbTree.root, IterationType.RECURSIVE)).toBe(true);
expect(rbTree.isBST(rbTree.root, 'RECURSIVE')).toBe(true);
expect(rbTree.dfs(n => n.key, 'in', rbTree.root, IterationType.ITERATIVE)).toEqual([
expect(rbTree.dfs(n => n.key, 'in', rbTree.root, 'ITERATIVE')).toEqual([
49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99
]);
expect(rbTree.dfs(n => n.key, 'in', rbTree.root, IterationType.RECURSIVE)).toEqual([
expect(rbTree.dfs(n => n.key, 'in', rbTree.root, 'RECURSIVE')).toEqual([
49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99
]);
@ -499,7 +504,7 @@ describe('RedBlackTree 2', () => {
expect(rbTree.size).toBe(0);
expect(rbTree.isBST()).toBe(true);
expect(rbTree.dfs(n => n.key, 'in', rbTree.root, IterationType.ITERATIVE)).toEqual([]);
expect(rbTree.dfs(n => n.key, 'in', rbTree.root, 'ITERATIVE')).toEqual([]);
rbTree.clear();
for (let i = 0; i < 1000; i++) {

View file

@ -1,12 +1,4 @@
import {
BinaryTreeNode,
BSTNode,
CP,
IterationType,
RedBlackTreeNode,
TreeMultiMap,
TreeMultiMapNode
} from '../../../../src';
import { BinaryTreeNode, BSTNode, RedBlackTreeNode, TreeMultiMap, TreeMultiMapNode } from '../../../../src';
import { isDebugTest } from '../../../config';
import { getRandomInt } from '../../../utils';
@ -40,7 +32,7 @@ describe('TreeMultiMap count', () => {
[2, 2],
[3, 3]
]);
tmm.lesserOrGreaterTraverse(node => (node.count += 2), CP.gt, 1);
tmm.lesserOrGreaterTraverse(node => (node.count += 2), 'GT', 1);
expect(tmm.getMutableCount()).toBe(7);
expect(tmm.count).toBe(3);
});
@ -159,7 +151,7 @@ describe('TreeMultiMap operations test1', () => {
node15 && tmm.dfs(node => (subTreeSum += node.key), 'pre', 15);
expect(subTreeSum).toBe(45);
let lesserSum = 0;
tmm.lesserOrGreaterTraverse((node: TreeMultiMapNode<number>) => (lesserSum += node.key), CP.lt, 10);
tmm.lesserOrGreaterTraverse((node: TreeMultiMapNode<number>) => (lesserSum += node.key), 'LT', 10);
expect(lesserSum).toBe(45);
expect(node15 instanceof TreeMultiMapNode);
@ -170,7 +162,7 @@ describe('TreeMultiMap operations test1', () => {
const node11 = tmm.getNode(11);
expect(node11 instanceof TreeMultiMapNode);
if (node11 instanceof TreeMultiMapNode) {
const allGreaterNodesAdded = tmm.lesserOrGreaterTraverse(node => (node.count += 2), CP.gt, 11);
const allGreaterNodesAdded = tmm.lesserOrGreaterTraverse(node => (node.count += 2), 'GT', 11);
expect(allGreaterNodesAdded);
}
@ -357,7 +349,7 @@ describe('TreeMultiMap operations test1', () => {
describe('TreeMultiMap operations test recursively1', () => {
it('should perform various operations on a Binary Search Tree with numeric values1', () => {
const tmm = new TreeMultiMap<number>([], { iterationType: IterationType.RECURSIVE });
const tmm = new TreeMultiMap<number>([], { iterationType: 'RECURSIVE' });
expect(tmm instanceof TreeMultiMap);
tmm.add([11, 11]);
@ -421,7 +413,7 @@ describe('TreeMultiMap operations test recursively1', () => {
lesserSum += node.key;
return node.key;
},
CP.lt,
'LT',
10
);
expect(lesserSum).toBe(45);
@ -434,7 +426,7 @@ describe('TreeMultiMap operations test recursively1', () => {
const node11 = tmm.getNode(11);
expect(node11 instanceof TreeMultiMapNode);
if (node11 instanceof TreeMultiMapNode) {
const allGreaterNodesAdded = tmm.lesserOrGreaterTraverse(node => (node.count += 2), CP.gt, 11);
const allGreaterNodesAdded = tmm.lesserOrGreaterTraverse(node => (node.count += 2), 'GT', 11);
expect(allGreaterNodesAdded);
}