mirror of
https://github.com/zrwusa/data-structure-typed.git
synced 2024-11-13 01:04:03 +00:00
feat: Refactor the BinaryTree's dfs method into a private helper function _dfs to prepare for a more generic implementation.
This commit is contained in:
parent
42235802c3
commit
e271f73de0
26
README.md
26
README.md
|
@ -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>8.07</td><td>123.93</td><td>0.00</td></tr><tr><td>100,000 add & poll</td><td>45.32</td><td>22.07</td><td>0.01</td></tr></table></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 add</td><td>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><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.03</td><td>12.98</td><td>0.00</td></tr><tr><td>100,000 add randomly</td><td>83.26</td><td>12.01</td><td>0.00</td></tr><tr><td>100,000 get</td><td>120.25</td><td>8.32</td><td>0.01</td></tr><tr><td>100,000 iterator</td><td>26.32</td><td>37.99</td><td>0.01</td></tr><tr><td>100,000 add & delete orderly</td><td>161.68</td><td>6.19</td><td>0.01</td></tr><tr><td>100,000 add & delete randomly</td><td>268.63</td><td>3.72</td><td>0.03</td></tr></table></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 add</td><td>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><div class="json-to-html-collapse clearfix 0">
|
||||
<div class='collapsible level0' ><span class='json-to-html-label'>queue</span></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>45.55</td><td>21.96</td><td>0.02</td></tr><tr><td>100,000 push & shift</td><td>5.54</td><td>180.36</td><td>0.00</td></tr><tr><td>Native JS Array 100,000 push & shift</td><td>2467.71</td><td>0.41</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>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><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>25.36</td><td>39.43</td><td>0.00</td></tr><tr><td>1,000,000 push & pop</td><td>32.13</td><td>31.12</td><td>0.00</td></tr><tr><td>1,000,000 push & shift</td><td>33.42</td><td>29.92</td><td>0.00</td></tr><tr><td>100,000 push & shift</td><td>3.59</td><td>278.92</td><td>3.21e-4</td></tr><tr><td>Native JS Array 100,000 push & shift</td><td>2427.03</td><td>0.41</td><td>0.21</td></tr><tr><td>100,000 unshift & shift</td><td>3.56</td><td>280.81</td><td>3.81e-4</td></tr><tr><td>Native JS Array 100,000 unshift & shift</td><td>4464.18</td><td>0.22</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>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><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>313.05</td><td>3.19</td><td>0.07</td></tr><tr><td>Native JS Map 1,000,000 set</td><td>224.48</td><td>4.45</td><td>0.05</td></tr><tr><td>Native JS Set 1,000,000 add</td><td>203.46</td><td>4.91</td><td>0.05</td></tr><tr><td>1,000,000 set & get</td><td>281.79</td><td>3.55</td><td>0.07</td></tr><tr><td>Native JS Map 1,000,000 set & get</td><td>289.57</td><td>3.45</td><td>0.03</td></tr><tr><td>Native JS Set 1,000,000 add & has</td><td>195.73</td><td>5.11</td><td>0.02</td></tr><tr><td>1,000,000 ObjKey set & get</td><td>348.39</td><td>2.87</td><td>0.03</td></tr><tr><td>Native JS Map 1,000,000 ObjKey set & get</td><td>315.23</td><td>3.17</td><td>0.04</td></tr><tr><td>Native JS Set 1,000,000 ObjKey add & has</td><td>335.83</td><td>2.98</td><td>0.06</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.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><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>48.09</td><td>20.79</td><td>0.00</td></tr><tr><td>100,000 getWords</td><td>93.17</td><td>10.73</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>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><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>278.91</td><td>3.59</td><td>0.01</td></tr><tr><td>100,000 add randomly</td><td>350.65</td><td>2.85</td><td>0.02</td></tr><tr><td>100,000 get</td><td>154.97</td><td>6.45</td><td>0.03</td></tr><tr><td>100,000 iterator</td><td>34.78</td><td>28.75</td><td>0.02</td></tr><tr><td>100,000 add & delete orderly</td><td>445.45</td><td>2.24</td><td>0.00</td></tr><tr><td>100,000 add & delete randomly</td><td>616.61</td><td>1.62</td><td>0.03</td></tr></table></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 add</td><td>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><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.07</td><td>141.45</td><td>7.19e-4</td></tr><tr><td>10,000 RBTree get randomly</td><td>9.33</td><td>107.21</td><td>1.48e-4</td></tr><tr><td>10,000 RBTree add & delete randomly</td><td>18.60</td><td>53.77</td><td>3.93e-4</td></tr><tr><td>10,000 AVLTree add randomly</td><td>30.39</td><td>32.91</td><td>0.01</td></tr><tr><td>10,000 AVLTree get randomly</td><td>10.70</td><td>93.49</td><td>0.00</td></tr><tr><td>10,000 AVLTree add & delete randomly</td><td>46.04</td><td>21.72</td><td>0.00</td></tr></table></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 RBTree add 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><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.13</td><td>7502.53</td><td>6.69e-5</td></tr><tr><td>1,000 addEdge</td><td>7.93</td><td>126.13</td><td>0.00</td></tr><tr><td>1,000 getVertex</td><td>0.05</td><td>2.19e+4</td><td>1.17e-5</td></tr><tr><td>1,000 getEdge</td><td>18.65</td><td>53.61</td><td>0.00</td></tr><tr><td>tarjan</td><td>158.86</td><td>6.30</td><td>0.01</td></tr><tr><td>topologicalSort</td><td>141.91</td><td>7.05</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>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><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>211.26</td><td>4.73</td><td>0.03</td></tr><tr><td>1,000,000 unshift</td><td>216.90</td><td>4.61</td><td>0.07</td></tr><tr><td>1,000,000 unshift & shift</td><td>208.45</td><td>4.80</td><td>0.05</td></tr><tr><td>1,000,000 addBefore</td><td>316.55</td><td>3.16</td><td>0.06</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>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><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>222.81</td><td>4.49</td><td>0.08</td></tr><tr><td>10,000 push & pop</td><td>235.91</td><td>4.24</td><td>0.01</td></tr><tr><td>10,000 addBefore</td><td>250.57</td><td>3.99</td><td>0.01</td></tr></table></div>
|
||||
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push & shift</td><td>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><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.64</td><td>36.17</td><td>8.81e-4</td></tr><tr><td>100,000 add & poll</td><td>75.52</td><td>13.24</td><td>9.91e-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.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><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>40.47</td><td>24.71</td><td>0.01</td></tr><tr><td>1,000,000 push & pop</td><td>47.47</td><td>21.07</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>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>
|
||||
|
||||
[//]: # (No deletion!!! End of Replace Section)
|
||||
|
|
|
@ -27,6 +27,7 @@ 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.
|
||||
|
@ -1373,8 +1374,7 @@ export class BinaryTree<
|
|||
callback?: C,
|
||||
pattern?: DFSOrderPattern,
|
||||
beginRoot?: R | BTNKeyOrNodeOrEntry<K, V, NODE>,
|
||||
iterationType?: IterationType,
|
||||
includeNull?: false
|
||||
iterationType?: IterationType
|
||||
): ReturnType<C>[];
|
||||
|
||||
dfs<C extends BTNCallback<NODE | null>>(
|
||||
|
@ -1382,7 +1382,7 @@ export class BinaryTree<
|
|||
pattern?: DFSOrderPattern,
|
||||
beginRoot?: R | BTNKeyOrNodeOrEntry<K, V, NODE>,
|
||||
iterationType?: IterationType,
|
||||
includeNull?: true
|
||||
includeNull?: boolean
|
||||
): ReturnType<C>[];
|
||||
|
||||
/**
|
||||
|
@ -1422,90 +1422,7 @@ export class BinaryTree<
|
|||
): ReturnType<C>[] {
|
||||
beginRoot = this.ensureNode(beginRoot);
|
||||
if (!beginRoot) return [];
|
||||
const ans: ReturnType<C>[] = [];
|
||||
if (iterationType === 'RECURSIVE') {
|
||||
const dfs = (node: OptBTNOrNull<NODE>) => {
|
||||
switch (pattern) {
|
||||
case 'IN':
|
||||
if (includeNull) {
|
||||
if (this.isRealNode(node) && this.isNodeOrNull(node.left)) dfs(node.left);
|
||||
this.isNodeOrNull(node) && ans.push(callback(node));
|
||||
if (this.isRealNode(node) && this.isNodeOrNull(node.right)) dfs(node.right);
|
||||
} else {
|
||||
if (this.isRealNode(node) && this.isRealNode(node.left)) dfs(node.left);
|
||||
this.isRealNode(node) && ans.push(callback(node));
|
||||
if (this.isRealNode(node) && this.isRealNode(node.right)) dfs(node.right);
|
||||
}
|
||||
break;
|
||||
case 'PRE':
|
||||
if (includeNull) {
|
||||
this.isNodeOrNull(node) && ans.push(callback(node));
|
||||
if (this.isRealNode(node) && this.isNodeOrNull(node.left)) dfs(node.left);
|
||||
if (this.isRealNode(node) && this.isNodeOrNull(node.right)) dfs(node.right);
|
||||
} else {
|
||||
this.isRealNode(node) && ans.push(callback(node));
|
||||
if (this.isRealNode(node) && this.isRealNode(node.left)) dfs(node.left);
|
||||
if (this.isRealNode(node) && this.isRealNode(node.right)) dfs(node.right);
|
||||
}
|
||||
break;
|
||||
case 'POST':
|
||||
if (includeNull) {
|
||||
if (this.isRealNode(node) && this.isNodeOrNull(node.left)) dfs(node.left);
|
||||
if (this.isRealNode(node) && this.isNodeOrNull(node.right)) dfs(node.right);
|
||||
this.isNodeOrNull(node) && ans.push(callback(node));
|
||||
} else {
|
||||
if (this.isRealNode(node) && this.isRealNode(node.left)) dfs(node.left);
|
||||
if (this.isRealNode(node) && this.isRealNode(node.right)) dfs(node.right);
|
||||
this.isRealNode(node) && ans.push(callback(node));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
dfs(beginRoot);
|
||||
} else {
|
||||
// 0: visit, 1: print
|
||||
const stack: { opt: 0 | 1; node: OptBTNOrNull<NODE> }[] = [{ opt: 0, node: beginRoot }];
|
||||
|
||||
while (stack.length > 0) {
|
||||
const cur = stack.pop();
|
||||
if (cur === undefined || this.isNIL(cur.node)) continue;
|
||||
if (includeNull) {
|
||||
if (cur.node === undefined) continue;
|
||||
} else {
|
||||
if (cur.node === null || cur.node === undefined) continue;
|
||||
}
|
||||
if (cur.opt === 1) {
|
||||
ans.push(callback(cur.node));
|
||||
} else {
|
||||
switch (pattern) {
|
||||
case 'IN':
|
||||
cur.node && stack.push({ opt: 0, node: cur.node.right });
|
||||
stack.push({ opt: 1, node: cur.node });
|
||||
cur.node && stack.push({ opt: 0, node: cur.node.left });
|
||||
break;
|
||||
case 'PRE':
|
||||
cur.node && stack.push({ opt: 0, node: cur.node.right });
|
||||
cur.node && stack.push({ opt: 0, node: cur.node.left });
|
||||
stack.push({ opt: 1, node: cur.node });
|
||||
break;
|
||||
case 'POST':
|
||||
stack.push({ opt: 1, node: cur.node });
|
||||
cur.node && stack.push({ opt: 0, node: cur.node.right });
|
||||
cur.node && stack.push({ opt: 0, node: cur.node.left });
|
||||
break;
|
||||
default:
|
||||
cur.node && stack.push({ opt: 0, node: cur.node.right });
|
||||
stack.push({ opt: 1, node: cur.node });
|
||||
cur.node && stack.push({ opt: 0, node: cur.node.left });
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ans;
|
||||
return this._dfs(callback, pattern, beginRoot, iterationType, includeNull);
|
||||
}
|
||||
|
||||
bfs<C extends BTNCallback<NODE>>(
|
||||
|
@ -2004,6 +1921,163 @@ export class BinaryTree<
|
|||
display(beginRoot);
|
||||
}
|
||||
|
||||
protected _dfs<C extends BTNCallback<NODE>>(
|
||||
callback?: C,
|
||||
pattern?: DFSOrderPattern,
|
||||
beginRoot?: R | BTNKeyOrNodeOrEntry<K, V, NODE>,
|
||||
iterationType?: IterationType
|
||||
): ReturnType<C>[];
|
||||
|
||||
protected _dfs<C extends BTNCallback<NODE | null>>(
|
||||
callback?: C,
|
||||
pattern?: DFSOrderPattern,
|
||||
beginRoot?: R | BTNKeyOrNodeOrEntry<K, V, NODE>,
|
||||
iterationType?: IterationType,
|
||||
includeNull?: boolean
|
||||
): ReturnType<C>[];
|
||||
|
||||
/**
|
||||
* Time complexity: O(n)
|
||||
* Space complexity: O(n)
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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
|
||||
): 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);
|
||||
};
|
||||
|
||||
const dfs = (node: OptBTNOrNull<NODE>) => {
|
||||
switch (pattern) {
|
||||
case 'IN':
|
||||
if (includeNull) {
|
||||
visitNullableLeft(node);
|
||||
ans.push(callback(node));
|
||||
visitNullableRight(node);
|
||||
} else {
|
||||
visitLeft(node);
|
||||
ans.push(callback(node));
|
||||
visitRight(node);
|
||||
}
|
||||
break;
|
||||
case 'PRE':
|
||||
if (includeNull) {
|
||||
ans.push(callback(node));
|
||||
visitNullableLeft(node);
|
||||
visitNullableRight(node);
|
||||
} else {
|
||||
ans.push(callback(node));
|
||||
visitLeft(node);
|
||||
visitRight(node);
|
||||
}
|
||||
break;
|
||||
case 'POST':
|
||||
if (includeNull) {
|
||||
visitNullableLeft(node);
|
||||
visitNullableRight(node);
|
||||
ans.push(callback(node));
|
||||
} else {
|
||||
visitLeft(node);
|
||||
visitRight(node);
|
||||
ans.push(callback(node));
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
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 });
|
||||
};
|
||||
const pushRight = (cur: DFSStackItem<NODE>) => {
|
||||
cur.node && stack.push({ opt: DFSOperation.VISIT, node: cur.node.right });
|
||||
};
|
||||
const pushParent = (cur: DFSStackItem<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));
|
||||
} else {
|
||||
switch (pattern) {
|
||||
case 'IN':
|
||||
pushRight(cur);
|
||||
pushParent(cur);
|
||||
pushLeft(cur);
|
||||
break;
|
||||
case 'PRE':
|
||||
pushRight(cur);
|
||||
pushLeft(cur);
|
||||
pushParent(cur);
|
||||
break;
|
||||
case 'POST':
|
||||
pushParent(cur);
|
||||
pushRight(cur);
|
||||
pushLeft(cur);
|
||||
break;
|
||||
default:
|
||||
pushRight(cur);
|
||||
pushParent(cur);
|
||||
pushLeft(cur);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ans;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(1)
|
||||
* Space Complexity: O(1)
|
||||
|
|
|
@ -557,7 +557,7 @@ export class BST<
|
|||
beginRoot: R | BTNKeyOrNodeOrEntry<K, V, NODE> = this.root,
|
||||
iterationType: IterationType = this.iterationType
|
||||
): ReturnType<C>[] {
|
||||
return super.dfs(callback, pattern, beginRoot, iterationType, false);
|
||||
return super.dfs(callback, pattern, beginRoot, iterationType);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -28,4 +28,11 @@ export type BTNPureKeyOrNodeOrEntry<K, V, NODE> = [K, OptValue<V>] | BTNPureKeyO
|
|||
|
||||
export type BinaryTreeDeleteResult<NODE> = { deleted: OptBTNOrNull<NODE>; needBalanced: OptBTNOrNull<NODE> };
|
||||
|
||||
export type BTNCallback<NODE, D = any> = (node: NODE) => D;
|
||||
export type BTNCallback<NODE, D = any> = (node: NODE) => D;
|
||||
|
||||
export enum DFSOperation {
|
||||
VISIT = 0,
|
||||
PROCESS = 1,
|
||||
}
|
||||
|
||||
export type DFSStackItem<NODE> = { opt: DFSOperation; node: OptBTNOrNull<NODE> }
|
|
@ -292,29 +292,178 @@ describe('BinaryTree', () => {
|
|||
expect(tree.getNodes(tree.getNodeByKey(2), undefined, false, tree.root)).toEqual([tree.getNodeByKey(2)]);
|
||||
});
|
||||
|
||||
it('should tree traverse', () => {
|
||||
tree.addMany([4, 2, 6, null, 1, 3, null, 5, null, 7]);
|
||||
expect(tree.dfs(node => node.key, 'PRE', undefined, 'ITERATIVE')).toEqual([4, 2, 1, 5, 6, 3, 7]);
|
||||
expect(tree.dfs(node => (node !== null ? node.key : null), 'PRE', undefined, 'ITERATIVE', false)).toEqual([
|
||||
4, 2, 1, 5, 6, 3, 7
|
||||
]);
|
||||
expect(tree.dfs(node => (node !== null ? node.key : null), 'PRE', undefined, 'ITERATIVE', true)).toEqual([
|
||||
4,
|
||||
2,
|
||||
null,
|
||||
1,
|
||||
5,
|
||||
null,
|
||||
6,
|
||||
3,
|
||||
7,
|
||||
null
|
||||
]);
|
||||
|
||||
expect(tree.dfs(node => node.key, 'PRE', undefined, 'RECURSIVE')).toEqual([4, 2, 1, 5, 6, 3, 7]);
|
||||
expect(tree.dfs(node => (node !== null ? node.key : null), 'PRE', undefined, 'RECURSIVE', false)).toEqual([
|
||||
4, 2, 1, 5, 6, 3, 7
|
||||
]);
|
||||
expect(tree.dfs(node => (node !== null ? node.key : null), 'PRE', undefined, 'RECURSIVE', true)).toEqual([
|
||||
4,
|
||||
2,
|
||||
null,
|
||||
1,
|
||||
5,
|
||||
null,
|
||||
6,
|
||||
3,
|
||||
7,
|
||||
null
|
||||
]);
|
||||
|
||||
expect(tree.dfs(node => node.key, 'IN', undefined, 'ITERATIVE')).toEqual([2, 5, 1, 4, 7, 3, 6]);
|
||||
expect(tree.dfs(node => (node !== null ? node.key : null), 'IN', undefined, 'ITERATIVE', false)).toEqual([
|
||||
2, 5, 1, 4, 7, 3, 6
|
||||
]);
|
||||
expect(tree.dfs(node => (node !== null ? node.key : null), 'IN', undefined, 'ITERATIVE', true)).toEqual([
|
||||
null,
|
||||
2,
|
||||
5,
|
||||
1,
|
||||
null,
|
||||
4,
|
||||
7,
|
||||
3,
|
||||
6,
|
||||
null
|
||||
]);
|
||||
|
||||
expect(tree.dfs(node => node.key, 'IN', undefined, 'RECURSIVE')).toEqual([2, 5, 1, 4, 7, 3, 6]);
|
||||
expect(tree.dfs(node => (node !== null ? node.key : null), 'IN', undefined, 'RECURSIVE', false)).toEqual([
|
||||
2, 5, 1, 4, 7, 3, 6
|
||||
]);
|
||||
expect(tree.dfs(node => (node !== null ? node.key : null), 'IN', undefined, 'RECURSIVE', true)).toEqual([
|
||||
null,
|
||||
2,
|
||||
5,
|
||||
1,
|
||||
null,
|
||||
4,
|
||||
7,
|
||||
3,
|
||||
6,
|
||||
null
|
||||
]);
|
||||
|
||||
expect(tree.dfs(node => node.key, 'POST', undefined, 'ITERATIVE')).toEqual([5, 1, 2, 7, 3, 6, 4]);
|
||||
expect(tree.dfs(node => (node !== null ? node.key : null), 'POST', undefined, 'ITERATIVE', false)).toEqual([
|
||||
5, 1, 2, 7, 3, 6, 4
|
||||
]);
|
||||
expect(tree.dfs(node => (node !== null ? node.key : null), 'POST', undefined, 'ITERATIVE', true)).toEqual([
|
||||
null,
|
||||
5,
|
||||
null,
|
||||
1,
|
||||
2,
|
||||
7,
|
||||
3,
|
||||
null,
|
||||
6,
|
||||
4
|
||||
]);
|
||||
|
||||
expect(tree.dfs(node => node.key, 'POST', undefined, 'RECURSIVE')).toEqual([5, 1, 2, 7, 3, 6, 4]);
|
||||
expect(tree.dfs(node => (node !== null ? node.key : null), 'POST', undefined, 'RECURSIVE', false)).toEqual([
|
||||
5, 1, 2, 7, 3, 6, 4
|
||||
]);
|
||||
expect(tree.dfs(node => (node !== null ? node.key : null), 'POST', undefined, 'RECURSIVE', true)).toEqual([
|
||||
null,
|
||||
5,
|
||||
null,
|
||||
1,
|
||||
2,
|
||||
7,
|
||||
3,
|
||||
null,
|
||||
6,
|
||||
4
|
||||
]);
|
||||
});
|
||||
|
||||
it('should sub tree traverse', () => {
|
||||
tree.addMany([4, 2, 6, null, 1, 3, null, 5, null, 7]);
|
||||
expect(tree.dfs(node => node.key, 'PRE', tree.getNode(6), 'ITERATIVE')).toEqual([6, 3, 7]);
|
||||
expect(tree.dfs(node => node.key, 'PRE', tree.getNode(6), 'ITERATIVE', false)).toEqual([6, 3, 7]);
|
||||
expect(tree.dfs(node => (node !== null ? node.key : null), 'PRE', tree.getNode(6), 'ITERATIVE', false)).toEqual([
|
||||
6, 3, 7
|
||||
]);
|
||||
expect(tree.dfs(node => (node !== null ? node.key : null), 'PRE', tree.getNode(6), 'ITERATIVE', true)).toEqual([
|
||||
6,
|
||||
3,
|
||||
7,
|
||||
null
|
||||
]);
|
||||
|
||||
expect(tree.dfs(node => node.key, 'PRE', tree.getNode(6), 'RECURSIVE')).toEqual([6, 3, 7]);
|
||||
expect(tree.dfs(node => (node ? node.key : null), 'PRE', tree.getNode(6), 'ITERATIVE', true)).toEqual([
|
||||
expect(tree.dfs(node => (node !== null ? node.key : null), 'PRE', tree.getNode(6), 'RECURSIVE', false)).toEqual([
|
||||
6, 3, 7
|
||||
]);
|
||||
expect(tree.dfs(node => (node !== null ? node.key : null), 'PRE', tree.getNode(6), 'RECURSIVE', true)).toEqual([
|
||||
6,
|
||||
3,
|
||||
7,
|
||||
null
|
||||
]);
|
||||
expect(tree.dfs(node => (node ? node.key : node), 'PRE', tree.getNode(6), 'ITERATIVE', true)).toEqual([
|
||||
6,
|
||||
3,
|
||||
|
||||
expect(tree.dfs(node => node.key, 'IN', tree.getNode(6), 'ITERATIVE')).toEqual([7, 3, 6]);
|
||||
expect(tree.dfs(node => (node !== null ? node.key : null), 'IN', tree.getNode(6), 'ITERATIVE', false)).toEqual([
|
||||
7, 3, 6
|
||||
]);
|
||||
expect(tree.dfs(node => (node !== null ? node.key : null), 'IN', tree.getNode(6), 'ITERATIVE', true)).toEqual([
|
||||
7,
|
||||
3,
|
||||
6,
|
||||
null
|
||||
]);
|
||||
expect(tree.dfs(node => (node ? node.key : null), 'PRE', tree.getNode(6), 'RECURSIVE', true)).toEqual([
|
||||
6,
|
||||
3,
|
||||
|
||||
expect(tree.dfs(node => node.key, 'IN', tree.getNode(6), 'RECURSIVE')).toEqual([7, 3, 6]);
|
||||
expect(tree.dfs(node => (node !== null ? node.key : null), 'IN', tree.getNode(6), 'RECURSIVE', false)).toEqual([
|
||||
7, 3, 6
|
||||
]);
|
||||
expect(tree.dfs(node => (node !== null ? node.key : null), 'IN', tree.getNode(6), 'RECURSIVE', true)).toEqual([
|
||||
7,
|
||||
3,
|
||||
6,
|
||||
null
|
||||
]);
|
||||
|
||||
expect(tree.dfs(node => node.key, 'POST', tree.getNode(6), 'ITERATIVE')).toEqual([7, 3, 6]);
|
||||
expect(tree.dfs(node => (node !== null ? node.key : null), 'POST', tree.getNode(6), 'ITERATIVE', false)).toEqual([
|
||||
7, 3, 6
|
||||
]);
|
||||
expect(tree.dfs(node => (node !== null ? node.key : null), 'POST', tree.getNode(6), 'ITERATIVE', true)).toEqual([
|
||||
7,
|
||||
3,
|
||||
null,
|
||||
6
|
||||
]);
|
||||
|
||||
expect(tree.dfs(node => node.key, 'POST', tree.getNode(6), 'RECURSIVE')).toEqual([7, 3, 6]);
|
||||
expect(tree.dfs(node => (node !== null ? node.key : null), 'POST', tree.getNode(6), 'RECURSIVE', false)).toEqual([
|
||||
7, 3, 6
|
||||
]);
|
||||
expect(tree.dfs(node => (node !== null ? node.key : null), 'POST', tree.getNode(6), 'RECURSIVE', true)).toEqual([
|
||||
7,
|
||||
3,
|
||||
null,
|
||||
6
|
||||
]);
|
||||
});
|
||||
|
||||
it('should clear the tree', () => {
|
||||
|
|
Loading…
Reference in a new issue