mirror of
https://github.com/zrwusa/data-structure-typed.git
synced 2024-11-23 04:44:04 +00:00
feat: The binary trees support storing values in a Map and provides parameters for Map mode. #111. Rename type definitions and parameter names to align with best practices.
This commit is contained in:
parent
8ae577315a
commit
28ff30ea4b
26
README.md
26
README.md
|
@ -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.66</td><td>150.18</td><td>2.19e-4</td></tr><tr><td>100,000 add & poll</td><td>35.35</td><td>28.29</td><td>8.55e-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.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><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>83.70</td><td>11.95</td><td>4.47e-4</td></tr><tr><td>100,000 add randomly</td><td>85.05</td><td>11.76</td><td>0.00</td></tr><tr><td>100,000 get</td><td>112.86</td><td>8.86</td><td>0.00</td></tr><tr><td>100,000 iterator</td><td>23.62</td><td>42.34</td><td>0.00</td></tr><tr><td>100,000 add & delete orderly</td><td>153.38</td><td>6.52</td><td>0.01</td></tr><tr><td>100,000 add & delete randomly</td><td>232.75</td><td>4.30</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>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><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>46.18</td><td>21.65</td><td>0.01</td></tr><tr><td>100,000 push & shift</td><td>5.40</td><td>185.33</td><td>0.00</td></tr><tr><td>Native JS Array 100,000 push & shift</td><td>2273.18</td><td>0.44</td><td>0.20</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>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><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.33</td><td>49.20</td><td>0.00</td></tr><tr><td>1,000,000 push & pop</td><td>26.35</td><td>37.95</td><td>0.00</td></tr><tr><td>1,000,000 push & shift</td><td>28.83</td><td>34.68</td><td>0.00</td></tr><tr><td>100,000 push & shift</td><td>2.55</td><td>392.71</td><td>3.48e-4</td></tr><tr><td>Native JS Array 100,000 push & shift</td><td>2285.23</td><td>0.44</td><td>0.25</td></tr><tr><td>100,000 unshift & shift</td><td>2.53</td><td>395.88</td><td>4.03e-4</td></tr><tr><td>Native JS Array 100,000 unshift & shift</td><td>4063.57</td><td>0.25</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>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><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>210.30</td><td>4.76</td><td>0.03</td></tr><tr><td>Native JS Map 1,000,000 set</td><td>217.28</td><td>4.60</td><td>0.03</td></tr><tr><td>Native JS Set 1,000,000 add</td><td>175.11</td><td>5.71</td><td>0.02</td></tr><tr><td>1,000,000 set & get</td><td>231.89</td><td>4.31</td><td>0.05</td></tr><tr><td>Native JS Map 1,000,000 set & get</td><td>278.86</td><td>3.59</td><td>0.03</td></tr><tr><td>Native JS Set 1,000,000 add & has</td><td>237.24</td><td>4.22</td><td>0.01</td></tr><tr><td>1,000,000 ObjKey set & get</td><td>387.96</td><td>2.58</td><td>0.07</td></tr><tr><td>Native JS Map 1,000,000 ObjKey set & get</td><td>348.73</td><td>2.87</td><td>0.07</td></tr><tr><td>Native JS Set 1,000,000 ObjKey add & has</td><td>295.33</td><td>3.39</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>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><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.24</td><td>23.13</td><td>6.15e-4</td></tr><tr><td>100,000 getWords</td><td>105.06</td><td>9.52</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 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><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>309.91</td><td>3.23</td><td>0.01</td></tr><tr><td>100,000 add randomly</td><td>368.42</td><td>2.71</td><td>0.00</td></tr><tr><td>100,000 get</td><td>171.25</td><td>5.84</td><td>0.00</td></tr><tr><td>100,000 iterator</td><td>26.14</td><td>38.25</td><td>0.00</td></tr><tr><td>100,000 add & delete orderly</td><td>511.40</td><td>1.96</td><td>0.00</td></tr><tr><td>100,000 add & delete randomly</td><td>687.43</td><td>1.45</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>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><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.30</td><td>136.94</td><td>9.11e-5</td></tr><tr><td>10,000 RBTree get randomly</td><td>12.92</td><td>77.41</td><td>1.62e-4</td></tr><tr><td>10,000 RBTree add & delete randomly</td><td>22.42</td><td>44.60</td><td>3.28e-4</td></tr><tr><td>10,000 AVLTree add randomly</td><td>28.34</td><td>35.29</td><td>3.30e-4</td></tr><tr><td>10,000 AVLTree get randomly</td><td>12.94</td><td>77.27</td><td>8.60e-5</td></tr><tr><td>10,000 AVLTree add & delete randomly</td><td>52.35</td><td>19.10</td><td>5.13e-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.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><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.09</td><td>1.07e+4</td><td>8.73e-7</td></tr><tr><td>1,000 addEdge</td><td>5.98</td><td>167.36</td><td>1.15e-4</td></tr><tr><td>1,000 getVertex</td><td>0.09</td><td>1.05e+4</td><td>8.10e-7</td></tr><tr><td>1,000 getEdge</td><td>23.42</td><td>42.69</td><td>0.00</td></tr><tr><td>tarjan</td><td>210.66</td><td>4.75</td><td>0.04</td></tr><tr><td>topologicalSort</td><td>152.36</td><td>6.56</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 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><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>196.74</td><td>5.08</td><td>0.04</td></tr><tr><td>1,000,000 unshift</td><td>172.87</td><td>5.78</td><td>0.01</td></tr><tr><td>1,000,000 unshift & shift</td><td>151.32</td><td>6.61</td><td>0.01</td></tr><tr><td>1,000,000 addBefore</td><td>262.75</td><td>3.81</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>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><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>164.52</td><td>6.08</td><td>0.03</td></tr><tr><td>10,000 push & pop</td><td>234.45</td><td>4.27</td><td>0.01</td></tr><tr><td>10,000 addBefore</td><td>275.79</td><td>3.63</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 & 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><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.74</td><td>32.53</td><td>0.00</td></tr><tr><td>100,000 add & poll</td><td>88.16</td><td>11.34</td><td>4.14e-4</td></tr></table></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 add</td><td>30.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><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.80</td><td>23.37</td><td>0.01</td></tr><tr><td>1,000,000 push & pop</td><td>48.13</td><td>20.78</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</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>
|
||||
|
||||
[//]: # (No deletion!!! End of Replace Section)
|
||||
|
|
48
package-lock.json
generated
48
package-lock.json
generated
|
@ -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.8",
|
||||
"avl-tree-typed": "^1.52.9",
|
||||
"benchmark": "^2.1.4",
|
||||
"binary-tree-typed": "^1.52.8",
|
||||
"bst-typed": "^1.52.8",
|
||||
"data-structure-typed": "^1.52.8",
|
||||
"binary-tree-typed": "^1.52.9",
|
||||
"bst-typed": "^1.52.9",
|
||||
"data-structure-typed": "^1.52.9",
|
||||
"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.8",
|
||||
"heap-typed": "^1.52.9",
|
||||
"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.8",
|
||||
"resolved": "https://registry.npmjs.org/avl-tree-typed/-/avl-tree-typed-1.52.8.tgz",
|
||||
"integrity": "sha512-8oU+KjIVtzF9U12NudYuQNBX/If1DL1bKrbqLtKk5RjEq1Jsl56/GIvuzbvKHnGgv9h7DpXHyJUCLjAz3zjhbg==",
|
||||
"version": "1.52.9",
|
||||
"resolved": "https://registry.npmjs.org/avl-tree-typed/-/avl-tree-typed-1.52.9.tgz",
|
||||
"integrity": "sha512-TfapTNrlIquhf1iwrzhc5pEejEhE0CogxiNlaI0nqkv2Qz2OkhvfmAtJOG5ndiFBp4btNZYFGHb+S/zXkEX82A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"data-structure-typed": "^1.52.8"
|
||||
"data-structure-typed": "^1.52.9"
|
||||
}
|
||||
},
|
||||
"node_modules/babel-jest": {
|
||||
|
@ -3602,13 +3602,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/binary-tree-typed": {
|
||||
"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==",
|
||||
"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==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"data-structure-typed": "^1.52.8"
|
||||
"data-structure-typed": "^1.52.9"
|
||||
}
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
|
@ -3691,13 +3691,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/bst-typed": {
|
||||
"version": "1.52.8",
|
||||
"resolved": "https://registry.npmjs.org/bst-typed/-/bst-typed-1.52.8.tgz",
|
||||
"integrity": "sha512-YMRUaz8jNxSymvKNNyeJR8HozHRgDWUw8PO0QLSvaW/c4Ed/KhpDSyBth52NClFnbJnNV2lTsd01k/VwuerimA==",
|
||||
"version": "1.52.9",
|
||||
"resolved": "https://registry.npmjs.org/bst-typed/-/bst-typed-1.52.9.tgz",
|
||||
"integrity": "sha512-7jgOhrYST+HBZRGvmKx3UZRt6ddBr9Ib807gfJ9+jRVuXQIK9m3hW1MSwXMovWs8tKpF0JZMCqj+uk+S8B85qg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"data-structure-typed": "^1.52.8"
|
||||
"data-structure-typed": "^1.52.9"
|
||||
}
|
||||
},
|
||||
"node_modules/buffer-from": {
|
||||
|
@ -4069,9 +4069,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/data-structure-typed": {
|
||||
"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==",
|
||||
"version": "1.52.9",
|
||||
"resolved": "https://registry.npmjs.org/data-structure-typed/-/data-structure-typed-1.52.9.tgz",
|
||||
"integrity": "sha512-tIAf4CqOdDz5XJZBtTjWwhOgLOwiMS+1kH9dN44x12klBcKavpUDUjncvrcAqLsVP5xTZSeehJ5teNa6YNgWQQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
|
@ -5946,13 +5946,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/heap-typed": {
|
||||
"version": "1.52.8",
|
||||
"resolved": "https://registry.npmjs.org/heap-typed/-/heap-typed-1.52.8.tgz",
|
||||
"integrity": "sha512-Zzq+V9IQMf8o2FrIeqc0kRxRyDxOyUPX5dXRi095LnpOFRzUXZoSl2hggbHfsjKEaKwLDRoJuS9t77alqmK4NQ==",
|
||||
"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==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"data-structure-typed": "^1.52.8"
|
||||
"data-structure-typed": "^1.52.9"
|
||||
}
|
||||
},
|
||||
"node_modules/html-escaper": {
|
||||
|
|
10
package.json
10
package.json
|
@ -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.8",
|
||||
"avl-tree-typed": "^1.52.9",
|
||||
"benchmark": "^2.1.4",
|
||||
"binary-tree-typed": "^1.52.8",
|
||||
"bst-typed": "^1.52.8",
|
||||
"data-structure-typed": "^1.52.8",
|
||||
"binary-tree-typed": "^1.52.9",
|
||||
"bst-typed": "^1.52.9",
|
||||
"data-structure-typed": "^1.52.9",
|
||||
"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.8",
|
||||
"heap-typed": "^1.52.9",
|
||||
"istanbul-badges-readme": "^1.9.0",
|
||||
"jest": "^29.7.0",
|
||||
"js-sdsl": "^4.4.2",
|
||||
|
|
|
@ -10,10 +10,9 @@ import type {
|
|||
AVLTreeMultiMapNodeNested,
|
||||
AVLTreeMultiMapOptions,
|
||||
BinaryTreeDeleteResult,
|
||||
BSTNKeyOrNode,
|
||||
BTNKeyOrNodeOrEntry,
|
||||
IterationType,
|
||||
BTNEntry
|
||||
BSTNOptKeyOrNode,
|
||||
BTNRep,
|
||||
IterationType
|
||||
} from '../../types';
|
||||
import { IBinaryTree } from '../../interfaces';
|
||||
import { AVLTree, AVLTreeNode } from './avl-tree';
|
||||
|
@ -64,7 +63,7 @@ export class AVLTreeMultiMapNode<
|
|||
export class AVLTreeMultiMap<
|
||||
K = any,
|
||||
V = any,
|
||||
R = BTNEntry<K, V>,
|
||||
R = object,
|
||||
NODE extends AVLTreeMultiMapNode<K, V, NODE> = AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNodeNested<K, V>>,
|
||||
TREE extends AVLTreeMultiMap<K, V, R, NODE, TREE> = AVLTreeMultiMap<
|
||||
K,
|
||||
|
@ -79,18 +78,18 @@ export class AVLTreeMultiMap<
|
|||
{
|
||||
/**
|
||||
* The constructor initializes a new AVLTreeMultiMap object with optional initial elements.
|
||||
* @param keysOrNodesOrEntriesOrRaws - The `keysOrNodesOrEntriesOrRaws` parameter is an
|
||||
* @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` 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(
|
||||
keysOrNodesOrEntriesOrRaws: Iterable<R | BTNKeyOrNodeOrEntry<K, V, NODE>> = [],
|
||||
keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V, NODE>> = [],
|
||||
options?: AVLTreeMultiMapOptions<K, V, R>
|
||||
) {
|
||||
super([], options);
|
||||
if (keysOrNodesOrEntriesOrRaws) this.addMany(keysOrNodesOrEntriesOrRaws);
|
||||
if (keysNodesEntriesOrRaws) this.addMany(keysNodesEntriesOrRaws);
|
||||
}
|
||||
|
||||
protected _count = 0;
|
||||
|
@ -143,6 +142,7 @@ 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 +151,20 @@ export class AVLTreeMultiMap<
|
|||
|
||||
/**
|
||||
* The function checks if the input is an instance of AVLTreeMultiMapNode.
|
||||
* @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
|
||||
* @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
|
||||
* an instance of the `AVLTreeMultiMapNode` class.
|
||||
*/
|
||||
override isNode(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R): keyOrNodeOrEntryOrRaw is NODE {
|
||||
return keyOrNodeOrEntryOrRaw instanceof AVLTreeMultiMapNode;
|
||||
override isNode(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R): keyNodeEntryOrRaw is NODE {
|
||||
return keyNodeEntryOrRaw instanceof AVLTreeMultiMapNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* The function `keyValueOrEntryOrRawElementToNode` converts a key, value, entry, or raw element into
|
||||
* The function `keyValueNodeEntryRawToNodeAndValue` converts a key, value, entry, or raw element into
|
||||
* a node object.
|
||||
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - The
|
||||
* `keyOrNodeOrEntryOrRaw` parameter can be of type `R` or `BTNKeyOrNodeOrEntry<K, V, NODE>`.
|
||||
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The
|
||||
* `keyNodeEntryOrRaw` parameter can be of type `R` or `BTNRep<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,28 +172,33 @@ 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 keyValueOrEntryOrRawElementToNode(
|
||||
keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R,
|
||||
override keyValueNodeEntryRawToNodeAndValue(
|
||||
keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R,
|
||||
value?: V,
|
||||
count = 1
|
||||
): NODE | undefined {
|
||||
if (keyOrNodeOrEntryOrRaw === undefined || keyOrNodeOrEntryOrRaw === null) return;
|
||||
if (this.isNode(keyOrNodeOrEntryOrRaw)) return keyOrNodeOrEntryOrRaw;
|
||||
): [NODE | undefined, V | undefined] {
|
||||
if (keyNodeEntryOrRaw === undefined || keyNodeEntryOrRaw === null) return [undefined, undefined];
|
||||
if (this.isNode(keyNodeEntryOrRaw)) return [keyNodeEntryOrRaw, value];
|
||||
|
||||
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.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._toEntryFn) {
|
||||
const [key, entryValue] = this._toEntryFn(keyOrNodeOrEntryOrRaw as R);
|
||||
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.isKey(keyOrNodeOrEntryOrRaw)) return this.createNode(keyOrNodeOrEntryOrRaw, value, count);
|
||||
|
||||
return;
|
||||
return [undefined, undefined];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -202,9 +207,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 {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,
|
||||
* @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,
|
||||
* 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.
|
||||
|
@ -213,12 +218,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(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R, value?: V, count = 1): boolean {
|
||||
const newNode = this.keyValueOrEntryOrRawElementToNode(keyOrNodeOrEntryOrRaw, value, count);
|
||||
override add(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R, value?: V, count = 1): boolean {
|
||||
const [newNode, newValue] = this.keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value, count);
|
||||
if (newNode === undefined) return false;
|
||||
|
||||
const orgNodeCount = newNode?.count || 0;
|
||||
const inserted = super.add(newNode);
|
||||
const inserted = super.add(newNode, newValue);
|
||||
if (inserted) {
|
||||
this._count += orgNodeCount;
|
||||
}
|
||||
|
@ -231,7 +236,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 {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - The `predicate`
|
||||
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - 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.
|
||||
|
@ -244,14 +249,11 @@ 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(
|
||||
keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R,
|
||||
ignoreCount = false
|
||||
): BinaryTreeDeleteResult<NODE>[] {
|
||||
override delete(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R, ignoreCount = false): BinaryTreeDeleteResult<NODE>[] {
|
||||
const deletedResult: BinaryTreeDeleteResult<NODE>[] = [];
|
||||
if (!this.root) return deletedResult;
|
||||
|
||||
const curr: NODE | undefined = this.getNode(keyOrNodeOrEntryOrRaw) ?? undefined;
|
||||
const curr: NODE | undefined = this.getNode(keyNodeEntryOrRaw) ?? undefined;
|
||||
if (!curr) return deletedResult;
|
||||
|
||||
const parent: NODE | undefined = curr?.parent ? curr.parent : undefined;
|
||||
|
@ -339,7 +341,8 @@ export class AVLTreeMultiMap<
|
|||
if (l > r) return;
|
||||
const m = l + Math.floor((r - l) / 2);
|
||||
const midNode = sorted[m];
|
||||
this.add(midNode.key, midNode.value, midNode.count);
|
||||
if (this._isMapMode) this.add(midNode.key, undefined, midNode.count);
|
||||
else this.add(midNode.key, midNode.value, midNode.count);
|
||||
buildBalanceBST(l, m - 1);
|
||||
buildBalanceBST(m + 1, r);
|
||||
};
|
||||
|
@ -355,7 +358,8 @@ export class AVLTreeMultiMap<
|
|||
if (l <= r) {
|
||||
const m = l + Math.floor((r - l) / 2);
|
||||
const midNode = sorted[m];
|
||||
this.add(midNode.key, midNode.value, midNode.count);
|
||||
if (this._isMapMode) this.add(midNode.key, undefined, midNode.count);
|
||||
else this.add(midNode.key, midNode.value, midNode.count);
|
||||
stack.push([m + 1, r]);
|
||||
stack.push([l, m - 1]);
|
||||
}
|
||||
|
@ -374,7 +378,9 @@ export class AVLTreeMultiMap<
|
|||
*/
|
||||
override clone(): TREE {
|
||||
const cloned = this.createTree();
|
||||
this.bfs(node => cloned.add(node.key, node.value, node.count));
|
||||
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;
|
||||
return cloned;
|
||||
}
|
||||
|
||||
|
@ -384,16 +390,16 @@ export class AVLTreeMultiMap<
|
|||
*
|
||||
* The `_swapProperties` function swaps the properties (key, value, count, height) between two nodes
|
||||
* in a binary search tree.
|
||||
* @param {R | BSTNKeyOrNode<K, NODE>} srcNode - The `srcNode` parameter represents the source node
|
||||
* @param {R | BSTNOptKeyOrNode<K, NODE>} srcNode - The `srcNode` parameter represents the source node
|
||||
* that will be swapped with the `destNode`.
|
||||
* @param {R | BSTNKeyOrNode<K, NODE>} destNode - The `destNode` parameter represents the destination
|
||||
* @param {R | BSTNOptKeyOrNode<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 | BSTNKeyOrNode<K, NODE>,
|
||||
destNode: R | BSTNKeyOrNode<K, NODE>
|
||||
srcNode: R | BSTNOptKeyOrNode<K, NODE>,
|
||||
destNode: R | BSTNOptKeyOrNode<K, NODE>
|
||||
): NODE | undefined {
|
||||
srcNode = this.ensureNode(srcNode);
|
||||
destNode = this.ensureNode(destNode);
|
||||
|
@ -404,12 +410,12 @@ export class AVLTreeMultiMap<
|
|||
tempNode.height = height;
|
||||
|
||||
destNode.key = srcNode.key;
|
||||
destNode.value = srcNode.value;
|
||||
if (!this._isMapMode) destNode.value = srcNode.value;
|
||||
destNode.count = srcNode.count;
|
||||
destNode.height = srcNode.height;
|
||||
|
||||
srcNode.key = tempNode.key;
|
||||
srcNode.value = tempNode.value;
|
||||
if (!this._isMapMode) srcNode.value = tempNode.value;
|
||||
srcNode.count = tempNode.count;
|
||||
srcNode.height = tempNode.height;
|
||||
}
|
||||
|
|
|
@ -11,9 +11,8 @@ import type {
|
|||
AVLTreeNodeNested,
|
||||
AVLTreeOptions,
|
||||
BinaryTreeDeleteResult,
|
||||
BSTNKeyOrNode,
|
||||
BTNKeyOrNodeOrEntry,
|
||||
BTNEntry
|
||||
BSTNOptKeyOrNode,
|
||||
BTNRep
|
||||
} from '../../types';
|
||||
import { IBinaryTree } from '../../interfaces';
|
||||
|
||||
|
@ -67,7 +66,7 @@ export class AVLTreeNode<
|
|||
export class AVLTree<
|
||||
K = any,
|
||||
V = any,
|
||||
R = BTNEntry<K, V>,
|
||||
R = object,
|
||||
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>>
|
||||
>
|
||||
|
@ -77,7 +76,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 keysOrNodesOrEntriesOrRaws - The `keysOrNodesOrEntriesOrRaws` parameter is an
|
||||
* @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` 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
|
||||
|
@ -85,12 +84,9 @@ export class AVLTree<
|
|||
* keys), `allowDuplicates` (a boolean indicating whether duplicate keys are allowed), and
|
||||
* `nodeBuilder` (
|
||||
*/
|
||||
constructor(
|
||||
keysOrNodesOrEntriesOrRaws: Iterable<R | BTNKeyOrNodeOrEntry<K, V, NODE>> = [],
|
||||
options?: AVLTreeOptions<K, V, R>
|
||||
) {
|
||||
constructor(keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V, NODE>> = [], options?: AVLTreeOptions<K, V, R>) {
|
||||
super([], options);
|
||||
if (keysOrNodesOrEntriesOrRaws) super.addMany(keysOrNodesOrEntriesOrRaws);
|
||||
if (keysNodesEntriesOrRaws) super.addMany(keysNodesEntriesOrRaws);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -116,6 +112,7 @@ 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
|
||||
|
@ -124,13 +121,13 @@ export class AVLTree<
|
|||
|
||||
/**
|
||||
* The function checks if the input is an instance of AVLTreeNode.
|
||||
* @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
|
||||
* @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
|
||||
* an instance of the `AVLTreeNode` class.
|
||||
*/
|
||||
override isNode(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R): keyOrNodeOrEntryOrRaw is NODE {
|
||||
return keyOrNodeOrEntryOrRaw instanceof AVLTreeNode;
|
||||
override isNode(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R): keyNodeEntryOrRaw is NODE {
|
||||
return keyNodeEntryOrRaw instanceof AVLTreeNode;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -139,17 +136,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 {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - The parameter
|
||||
* `keyOrNodeOrEntryOrRaw` can accept values of type `R`, `BTNKeyOrNodeOrEntry<K, V, NODE>`, or
|
||||
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
|
||||
* `keyNodeEntryOrRaw` can accept values of type `R`, `BTNRep<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(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);
|
||||
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);
|
||||
return inserted;
|
||||
}
|
||||
|
||||
|
@ -159,15 +156,15 @@ export class AVLTree<
|
|||
*
|
||||
* The function overrides the delete method in a TypeScript class, performs deletion, and then
|
||||
* balances the tree if necessary.
|
||||
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - The `keyOrNodeOrEntryOrRaw`
|
||||
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The `keyNodeEntryOrRaw`
|
||||
* 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(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R): BinaryTreeDeleteResult<NODE>[] {
|
||||
const deletedResults = super.delete(keyOrNodeOrEntryOrRaw);
|
||||
override delete(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R): BinaryTreeDeleteResult<NODE>[] {
|
||||
const deletedResults = super.delete(keyNodeEntryOrRaw);
|
||||
for (const { needBalanced } of deletedResults) {
|
||||
if (needBalanced) {
|
||||
this._balancePath(needBalanced);
|
||||
|
@ -182,16 +179,16 @@ export class AVLTree<
|
|||
*
|
||||
* The `_swapProperties` function swaps the key, value, and height properties between two nodes in a
|
||||
* binary search tree.
|
||||
* @param {R | BSTNKeyOrNode<K, NODE>} srcNode - The `srcNode` parameter represents either a node
|
||||
* @param {R | BSTNOptKeyOrNode<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 | BSTNKeyOrNode<K, NODE>} destNode - The `destNode` parameter is either an instance of
|
||||
* `R` or an instance of `BSTNKeyOrNode<K, NODE>`.
|
||||
* @param {R | BSTNOptKeyOrNode<K, NODE>} destNode - The `destNode` parameter is either an instance of
|
||||
* `R` or an instance of `BSTNOptKeyOrNode<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 | BSTNKeyOrNode<K, NODE>,
|
||||
destNode: R | BSTNKeyOrNode<K, NODE>
|
||||
srcNode: R | BSTNOptKeyOrNode<K, NODE>,
|
||||
destNode: R | BSTNOptKeyOrNode<K, NODE>
|
||||
): NODE | undefined {
|
||||
const srcNodeEnsured = this.ensureNode(srcNode);
|
||||
const destNodeEnsured = this.ensureNode(destNode);
|
||||
|
@ -204,11 +201,11 @@ export class AVLTree<
|
|||
tempNode.height = height;
|
||||
|
||||
destNodeEnsured.key = srcNodeEnsured.key;
|
||||
destNodeEnsured.value = srcNodeEnsured.value;
|
||||
if (!this._isMapMode) destNodeEnsured.value = srcNodeEnsured.value;
|
||||
destNodeEnsured.height = srcNodeEnsured.height;
|
||||
|
||||
srcNodeEnsured.key = tempNode.key;
|
||||
srcNodeEnsured.value = tempNode.value;
|
||||
if (!this._isMapMode) srcNodeEnsured.value = tempNode.value;
|
||||
srcNodeEnsured.height = tempNode.height;
|
||||
}
|
||||
|
||||
|
@ -432,10 +429,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 {BTNKeyOrNodeOrEntry<K, V, NODE> | R} node - The `node` parameter can be of type `R` or
|
||||
* `BTNKeyOrNodeOrEntry<K, V, NODE>`.
|
||||
* @param {BTNRep<K, V, NODE> | R} node - The `node` parameter can be of type `R` or
|
||||
* `BTNRep<K, V, NODE>`.
|
||||
*/
|
||||
protected _balancePath(node: BTNKeyOrNodeOrEntry<K, V, NODE> | R): void {
|
||||
protected _balancePath(node: BTNRep<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
|
@ -7,18 +7,17 @@
|
|||
*/
|
||||
import type {
|
||||
BSTNested,
|
||||
BSTNKeyOrNode,
|
||||
BSTNodeNested,
|
||||
BSTNOptKeyOrNode,
|
||||
BSTOptions,
|
||||
BTNCallback,
|
||||
BTNEntry,
|
||||
BTNKeyOrNodeOrEntry,
|
||||
BTNPredicate,
|
||||
BTNRep,
|
||||
Comparator,
|
||||
CP,
|
||||
DFSOrderPattern,
|
||||
IterationType,
|
||||
OptBSTN
|
||||
NodeCallback,
|
||||
NodePredicate,
|
||||
OptNode
|
||||
} from '../../types';
|
||||
import { BinaryTree, BinaryTreeNode } from './binary-tree';
|
||||
import { IBinaryTree } from '../../interfaces';
|
||||
|
@ -45,16 +44,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(): OptBSTN<NODE> {
|
||||
override get left(): OptNode<NODE> {
|
||||
return this._left;
|
||||
}
|
||||
|
||||
/**
|
||||
* The function sets the left child of a node and updates the parent reference of the child.
|
||||
* @param {OptBSTN<NODE>} v - The parameter `v` is of type `OptBSTN<NODE>`. It can either be an
|
||||
* @param {OptNode<NODE>} v - The parameter `v` is of type `OptNode<NODE>`. It can either be an
|
||||
* instance of the `NODE` class or `undefined`.
|
||||
*/
|
||||
override set left(v: OptBSTN<NODE>) {
|
||||
override set left(v: OptNode<NODE>) {
|
||||
if (v) {
|
||||
v.parent = this as unknown as NODE;
|
||||
}
|
||||
|
@ -68,16 +67,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(): OptBSTN<NODE> {
|
||||
override get right(): OptNode<NODE> {
|
||||
return this._right;
|
||||
}
|
||||
|
||||
/**
|
||||
* The function sets the right child of a node and updates the parent reference of the child.
|
||||
* @param {OptBSTN<NODE>} v - The parameter `v` is of type `OptBSTN<NODE>`. It can either be a
|
||||
* @param {OptNode<NODE>} v - The parameter `v` is of type `OptNode<NODE>`. It can either be a
|
||||
* `NODE` object or `undefined`.
|
||||
*/
|
||||
override set right(v: OptBSTN<NODE>) {
|
||||
override set right(v: OptNode<NODE>) {
|
||||
if (v) {
|
||||
v.parent = this as unknown as NODE;
|
||||
}
|
||||
|
@ -97,7 +96,7 @@ export class BSTNode<K = any, V = any, NODE extends BSTNode<K, V, NODE> = BSTNod
|
|||
export class BST<
|
||||
K = any,
|
||||
V = any,
|
||||
R = BTNEntry<K, V>,
|
||||
R = object,
|
||||
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>>
|
||||
>
|
||||
|
@ -106,16 +105,13 @@ export class BST<
|
|||
{
|
||||
/**
|
||||
* This is the constructor function for a Binary Search Tree class in TypeScript.
|
||||
* @param keysOrNodesOrEntriesOrRaws - The `keysOrNodesOrEntriesOrRaws` parameter is an
|
||||
* @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` 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(
|
||||
keysOrNodesOrEntriesOrRaws: Iterable<R | BTNKeyOrNodeOrEntry<K, V, NODE>> = [],
|
||||
options?: BSTOptions<K, V, R>
|
||||
) {
|
||||
constructor(keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V, NODE>> = [], options?: BSTOptions<K, V, R>) {
|
||||
super([], options);
|
||||
|
||||
if (options) {
|
||||
|
@ -123,7 +119,7 @@ export class BST<
|
|||
if (comparator) this._comparator = comparator;
|
||||
}
|
||||
|
||||
if (keysOrNodesOrEntriesOrRaws) this.addMany(keysOrNodesOrEntriesOrRaws);
|
||||
if (keysNodesEntriesOrRaws) this.addMany(keysNodesEntriesOrRaws);
|
||||
}
|
||||
|
||||
protected override _root?: NODE = undefined;
|
||||
|
@ -132,7 +128,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(): OptBSTN<NODE> {
|
||||
override get root(): OptNode<NODE> {
|
||||
return this._root;
|
||||
}
|
||||
|
||||
|
@ -158,6 +154,7 @@ 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
|
||||
|
@ -166,18 +163,20 @@ export class BST<
|
|||
|
||||
/**
|
||||
* The function overrides a method and converts a key, value pair or entry or raw element to a node.
|
||||
* @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
|
||||
* @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
|
||||
* 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 keyValueOrEntryOrRawElementToNode(
|
||||
keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R,
|
||||
override keyValueNodeEntryRawToNodeAndValue(
|
||||
keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R,
|
||||
value?: V
|
||||
): OptBSTN<NODE> {
|
||||
return super.keyValueOrEntryOrRawElementToNode(keyOrNodeOrEntryOrRaw, value) ?? undefined;
|
||||
): [OptNode<NODE>, V | undefined] {
|
||||
const [node, tValue] = super.keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value);
|
||||
if (node === null) return [undefined, undefined];
|
||||
return [node, tValue ?? value];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -186,8 +185,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 {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - The parameter
|
||||
* `keyOrNodeOrEntryOrRaw` can accept a value of type `R`, which represents the key, node,
|
||||
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
|
||||
* `keyNodeEntryOrRaw` 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
|
||||
|
@ -196,21 +195,21 @@ export class BST<
|
|||
* not be ensured.
|
||||
*/
|
||||
override ensureNode(
|
||||
keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R,
|
||||
keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R,
|
||||
iterationType: IterationType = this.iterationType
|
||||
): OptBSTN<NODE> {
|
||||
return super.ensureNode(keyOrNodeOrEntryOrRaw, iterationType) ?? undefined;
|
||||
): OptNode<NODE> {
|
||||
return super.ensureNode(keyNodeEntryOrRaw, iterationType) ?? undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* The function checks if the input is an instance of the BSTNode class.
|
||||
* @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
|
||||
* @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
|
||||
* an instance of the `BSTNode` class.
|
||||
*/
|
||||
override isNode(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R): keyOrNodeOrEntryOrRaw is NODE {
|
||||
return keyOrNodeOrEntryOrRaw instanceof BSTNode;
|
||||
override isNode(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R): keyNodeEntryOrRaw is NODE {
|
||||
return keyNodeEntryOrRaw instanceof BSTNode;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -230,18 +229,19 @@ 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 {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - The parameter
|
||||
* `keyOrNodeOrEntryOrRaw` can accept a value of type `R` or `BTNKeyOrNodeOrEntry<K, V, NODE>`.
|
||||
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
|
||||
* `keyNodeEntryOrRaw` can accept a value of type `R` or `BTNRep<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(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R, value?: V): boolean {
|
||||
const newNode = this.keyValueOrEntryOrRawElementToNode(keyOrNodeOrEntryOrRaw, value);
|
||||
override add(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R, value?: V): boolean {
|
||||
const [newNode, newValue] = this.keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, 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,6 +254,7 @@ 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;
|
||||
}
|
||||
|
@ -261,6 +262,7 @@ export class BST<
|
|||
} else {
|
||||
if (current.right === undefined) {
|
||||
current.right = newNode;
|
||||
if (this._isMapMode) this._setValue(newNode?.key, newValue);
|
||||
this._size++;
|
||||
return true;
|
||||
}
|
||||
|
@ -277,7 +279,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 keysOrNodesOrEntriesOrRaws - An iterable containing keys, nodes, entries, or raw
|
||||
* @param keysNodesEntriesOrRaws - 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
|
||||
|
@ -293,7 +295,7 @@ export class BST<
|
|||
* successfully inserted into the data structure.
|
||||
*/
|
||||
override addMany(
|
||||
keysOrNodesOrEntriesOrRaws: Iterable<R | BTNKeyOrNodeOrEntry<K, V, NODE>>,
|
||||
keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V, NODE>>,
|
||||
values?: Iterable<V | undefined>,
|
||||
isBalanceAdd = true,
|
||||
iterationType: IterationType = this.iterationType
|
||||
|
@ -307,7 +309,7 @@ export class BST<
|
|||
}
|
||||
|
||||
if (!isBalanceAdd) {
|
||||
for (const kve of keysOrNodesOrEntriesOrRaws) {
|
||||
for (const kve of keysNodesEntriesOrRaws) {
|
||||
const value = valuesIterator?.next().value;
|
||||
inserted.push(this.add(kve, value));
|
||||
}
|
||||
|
@ -315,18 +317,18 @@ export class BST<
|
|||
}
|
||||
|
||||
const realBTNExemplars: {
|
||||
key: R | BTNKeyOrNodeOrEntry<K, V, NODE>;
|
||||
key: R | BTNRep<K, V, NODE>;
|
||||
value: V | undefined;
|
||||
orgIndex: number;
|
||||
}[] = [];
|
||||
|
||||
let i = 0;
|
||||
for (const kve of keysOrNodesOrEntriesOrRaws) {
|
||||
for (const kve of keysNodesEntriesOrRaws) {
|
||||
realBTNExemplars.push({ key: kve, value: valuesIterator?.next().value, orgIndex: i });
|
||||
i++;
|
||||
}
|
||||
|
||||
let sorted: { key: R | BTNKeyOrNodeOrEntry<K, V, NODE>; value: V | undefined; orgIndex: number }[] = [];
|
||||
let sorted: { key: R | BTNRep<K, V, NODE>; value: V | undefined; orgIndex: number }[] = [];
|
||||
|
||||
sorted = realBTNExemplars.sort(({ key: a }, { key: b }) => {
|
||||
let keyA: K | undefined | null, keyB: K | undefined | null;
|
||||
|
@ -352,7 +354,7 @@ export class BST<
|
|||
return 0;
|
||||
});
|
||||
|
||||
const _dfs = (arr: { key: R | BTNKeyOrNodeOrEntry<K, V, NODE>; value: V | undefined; orgIndex: number }[]) => {
|
||||
const _dfs = (arr: { key: R | BTNRep<K, V, NODE>; value: V | undefined; orgIndex: number }[]) => {
|
||||
if (arr.length === 0) return;
|
||||
|
||||
const mid = Math.floor((arr.length - 1) / 2);
|
||||
|
@ -394,35 +396,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 predicate and iteration type.
|
||||
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R | BTNPredicate<NODE>} predicate - The `predicate`
|
||||
* given keyNodeEntryRawOrPredicate and iteration type.
|
||||
* @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate - The `keyNodeEntryRawOrPredicate`
|
||||
* parameter in the `getNodes` method is used to filter the nodes that will be returned. It can be a
|
||||
* key, a node, an entry, or a custom predicate function that determines whether a node should be
|
||||
* key, a node, an entry, or a custom keyNodeEntryRawOrPredicate function that determines whether a node should be
|
||||
* included in the result.
|
||||
* @param [onlyOne=false] - The `onlyOne` parameter in the `getNodes` method is a boolean flag that
|
||||
* determines whether to return only the first node that matches the predicate (`true`) or all nodes
|
||||
* that match the predicate (`false`). If `onlyOne` is set to `true`, the method will stop iterating
|
||||
* 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
|
||||
* and
|
||||
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} beginRoot - The `beginRoot` parameter in the
|
||||
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
||||
* `getNodes` method is used to specify the starting point for traversing the tree when searching for
|
||||
* nodes that match a given predicate. It represents the root node of the subtree where the search
|
||||
* nodes that match a given keyNodeEntryRawOrPredicate. It represents the root node of the subtree where the search
|
||||
* should begin. If not explicitly provided, the default value for `begin
|
||||
* @param {IterationType} iterationType - The `iterationType` parameter in the `getNodes` method
|
||||
* specifies the type of iteration to be performed when traversing the nodes of a binary tree. It can
|
||||
* have two possible values:
|
||||
* @returns The `getNodes` method returns an array of nodes that satisfy the given predicate.
|
||||
* @returns The `getNodes` method returns an array of nodes that satisfy the given keyNodeEntryRawOrPredicate.
|
||||
*/
|
||||
override getNodes(
|
||||
predicate: BTNKeyOrNodeOrEntry<K, V, NODE> | R | BTNPredicate<NODE>,
|
||||
keyNodeEntryRawOrPredicate: BTNRep<K, V, NODE> | R | NodePredicate<NODE>,
|
||||
onlyOne = false,
|
||||
beginRoot: BTNKeyOrNodeOrEntry<K, V, NODE> | R = this._root,
|
||||
startNode: BTNRep<K, V, NODE> | R = this._root,
|
||||
iterationType: IterationType = this.iterationType
|
||||
): NODE[] {
|
||||
if (predicate === undefined) return [];
|
||||
if (predicate === null) return [];
|
||||
beginRoot = this.ensureNode(beginRoot);
|
||||
if (!beginRoot) return [];
|
||||
const callback = this._ensurePredicate(predicate);
|
||||
if (keyNodeEntryRawOrPredicate === undefined) return [];
|
||||
if (keyNodeEntryRawOrPredicate === null) return [];
|
||||
startNode = this.ensureNode(startNode);
|
||||
if (!startNode) return [];
|
||||
const callback = this._ensurePredicate(keyNodeEntryRawOrPredicate);
|
||||
const ans: NODE[] = [];
|
||||
|
||||
if (iterationType === 'RECURSIVE') {
|
||||
|
@ -433,27 +435,53 @@ export class BST<
|
|||
}
|
||||
|
||||
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return;
|
||||
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);
|
||||
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);
|
||||
} else {
|
||||
if (this.isRealNode(cur.left)) dfs(cur.left);
|
||||
if (this.isRealNode(cur.right)) dfs(cur.right);
|
||||
}
|
||||
};
|
||||
|
||||
dfs(beginRoot);
|
||||
dfs(startNode);
|
||||
} else {
|
||||
const stack = [beginRoot];
|
||||
const stack = [startNode];
|
||||
while (stack.length > 0) {
|
||||
const cur = stack.pop()!;
|
||||
if (callback(cur)) {
|
||||
ans.push(cur);
|
||||
if (onlyOne) return ans;
|
||||
}
|
||||
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);
|
||||
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);
|
||||
} else {
|
||||
if (this.isRealNode(cur.right)) stack.push(cur.right);
|
||||
if (this.isRealNode(cur.left)) stack.push(cur.left);
|
||||
|
@ -468,10 +496,10 @@ export class BST<
|
|||
* Time Complexity: O(log n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* 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
|
||||
* 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
|
||||
* 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.
|
||||
|
@ -479,17 +507,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 (`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 `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 first node found or `undefined` if no node is found.
|
||||
*/
|
||||
override getNode(
|
||||
predicate: BTNKeyOrNodeOrEntry<K, V, NODE> | R | BTNPredicate<NODE>,
|
||||
beginRoot: R | BSTNKeyOrNode<K, NODE> = this._root,
|
||||
keyNodeEntryRawOrPredicate: BTNRep<K, V, NODE> | R | NodePredicate<NODE>,
|
||||
startNode: R | BSTNOptKeyOrNode<K, NODE> = this._root,
|
||||
iterationType: IterationType = this.iterationType
|
||||
): OptBSTN<NODE> {
|
||||
return this.getNodes(predicate, true, beginRoot, iterationType)[0] ?? undefined;
|
||||
): OptNode<NODE> {
|
||||
return this.getNodes(keyNodeEntryRawOrPredicate, true, startNode, iterationType)[0] ?? undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -505,7 +533,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): OptBSTN<NODE> {
|
||||
override getNodeByKey(key: K, iterationType: IterationType = this.iterationType): OptNode<NODE> {
|
||||
return this.getNode(key, this._root, iterationType);
|
||||
}
|
||||
|
||||
|
@ -517,11 +545,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_BTN_CALLBACK`. The type `C` represents the type of the callback function.
|
||||
* `this._DEFAULT_NODE_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 {BTNKeyOrNodeOrEntry<K, V, NODE> | R} beginRoot - The `beginRoot` parameter is the starting
|
||||
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` 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
|
||||
|
@ -529,13 +557,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 BTNCallback<NODE>>(
|
||||
callback: C = this._DEFAULT_BTN_CALLBACK as C,
|
||||
override dfs<C extends NodeCallback<NODE>>(
|
||||
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
||||
pattern: DFSOrderPattern = 'IN',
|
||||
beginRoot: BTNKeyOrNodeOrEntry<K, V, NODE> | R = this._root,
|
||||
startNode: BTNRep<K, V, NODE> | R = this._root,
|
||||
iterationType: IterationType = this.iterationType
|
||||
): ReturnType<C>[] {
|
||||
return super.dfs(callback, pattern, beginRoot, iterationType);
|
||||
return super.dfs(callback, pattern, startNode, iterationType);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -547,7 +575,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 {BTNKeyOrNodeOrEntry<K, V, NODE> | R} beginRoot - The `beginRoot` parameter is the starting
|
||||
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` 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
|
||||
|
@ -555,12 +583,12 @@ export class BST<
|
|||
* the following values:
|
||||
* @returns an array of the return type of the callback function.
|
||||
*/
|
||||
override bfs<C extends BTNCallback<NODE>>(
|
||||
callback: C = this._DEFAULT_BTN_CALLBACK as C,
|
||||
beginRoot: BTNKeyOrNodeOrEntry<K, V, NODE> | R = this._root,
|
||||
override bfs<C extends NodeCallback<NODE>>(
|
||||
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
||||
startNode: BTNRep<K, V, NODE> | R = this._root,
|
||||
iterationType: IterationType = this.iterationType
|
||||
): ReturnType<C>[] {
|
||||
return super.bfs(callback, beginRoot, iterationType, false);
|
||||
return super.bfs(callback, startNode, iterationType, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -570,9 +598,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
|
||||
* `BTNCallback<NODE>`. It represents a callback function that will be called for each node in the
|
||||
* `NodeCallback<NODE>`. It represents a callback function that will be called for each node in the
|
||||
* tree during the iteration process.
|
||||
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} beginRoot - The `beginRoot` parameter is the starting
|
||||
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` 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
|
||||
|
@ -581,12 +609,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 BTNCallback<NODE>>(
|
||||
callback: C = this._DEFAULT_BTN_CALLBACK as C,
|
||||
beginRoot: BTNKeyOrNodeOrEntry<K, V, NODE> | R = this._root,
|
||||
override listLevels<C extends NodeCallback<NODE>>(
|
||||
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
||||
startNode: BTNRep<K, V, NODE> | R = this._root,
|
||||
iterationType: IterationType = this.iterationType
|
||||
): ReturnType<C>[][] {
|
||||
return super.listLevels(callback, beginRoot, iterationType, false);
|
||||
return super.listLevels(callback, startNode, iterationType, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -601,7 +629,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 {BTNKeyOrNodeOrEntry<K, V, NODE> | R} targetNode - The `targetNode` parameter is the node in
|
||||
* @param {BTNRep<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,
|
||||
|
@ -610,14 +638,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 BTNCallback<NODE>>(
|
||||
callback: C = this._DEFAULT_BTN_CALLBACK as C,
|
||||
lesserOrGreaterTraverse<C extends NodeCallback<NODE>>(
|
||||
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
||||
lesserOrGreater: CP = -1,
|
||||
targetNode: BTNKeyOrNodeOrEntry<K, V, NODE> | R = this._root,
|
||||
targetNode: BTNRep<K, V, NODE> | R = this._root,
|
||||
iterationType: IterationType = this.iterationType
|
||||
): ReturnType<C>[] {
|
||||
const targetNodeEnsured = this.ensureNode(targetNode);
|
||||
const ans: ReturnType<BTNCallback<NODE>>[] = [];
|
||||
const ans: ReturnType<NodeCallback<NODE>>[] = [];
|
||||
if (!this._root) return ans;
|
||||
if (!targetNodeEnsured) return ans;
|
||||
|
||||
|
@ -665,7 +693,7 @@ export class BST<
|
|||
perfectlyBalance(iterationType: IterationType = this.iterationType): boolean {
|
||||
const sorted = this.dfs(node => node, 'IN'),
|
||||
n = sorted.length;
|
||||
this.clear();
|
||||
this._clearNodes();
|
||||
|
||||
if (sorted.length < 1) return false;
|
||||
if (iterationType === 'RECURSIVE') {
|
||||
|
@ -673,7 +701,8 @@ export class BST<
|
|||
if (l > r) return;
|
||||
const m = l + Math.floor((r - l) / 2);
|
||||
const midNode = sorted[m];
|
||||
this.add([midNode.key, midNode.value]);
|
||||
if (this._isMapMode) this.add(midNode.key);
|
||||
else this.add([midNode.key, midNode.value]);
|
||||
buildBalanceBST(l, m - 1);
|
||||
buildBalanceBST(m + 1, r);
|
||||
};
|
||||
|
@ -689,7 +718,8 @@ export class BST<
|
|||
if (l <= r) {
|
||||
const m = l + Math.floor((r - l) / 2);
|
||||
const midNode = sorted[m];
|
||||
this.add([midNode.key, midNode.value]);
|
||||
if (this._isMapMode) this.add(midNode.key);
|
||||
else this.add([midNode.key, midNode.value]);
|
||||
stack.push([m + 1, r]);
|
||||
stack.push([l, m - 1]);
|
||||
}
|
||||
|
@ -717,7 +747,7 @@ export class BST<
|
|||
let balanced = true;
|
||||
|
||||
if (iterationType === 'RECURSIVE') {
|
||||
const _height = (cur: OptBSTN<NODE>): number => {
|
||||
const _height = (cur: OptNode<NODE>): number => {
|
||||
if (!cur) return 0;
|
||||
const leftHeight = _height(cur.left),
|
||||
rightHeight = _height(cur.right);
|
||||
|
@ -727,8 +757,8 @@ export class BST<
|
|||
_height(this._root);
|
||||
} else {
|
||||
const stack: NODE[] = [];
|
||||
let node: OptBSTN<NODE> = this._root,
|
||||
last: OptBSTN<NODE> = undefined;
|
||||
let node: OptNode<NODE> = this._root,
|
||||
last: OptNode<NODE> = undefined;
|
||||
const depths: Map<NODE, number> = new Map();
|
||||
|
||||
while (stack.length > 0 || node) {
|
||||
|
@ -779,9 +809,9 @@ export class BST<
|
|||
/**
|
||||
* The function sets the root of a tree-like structure and updates the parent property of the new
|
||||
* root.
|
||||
* @param {OptBSTN<NODE>} v - v is a parameter of type NODE or undefined.
|
||||
* @param {OptNode<NODE>} v - v is a parameter of type NODE or undefined.
|
||||
*/
|
||||
protected override _setRoot(v: OptBSTN<NODE>) {
|
||||
protected override _setRoot(v: OptNode<NODE>) {
|
||||
if (v) {
|
||||
v.parent = undefined;
|
||||
}
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import type {
|
||||
BinaryTreeDeleteResult,
|
||||
BTNKeyOrNodeOrEntry,
|
||||
BTNRep,
|
||||
CRUD,
|
||||
OptBSTN,
|
||||
OptNode,
|
||||
RBTNColor,
|
||||
RBTreeOptions,
|
||||
RedBlackTreeNested,
|
||||
RedBlackTreeNodeNested,
|
||||
BTNEntry
|
||||
RedBlackTreeNodeNested
|
||||
} from '../../types';
|
||||
import { BST, BSTNode } from './bst';
|
||||
import { IBinaryTree } from '../../interfaces';
|
||||
|
@ -55,7 +54,7 @@ export class RedBlackTreeNode<
|
|||
export class RedBlackTree<
|
||||
K = any,
|
||||
V = any,
|
||||
R = BTNEntry<K, V>,
|
||||
R = object,
|
||||
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>>
|
||||
>
|
||||
|
@ -64,7 +63,7 @@ export class RedBlackTree<
|
|||
{
|
||||
/**
|
||||
* This is the constructor function for a Red-Black Tree data structure in TypeScript.
|
||||
* @param keysOrNodesOrEntriesOrRaws - The `keysOrNodesOrEntriesOrRaws` parameter is an
|
||||
* @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` 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
|
||||
|
@ -72,16 +71,13 @@ export class RedBlackTree<
|
|||
* configuring the behavior of the Red-Black Tree. The specific properties and their meanings would
|
||||
* depend on the implementation
|
||||
*/
|
||||
constructor(
|
||||
keysOrNodesOrEntriesOrRaws: Iterable<R | BTNKeyOrNodeOrEntry<K, V, NODE>> = [],
|
||||
options?: RBTreeOptions<K, V, R>
|
||||
) {
|
||||
constructor(keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V, NODE>> = [], options?: RBTreeOptions<K, V, R>) {
|
||||
super([], options);
|
||||
|
||||
this._root = this.NIL;
|
||||
|
||||
if (keysOrNodesOrEntriesOrRaws) {
|
||||
this.addMany(keysOrNodesOrEntriesOrRaws);
|
||||
if (keysNodesEntriesOrRaws) {
|
||||
this.addMany(keysNodesEntriesOrRaws);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,6 +118,7 @@ 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
|
||||
|
@ -133,13 +130,13 @@ export class RedBlackTree<
|
|||
* Space Complexity: O(1)
|
||||
*
|
||||
* The function checks if the input is an instance of the RedBlackTreeNode class.
|
||||
* @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
|
||||
* @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
|
||||
* an instance of the `RedBlackTreeNode` class.
|
||||
*/
|
||||
override isNode(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R): keyOrNodeOrEntryOrRaw is NODE {
|
||||
return keyOrNodeOrEntryOrRaw instanceof RedBlackTreeNode;
|
||||
override isNode(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R): keyNodeEntryOrRaw is NODE {
|
||||
return keyNodeEntryOrRaw instanceof RedBlackTreeNode;
|
||||
}
|
||||
|
||||
// /**
|
||||
|
@ -151,29 +148,29 @@ export class RedBlackTree<
|
|||
// * Time Complexity: O(1)
|
||||
// * Space Complexity: O(1)
|
||||
// *
|
||||
// * The function `keyValueOrEntryOrRawElementToNode` takes a key, value, or entry and returns a node if it is
|
||||
// * The function `keyValueNodeEntryRawToNodeAndValue` takes a key, value, or entry and returns a node if it is
|
||||
// * valid, otherwise it returns undefined.
|
||||
// * @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).
|
||||
// * @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).
|
||||
// * @returns {NODE | undefined} - The corresponding Red-Black Tree node, or `undefined` if conversion fails.
|
||||
// */
|
||||
// override keyValueOrEntryOrRawElementToNode(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R, value?: V): NODE | undefined {
|
||||
// override keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R, value?: V): NODE | undefined {
|
||||
//
|
||||
// if (keyOrNodeOrEntryOrRaw === null || keyOrNodeOrEntryOrRaw === undefined) return;
|
||||
// if (this.isNode(keyOrNodeOrEntryOrRaw)) return keyOrNodeOrEntryOrRaw;
|
||||
// if (keyNodeEntryOrRaw === null || keyNodeEntryOrRaw === undefined) return;
|
||||
// if (this.isNode(keyNodeEntryOrRaw)) return keyNodeEntryOrRaw;
|
||||
//
|
||||
// if (this._toEntryFn) {
|
||||
// const [key, entryValue] = this._toEntryFn(keyOrNodeOrEntryOrRaw as R);
|
||||
// if (this.isKey(key)) return this.createNode(key, entryValue ?? value, 'RED');
|
||||
// const [key, entryValue] = this._toEntryFn(keyNodeEntryOrRaw as R);
|
||||
// if (this.isKey(key)) return this.createNode(key, value ?? entryValue, 'RED');
|
||||
// }
|
||||
//
|
||||
// if (this.isEntry(keyOrNodeOrEntryOrRaw)) {
|
||||
// const [key, value] = keyOrNodeOrEntryOrRaw;
|
||||
// if (this.isEntry(keyNodeEntryOrRaw)) {
|
||||
// const [key, value] = keyNodeEntryOrRaw;
|
||||
// if (key === undefined || key === null) return;
|
||||
// else return this.createNode(key, value, 'RED');
|
||||
// }
|
||||
//
|
||||
// if (this.isKey(keyOrNodeOrEntryOrRaw)) return this.createNode(keyOrNodeOrEntryOrRaw, value, 'RED');
|
||||
// if (this.isKey(keyNodeEntryOrRaw)) return this.createNode(keyNodeEntryOrRaw, value, 'RED');
|
||||
//
|
||||
// return ;
|
||||
// }
|
||||
|
@ -196,8 +193,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 {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - The parameter
|
||||
* `keyOrNodeOrEntryOrRaw` can accept a value of type `R` or `BTNKeyOrNodeOrEntry<K, V, NODE>`.
|
||||
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
|
||||
* `keyNodeEntryOrRaw` can accept a value of type `R` or `BTNRep<K, V, NODE>`.
|
||||
* @param {V} [value] - The `value` parameter is an optional value that you want to associate with
|
||||
* the key in the data structure. It represents the value that you want to add or update in the data
|
||||
* structure.
|
||||
|
@ -205,8 +202,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(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R, value?: V): boolean {
|
||||
const newNode = this.keyValueOrEntryOrRawElementToNode(keyOrNodeOrEntryOrRaw, value);
|
||||
override add(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R, value?: V): boolean {
|
||||
const [newNode, newValue] = this.keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value);
|
||||
if (!this.isRealNode(newNode)) return false;
|
||||
|
||||
const insertStatus = this._insert(newNode);
|
||||
|
@ -218,6 +215,7 @@ export class RedBlackTree<
|
|||
} else {
|
||||
return false;
|
||||
}
|
||||
if (this._isMapMode) this._setValue(newNode.key, newValue);
|
||||
this._size++;
|
||||
return true;
|
||||
} else return insertStatus === 'UPDATED';
|
||||
|
@ -229,7 +227,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 {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - The `keyOrNodeOrEntryOrRaw`
|
||||
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The `keyNodeEntryOrRaw`
|
||||
* 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.
|
||||
|
@ -237,16 +235,13 @@ export class RedBlackTree<
|
|||
* objects. Each object in the array contains information about the deleted node and whether
|
||||
* balancing is needed.
|
||||
*/
|
||||
override delete(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R): BinaryTreeDeleteResult<NODE>[] {
|
||||
if (keyOrNodeOrEntryOrRaw === null) return [];
|
||||
override delete(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R): BinaryTreeDeleteResult<NODE>[] {
|
||||
if (keyNodeEntryOrRaw === null) return [];
|
||||
|
||||
const results: BinaryTreeDeleteResult<NODE>[] = [];
|
||||
let nodeToDelete: OptBSTN<NODE>;
|
||||
if (this._isPredicated(keyOrNodeOrEntryOrRaw)) nodeToDelete = this.getNode(keyOrNodeOrEntryOrRaw);
|
||||
else
|
||||
nodeToDelete = this.isRealNode(keyOrNodeOrEntryOrRaw)
|
||||
? keyOrNodeOrEntryOrRaw
|
||||
: this.getNode(keyOrNodeOrEntryOrRaw);
|
||||
let nodeToDelete: OptNode<NODE>;
|
||||
if (this._isPredicate(keyNodeEntryOrRaw)) nodeToDelete = this.getNode(keyNodeEntryOrRaw);
|
||||
else nodeToDelete = this.isRealNode(keyNodeEntryOrRaw) ? keyNodeEntryOrRaw : this.getNode(keyNodeEntryOrRaw);
|
||||
|
||||
if (!nodeToDelete) {
|
||||
return results;
|
||||
|
@ -287,6 +282,7 @@ 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
|
||||
|
|
|
@ -7,15 +7,14 @@
|
|||
*/
|
||||
import type {
|
||||
BinaryTreeDeleteResult,
|
||||
BSTNKeyOrNode,
|
||||
BTNKeyOrNodeOrEntry,
|
||||
BSTNOptKeyOrNode,
|
||||
BTNRep,
|
||||
IterationType,
|
||||
OptBSTN,
|
||||
OptNode,
|
||||
RBTNColor,
|
||||
TreeMultiMapNested,
|
||||
TreeMultiMapNodeNested,
|
||||
TreeMultiMapOptions,
|
||||
BTNEntry
|
||||
TreeMultiMapOptions
|
||||
} from '../../types';
|
||||
import { IBinaryTree } from '../../interfaces';
|
||||
import { RedBlackTree, RedBlackTreeNode } from './rb-tree';
|
||||
|
@ -65,7 +64,7 @@ export class TreeMultiMapNode<
|
|||
export class TreeMultiMap<
|
||||
K = any,
|
||||
V = any,
|
||||
R = BTNEntry<K, V>,
|
||||
R = object,
|
||||
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>>
|
||||
>
|
||||
|
@ -74,19 +73,16 @@ export class TreeMultiMap<
|
|||
{
|
||||
/**
|
||||
* The constructor function initializes a TreeMultiMap object with optional initial data.
|
||||
* @param keysOrNodesOrEntriesOrRaws - The parameter `keysOrNodesOrEntriesOrRaws` is an
|
||||
* @param keysNodesEntriesOrRaws - The parameter `keysNodesEntriesOrRaws` 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(
|
||||
keysOrNodesOrEntriesOrRaws: Iterable<BTNKeyOrNodeOrEntry<K, V, NODE>> = [],
|
||||
options?: TreeMultiMapOptions<K, V, R>
|
||||
) {
|
||||
constructor(keysNodesEntriesOrRaws: Iterable<BTNRep<K, V, NODE>> = [], options?: TreeMultiMapOptions<K, V, R>) {
|
||||
super([], options);
|
||||
if (keysOrNodesOrEntriesOrRaws) this.addMany(keysOrNodesOrEntriesOrRaws);
|
||||
if (keysNodesEntriesOrRaws) this.addMany(keysNodesEntriesOrRaws);
|
||||
}
|
||||
|
||||
protected _count = 0;
|
||||
|
@ -142,6 +138,7 @@ 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
|
||||
|
@ -149,10 +146,10 @@ export class TreeMultiMap<
|
|||
}
|
||||
|
||||
/**
|
||||
* The function `keyValueOrEntryOrRawElementToNode` takes in a key, value, and count and returns a
|
||||
* The function `keyValueNodeEntryRawToNodeAndValue` takes in a key, value, and count and returns a
|
||||
* node based on the input.
|
||||
* @param {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - The parameter
|
||||
* `keyOrNodeOrEntryOrRaw` can be of type `R` or `BTNKeyOrNodeOrEntry<K, V, NODE>`.
|
||||
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
|
||||
* `keyNodeEntryOrRaw` can be of type `R` or `BTNRep<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.
|
||||
|
@ -160,40 +157,42 @@ 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 keyValueOrEntryOrRawElementToNode(
|
||||
keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R,
|
||||
override keyValueNodeEntryRawToNodeAndValue(
|
||||
keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R,
|
||||
value?: V,
|
||||
count = 1
|
||||
): NODE | undefined {
|
||||
if (keyOrNodeOrEntryOrRaw === undefined || keyOrNodeOrEntryOrRaw === null) return;
|
||||
): [NODE | undefined, V | undefined] {
|
||||
if (keyNodeEntryOrRaw === undefined || keyNodeEntryOrRaw === null) return [undefined, undefined];
|
||||
|
||||
if (this.isNode(keyOrNodeOrEntryOrRaw)) return keyOrNodeOrEntryOrRaw;
|
||||
if (this.isNode(keyNodeEntryOrRaw)) return [keyNodeEntryOrRaw, value];
|
||||
|
||||
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.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._toEntryFn) {
|
||||
const [key, entryValue] = this._toEntryFn(keyOrNodeOrEntryOrRaw as R);
|
||||
if (this.isKey(key)) return this.createNode(key, value ?? entryValue, 'BLACK', count);
|
||||
const [key, entryValue] = this._toEntryFn(keyNodeEntryOrRaw as R);
|
||||
const finalValue = value ?? entryValue;
|
||||
if (this.isKey(key)) return [this.createNode(key, finalValue, 'BLACK', count), finalValue];
|
||||
}
|
||||
|
||||
if (this.isKey(keyOrNodeOrEntryOrRaw)) return this.createNode(keyOrNodeOrEntryOrRaw, value, 'BLACK', count);
|
||||
if (this.isKey(keyNodeEntryOrRaw)) return [this.createNode(keyNodeEntryOrRaw, value, 'BLACK', count), value];
|
||||
|
||||
return;
|
||||
return [undefined, undefined];
|
||||
}
|
||||
|
||||
/**
|
||||
* The function checks if the input is an instance of the TreeMultiMapNode class.
|
||||
* @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
|
||||
* @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
|
||||
* an instance of the `TreeMultiMapNode` class.
|
||||
*/
|
||||
override isNode(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R): keyOrNodeOrEntryOrRaw is NODE {
|
||||
return keyOrNodeOrEntryOrRaw instanceof TreeMultiMapNode;
|
||||
override isNode(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R): keyNodeEntryOrRaw is NODE {
|
||||
return keyNodeEntryOrRaw instanceof TreeMultiMapNode;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -202,8 +201,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 {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - The
|
||||
* `keyOrNodeOrEntryOrRaw` parameter can accept one of the following types:
|
||||
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The
|
||||
* `keyNodeEntryOrRaw` 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
|
||||
|
@ -212,10 +211,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(keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R, value?: V, count = 1): boolean {
|
||||
const newNode = this.keyValueOrEntryOrRawElementToNode(keyOrNodeOrEntryOrRaw, value, count);
|
||||
override add(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R, value?: V, count = 1): boolean {
|
||||
const [newNode, newValue] = this.keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value, count);
|
||||
const orgCount = newNode?.count || 0;
|
||||
const isSuccessAdded = super.add(newNode);
|
||||
const isSuccessAdded = super.add(newNode, newValue);
|
||||
|
||||
if (isSuccessAdded) {
|
||||
this._count += orgCount;
|
||||
|
@ -231,7 +230,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 {BTNKeyOrNodeOrEntry<K, V, NODE> | R} keyOrNodeOrEntryOrRaw - The `predicate`
|
||||
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - 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
|
||||
|
@ -240,20 +239,14 @@ export class TreeMultiMap<
|
|||
* `ignoreCount` is `false
|
||||
* @returns The `override delete` method returns an array of `BinaryTreeDeleteResult<NODE>` objects.
|
||||
*/
|
||||
override delete(
|
||||
keyOrNodeOrEntryOrRaw: BTNKeyOrNodeOrEntry<K, V, NODE> | R,
|
||||
ignoreCount = false
|
||||
): BinaryTreeDeleteResult<NODE>[] {
|
||||
if (keyOrNodeOrEntryOrRaw === null) return [];
|
||||
override delete(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R, ignoreCount = false): BinaryTreeDeleteResult<NODE>[] {
|
||||
if (keyNodeEntryOrRaw === null) return [];
|
||||
|
||||
const results: BinaryTreeDeleteResult<NODE>[] = [];
|
||||
|
||||
let nodeToDelete: OptBSTN<NODE>;
|
||||
if (this._isPredicated(keyOrNodeOrEntryOrRaw)) nodeToDelete = this.getNode(keyOrNodeOrEntryOrRaw);
|
||||
else
|
||||
nodeToDelete = this.isRealNode(keyOrNodeOrEntryOrRaw)
|
||||
? keyOrNodeOrEntryOrRaw
|
||||
: this.getNode(keyOrNodeOrEntryOrRaw);
|
||||
let nodeToDelete: OptNode<NODE>;
|
||||
if (this._isPredicate(keyNodeEntryOrRaw)) nodeToDelete = this.getNode(keyNodeEntryOrRaw);
|
||||
else nodeToDelete = this.isRealNode(keyNodeEntryOrRaw) ? keyNodeEntryOrRaw : this.getNode(keyNodeEntryOrRaw);
|
||||
|
||||
if (!nodeToDelete) {
|
||||
return results;
|
||||
|
@ -374,7 +367,8 @@ export class TreeMultiMap<
|
|||
if (l > r) return;
|
||||
const m = l + Math.floor((r - l) / 2);
|
||||
const midNode = sorted[m];
|
||||
this.add(midNode.key, midNode.value, midNode.count);
|
||||
if (this._isMapMode) this.add(midNode.key, undefined, midNode.count);
|
||||
else this.add(midNode.key, midNode.value, midNode.count);
|
||||
buildBalanceBST(l, m - 1);
|
||||
buildBalanceBST(m + 1, r);
|
||||
};
|
||||
|
@ -390,7 +384,8 @@ export class TreeMultiMap<
|
|||
if (l <= r) {
|
||||
const m = l + Math.floor((r - l) / 2);
|
||||
const midNode = sorted[m];
|
||||
this.add(midNode.key, midNode.value, midNode.count);
|
||||
if (this._isMapMode) this.add(midNode.key, undefined, midNode.count);
|
||||
else this.add(midNode.key, midNode.value, midNode.count);
|
||||
stack.push([m + 1, r]);
|
||||
stack.push([l, m - 1]);
|
||||
}
|
||||
|
@ -409,7 +404,8 @@ export class TreeMultiMap<
|
|||
*/
|
||||
override clone(): TREE {
|
||||
const cloned = this.createTree();
|
||||
this.bfs(node => cloned.add(node.key, node.value, node.count));
|
||||
this.bfs(node => cloned.add(node.key, undefined, node.count));
|
||||
if (this._isMapMode) cloned._store = this._store;
|
||||
return cloned;
|
||||
}
|
||||
|
||||
|
@ -419,17 +415,17 @@ export class TreeMultiMap<
|
|||
*
|
||||
* The `_swapProperties` function swaps the properties (key, value, count, color) between two nodes
|
||||
* in a binary search tree.
|
||||
* @param {R | BSTNKeyOrNode<K, NODE>} srcNode - The `srcNode` parameter represents the source node
|
||||
* @param {R | BSTNOptKeyOrNode<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 `BSTNKeyOrNode<K, NODE>` class.
|
||||
* @param {R | BSTNKeyOrNode<K, NODE>} destNode - The `destNode` parameter represents the destination
|
||||
* instance of the `BSTNOptKeyOrNode<K, NODE>` class.
|
||||
* @param {R | BSTNOptKeyOrNode<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 | BSTNKeyOrNode<K, NODE>,
|
||||
destNode: R | BSTNKeyOrNode<K, NODE>
|
||||
srcNode: R | BSTNOptKeyOrNode<K, NODE>,
|
||||
destNode: R | BSTNOptKeyOrNode<K, NODE>
|
||||
): NODE | undefined {
|
||||
srcNode = this.ensureNode(srcNode);
|
||||
destNode = this.ensureNode(destNode);
|
||||
|
@ -440,12 +436,12 @@ export class TreeMultiMap<
|
|||
tempNode.color = color;
|
||||
|
||||
destNode.key = srcNode.key;
|
||||
destNode.value = srcNode.value;
|
||||
if (!this._isMapMode) destNode.value = srcNode.value;
|
||||
destNode.count = srcNode.count;
|
||||
destNode.color = srcNode.color;
|
||||
|
||||
srcNode.key = tempNode.key;
|
||||
srcNode.value = tempNode.value;
|
||||
if (!this._isMapMode) srcNode.value = tempNode.value;
|
||||
srcNode.count = tempNode.count;
|
||||
srcNode.color = tempNode.color;
|
||||
}
|
||||
|
|
|
@ -266,9 +266,9 @@ export class Trie<R = any> extends IterableElementBase<string, R, Trie<R>> {
|
|||
*
|
||||
*/
|
||||
getHeight(): number {
|
||||
const beginRoot = this.root;
|
||||
const startNode = this.root;
|
||||
let maxDepth = 0;
|
||||
if (beginRoot) {
|
||||
if (startNode) {
|
||||
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(beginRoot, 0);
|
||||
bfs(startNode, 0);
|
||||
}
|
||||
return maxDepth;
|
||||
}
|
||||
|
|
|
@ -4,14 +4,14 @@ import type {
|
|||
BinaryTreeNested,
|
||||
BinaryTreeNodeNested,
|
||||
BinaryTreeOptions,
|
||||
BTNKeyOrNodeOrEntry,
|
||||
BTNPredicate
|
||||
BTNRep,
|
||||
NodePredicate
|
||||
} from '../types';
|
||||
|
||||
export interface IBinaryTree<
|
||||
K = any,
|
||||
V = any,
|
||||
R = [K, V],
|
||||
R = object,
|
||||
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: BTNKeyOrNodeOrEntry<K, V, NODE>, value?: V, count?: number): boolean;
|
||||
add(keyOrNodeOrEntryOrRawElement: BTNRep<K, V, NODE>, value?: V, count?: number): boolean;
|
||||
|
||||
addMany(nodes: Iterable<BTNKeyOrNodeOrEntry<K, V, NODE>>, values?: Iterable<V | undefined>): boolean[];
|
||||
addMany(nodes: Iterable<BTNRep<K, V, NODE>>, values?: Iterable<V | undefined>): boolean[];
|
||||
|
||||
delete(predicate: R | BTNKeyOrNodeOrEntry<K, V, NODE> | BTNPredicate<NODE>): BinaryTreeDeleteResult<NODE>[];
|
||||
delete(predicate: R | BTNRep<K, V, NODE> | NodePredicate<NODE>): BinaryTreeDeleteResult<NODE>[];
|
||||
}
|
||||
|
|
|
@ -6,31 +6,30 @@ 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?: (rawElement: R) => BTNEntry<K, V>;
|
||||
iterationType?: IterationType;
|
||||
toEntryFn?: ToEntryFn<K, V, R>;
|
||||
isMapMode?: boolean;
|
||||
}
|
||||
|
||||
export type BinaryTreePrintOptions = { isShowUndefined?: boolean; isShowNull?: boolean; isShowRedBlackNIL?: boolean };
|
||||
|
||||
export type OptBTNOrNull<NODE> = NODE | null | undefined;
|
||||
export type OptNodeOrNull<NODE> = NODE | null | undefined;
|
||||
|
||||
export type OptBTNKeyOrNull<K> = K | null | undefined;
|
||||
export type BTNOptKeyOrNull<K> = K | null | undefined;
|
||||
|
||||
export type BTNEntry<K, V> = [OptBTNKeyOrNull<K>, OptValue<V>];
|
||||
export type BTNEntry<K, V> = [BTNOptKeyOrNull<K>, OptValue<V>];
|
||||
|
||||
export type BTNKeyOrNode<K, NODE> = OptBTNKeyOrNull<K> | NODE;
|
||||
export type BTNOptKeyNodeOrNull<K, NODE> = BTNOptKeyOrNull<K> | NODE;
|
||||
|
||||
export type BTNKeyOrNodeOrEntry<K, V, NODE> = BTNEntry<K, V> | BTNKeyOrNode<K, NODE>;
|
||||
export type BTNRep<K, V, NODE> = BTNEntry<K, V> | BTNOptKeyNodeOrNull<K, NODE>;
|
||||
|
||||
export type BTNPureKeyOrNode<K, NODE> = K | NODE;
|
||||
export type BinaryTreeDeleteResult<NODE> = { deleted: OptNodeOrNull<NODE>; needBalanced: OptNodeOrNull<NODE> };
|
||||
|
||||
export type BTNPureKeyOrNodeOrEntry<K, V, NODE> = [K, OptValue<V>] | BTNPureKeyOrNode<K, NODE>;
|
||||
export type NodeCallback<NODE, D = any> = (node: NODE) => D;
|
||||
|
||||
export type BinaryTreeDeleteResult<NODE> = { deleted: OptBTNOrNull<NODE>; needBalanced: OptBTNOrNull<NODE> };
|
||||
export type NodePredicate<NODE> = (node: NODE) => boolean;
|
||||
|
||||
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> }
|
||||
export type DFSStackItem<NODE> = { opt: DFSOperation; node: OptNodeOrNull<NODE> }
|
||||
|
|
|
@ -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 OptBSTNKey<K> = K | undefined;
|
||||
export type BSTNOptKey<K> = K | undefined;
|
||||
|
||||
export type OptBSTN<NODE> = NODE | undefined;
|
||||
export type OptNode<NODE> = NODE | undefined;
|
||||
|
||||
export type BSTNKeyOrNode<K, NODE> = OptBSTNKey<K> | NODE;
|
||||
export type BSTNOptKeyOrNode<K, NODE> = BSTNOptKey<K> | NODE;
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import * as Benchmark from 'benchmark';
|
|||
import { getRandomIntArray, magnitude } from '../../../utils';
|
||||
|
||||
const suite = new Benchmark.Suite();
|
||||
const avlTree = new AVLTree<number>();
|
||||
const avlTree = new AVLTree<number>([], { isMapMode: true });
|
||||
const { HUNDRED_THOUSAND } = magnitude;
|
||||
const randomArray = getRandomIntArray(HUNDRED_THOUSAND, 0, HUNDRED_THOUSAND - 1, true);
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@ import * as Benchmark from 'benchmark';
|
|||
import { getRandomIntArray, magnitude } from '../../../utils';
|
||||
|
||||
const suite = new Benchmark.Suite();
|
||||
const rbTree = new RedBlackTree();
|
||||
const avlTree = new AVLTree();
|
||||
const rbTree = new RedBlackTree<number>([], { isMapMode: true });
|
||||
const avlTree = new AVLTree<number>([], { isMapMode: true });
|
||||
const { TEN_THOUSAND } = magnitude;
|
||||
const arr = getRandomIntArray(TEN_THOUSAND, 0, TEN_THOUSAND - 1, true);
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import * as Benchmark from 'benchmark';
|
|||
import { getRandomIntArray, magnitude } from '../../../utils';
|
||||
|
||||
const suite = new Benchmark.Suite();
|
||||
const biTree = new BinaryTree<number>();
|
||||
const biTree = new BinaryTree<number>([], { isMapMode: true });
|
||||
const { THOUSAND } = magnitude;
|
||||
const arr = getRandomIntArray(THOUSAND, 0, THOUSAND, true);
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import * as Benchmark from 'benchmark';
|
|||
import { getRandomIntArray, magnitude } from '../../../utils';
|
||||
|
||||
const suite = new Benchmark.Suite();
|
||||
const bst = new BST<number>();
|
||||
const bst = new BST<number>([], { isMapMode: true });
|
||||
const { TEN_THOUSAND } = magnitude;
|
||||
const arr = getRandomIntArray(TEN_THOUSAND, 0, TEN_THOUSAND, true);
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import { OrderedMap } from 'js-sdsl';
|
|||
import { isCompetitor } from '../../../config';
|
||||
|
||||
const suite = new Benchmark.Suite();
|
||||
const rbTree = new RedBlackTree();
|
||||
const rbTree = new RedBlackTree<number>([], { isMapMode: true });
|
||||
const { HUNDRED_THOUSAND } = magnitude;
|
||||
const randomArray = getRandomIntArray(HUNDRED_THOUSAND, 0, HUNDRED_THOUSAND - 1, true);
|
||||
const cOrderedMap = new OrderedMap<number, number>();
|
||||
|
|
|
@ -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.root?.right?.value).toBe('c');
|
||||
expect(cloned.get(cloned.root?.right)).toBe('c');
|
||||
});
|
||||
|
||||
it('should keys', () => {
|
||||
|
@ -761,3 +761,115 @@ 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);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -33,7 +33,6 @@ 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);
|
||||
|
@ -437,3 +436,90 @@ 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');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -20,6 +20,8 @@ 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;
|
||||
|
@ -319,26 +321,28 @@ 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);
|
||||
|
@ -729,34 +733,40 @@ describe('BinaryTree', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
it('should keyValueOrEntryOrRawElementToNode', () => {
|
||||
it('should keyValueNodeEntryRawToNodeAndValue', () => {
|
||||
const tree = new BinaryTree<number>();
|
||||
const node0 = tree.keyValueOrEntryOrRawElementToNode(0);
|
||||
expect(node0).toEqual({
|
||||
_left: undefined,
|
||||
_right: undefined,
|
||||
key: 0,
|
||||
parent: undefined,
|
||||
value: undefined
|
||||
});
|
||||
const node0 = tree.keyValueNodeEntryRawToNodeAndValue(0);
|
||||
expect(node0).toEqual([
|
||||
{
|
||||
_left: undefined,
|
||||
_right: undefined,
|
||||
key: 0,
|
||||
parent: undefined,
|
||||
value: undefined
|
||||
},
|
||||
undefined
|
||||
]);
|
||||
|
||||
const nodeUndefined = tree.keyValueOrEntryOrRawElementToNode(undefined);
|
||||
expect(nodeUndefined).toBe(undefined);
|
||||
const nodeUndefined = tree.keyValueNodeEntryRawToNodeAndValue(undefined);
|
||||
expect(nodeUndefined).toEqual([undefined, undefined]);
|
||||
|
||||
const nodeNull = tree.keyValueOrEntryOrRawElementToNode(null);
|
||||
expect(nodeNull).toBe(null);
|
||||
const nodeNull = tree.keyValueNodeEntryRawToNodeAndValue(null);
|
||||
expect(nodeNull).toEqual([null, undefined]);
|
||||
|
||||
const nodeWithSeparateValue = tree.keyValueOrEntryOrRawElementToNode(7, 77);
|
||||
expect(nodeWithSeparateValue?.value).toBe(77);
|
||||
const [, nodeWithSeparateValue] = tree.keyValueNodeEntryRawToNodeAndValue(7, 77);
|
||||
expect(nodeWithSeparateValue).toBe(77);
|
||||
|
||||
expect(tree.keyValueOrEntryOrRawElementToNode([undefined, 2])).toBe(undefined);
|
||||
expect(tree.keyValueNodeEntryRawToNodeAndValue([undefined, 2])).toEqual([undefined, undefined]);
|
||||
|
||||
expect(tree.keyValueOrEntryOrRawElementToNode(Symbol('test') as unknown as number)).toBe(undefined);
|
||||
expect(tree.keyValueNodeEntryRawToNodeAndValue(Symbol('test') as unknown as number)).toEqual([
|
||||
undefined,
|
||||
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.keyValueOrEntryOrRawElementToNode({ obj: { id: 1 } })).toBe(undefined);
|
||||
expect(bTree.keyValueNodeEntryRawToNodeAndValue({ obj: { id: 1 } })).toEqual([undefined, undefined]);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -1150,17 +1160,21 @@ describe('BinaryTree', () => {
|
|||
tree.add([2, 'B']);
|
||||
tree.add([null, 'null']);
|
||||
|
||||
const nodes = tree.getNodes(node => node.value === 'B');
|
||||
const nodes = tree.isMapMode ? tree.getNodes(node => node.key === 2) : tree.getNodes(node => node.value === 'B');
|
||||
|
||||
expect(nodes.length).toBe(1);
|
||||
expect(nodes[0].key).toBe(2);
|
||||
|
||||
const nodesRec = tree.getNodes(node => node.value === 'B', false, tree.root, 'RECURSIVE');
|
||||
const nodesRec = tree.isMapMode
|
||||
? tree.getNodes(node => node.key === 2, false, tree.root, 'RECURSIVE')
|
||||
: tree.getNodes(node => node.value === 'B', false, tree.root, 'RECURSIVE');
|
||||
|
||||
expect(nodesRec.length).toBe(1);
|
||||
expect(nodesRec[0].key).toBe(2);
|
||||
|
||||
const nodesItr = tree.getNodes(node => node.value === 'B', false, tree.root, 'ITERATIVE');
|
||||
const nodesItr = tree.isMapMode
|
||||
? tree.getNodes(node => node.key === 2, false, tree.root, 'ITERATIVE')
|
||||
: tree.getNodes(node => node.value === 'B', false, tree.root, 'ITERATIVE');
|
||||
|
||||
expect(nodesItr.length).toBe(1);
|
||||
expect(nodesItr[0].key).toBe(2);
|
||||
|
@ -1206,6 +1220,98 @@ 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(() => {
|
||||
|
@ -1273,7 +1379,8 @@ describe('BinaryTree iterative methods test', () => {
|
|||
it('should clone work well', () => {
|
||||
const cloned = binaryTree.clone();
|
||||
expect(cloned.root?.left?.key).toBe(2);
|
||||
expect(cloned.root?.right?.value).toBe('c');
|
||||
if (cloned.isMapMode) expect(cloned.get(cloned.root?.right)).toBe('c');
|
||||
else expect(cloned.root?.right?.value).toBe('c');
|
||||
});
|
||||
|
||||
it('should keys', () => {
|
||||
|
@ -1315,3 +1422,19 @@ 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');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { BinaryTreeNode, BST, BSTNode } from '../../../../src';
|
||||
import { isDebugTest, SYSTEM_MAX_CALL_STACK, isTestStackOverflow } from '../../../config';
|
||||
import { isDebugTest, isTestStackOverflow, SYSTEM_MAX_CALL_STACK } from '../../../config';
|
||||
|
||||
const isDebug = isDebugTest;
|
||||
|
||||
|
@ -450,22 +450,25 @@ describe('BST operations test', () => {
|
|||
expect(bfsNodes[2].key).toBe(16);
|
||||
});
|
||||
|
||||
it('should keyValueOrEntryOrRawElementToNode', () => {
|
||||
it('should keyValueNodeEntryRawToNodeAndValue', () => {
|
||||
const bst = new BST<number>();
|
||||
const node0 = bst.keyValueOrEntryOrRawElementToNode(0);
|
||||
expect(node0).toEqual({
|
||||
_left: undefined,
|
||||
_right: undefined,
|
||||
key: 0,
|
||||
parent: undefined,
|
||||
value: undefined
|
||||
});
|
||||
const node0 = bst.keyValueNodeEntryRawToNodeAndValue(0);
|
||||
expect(node0).toEqual([
|
||||
{
|
||||
_left: undefined,
|
||||
_right: undefined,
|
||||
key: 0,
|
||||
parent: undefined,
|
||||
value: undefined
|
||||
},
|
||||
undefined
|
||||
]);
|
||||
|
||||
const nodeUndefined = bst.keyValueOrEntryOrRawElementToNode(undefined);
|
||||
expect(nodeUndefined).toBe(undefined);
|
||||
const nodeUndefined = bst.keyValueNodeEntryRawToNodeAndValue(undefined);
|
||||
expect(nodeUndefined).toEqual([undefined, undefined]);
|
||||
|
||||
const nodeNull = bst.keyValueOrEntryOrRawElementToNode(null);
|
||||
expect(nodeNull).toBe(undefined);
|
||||
const nodeNull = bst.keyValueNodeEntryRawToNodeAndValue(null);
|
||||
expect(nodeNull).toEqual([undefined, undefined]);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -496,7 +499,7 @@ describe('BST operations test recursively', () => {
|
|||
expect(nodeId10?.key).toBe(10);
|
||||
|
||||
const nodeVal9 = bst.getNode(node => node.value === 9);
|
||||
expect(nodeVal9?.key).toBe(undefined);
|
||||
expect(bst.get(nodeVal9?.key)).toBe(undefined);
|
||||
|
||||
const leftMost = bst.getLeftMost();
|
||||
expect(leftMost).toBe(1);
|
||||
|
@ -1210,3 +1213,300 @@ 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']);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -817,7 +817,8 @@ describe('TreeMultiMap iterative methods test', () => {
|
|||
expect(treeMM.getComputedCount()).toBe(21);
|
||||
const cloned = treeMM.clone();
|
||||
expect(cloned.root?.left?.key).toBe(1);
|
||||
expect(cloned.root?.right?.value).toBe('c');
|
||||
if (cloned.isMapMode) expect(cloned.get(cloned.root?.right)).toBe('c');
|
||||
else expect(cloned.root?.right?.value).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should keys', () => {
|
||||
|
@ -835,3 +836,140 @@ 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');
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue