From fc01840930df04deef0157e6d0d7eccbed43922d Mon Sep 17 00:00:00 2001 From: Foldster Date: Wed, 6 May 2020 17:48:58 -0400 Subject: [PATCH 1/4] adding matlab implementation to tree traversal --- contents/tree_traversal/code/matlab/tree.m | 149 +++++++++++++++++++++ contents/tree_traversal/tree_traversal.md | 21 ++- 2 files changed, 164 insertions(+), 6 deletions(-) create mode 100644 contents/tree_traversal/code/matlab/tree.m diff --git a/contents/tree_traversal/code/matlab/tree.m b/contents/tree_traversal/code/matlab/tree.m new file mode 100644 index 000000000..e6ae313d5 --- /dev/null +++ b/contents/tree_traversal/code/matlab/tree.m @@ -0,0 +1,149 @@ +main() + +%% Functions + +function root = create_tree() + node = @(k,v) containers.Map(k,v); + + node2 = node(2, {{}}); node3 = node(3, {{}}); node4 = node(4, {{}}); + node6 = node(6, {{}}); node7 = node(7, {{}}); node8 = node(8, {{}}); + node10 = node(10, {{}}); node11 = node(11, {{}}); node12 = node(12, {{}}); + + node1 = node(1, {node2, node3, node4}); + node5 = node(5, {node6, node7, node8}); + node9 = node(9, {node10, node11, node12}); + + root = node(0, {node1, node5, node9}); +end + +function root = create_btree() + node = @(k,v) containers.Map(k,v); + + node2 = node(2, {{}}); node3 = node(3, {{}}); + node5 = node(5, {{}}); node6 = node(6, {{}}); + + node1 = node(1, {node2, node3}); + node4 = node(4, {node5, node6}); + + root = node(0, {node1, node4}); +end + +function DFS_recursive(n) + + cell_index = @(a, b) a{b}; + ID = cell_index(keys(n), 1); + + fprintf('%u ', ID); + + children = cell_index(values(n), 1); + for i = children + child = i{1}; + if length(child) + DFS_recursive(child); + end + end +end + +function DFS_recursive_postorder(n) + + cell_index = @(a, b) a{b}; + + children = cell_index(values(n), 1); + for i = children + child = i{1}; + if length(child) + DFS_recursive_postorder(child); + end + end + + ID = cell_index(keys(n), 1); + fprintf('%u ', ID); + +end + +function DFS_recursive_inorder_btree(n) + + cell_index = @(a, b) a{b}; + ID = cell_index(keys(n), 1); + children = cell_index(values(n), 1); + + if length(children) == 2 + DFS_recursive_inorder_btree(children{1}) + fprintf('%u ', ID) + DFS_recursive_inorder_btree(children{2}) + elseif length(children) == 1 + if length(children{1}) + DFS_recursive_inorder_btree(children{1}) + end + fprintf('%u ', ID) + else + fprintf("Not a binary tree!") + end +end + +function DFS_stack(n) + + cell_index = @(a, b) a{b}; + node_stack = {n}; + + while length(node_stack) > 0 + + parent = node_stack{end}; + node_stack(end) = []; + + ID = cell_index(keys(parent), 1); + fprintf('%u ', ID); + + children = cell_index(values(parent), 1); + + for i = flip(children) + child = i{1}; + if length(child) + node_stack = {node_stack{:} child}; + end + end + end +end + +function BFS_queue(n) + + cell_index = @(a, b) a{b}; + node_queue = {n}; + + while length(node_queue) > 0 + next_nodes = {}; + for parent_cell = node_queue + parent = parent_cell{1}; + ID = cell_index(keys(parent), 1); + fprintf('%u ', ID); + children = cell_index(values(parent), 1); + for i = children + child = i{1}; + if length(child) + next_nodes = {next_nodes{:}, child}; + end + end + end + node_queue = next_nodes; + end +end + +function main() + root = create_tree(); + rootb = create_btree(); + + fprintf('\nDFS Recursive\n') + DFS_recursive(root) + + fprintf('\nDFS Recursive Postorder\n') + DFS_recursive_postorder(root) + + fprintf('\nDFS Recursive Inorder Binary Tree\n') + DFS_recursive_inorder_btree(rootb) + + fprintf('\nDFS Stack\n') + DFS_stack(root) + + fprintf('\nBFS Queue\n') + BFS_queue(root) +end \ No newline at end of file diff --git a/contents/tree_traversal/tree_traversal.md b/contents/tree_traversal/tree_traversal.md index adfa0216c..d5598d8f3 100644 --- a/contents/tree_traversal/tree_traversal.md +++ b/contents/tree_traversal/tree_traversal.md @@ -38,6 +38,8 @@ As a note, a `node` struct is not necessary in javascript, so this is an example [import:24-27, lang:"asm-x64"](code/asm-x64/tree_traversal.s) {% sample lang="emojic" %} [import:1-3, lang:"emojicode"](code/emojicode/tree_traversal.emojic) +{% sample lang="m" %} +[import:6-6, lang:"matlab"](code/matlab/tree.m) {% endmethod %} 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 [import:290-314, lang:"asm-x64"](code/asm-x64/tree_traversal.s) {% sample lang="emojic" %} [import:27-34, lang:"emojicode"](code/emojicode/tree_traversal.emojic) +{% sample lang="m" %} +[import:31-45, lang:"matlab"](code/matlab/tree.m) {% endmethod %} 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 [import:316-344, lang:"asm-x64"](code/asm-x64/tree_traversal.s) {% sample lang="emojic" %} [import:36-43, lang:"emojicode"](code/emojicode/tree_traversal.emojic) +{% sample lang="m" %} +[import:47-62, lang:"matlab"](code/matlab/tree.m) {% endmethod %}

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

