views:

746

answers:

4

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). :)

+1  A: 

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.

Svante
+1  A: 

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!

crazybyte
The simple one-liner would have been: `(defun depth (tree) (1+ (apply #'max -1 (mapcar #'depth (rest tree)))))`, assuming that depth is defined as the maximum number of edges down.
Svante
I'm afraid I have to reconsider my answer given yesterday. It seems that one of the conditions is not to transform the list that describes the tree from one format to the other format, so I'm back to the starting point of not having a clue how to parse the list and calculate the depth of the binary tree. Any suggestion how to do this is welcomed and greatly appreciated. Thanks
crazybyte
+2  A: 

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)
Rainer Joswig
+1  A: 

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)))))
Jason Orendorff