Skip to content

Commit 691a7e4

Browse files
authored
Tree Traversal in Common Lisp (algorithm-archivists#623)
1 parent 8e6cb6a commit 691a7e4

File tree

2 files changed

+110
-3
lines changed

2 files changed

+110
-3
lines changed
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
;;;; Tree traversal in Common Lisp
2+
3+
(defstruct node data children)
4+
5+
(defun dfs-recursive (node)
6+
"A depth first approach for printing out all values in a tree."
7+
(when (node-data node)
8+
(format t "~a " (node-data node)))
9+
(loop for child in (node-children node) do
10+
(dfs-recursive child)))
11+
12+
(defun dfs-recursive-postorder (node)
13+
"A depth first approach for printing out all values in a tree starting from the bottom."
14+
(loop for child in (node-children node) do
15+
(dfs-recursive-postorder child))
16+
(when (node-data node)
17+
(format t "~a " (node-data node))))
18+
19+
(defun dfs-recursive-inorder-btree (node)
20+
"A depth first search approach for printing all values in a binary tree."
21+
(case (length (node-children node))
22+
(2
23+
(dfs-recursive-inorder-btree (first (node-children node)))
24+
(format t "~a " (node-data node))
25+
(dfs-recursive-inorder-btree (second (node-children node))))
26+
(1
27+
(dfs-recursive-inorder-btree (first (node-children node)))
28+
(format t "~a " (node-data node)))
29+
(0
30+
(format t "~a " (node-data node)))
31+
(t
32+
(print "Invalid binary tree."))))
33+
34+
(defun dfs-stack (node)
35+
"A depth first approach for printing out all values in a tree using a stack."
36+
(loop
37+
with stack = (list node)
38+
with temp = nil
39+
while (> (length stack) 0) do
40+
(format t "~a " (node-data (first stack)))
41+
(setf temp (pop stack))
42+
(loop for child in (node-children temp) do
43+
(push child stack))))
44+
45+
(defun bfs-queue (node)
46+
"A breadth first search approach for printing out all values in a tree."
47+
(loop
48+
with queue = (list node)
49+
with temp = nil
50+
while (> (length queue) 0) do
51+
(format t "~a " (node-data (first queue)))
52+
(setf temp (pop queue))
53+
;; If the queue is empty, the queue should be filled with the children nodes.
54+
(if (eql queue nil)
55+
(setf queue (node-children temp))
56+
(nconc queue (node-children temp)))))
57+
58+
(defun make-tree (num-rows num-child)
59+
"Creates a simple tree, where every node has 'num-child' children and is 'num-rows' deep."
60+
;; A tree with 0 rows can't be created.
61+
(if (eql num-rows 1)
62+
(make-node
63+
:data 1
64+
:children nil)
65+
(make-node
66+
:data num-rows
67+
:children (loop repeat num-child collect (make-tree (1- num-rows) num-child)))))
68+
69+
;; A tree for testing
70+
(defvar tree (make-tree 3 3))
71+
72+
;; A binary tree for testing
73+
(defvar binary-tree (make-tree 3 2))
74+
75+
;; Should print: 3 2 1 1 1 2 1 1 1 2 1 1 1
76+
(dfs-recursive tree)
77+
(format t "~%")
78+
79+
;; Should print: 1 1 1 2 1 1 1 2 1 1 1 2 3
80+
(dfs-recursive-postorder tree)
81+
(format t "~%")
82+
83+
;; Should print: 1 2 1 3 1 2 1
84+
(dfs-recursive-inorder-btree binary-tree)
85+
(format t "~%")
86+
87+
;; Should print: 3 2 1 1 1 2 1 1 1 2 1 1 1
88+
(dfs-stack tree)
89+
(format t "~%")
90+
91+
;; Should print: 3 2 2 2 1 1 1 1 1 1 1 1 1
92+
(bfs-queue tree)
93+
(format t "~%")

contents/tree_traversal/tree_traversal.md

Lines changed: 17 additions & 3 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="lisp" %}
42+
[import:3-3, lang:"lisp"](code/clisp/tree-traversal.lisp)
4143
{% sample lang="m" %}
4244
[import:6-6, lang:"matlab"](code/matlab/tree.m)
4345
{% endmethod %}
@@ -79,6 +81,8 @@ Because of this, the most straightforward way to traverse the tree might be recu
7981
[import:290-314, lang:"asm-x64"](code/asm-x64/tree_traversal.s)
8082
{% sample lang="emojic" %}
8183
[import:27-34, lang:"emojicode"](code/emojicode/tree_traversal.emojic)
84+
{% sample lang="lisp" %}
85+
[import:5-10, lang:"lisp"](code/clisp/tree-traversal.lisp)
8286
{% sample lang="m" %}
8387
[import:31-45, lang:"matlab"](code/matlab/tree.m)
8488
{% endmethod %}
@@ -129,6 +133,8 @@ Now, in this case the first element searched through is still the root of the tr
129133
[import:316-344, lang:"asm-x64"](code/asm-x64/tree_traversal.s)
130134
{% sample lang="emojic" %}
131135
[import:36-43, lang:"emojicode"](code/emojicode/tree_traversal.emojic)
136+
{% sample lang="lisp" %}
137+
[import:12-17, lang:"lisp"](code/clisp/tree-traversal.lisp)
132138
{% sample lang="m" %}
133139
[import:47-62, lang:"matlab"](code/matlab/tree.m)
134140
{% endmethod %}
@@ -174,13 +180,15 @@ In this case, the first node visited is at the bottom of the tree and moves up t
174180
[import:346-396, lang:"asm-x64"](code/asm-x64/tree_traversal.s)
175181
{% sample lang="emojic" %}
176182
[import:45-62, lang:"emojicode"](code/emojicode/tree_traversal.emojic)
183+
{% sample lang="lisp" %}
184+
[import:19-32, lang:"lisp"](code/clisp/tree-traversal.lisp)
177185
{% sample lang="m" %}
178186
[import:64-82, lang:"matlab"](code/matlab/tree.m)
179187
{% endmethod %}
180188