- -

- - The order here seems to be some mix of the other 2 methods and works through the binary tree from left to right. Now, at this point, it might seem that the only way to search through a recursive data structure is with recursion, but this is not necessarily the case! Rather surprisingly, we can perform a DFS non-recursively by using a stack, which are data structures that hold multiple elements, but only allow you to interact with the very last element you put in. The idea here is simple: @@ -221,12 +224,14 @@ In code, it looks like this: [import:398-445, lang:"asm-x64"](code/asm-x64/tree_traversal.s) {% sample lang="emojic" %} [import:64-79, lang:"emojicode"](code/emojicode/tree_traversal.emojic) +{% sample lang="m" %} +[import:84-106, lang:"matlab"](code/matlab/tree.m) {% endmethod %} 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:

- +

And this is exactly what Breadth-First Search (BFS) does! On top of that, it can be implemented in the same way as the `DFS_stack(...)` function above, simply by swapping the `stack` for a `queue`, which is similar to a stack, except that it only allows you to interact with the very first element instead of the last. In code, this looks something like: @@ -266,6 +271,8 @@ And this is exactly what Breadth-First Search (BFS) does! On top of that, it can [import:447-498, lang:"asm-x64"](code/asm-x64/tree_traversal.s) {% sample lang="emojic" %} [import:81-96, lang:"emojicode"](code/emojicode/tree_traversal.emojic) +{% sample lang="m" %} +[import:108-129, lang:"matlab"](code/matlab/tree.m) {% endmethod %} ## Video Explanation @@ -324,6 +331,8 @@ The code snippets were taken from this [Scratch project](https://scratch.mit.edu [import, lang:"asm-x64"](code/asm-x64/tree_traversal.s) {% sample lang="emojic" %} [import, lang:"emojicode"](code/emojicode/tree_traversal.emojic) +{% sample lang="m" %} +[import, lang:"matlab"](code/matlab/tree.m) {% endmethod %} From 76cf2bb69f8bfdef7a1bac3f681c3ca105465dfe Mon Sep 17 00:00:00 2001 From: Foldster Date: Wed, 6 May 2020 17:57:00 -0400 Subject: [PATCH 2/4] adding matlab implementation to tree traversal algorithm --- contents/tree_traversal/tree_traversal.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/contents/tree_traversal/tree_traversal.md b/contents/tree_traversal/tree_traversal.md index d5598d8f3..cf90ec0d1 100644 --- a/contents/tree_traversal/tree_traversal.md +++ b/contents/tree_traversal/tree_traversal.md @@ -178,6 +178,11 @@ In this case, the first node visited is at the bottom of the tree and moves up t [import:64-82, lang:"matlab"](code/matlab/tree.m) {% endmethod %} +

