I am trying to iterate through a tree inorder in Lisp. So far, I managed building the Postorder traversal but inorder gives me headaches..
The tree's format is this:
A
/ \
B C (A 2 B 0 C 2 D 0 E 0)
/ \
D E
(defun traverseTreeMain (l)
(traverseTree l nil)
)
(defun traverseTree (l lc)
(cond
((and (null l) (null lc)) nil)
((null l) (append nil (traverseTree lc nil)))
((=(cadr l) 0) (append (list (car l)) (traverseTree (cddr l) lc) ))
((= (cadr l) 1) (append nil (traverseTree (cddr l)
(append ( list (car l) (- (cadr l) 1) ) lc)
)
)
)
(t (append nil (traverseTree (cddr l) (append lc (list (car l) (- (cadr l) 1))))))
)
)
;;run: (traverseTreeMain '(A 2 B 0 C 2 D 0 E 0)) --POSTORDER
;;=> (B D E C A)
A possible approach here is first to construct the tree out of the preorder notation. To represent the binary tree nodes, we can use three-element lists (triplets). The first item in the triplet is the symbol:
A
,B
, ... the next two elements are the left and right references.Now, how to turn the syntax:
into a tree? One approach is to reverse the syntax first:
And now, we treat this as a little computer program written in a simple stack-based language with two instructions: numbers and symbols. We scan the syntax from left to right. When we see a number, we push it on the stack. When we see a symbol, we pop the top of a stack, which should be a number. That number then tells us how many nodes to pop off the stack: 0, 1 or 2. We do as we are told, and construct a tree out of the symbol, and that many child nodes. Then we put the tree on the stack. Code:
Note that the
(pop stack)
expression in thedolist
calculates the result value fordolist
, which is the return value for the function. When we are done interpreting the syntax, the complete tree is the only item left in the stack, and so we pop that.No effort is put into handling any errors in the syntax; we assume that the syntax is an error-free description of a tree.
Test:
Additional cases:
Looks good. The tree is rooted at
A
, with two children(B)
and(C (D) (E))
.(B)
means a B node with no children, and so Forth ... pardon the pun!This resulting structure can be walked in any order with ease.
Here is preorder traversal, using a callback function to process the symbols in the nodes. To "visit" means to pass the symbol to the callback. The user of the function specifies a function which does something, like collect the symbols passed to the callback:
Test:
The callback
lambda
pushes the items it receives into the output list, which is then destructively reversed.Inorder is left as a trivial exercise for the reader.
Another solution can be found by adapting the solution to this question: Transforming trees in lisp, where it is required to transform a tree from your notation to the list notation
(node left-child right-child)
.Here is the solution:
The auxiliary function
inorder-sequence
at each call receives the rest of the list, and returns a couple of values:the list containing the inorder of the part competing to the current recursive call, and
a list containing the rest of the elements that must be analyzed.
In this way, at each recursive step, the function itself can use the second value to generate the relative inorder.
Note that this approach works for any kind of elements as nodes of the tree, including integers.