Skip to content

Commit 2f06313

Browse files
foldstersleios
andauthored
Tree traversal in MATLAB (#690)
* adding matlab implementation to tree traversal * adding matlab implementation to tree traversal algorithm * replaced length truth comparison with not empty comparison for better performance * finishing replacements Co-authored-by: James Schloss <jrs.schloss@gmail.com>
1 parent fb14e81 commit 2f06313

File tree

2 files changed

+167
-4
lines changed

2 files changed

+167
-4
lines changed
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
main()
2+
3+
%% Functions
4+
5+
function root = create_tree()
6+
node = @(k,v) containers.Map(k,v);
7+
8+
node2 = node(2, {{}}); node3 = node(3, {{}}); node4 = node(4, {{}});
9+
node6 = node(6, {{}}); node7 = node(7, {{}}); node8 = node(8, {{}});
10+
node10 = node(10, {{}}); node11 = node(11, {{}}); node12 = node(12, {{}});
11+
12+
node1 = node(1, {node2, node3, node4});
13+
node5 = node(5, {node6, node7, node8});
14+
node9 = node(9, {node10, node11, node12});
15+
16+
root = node(0, {node1, node5, node9});
17+
end
18+
19+
function root = create_btree()
20+
node = @(k,v) containers.Map(k,v);
21+
22+
node2 = node(2, {{}}); node3 = node(3, {{}});
23+
node5 = node(5, {{}}); node6 = node(6, {{}});
24+
25+
node1 = node(1, {node2, node3});
26+
node4 = node(4, {node5, node6});
27+
28+
root = node(0, {node1, node4});
29+
end
30+
31+
function DFS_recursive(n)
32+
33+
cell_index = @(a, b) a{b};
34+
ID = cell_index(keys(n), 1);
35+
36+
fprintf('%u ', ID);
37+
38+
children = cell_index(values(n), 1);
39+
for i = children
40+
child = i{1};
41+
if ~isempty(child)
42+
DFS_recursive(child);
43+
end
44+
end
45+
end
46+
47+
function DFS_recursive_postorder(n)
48+
49+
cell_index = @(a, b) a{b};
50+
51+
children = cell_index(values(n), 1);
52+
for i = children
53+
child = i{1};
54+
if ~isempty(child)
55+
DFS_recursive_postorder(child);
56+
end
57+
end
58+
59+
ID = cell_index(keys(n), 1);
60+
fprintf('%u ', ID);
61+
62+
end
63+
64+
function DFS_recursive_inorder_btree(n)
65+
66+
cell_index = @(a, b) a{b};
67+
ID = cell_index(keys(n), 1);
68+
children = cell_index(values(n), 1);
69+
70+
if length(children) == 2
71+
DFS_recursive_inorder_btree(children{1})
72+
fprintf('%u ', ID)
73+
DFS_recursive_inorder_btree(children{2})
74+
elseif length(children) == 1
75+
if ~isempty(children{1})
76+
DFS_recursive_inorder_btree(children{1})
77+
end
78+
fprintf('%u ', ID)
79+
else
80+
fprintf("Not a binary tree!")
81+
end
82+
end
83+
84+
function DFS_stack(n)
85+
86+
cell_index = @(a, b) a{b};
87+
node_stack = {n};
88+
89+
while ~isempty(node_stack)
90+
91+
parent = node_stack{end};
92+
node_stack(end) = [];
93+
94+
ID = cell_index(keys(parent), 1);
95+
fprintf('%u ', ID);
96+
97+
children = cell_index(values(parent), 1);
98+
99+
for i = flip(children)
100+
child = i{1};
101+
if ~isempty(child)
102+
node_stack = {node_stack{:} child};
103+
end
104+
end
105+
end
106+
end
107+
108+
function BFS_queue(n)
109+
110+
cell_index = @(a, b) a{b};
111+
node_queue = {n};
112+
113+
while ~isempty(node_queue)
114+
next_nodes = {};
115+
for parent_cell = node_queue
116+
parent = parent_cell{1};
117+
ID = cell_index(keys(parent), 1);
118+
fprintf('%u ', ID);
119+
children = cell_index(values(parent), 1);
120+
for i = children
121+
child = i{1};
122+
if ~isempty(child)
123+
next_nodes = {next_nodes{:}, child};
124+
end
125+
end
126+
end
127+
node_queue = next_nodes;
128+
end
129+
end
130+
131+
function main()
132+
root = create_tree();
133+
rootb = create_btree();
134+
135+
fprintf('\nDFS Recursive\n')
136+
DFS_recursive(root)
137+
138+
fprintf('\nDFS Recursive Postorder\n')
139+
DFS_recursive_postorder(root)
140+
141+
fprintf('\nDFS Recursive Inorder Binary Tree\n')
142+
DFS_recursive_inorder_btree(rootb)
143+
144+
fprintf('\nDFS Stack\n')
145+
DFS_stack(root)
146+
147+
fprintf('\nBFS Queue\n')
148+
BFS_queue(root)
149+
fprintf('\n')
150+
end

contents/tree_traversal/tree_traversal.md

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ As a note, a `node` struct is not necessary in javascript, so this is an example
3838
[import:24-27, lang:"asm-x64"](code/asm-x64/tree_traversal.s)
3939
{% sample lang="emojic" %}
4040
[import:1-3, lang:"emojicode"](code/emojicode/tree_traversal.emojic)
41+
{% sample lang="m" %}
42+
[import:6-6, lang:"matlab"](code/matlab/tree.m)
4143
{% endmethod %}
4244

4345
Because of this, the most straightforward way to traverse the tree might be recursive. This naturally leads us to the Depth-First Search (DFS) method:
@@ -77,6 +79,8 @@ Because of this, the most straightforward way to traverse the tree might be recu
7779
[import:290-314, lang:"asm-x64"](code/asm-x64/tree_traversal.s)
7880
{% sample lang="emojic" %}
7981
[import:27-34, lang:"emojicode"](code/emojicode/tree_traversal.emojic)
82+
{% sample lang="m" %}
83+
[import:31-45, lang:"matlab"](code/matlab/tree.m)
8084
{% endmethod %}
8185

8286
At least to me, this makes a lot of sense. We fight recursion with recursion! First, we first output the node we are on and then we call `DFS_recursive(...)` on each of its children nodes. This method of tree traversal does what its name implies: it goes to the depths of the tree first before going through the rest of the branches. In this case, the ordering looks like:
@@ -125,6 +129,8 @@ Now, in this case the first element searched through is still the root of the tr
125129
[import:316-344, lang:"asm-x64"](code/asm-x64/tree_traversal.s)
126130
{% sample lang="emojic" %}
127131
[import:36-43, lang:"emojicode"](code/emojicode/tree_traversal.emojic)
132+
{% sample lang="m" %}
133+
[import:47-62, lang:"matlab"](code/matlab/tree.m)
128134
{% endmethod %}
129135

130136
<p>
@@ -168,12 +174,13 @@ In this case, the first node visited is at the bottom of the tree and moves up t
168174
[import:346-396, lang:"asm-x64"](code/asm-x64/tree_traversal.s)
169175
{% sample lang="emojic" %}
170176
[import:45-62, lang:"emojicode"](code/emojicode/tree_traversal.emojic)
177+
{% sample lang="m" %}
178+
[import:64-82, lang:"matlab"](code/matlab/tree.m)
171179
{% endmethod %}
172180

173-
<p>
174-
<img class="center" src="res/DFS_in.png" style="width:70%" />
175-
</p>
176-
181+
<p>
182+
<img class="center" src="res/DFS_in.png" width="500" />
183+
</p>
177184

178185
The order here seems to be some mix of the other 2 methods and works through the binary tree from left to right.
179186

@@ -221,6 +228,8 @@ In code, it looks like this:
221228
[import:398-445, lang:"asm-x64"](code/asm-x64/tree_traversal.s)
222229
{% sample lang="emojic" %}
223230
[import:64-79, lang:"emojicode"](code/emojicode/tree_traversal.emojic)
231+
{% sample lang="m" %}
232+
[import:84-106, lang:"matlab"](code/matlab/tree.m)
224233
{% endmethod %}
225234

226235
All this said, there are a few details about DFS that might not be ideal, depending on the situation. For example, if we use DFS on an incredibly long tree, we will spend a lot of time going further and further down a single branch without searching the rest of the data structure. In addition, it is not the natural way humans would order a tree if asked to number all the nodes from top to bottom. I would argue a more natural traversal order would look something like this:
@@ -266,6 +275,8 @@ And this is exactly what Breadth-First Search (BFS) does! On top of that, it can
266275
[import:447-498, lang:"asm-x64"](code/asm-x64/tree_traversal.s)
267276
{% sample lang="emojic" %}
268277
[import:81-96, lang:"emojicode"](code/emojicode/tree_traversal.emojic)
278+
{% sample lang="m" %}
279+
[import:108-129, lang:"matlab"](code/matlab/tree.m)
269280
{% endmethod %}
270281

271282
## Video Explanation
@@ -324,6 +335,8 @@ The code snippets were taken from this [Scratch project](https://scratch.mit.edu
324335
[import, lang:"asm-x64"](code/asm-x64/tree_traversal.s)
325336
{% sample lang="emojic" %}
326337
[import, lang:"emojicode"](code/emojicode/tree_traversal.emojic)
338+
{% sample lang="m" %}
339+
[import, lang:"matlab"](code/matlab/tree.m)
327340
{% endmethod %}
328341

329342

0 commit comments

Comments
 (0)