181-
<p>
182-
<img class="center" src="res/DFS_in.png" width="500" />
183-
</p>
189+
<p>
190+
<img class="center" src="res/DFS_in.png" width="500" />
191+
</p>
184192

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

@@ -228,6 +236,8 @@ In code, it looks like this:
228236
[import:398-445, lang:"asm-x64"](code/asm-x64/tree_traversal.s)
229237
{% sample lang="emojic" %}
230238
[import:64-79, lang:"emojicode"](code/emojicode/tree_traversal.emojic)
239+
{% sample lang="lisp" %}
240+
[import:34-43, lang:"lisp"](code/clisp/tree-traversal.lisp)
231241
{% sample lang="m" %}
232242
[import:84-106, lang:"matlab"](code/matlab/tree.m)
233243
{% endmethod %}
@@ -275,6 +285,8 @@ And this is exactly what Breadth-First Search (BFS) does! On top of that, it can
275285
[import:447-498, lang:"asm-x64"](code/asm-x64/tree_traversal.s)
276286
{% sample lang="emojic" %}
277287
[import:81-96, lang:"emojicode"](code/emojicode/tree_traversal.emojic)
288+
{% sample lang="lisp" %}
289+
[import:45-56, lang:"lisp"](code/clisp/tree-traversal.lisp)
278290
{% sample lang="m" %}
279291
[import:108-129, lang:"matlab"](code/matlab/tree.m)
280292
{% endmethod %}
@@ -335,6 +347,8 @@ The code snippets were taken from this [Scratch project](https://scratch.mit.edu
335347
[import, lang:"asm-x64"](code/asm-x64/tree_traversal.s)
336348
{% sample lang="emojic" %}
337349
[import, lang:"emojicode"](code/emojicode/tree_traversal.emojic)
350+
{% sample lang="lisp" %}
351+
[import, lang:"lisp"](code/clisp/tree-traversal.lisp)
338352
{% sample lang="m" %}
339353
[import, lang:"matlab"](code/matlab/tree.m)
340354
{% endmethod %}

0 commit comments

Comments
 (0)