Reputation: 10599
I have the following binary tree
A / \ B C / \ D E
represented as a list in Lisp (A 2 B 0 C 2 D 0 E 0) where the letters are node names and the numbers are the number of child nodes (0 for none, 1 one node, 2 two nodes). I need to find highest from root node to leaf depth of the tree (the depth of the binary tree that is) recursively. I'm pretty new to Lisp and I can't figure how to implement it. This is what I manage to come up with until now:
(defun depth (tree) "Returns the depth of the argument tree." (check-type tree list) (if (= (second tree) 0) 0 (1+ (get-btree-max-depth (cddr tree))))) (defun get-btree-max-depth (btree) "Returns the maximum depth of the argument tree." (check-type btree list) (if (= (second btree) 0) 0 (max (depth (cddr btree)) (get-btree-max-depth (cddr btree)))))
but it doesn't work properly. I also browsed similar postings but I didn't find anything useful that could help me. Could somebody give me a suggestion to help figure this out? Thank you!
P.S. This is part of a small project that I will present at University but also my own way of getting better in Lisp (I saw that many similar posts had questions asking if the posting is related to homework). :)
Upvotes: 4
Views: 4852
Reputation: 45086
Here's one in continuation-passing style:
(defun oddtree-height (oddtree)
(suboddtree-height oddtree
#'(lambda (h remainder)
(if (null remainder) h nil))))
(defun suboddtree-height (oddtree c)
(max-height-of-suboddtrees (cadr oddtree)
0
(cddr oddtree)
#'(lambda (h remainder)
(funcall c (+ h 1) remainder))))
(defun max-height-of-suboddtrees (n best oddtree c)
(if (= n 0)
(funcall c best oddtree)
(suboddtree-height oddtree
#'(lambda (h remainder)
(max-height-of-suboddtrees (- n 1) (max best h) remainder c)))))
Upvotes: 1
Reputation: 139251
How about this one? No transformation of the tree needed.
(defun depth-rec (tree)
(labels ((depth-rec-aux (depth) ; self-recursive function
(if (null tree) ; no more nodes
depth ; -> return the current depth
(let ((n (second tree))) ; number of subnodes
(pop tree) (pop tree) ; remove the current node
(case n
(0 (1+ depth)) ; no subnode, 1+depth
(1 (depth-rec-aux (1+ depth))) ; one subnode, its depth+1
(2 (max (depth-rec-aux (1+ depth)) ; two subnodes, their max
(depth-rec-aux (1+ depth)))))))))
(depth-rec-aux 0))) ; start depth is 0
Another version:
(defun depth-rec (tree &aux (max 0))
(labels ((depth-rec-aux (depth)
(when tree
(pop tree)
(let ((n (pop tree)))
(if (zerop n)
(setf max (max max (1+ depth)))
(loop repeat n do (depth-rec-aux (1+ depth))))))))
(depth-rec-aux 0))
max)
Upvotes: 3
Reputation: 10599
Using Artelius's and Svante's answer I managed to solve the issue. Here is the code, perhaps it will be of some help to somebody else in need.
(defun btree-max-depth (btree) "Returns the maximum depth of the binary tree." (check-type btree list) (if (null btree) 0 ; the max depth of the members of () (max (depth (first btree)) (btree-max-depth (rest btree))))) (defun depth (tree) "Returns the depth of the argument TREE." (if (atom tree) 0 ; an atomic tree has a depth of 0 (1+ (btree-max-depth tree))))
Thanks Artelius and Svante for your help!
Upvotes: 0
Reputation: 51501
I would first transform the list to a tree:
(defun tlist->tree (tlist)
"Transforms a tree represented as a kind of plist into a tree.
A tree like:
A
/ \
B C
/ / \
F D E
would have a tlist representation of (A 2 B 1 F 0 C 2 D 0 E 0).
The tree representation would be (A (B (F)) (C (D) (E)))"
(let (tree)
(push (pop tlist) tree)
(dotimes (i (pop tlist))
(multiple-value-bind (subnode rest-tlist) (tlist->tree tlist)
(push subnode tree)
(setf tlist rest-tlist)))
(values (nreverse tree) tlist)))
I wonder if you couldn't start with this tree representation to begin with.
Then, finding the depth of a tree in tree representation is a simple recursive one-liner.
Upvotes: 2