Skip to content

Commit 508d9a3

Browse files
NIFR91jiegillet
authored andcommitted
Added Tree traversal in Crystal-lang (#339)
* Added Tree Traversal in Crystal
1 parent 0ee2f8e commit 508d9a3

File tree

3 files changed

+130
-1
lines changed

3 files changed

+130
-1
lines changed

CONTRIBUTORS.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,3 @@ Bendik Samseth
6161
Trashtalk
6262
<br>
6363
Cyrus Burt
64-
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
class Node
2+
property id, children
3+
def initialize(@id : Int32, @children : Array(Node))
4+
end
5+
end
6+
7+
def dfs_recursive(node)
8+
print node.id
9+
node.children.each{ |child| dfs_recursive child }
10+
end
11+
12+
def dfs_recursive_postorder(node)
13+
node.children.each{ |child| dfs_recursive_postorder child }
14+
print node.id
15+
end
16+
17+
def dfs_recursive_inorder_btree(node)
18+
case node.children.size
19+
when 2
20+
dfs_recursive_inorder_btree node.children[0]
21+
print node.id
22+
dfs_recursive_inorder_btree node.children[1]
23+
when 1
24+
dfs_recursive_inorder_btree node.children[0]
25+
print node.id
26+
when 0
27+
print node.id
28+
else
29+
print "Not a binary tree!"
30+
end
31+
end
32+
33+
def dfs_stack(node)
34+
stack = [node]
35+
36+
until stack.empty?
37+
temp = stack.pop
38+
print temp.id
39+
temp.children.each{ |child| stack.push child }
40+
end
41+
end
42+
43+
def bfs_queue(node)
44+
queue = Deque.new [node]
45+
46+
until queue.empty?
47+
temp = queue.shift
48+
print temp.id
49+
temp.children.each{ |child| queue.push child }
50+
end
51+
end
52+
53+
def create_tree(levels, num_childs)
54+
55+
children = [] of Node
56+
unless levels == 0
57+
num_childs.times{children.push create_tree levels-1, num_childs }
58+
end
59+
60+
Node.new(levels, children)
61+
end
62+
63+
def print_tree(node, depth = [] of String)
64+
puts "(#{node.id})"
65+
depth.push " "
66+
len = node.children.size - 1
67+
68+
(0 .. len).each do |i|
69+
depth.each{|c| print c}
70+
unless i == len
71+
print ""
72+
depth.push ""
73+
print_tree node.children[i], depth
74+
depth.pop
75+
else
76+
print ""
77+
depth.push " "
78+
print_tree node.children[i], depth
79+
depth.pop
80+
end
81+
end
82+
depth.pop
83+
end
84+
85+
def main
86+
puts "Creating Tree"
87+
root = create_tree levels: 2, num_childs: 3
88+
print_tree root
89+
90+
puts "Using recursive DFS:"
91+
dfs_recursive root
92+
puts
93+
94+
puts "Using recursive DFS with post-order traversal:"
95+
dfs_recursive_postorder root
96+
puts
97+
98+
puts "Using stack-based DFS:"
99+
dfs_stack root
100+
puts
101+
102+
puts "Using queue-based BFS:"
103+
bfs_queue root
104+
puts
105+
106+
puts "Creating binary tree to test in-order traversal"
107+
root_bin = create_tree levels: 3, num_childs: 2
108+
print_tree root_bin
109+
110+
puts "Using In-order DFS:"
111+
dfs_recursive_inorder_btree root_bin
112+
puts
113+
end
114+
115+
main
116+

contents/tree_traversal/tree_traversal.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ This has not been implemented in your chosen language, so here is the Julia code
3030
[import:1-9, lang:"swift"](code/swift/tree.swift)
3131
{% sample lang="php"%}
3232
[import:3-27, lang:"php"](code/php/tree_traversal.php)
33+
{% sample lang="crystal" %}
34+
[import:1-5, lang:"crystal"](code/crystal/tree-traversal.cr)
3335
{% endmethod %}
3436

3537
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:
@@ -62,6 +64,8 @@ Because of this, the most straightforward way to traverse the tree might be recu
6264
[import:24-30, lang:"swift"](code/swift/tree.swift)
6365
{% sample lang="php"%}
6466
[import:31-35, lang:"php"](code/php/tree_traversal.php)
67+
{% sample lang="crystal" %}
68+
[import:7-10, lang:"crystal"](code/crystal/tree-traversal.cr)
6569
{% endmethod %}
6670

6771
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:
@@ -102,6 +106,8 @@ Now, in this case the first element searched through is still the root of the tr
102106
[import:32-38, lang:"swift"](code/swift/tree.swift)
103107
{% sample lang="php"%}
104108
[import:37-41, lang:"php"](code/php/tree_traversal.php)
109+
{% sample lang="crystal" %}
110+
[import:12-15, lang:"crystal"](code/crystal/tree-traversal.cr)
105111
{% endmethod %}
106112

107113
<p>
@@ -137,6 +143,8 @@ In this case, the first node visited is at the bottom of the tree and moves up t
137143
[import:40-53, lang:"swift"](code/swift/tree.swift)
138144
{% sample lang="php"%}
139145
[import:43-62, lang:"php"](code/php/tree_traversal.php)
146+
{% sample lang="crystal" %}
147+
[import:17-31, lang:"crystal"](code/crystal/tree-traversal.cr)
140148
{% endmethod %}
141149

142150
<p>
@@ -183,6 +191,8 @@ This has not been implemented in your chosen language, so here is the Julia code
183191
[import:55-67, lang:"swift"](code/swift/tree.swift)
184192
{% sample lang="php"%}
185193
[import:64-73, lang:"php"](code/php/tree_traversal.php)
194+
{% sample lang="crystal" %}
195+
[import:33-41, lang:"crystal"](code/crystal/tree-traversal.cr)
186196
{% endmethod %}
187197

188198
All this said, there are a few details about DFS that might not be idea, 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:
@@ -220,6 +230,8 @@ And this is exactly what Breadth-First Search (BFS) does! On top of that, it can
220230
[import:69-81, lang:"swift"](code/swift/tree.swift)
221231
{% sample lang="php"%}
222232
[import:65-74, lang:"php"](code/php/tree_traversal.php)
233+
{% sample lang="crystal" %}
234+
[import:43-51, lang:"crystal"](code/crystal/tree-traversal.cr)
223235
{% endmethod %}
224236

225237
## Example Code
@@ -259,6 +271,8 @@ The code snippets were taken from this [Scratch project](https://scratch.mit.edu
259271
[import, lang:"swift"](code/swift/tree.swift)
260272
{% sample lang="php"%}
261273
[import, lang:"php"](code/php/tree_traversal.php)
274+
{% sample lang="crystal" %}
275+
[import, lang:"crystal"](code/crystal/tree-traversal.cr)
262276
{% endmethod %}
263277

264278

0 commit comments

Comments
 (0)