+ +

+ + The order here seems to be some mix of the other 2 methods and works through the binary tree from left to right. Now, at this point, it might seem that the only way to search through a recursive data structure is with recursion, but this is not necessarily the case! Rather surprisingly, we can perform a DFS non-recursively by using a stack, which are data structures that hold multiple elements, but only allow you to interact with the very last element you put in. The idea here is simple: @@ -231,7 +236,7 @@ In code, it looks like this: 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:

- +

And this is exactly what Breadth-First Search (BFS) does! On top of that, it can be implemented in the same way as the `DFS_stack(...)` function above, simply by swapping the `stack` for a `queue`, which is similar to a stack, except that it only allows you to interact with the very first element instead of the last. In code, this looks something like: From 497e0d881fc7c36090d0aa0767064046a4c57afe Mon Sep 17 00:00:00 2001 From: Foldster Date: Mon, 25 May 2020 17:49:20 -0400 Subject: [PATCH 3/4] replaced length truth comparison with not empty comparison for better performance --- contents/tree_traversal/code/matlab/tree.m | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/contents/tree_traversal/code/matlab/tree.m b/contents/tree_traversal/code/matlab/tree.m index e6ae313d5..398ed6ffc 100644 --- a/contents/tree_traversal/code/matlab/tree.m +++ b/contents/tree_traversal/code/matlab/tree.m @@ -38,7 +38,7 @@ function DFS_recursive(n) children = cell_index(values(n), 1); for i = children child = i{1}; - if length(child) + if ~isempty(child) DFS_recursive(child); end end @@ -51,7 +51,7 @@ function DFS_recursive_postorder(n) children = cell_index(values(n), 1); for i = children child = i{1}; - if length(child) + if ~isempty(child) DFS_recursive_postorder(child); end end @@ -98,7 +98,7 @@ function DFS_stack(n) for i = flip(children) child = i{1}; - if length(child) + if ~isempty(child) node_stack = {node_stack{:} child}; end end @@ -119,7 +119,7 @@ function BFS_queue(n) children = cell_index(values(parent), 1); for i = children child = i{1}; - if length(child) + if ~isempty(child) next_nodes = {next_nodes{:}, child}; end end @@ -146,4 +146,5 @@ function main() fprintf('\nBFS Queue\n') BFS_queue(root) + fprintf('\n') end \ No newline at end of file From 630a2030a642d1f0dcf945837c9b58c123b91530 Mon Sep 17 00:00:00 2001 From: Foldster Date: Mon, 25 May 2020 17:58:50 -0400 Subject: [PATCH 4/4] finishing replacements --- contents/tree_traversal/code/matlab/tree.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contents/tree_traversal/code/matlab/tree.m b/contents/tree_traversal/code/matlab/tree.m index 398ed6ffc..69d6ee856 100644 --- a/contents/tree_traversal/code/matlab/tree.m +++ b/contents/tree_traversal/code/matlab/tree.m @@ -72,7 +72,7 @@ function DFS_recursive_inorder_btree(n) fprintf('%u ', ID) DFS_recursive_inorder_btree(children{2}) elseif length(children) == 1 - if length(children{1}) + if ~isempty(children{1}) DFS_recursive_inorder_btree(children{1}) end fprintf('%u ', ID) @@ -86,7 +86,7 @@ function DFS_stack(n) cell_index = @(a, b) a{b}; node_stack = {n}; - while length(node_stack) > 0 + while ~isempty(node_stack) parent = node_stack{end}; node_stack(end) = []; @@ -110,7 +110,7 @@ function BFS_queue(n) cell_index = @(a, b) a{b}; node_queue = {n}; - while length(node_queue) > 0 + while ~isempty(node_queue) next_nodes = {}; for parent_cell = node_queue parent = parent_cell{1};