refactor: To standardize the _dfs method of the BinaryTree to achieve full generalization.

This commit is contained in:
Revone 2024-10-21 20:55:48 +13:00
parent e271f73de0
commit 5a492c1801
2 changed files with 100 additions and 101 deletions

View file

@ -823,43 +823,43 @@ Version 11.7.9
[//]: # (No deletion!!! Start of Replace Section)
<div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>heap</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 add</td><td>7.60</td><td>131.64</td><td>2.41e-4</td></tr><tr><td>100,000 add & poll</td><td>44.04</td><td>22.71</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>7.49</td><td>133.43</td><td>2.10e-4</td></tr><tr><td>100,000 add & poll</td><td>44.08</td><td>22.69</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'>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>77.11</td><td>12.97</td><td>0.00</td></tr><tr><td>100,000 add randomly</td><td>81.38</td><td>12.29</td><td>0.00</td></tr><tr><td>100,000 get</td><td>112.22</td><td>8.91</td><td>0.00</td></tr><tr><td>100,000 iterator</td><td>28.64</td><td>34.91</td><td>0.00</td></tr><tr><td>100,000 add & delete orderly</td><td>158.80</td><td>6.30</td><td>0.02</td></tr><tr><td>100,000 add & delete randomly</td><td>230.07</td><td>4.35</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>79.16</td><td>12.63</td><td>0.00</td></tr><tr><td>100,000 add randomly</td><td>84.35</td><td>11.85</td><td>0.00</td></tr><tr><td>100,000 get</td><td>111.74</td><td>8.95</td><td>0.00</td></tr><tr><td>100,000 iterator</td><td>26.61</td><td>37.58</td><td>0.00</td></tr><tr><td>100,000 add & delete orderly</td><td>160.05</td><td>6.25</td><td>0.02</td></tr><tr><td>100,000 add & delete randomly</td><td>234.55</td><td>4.26</td><td>0.01</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>queue</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>42.26</td><td>23.67</td><td>0.01</td></tr><tr><td>100,000 push & shift</td><td>5.07</td><td>197.32</td><td>5.97e-4</td></tr><tr><td>Native JS Array 100,000 push & shift</td><td>2252.79</td><td>0.44</td><td>0.17</td></tr></table></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>40.70</td><td>24.57</td><td>0.01</td></tr><tr><td>100,000 push & shift</td><td>5.15</td><td>194.25</td><td>6.57e-4</td></tr><tr><td>Native JS Array 100,000 push & shift</td><td>2143.37</td><td>0.47</td><td>0.15</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>deque</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>23.30</td><td>42.92</td><td>0.00</td></tr><tr><td>1,000,000 push & pop</td><td>31.90</td><td>31.34</td><td>0.00</td></tr><tr><td>1,000,000 push & shift</td><td>32.70</td><td>30.58</td><td>0.00</td></tr><tr><td>100,000 push & shift</td><td>3.40</td><td>293.73</td><td>2.64e-4</td></tr><tr><td>Native JS Array 100,000 push & shift</td><td>2225.02</td><td>0.45</td><td>0.08</td></tr><tr><td>100,000 unshift & shift</td><td>3.34</td><td>299.68</td><td>2.48e-4</td></tr><tr><td>Native JS Array 100,000 unshift & shift</td><td>3993.22</td><td>0.25</td><td>0.13</td></tr></table></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>24.74</td><td>40.43</td><td>0.00</td></tr><tr><td>1,000,000 push & pop</td><td>31.38</td><td>31.87</td><td>0.00</td></tr><tr><td>1,000,000 push & shift</td><td>32.12</td><td>31.13</td><td>0.00</td></tr><tr><td>100,000 push & shift</td><td>3.39</td><td>295.24</td><td>3.62e-4</td></tr><tr><td>Native JS Array 100,000 push & shift</td><td>2348.52</td><td>0.43</td><td>0.21</td></tr><tr><td>100,000 unshift & shift</td><td>3.28</td><td>304.60</td><td>2.76e-4</td></tr><tr><td>Native JS Array 100,000 unshift & shift</td><td>4062.43</td><td>0.25</td><td>0.12</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>106.42</td><td>9.40</td><td>0.01</td></tr><tr><td>Native JS Map 1,000,000 set</td><td>204.68</td><td>4.89</td><td>0.01</td></tr><tr><td>Native JS Set 1,000,000 add</td><td>166.12</td><td>6.02</td><td>0.01</td></tr><tr><td>1,000,000 set & get</td><td>118.98</td><td>8.40</td><td>0.02</td></tr><tr><td>Native JS Map 1,000,000 set & get</td><td>265.16</td><td>3.77</td><td>0.01</td></tr><tr><td>Native JS Set 1,000,000 add & has</td><td>169.18</td><td>5.91</td><td>0.01</td></tr><tr><td>1,000,000 ObjKey set & get</td><td>315.90</td><td>3.17</td><td>0.03</td></tr><tr><td>Native JS Map 1,000,000 ObjKey set & get</td><td>291.11</td><td>3.44</td><td>0.03</td></tr><tr><td>Native JS Set 1,000,000 ObjKey add & has</td><td>272.99</td><td>3.66</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>106.65</td><td>9.38</td><td>0.02</td></tr><tr><td>Native JS Map 1,000,000 set</td><td>201.70</td><td>4.96</td><td>0.01</td></tr><tr><td>Native JS Set 1,000,000 add</td><td>163.55</td><td>6.11</td><td>0.01</td></tr><tr><td>1,000,000 set & get</td><td>115.56</td><td>8.65</td><td>0.02</td></tr><tr><td>Native JS Map 1,000,000 set & get</td><td>264.29</td><td>3.78</td><td>0.01</td></tr><tr><td>Native JS Set 1,000,000 add & has</td><td>171.96</td><td>5.82</td><td>0.01</td></tr><tr><td>1,000,000 ObjKey set & get</td><td>326.27</td><td>3.06</td><td>0.05</td></tr><tr><td>Native JS Map 1,000,000 ObjKey set & get</td><td>322.17</td><td>3.10</td><td>0.06</td></tr><tr><td>Native JS Set 1,000,000 ObjKey add & has</td><td>241.34</td><td>4.14</td><td>0.03</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>trie</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 push</td><td>44.81</td><td>22.31</td><td>0.00</td></tr><tr><td>100,000 getWords</td><td>83.75</td><td>11.94</td><td>0.00</td></tr></table></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 push</td><td>44.21</td><td>22.62</td><td>0.00</td></tr><tr><td>100,000 getWords</td><td>85.22</td><td>11.73</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>270.91</td><td>3.69</td><td>0.02</td></tr><tr><td>100,000 add randomly</td><td>344.71</td><td>2.90</td><td>0.00</td></tr><tr><td>100,000 get</td><td>128.80</td><td>7.76</td><td>0.00</td></tr><tr><td>100,000 iterator</td><td>32.88</td><td>30.41</td><td>0.01</td></tr><tr><td>100,000 add & delete orderly</td><td>456.46</td><td>2.19</td><td>0.00</td></tr><tr><td>100,000 add & delete randomly</td><td>604.25</td><td>1.65</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>269.92</td><td>3.70</td><td>0.01</td></tr><tr><td>100,000 add randomly</td><td>317.13</td><td>3.15</td><td>0.00</td></tr><tr><td>100,000 get</td><td>127.74</td><td>7.83</td><td>0.00</td></tr><tr><td>100,000 iterator</td><td>29.99</td><td>33.34</td><td>0.01</td></tr><tr><td>100,000 add & delete orderly</td><td>431.27</td><td>2.32</td><td>0.00</td></tr><tr><td>100,000 add & delete randomly</td><td>580.91</td><td>1.72</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'>binary-tree-overall</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 RBTree add randomly</td><td>6.64</td><td>150.66</td><td>8.06e-5</td></tr><tr><td>10,000 RBTree get randomly</td><td>9.24</td><td>108.23</td><td>1.40e-4</td></tr><tr><td>10,000 RBTree add & delete randomly</td><td>18.25</td><td>54.79</td><td>2.59e-4</td></tr><tr><td>10,000 AVLTree add randomly</td><td>23.57</td><td>42.43</td><td>1.78e-4</td></tr><tr><td>10,000 AVLTree get randomly</td><td>9.69</td><td>103.21</td><td>8.94e-5</td></tr><tr><td>10,000 AVLTree add & delete randomly</td><td>44.37</td><td>22.54</td><td>4.23e-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>6.73</td><td>148.59</td><td>1.04e-4</td></tr><tr><td>10,000 RBTree get randomly</td><td>9.48</td><td>105.50</td><td>1.07e-4</td></tr><tr><td>10,000 RBTree add & delete randomly</td><td>18.40</td><td>54.33</td><td>2.70e-4</td></tr><tr><td>10,000 AVLTree add randomly</td><td>23.57</td><td>42.43</td><td>1.73e-4</td></tr><tr><td>10,000 AVLTree get randomly</td><td>9.70</td><td>103.06</td><td>7.92e-5</td></tr><tr><td>10,000 AVLTree add & delete randomly</td><td>44.43</td><td>22.51</td><td>3.33e-4</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>directed-graph</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000 addVertex</td><td>0.10</td><td>9718.49</td><td>1.33e-6</td></tr><tr><td>1,000 addEdge</td><td>6.28</td><td>159.34</td><td>1.59e-4</td></tr><tr><td>1,000 getVertex</td><td>0.04</td><td>2.57e+4</td><td>5.33e-7</td></tr><tr><td>1,000 getEdge</td><td>22.43</td><td>44.58</td><td>0.00</td></tr><tr><td>tarjan</td><td>200.86</td><td>4.98</td><td>0.01</td></tr><tr><td>topologicalSort</td><td>176.95</td><td>5.65</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>9723.27</td><td>2.46e-6</td></tr><tr><td>1,000 addEdge</td><td>6.26</td><td>159.78</td><td>7.28e-4</td></tr><tr><td>1,000 getVertex</td><td>0.04</td><td>2.54e+4</td><td>4.17e-7</td></tr><tr><td>1,000 getEdge</td><td>22.64</td><td>44.16</td><td>0.00</td></tr><tr><td>tarjan</td><td>200.14</td><td>5.00</td><td>0.01</td></tr><tr><td>topologicalSort</td><td>175.91</td><td>5.68</td><td>0.01</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>doubly-linked-list</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>205.86</td><td>4.86</td><td>0.07</td></tr><tr><td>1,000,000 unshift</td><td>199.96</td><td>5.00</td><td>0.03</td></tr><tr><td>1,000,000 unshift & shift</td><td>180.94</td><td>5.53</td><td>0.02</td></tr><tr><td>1,000,000 addBefore</td><td>308.98</td><td>3.24</td><td>0.10</td></tr></table></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>196.17</td><td>5.10</td><td>0.03</td></tr><tr><td>1,000,000 unshift</td><td>203.73</td><td>4.91</td><td>0.04</td></tr><tr><td>1,000,000 unshift & shift</td><td>186.32</td><td>5.37</td><td>0.04</td></tr><tr><td>1,000,000 addBefore</td><td>298.35</td><td>3.35</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'>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>206.48</td><td>4.84</td><td>0.09</td></tr><tr><td>10,000 push & pop</td><td>224.13</td><td>4.46</td><td>0.01</td></tr><tr><td>10,000 addBefore</td><td>246.92</td><td>4.05</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>210.62</td><td>4.75</td><td>0.09</td></tr><tr><td>10,000 push & pop</td><td>226.02</td><td>4.42</td><td>0.02</td></tr><tr><td>10,000 addBefore</td><td>249.35</td><td>4.01</td><td>0.01</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>priority-queue</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 add</td><td>27.02</td><td>37.01</td><td>2.69e-4</td></tr><tr><td>100,000 add & poll</td><td>75.97</td><td>13.16</td><td>5.61e-4</td></tr></table></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 add</td><td>27.23</td><td>36.72</td><td>7.64e-4</td></tr><tr><td>100,000 add & poll</td><td>76.66</td><td>13.04</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>38.52</td><td>25.96</td><td>0.00</td></tr><tr><td>1,000,000 push & pop</td><td>46.95</td><td>21.30</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>37.10</td><td>26.96</td><td>0.00</td></tr><tr><td>1,000,000 push & pop</td><td>44.72</td><td>22.36</td><td>0.01</td></tr></table></div>
</div>
[//]: # (No deletion!!! End of Replace Section)

View file

@ -22,12 +22,12 @@ import type {
NodeDisplayLayout,
OptBTNOrNull
} from '../../types';
import { DFSOperation, DFSStackItem } from '../../types';
import { IBinaryTree } from '../../interfaces';
import { trampoline } from '../../utils';
import { Queue } from '../queue';
import { IterableEntryBase } from '../base';
import * as console from 'console';
import { DFSOperation, DFSStackItem } from '../../types';
/**
* Represents a node in a binary tree.
@ -340,7 +340,7 @@ export class BinaryTree<
* `BTNKeyOrNodeOrEntry<K, V, NODE>`.
* @returns a boolean value.
*/
isNodeOrNull(node: R | BTNKeyOrNodeOrEntry<K, V, NODE>): node is NODE | null {
isRealNodeOrNull(node: R | BTNKeyOrNodeOrEntry<K, V, NODE>): node is NODE | null {
return this.isRealNode(node) || node === null;
}
@ -1487,8 +1487,8 @@ export class BinaryTree<
ans.push(callback(current));
if (includeNull) {
if (current && this.isNodeOrNull(current.left)) queue.push(current.left);
if (current && this.isNodeOrNull(current.right)) queue.push(current.right);
if (current && this.isRealNodeOrNull(current.left)) queue.push(current.left);
if (current && this.isRealNodeOrNull(current.right)) queue.push(current.right);
} else {
if (this.isRealNode(current.left)) queue.push(current.left);
if (this.isRealNode(current.right)) queue.push(current.right);
@ -1508,8 +1508,8 @@ export class BinaryTree<
ans.push(callback(current));
if (includeNull) {
if (current && this.isNodeOrNull(current.left)) queue.push(current.left);
if (current && this.isNodeOrNull(current.right)) queue.push(current.right);
if (current && this.isRealNodeOrNull(current.left)) queue.push(current.left);
if (current && this.isRealNodeOrNull(current.right)) queue.push(current.right);
} else {
if (this.isRealNode(current.left)) queue.push(current.left);
if (this.isRealNode(current.right)) queue.push(current.right);
@ -1637,8 +1637,8 @@ export class BinaryTree<
if (!levelsNodes[level]) levelsNodes[level] = [];
levelsNodes[level].push(callback(node));
if (includeNull) {
if (node && this.isNodeOrNull(node.left)) _recursive(node.left, level + 1);
if (node && this.isNodeOrNull(node.right)) _recursive(node.right, level + 1);
if (node && this.isRealNodeOrNull(node.left)) _recursive(node.left, level + 1);
if (node && this.isRealNodeOrNull(node.right)) _recursive(node.right, level + 1);
} else {
if (node && node.left) _recursive(node.left, level + 1);
if (node && node.right) _recursive(node.right, level + 1);
@ -1657,8 +1657,8 @@ export class BinaryTree<
levelsNodes[level].push(callback(node));
if (includeNull) {
if (node && this.isNodeOrNull(node.right)) stack.push([node.right, level + 1]);
if (node && this.isNodeOrNull(node.left)) stack.push([node.left, level + 1]);
if (node && this.isRealNodeOrNull(node.right)) stack.push([node.right, level + 1]);
if (node && this.isRealNodeOrNull(node.left)) stack.push([node.left, level + 1]);
} else {
if (node && node.right) stack.push([node.right, level + 1]);
if (node && node.left) stack.push([node.left, level + 1]);
@ -1945,83 +1945,89 @@ export class BinaryTree<
* Time complexity: O(n)
* Space complexity: O(n)
*
* The `dfs` function performs a depth-first search traversal on a binary tree, executing a callback
* function on each node according to a specified pattern and iteration type.
* @param {C} callback - The `callback` parameter is a function that will be called for each node
* visited during the depth-first search. It takes a node as an argument and returns a value. The
* return type of the callback function is determined by the generic type `C`.
* @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter determines the order in which the
* nodes are visited during the depth-first search. It can have one of the following values:
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} beginRoot - The `beginRoot` parameter is the starting
* point of the depth-first search. It can be either a node object, a key-value pair, or a key. If it
* is a key or key-value pair, the method will find the corresponding node in the tree and start the
* search from there.
* @param {IterationType} [iterationType=ITERATIVE] - The `iterationType` parameter determines the
* type of iteration to use during the depth-first search. It can have two possible values:
* @param [includeNull=false] - The `includeNull` parameter is a boolean value that determines
* whether or not to include null values in the depth-first search traversal. If `includeNull` is set
* to `true`, null values will be included in the traversal. If `includeNull` is set to `false`, null
* values will
* @returns an array of the return types of the callback function.
* The function `_dfs` performs a depth-first search traversal on a binary tree structure based on
* the specified order pattern and callback function.
* @param {C} callback - The `callback` parameter is a function that will be called on each node
* visited during the depth-first search. It is of type `C`, which extends
* `BTNCallback<OptBTNOrNull<NODE>>`. The default value is set to `this._DEFAULT_CALLBACK` if not
* provided.
* @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `_dfs` method specifies the
* order in which the Depth-First Search (DFS) algorithm should traverse the nodes in a binary tree.
* It can have one of the following values:
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} beginRoot - The `beginRoot` parameter in the `_dfs`
* method is used to specify the starting point for the depth-first search traversal in a binary
* tree. It can be provided as either the root node of the tree or a key, node, or entry that exists
* in the tree. If no specific `
* @param {IterationType} iterationType - The `iterationType` parameter in the `_dfs` method
* specifies the type of iteration to be performed during the Depth-First Search (DFS) traversal. It
* can have two possible values:
* @param [includeNull=false] - The `includeNull` parameter in the `_dfs` method is a boolean flag
* that determines whether null nodes should be included in the depth-first search traversal. If
* `includeNull` is set to `true`, the traversal will consider null nodes as valid nodes to visit and
* process. If set to `
* @param shouldVisitLeft - The `shouldVisitLeft` parameter is a function that takes a node as input
* and returns a boolean value. It is used to determine whether the left child of a node should be
* visited during the depth-first search traversal. By default, it checks if the node is truthy (not
* null or undefined
* @param shouldVisitRight - The `shouldVisitRight` parameter is a function that takes a node as
* input and returns a boolean value. It is used to determine whether the right child of a node
* should be visited during the depth-first search traversal. The default implementation checks if
* the node is truthy before visiting the right child.
* @param shouldVisitRoot - The `shouldVisitRoot` parameter is a function that takes a node as an
* argument and returns a boolean value. It is used to determine whether a given node should be
* visited during the depth-first search traversal based on certain conditions. The default
* implementation checks if the node is a real node or null based
* @param shouldProcessRoot - The `shouldProcessRoot` parameter is a function that takes a node as
* input and returns a boolean value indicating whether the node should be processed during the
* depth-first search traversal. The default implementation of this function simply returns `true`,
* meaning that by default all nodes will be processed. However, you can
* @returns The `_dfs` method returns an array of the return type of the callback function provided
* as input.
*/
protected _dfs<C extends BTNCallback<OptBTNOrNull<NODE>>>(
callback: C = this._DEFAULT_CALLBACK as C,
pattern: DFSOrderPattern = 'IN',
beginRoot: R | BTNKeyOrNodeOrEntry<K, V, NODE> = this.root,
iterationType: IterationType = this.iterationType,
includeNull = false
includeNull = false,
shouldVisitLeft: (node: OptBTNOrNull<NODE>) => boolean = node => !!node,
shouldVisitRight: (node: OptBTNOrNull<NODE>) => boolean = node => !!node,
shouldVisitRoot: (node: OptBTNOrNull<NODE>) => boolean = node => {
if (includeNull) return this.isRealNodeOrNull(node);
return this.isRealNode(node);
},
shouldProcessRoot: (node: OptBTNOrNull<NODE>) => boolean = node => true
): ReturnType<C>[] {
beginRoot = this.ensureNode(beginRoot);
if (!beginRoot) return [];
const ans: ReturnType<C>[] = [];
if (iterationType === 'RECURSIVE') {
const visitNullableLeft = (node: OptBTNOrNull<NODE>) => {
if (node && this.isNodeOrNull(node.left)) dfs(node.left);
};
const visitLeft = (node: OptBTNOrNull<NODE>) => {
if (node && this.isRealNode(node.left)) dfs(node.left);
};
const visitNullableRight = (node: OptBTNOrNull<NODE>) => {
if (node && this.isNodeOrNull(node.right)) dfs(node.right);
};
const visitRight = (node: OptBTNOrNull<NODE>) => {
if (node && this.isRealNode(node.right)) dfs(node.right);
};
if (iterationType === 'RECURSIVE') {
const dfs = (node: OptBTNOrNull<NODE>) => {
if (!shouldVisitRoot(node)) return;
const visitLeft = () => {
if (shouldVisitLeft(node)) dfs(node?.left);
};
const visitRight = () => {
if (shouldVisitRight(node)) dfs(node?.right);
};
switch (pattern) {
case 'IN':
if (includeNull) {
visitNullableLeft(node);
ans.push(callback(node));
visitNullableRight(node);
} else {
visitLeft(node);
ans.push(callback(node));
visitRight(node);
}
visitLeft();
if (shouldProcessRoot(node)) ans.push(callback(node));
visitRight();
break;
case 'PRE':
if (includeNull) {
ans.push(callback(node));
visitNullableLeft(node);
visitNullableRight(node);
} else {
ans.push(callback(node));
visitLeft(node);
visitRight(node);
}
if (shouldProcessRoot(node)) ans.push(callback(node));
visitLeft();
visitRight();
break;
case 'POST':
if (includeNull) {
visitNullableLeft(node);
visitNullableRight(node);
ans.push(callback(node));
} else {
visitLeft(node);
visitRight(node);
ans.push(callback(node));
}
visitLeft();
visitRight();
if (shouldProcessRoot(node)) ans.push(callback(node));
break;
}
};
@ -2029,47 +2035,40 @@ export class BinaryTree<
dfs(beginRoot);
} else {
const stack: DFSStackItem<NODE>[] = [{ opt: DFSOperation.VISIT, node: beginRoot }];
const pushLeft = (cur: DFSStackItem<NODE>) => {
cur.node && stack.push({ opt: DFSOperation.VISIT, node: cur.node.left });
if (shouldVisitLeft(cur.node)) stack.push({ opt: DFSOperation.VISIT, node: cur.node?.left });
};
const pushRight = (cur: DFSStackItem<NODE>) => {
cur.node && stack.push({ opt: DFSOperation.VISIT, node: cur.node.right });
if (shouldVisitRight(cur.node)) stack.push({ opt: DFSOperation.VISIT, node: cur.node?.right });
};
const pushParent = (cur: DFSStackItem<NODE>) => {
stack.push({ opt: DFSOperation.PROCESS, node: cur.node });
const pushRoot = (cur: DFSStackItem<NODE>) => {
if (shouldVisitRoot(cur.node)) stack.push({ opt: DFSOperation.PROCESS, node: cur.node });
};
while (stack.length > 0) {
const cur = stack.pop();
if (cur === undefined) continue;
if (includeNull) {
if (!this.isNodeOrNull(cur.node)) continue;
} else {
if (!this.isRealNode(cur.node)) continue;
}
if (cur.opt === 1) {
ans.push(callback(cur.node));
if (!shouldVisitRoot(cur.node)) continue;
if (cur.opt === DFSOperation.PROCESS) {
if (shouldProcessRoot(cur.node)) ans.push(callback(cur.node));
} else {
switch (pattern) {
case 'IN':
pushRight(cur);
pushParent(cur);
pushRoot(cur);
pushLeft(cur);
break;
case 'PRE':
pushRight(cur);
pushLeft(cur);
pushParent(cur);
pushRoot(cur);
break;
case 'POST':
pushParent(cur);
pushRoot(cur);
pushRight(cur);
pushLeft(cur);
break;
default:
pushRight(cur);
pushParent(cur);
pushLeft(cur);
break;
}
}
}