Skip to content

Commit f512f11

Browse files
committed
Tree traversal in smalltalk
1 parent fc9947e commit f512f11

File tree

2 files changed

+115
-0
lines changed

2 files changed

+115
-0
lines changed
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
Object subclass: #Node
2+
instanceVariableNames: 'children data'
3+
classVariableNames: ''
4+
package: ''
5+
6+
Node>>children
7+
"Children getter."
8+
^ children
9+
10+
Node>>children: newChildren
11+
"Children setter."
12+
children := newChildren.
13+
14+
Node>>data
15+
"Data getter"
16+
^ data
17+
18+
Node>>data: newData
19+
"Data setter"
20+
data := newData.
21+
22+
Node>>dfsRecursive
23+
"Recursive depth first search."
24+
data isNil ifFalse: [
25+
Transcript show: data.
26+
Transcript cr.
27+
].
28+
children collect: [ :each | each dfsRecursive].
29+
30+
Node>>dfsRecursivePostorder
31+
"Recursive depth first search (post-order)."
32+
children collect: [ :each | each dfsRecursivePostorder ].
33+
data isNil ifTrue: [ ^ self ].
34+
Transcript show: data.
35+
Transcript cr.
36+
37+
Node>>dfsInOrderBinaryTree
38+
"Recursive depth first search on a binary tree in order."
39+
children size = 2 ifTrue: [
40+
(children at: 1) dfsInOrderBinaryTree.
41+
Transcript show: data.
42+
Transcript cr.
43+
(children at: 2) dfsInOrderBinaryTree.
44+
^self.
45+
].
46+
children size = 1 ifTrue: [
47+
(children at: 1) dfsInOrderBinaryTree.
48+
Transcript show: data.
49+
Transcript cr.
50+
^self.
51+
].
52+
children size = 0 ifTrue: [
53+
Transcript show: data.
54+
Transcript cr.
55+
^self.
56+
].
57+
Transcript show: 'This is not a binary tree!'.
58+
Transcript cr.
59+
children length
60+
61+
Node>>dfsStack
62+
"Depth-first search with a stack."
63+
| stack top |
64+
stack := Stack new.
65+
stack push: self.
66+
[stack size > 0] whileTrue: [
67+
top := stack pop.
68+
Transcript show: top data.
69+
Transcript cr.
70+
top children reverseDo: [ :child |
71+
stack push: child
72+
].
73+
].
74+
75+
Node>>bfs
76+
"A breadth-first tree search using queues."
77+
| queue current |
78+
queue := LinkedList with: self.
79+
[ queue size > 0 ] whileTrue: [
80+
current := queue first.
81+
queue removeFirst.
82+
Transcript show: current.
83+
Transcript cr.
84+
current children collect: [ :child |
85+
queue addLast: child
86+
].
87+
]
88+
89+
| test |
90+
test := Node new: 1 children: { Node new: 2.
91+
Node new: 3 children: { Node new: 4.
92+
Node new: 5. } }.
93+
test dfsRecursive.
94+
Transcript cr.
95+
test dfsRecursivePostorder.
96+
Transcript cr.
97+
test dfsInOrderBinaryTree.
98+
Transcript cr.
99+
test dfsStack.
100+
Transcript cr.
101+
test bfs.

contents/tree_traversal/tree_traversal.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ This has not been implemented in your chosen language, so here is the Julia code
3232
[import:3-27, lang:"php"](code/php/tree_traversal.php)
3333
{% sample lang="crystal" %}
3434
[import:1-5, lang:"crystal"](code/crystal/tree-traversal.cr)
35+
{% sample lang="st" %}
36+
[import:1-20, lang:"st"](code/smalltalk/tree_traversal.st)
3537
{% endmethod %}
3638

3739
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:
@@ -66,6 +68,8 @@ Because of this, the most straightforward way to traverse the tree might be recu
6668
[import:31-35, lang:"php"](code/php/tree_traversal.php)
6769
{% sample lang="crystal" %}
6870
[import:7-10, lang:"crystal"](code/crystal/tree-traversal.cr)
71+
{% sample lang="st" %}
72+
[import:22-28, lang:"st"](code/smalltalk/tree_traversal.st)
6973
{% endmethod %}
7074

7175
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:
@@ -108,6 +112,8 @@ Now, in this case the first element searched through is still the root of the tr
108112
[import:37-41, lang:"php"](code/php/tree_traversal.php)
109113
{% sample lang="crystal" %}
110114
[import:12-15, lang:"crystal"](code/crystal/tree-traversal.cr)
115+
{% sample lang="st" %}
116+
[import:30-35, lang:"st"](code/smalltalk/tree_traversal.st)
111117
{% endmethod %}
112118

113119
<p>
@@ -145,6 +151,8 @@ In this case, the first node visited is at the bottom of the tree and moves up t
145151
[import:43-62, lang:"php"](code/php/tree_traversal.php)
146152
{% sample lang="crystal" %}
147153
[import:17-31, lang:"crystal"](code/crystal/tree-traversal.cr)
154+
{% sample lang="st" %}
155+
[import:37-59, lang:"st"](code/smalltalk/tree_traversal.st)
148156
{% endmethod %}
149157

150158
<p>
@@ -192,6 +200,8 @@ In code, it looks like this:
192200
[import:64-73, lang:"php"](code/php/tree_traversal.php)
193201
{% sample lang="crystal" %}
194202
[import:33-41, lang:"crystal"](code/crystal/tree-traversal.cr)
203+
{% sample lang="st" %}
204+
[import:61-73, lang:"st"](code/smalltalk/tree_traversal.st)
195205
{% endmethod %}
196206

197207
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:
@@ -231,6 +241,8 @@ And this is exactly what Breadth-First Search (BFS) does! On top of that, it can
231241
[import:65-74, lang:"php"](code/php/tree_traversal.php)
232242
{% sample lang="crystal" %}
233243
[import:43-51, lang:"crystal"](code/crystal/tree-traversal.cr)
244+
{% sample lang="st" %}
245+
[import:75-87, lang:"st"](code/smalltalk/tree_traversal.st)
234246
{% endmethod %}
235247

236248
## Example Code
@@ -272,6 +284,8 @@ The code snippets were taken from this [Scratch project](https://scratch.mit.edu
272284
[import, lang:"php"](code/php/tree_traversal.php)
273285
{% sample lang="crystal" %}
274286
[import, lang:"crystal"](code/crystal/tree-traversal.cr)
287+
{% sample lang="st" %}
288+
[import, lang:"st"](code/smalltalk/tree_traversal.st)
275289
{% endmethod %}
276290

277291

0 commit comments

Comments
 (0)