Tree traversal

From Rosetta Code
Revision as of 16:40, 15 September 2009 by rosettacode>Glennj (→‎{{header|Ruby}}: add class method to construct a tree from a nested list of values.)
Task
Tree traversal
You are encouraged to solve this task according to the task description, using any language you may know.

Implement a binary tree where each node carries an integer, and implement preoder, inorder, postorder and level-order traversal. Use those traversals to output the following tree:

         1
        / \
       /   \
      /     \
     2       3
    / \     /
   4   5   6
  /       / \
 7       8   9

The correct output should look like this:

preorder:    1 2 4 7 5 3 6 8 9
inorder:     7 4 2 5 1 8 6 9 3
postorder:   7 4 5 2 8 9 6 3 1
level-order: 1 2 3 4 5 6 7 8 9

This article has more information on traversing trees.

Ada

<lang Ada>with Ada.Text_Io; use Ada.Text_Io; with Ada.Unchecked_Deallocation; with Ada.Containers.Doubly_Linked_Lists;

procedure Tree_Traversal is

  type Node;
  type Node_Access is access Node;
  type Node is record
     Left : Node_Access := null;
     Right : Node_Access := null;
     Data : Integer;
  end record;
  procedure Destroy_Tree(N : in out Node_Access) is
     procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);
  begin
     if N.Left /= null then
        Destroy_Tree(N.Left);
     end if;
     if N.Right /= null then 
        Destroy_Tree(N.Right);
     end if;
     Free(N);
  end Destroy_Tree;
  function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is
     Temp : Node_Access := new Node;
  begin
     Temp.Data := Value;
     Temp.Left := Left;
     Temp.Right := Right;
     return Temp;
  end Tree;
  procedure Preorder(N : Node_Access) is
  begin
     Put(Integer'Image(N.Data));
     if N.Left /= null then
        Preorder(N.Left);
     end if;
     if N.Right /= null then
        Preorder(N.Right);
     end if;
  end Preorder;
  procedure Inorder(N : Node_Access) is
  begin
     if N.Left /= null then
        Inorder(N.Left);
     end if;
     Put(Integer'Image(N.Data));
     if N.Right /= null then
        Inorder(N.Right);
     end if;
  end Inorder;
  procedure Postorder(N : Node_Access) is
  begin
     if N.Left /= null then
        Postorder(N.Left);
     end if;
     if N.Right /= null then
        Postorder(N.Right);
     end if;
     Put(Integer'Image(N.Data));
  end Postorder;
  procedure Levelorder(N : Node_Access) is
     package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);
     use Queues;
     Node_Queue : List;
     Next : Node_Access;
  begin
     Node_Queue.Append(N);
     while not Is_Empty(Node_Queue) loop
        Next := First_Element(Node_Queue);
        Delete_First(Node_Queue);
        Put(Integer'Image(Next.Data));
        if Next.Left /= null then
           Node_Queue.Append(Next.Left);
        end if;
        if Next.Right /= null then
           Node_Queue.Append(Next.Right);
        end if;
     end loop;
  end Levelorder;
  N : Node_Access;

begin

  N := Tree(1, 
     Tree(2,
        Tree(4,
           Tree(7, null, null),
           null),
        Tree(5, null, null)),
     Tree(3,
        Tree(6,
           Tree(8, null, null),
           Tree(9, null, null)),
        null));
        
  Put("preorder:    ");
  Preorder(N);
  New_Line;
  Put("inorder:     ");
  Inorder(N);
  New_Line;
  Put("postorder:   ");
  Postorder(N);
  New_Line;
  Put("level order: ");
  Levelorder(N);
  New_Line;
  Destroy_Tree(N);

end Tree_traversal;</lang>

C

<lang c>#include <stdlib.h>

  1. include <stdio.h>

typedef struct node_s {

 int value;
 struct node_s* left;
 struct node_s* right;

} *node;

node tree(int v, node l, node r) {

 node n = malloc(sizeof(struct node_s));
 n->value = v;
 n->left  = l;
 n->right = r;
 return n;

}

void destroy_tree(node n) {

 if (n->left)
   destroy_tree(n->left);
 if (n->right)
   destroy_tree(n->right);
 free(n);

}

void preorder(node n, void (*f)(int)) {

 f(n->value);
 if (n->left)
   preorder(n->left, f);
 if (n->right)
   preorder(n->right, f);

}

void inorder(node n, void (*f)(int)) {

 if (n->left)
   inorder(n->left, f);
 f(n->value);
 if (n->right)
   inorder(n->right, f);

}

void postorder(node n, void (*f)(int)) {

 if (n->left)
   postorder(n->left, f);
 if (n->right)
   postorder(n->right, f);
 f(n->value);

}

/* helper queue for levelorder */ typedef struct qnode_s {

 struct qnode_s* next;
 node value;

} *qnode;

typedef struct { qnode begin, end; } queue;

void enqueue(queue* q, node n) {

 qnode node = malloc(sizeof(struct qnode_s));
 node->value = n;
 node->next = 0;
 if (q->end)
   q->end->next = node;
 else
   q->begin = node;
 q->end = node;

}

node dequeue(queue* q) {

 node tmp = q->begin->value;
 qnode second = q->begin->next;
 free(q->begin);
 q->begin = second;
 if (!q->begin)
   q->end = 0;
 return tmp;

}

int queue_empty(queue* q) {

 return !q->begin;

}

void levelorder(node n, void(*f)(int)) {

 queue nodequeue = {};
 enqueue(&nodequeue, n);
 while (!queue_empty(&nodequeue))
 {
   node next = dequeue(&nodequeue);
   f(next->value);
   if (next->left)
     enqueue(&nodequeue, next->left);
   if (next->right)
     enqueue(&nodequeue, next->right);
 }

}

void print(int n) {

 printf("%d ", n);

}

int main() {

 node n = tree(1,
               tree(2,
                    tree(4,
                         tree(7, 0, 0),
                         0),
                    tree(5, 0, 0)),
               tree(3,
                    tree(6,
                         tree(8, 0, 0),
                         tree(9, 0, 0)),
                    0));
 printf("preorder:    ");
 preorder(n, print);
 printf("\n");
 printf("inorder:     ");
 inorder(n, print);
 printf("\n");
 printf("postorder:   ");
 postorder(n, print);
 printf("\n");
 printf("level-order: ");
 levelorder(n, print);
 printf("\n");
 destroy_tree(n);
 return 0;

}</lang>

C++

Compiler: g++ (version 4.3.2 20081105 (Red Hat 4.3.2-7))

Library: Boost version 1.39.0

<lang cpp>#include <boost/scoped_ptr.hpp>

  1. include <iostream>
  2. include <queue>

template<typename T> class TreeNode { public:

 TreeNode(const T& n, TreeNode* left = NULL, TreeNode* right = NULL)
   : mValue(n),
     mLeft(left),
     mRight(right) {}
 T getValue() const {
   return mValue;
 }
 TreeNode* left() const {
   return mLeft.get();
 }
 TreeNode* right() const {
   return mRight.get();
 }
 void preorderTraverse() const {
   std::cout << " " << getValue();
   if(mLeft)  { mLeft->preorderTraverse();  }
   if(mRight) { mRight->preorderTraverse(); }
 }
 void inorderTraverse() const {
   if(mLeft)  { mLeft->inorderTraverse();  }
   std::cout << " " << getValue();
   if(mRight) { mRight->inorderTraverse(); }
 }
 void postorderTraverse() const {
   if(mLeft)  { mLeft->postorderTraverse();  }
   if(mRight) { mRight->postorderTraverse(); }
   std::cout << " " << getValue();
 }
 void levelorderTraverse() const {
   std::queue<const TreeNode*> q;
   q.push(this);
   while(!q.empty()) {
     const TreeNode* n = q.front();
     q.pop();
     std::cout << " " << n->getValue();
     if(n->left())  { q.push(n->left());  }
     if(n->right()) { q.push(n->right()); }
   }
 }

protected:

 T mValue;
 boost::scoped_ptr<TreeNode> mLeft;
 boost::scoped_ptr<TreeNode> mRight;

private:

 TreeNode();

};

int main() {

 TreeNode<int> root(1,
   new TreeNode<int>(2,
     new TreeNode<int>(4,
       new TreeNode<int>(7)),
     new TreeNode<int>(5)),
   new TreeNode<int>(3,
     new TreeNode<int>(6,
       new TreeNode<int>(8),
       new TreeNode<int>(9))));
 std::cout << "preorder:   ";
 root.preorderTraverse();
 std::cout << std::endl;
 std::cout << "inorder:    ";
 root.inorderTraverse();
 std::cout << std::endl;
 std::cout << "postorder:  ";
 root.postorderTraverse();
 std::cout << std::endl;
 std::cout << "level-order:";
 root.levelorderTraverse();
 std::cout << std::endl;
 return 0;

} </lang>

Common Lisp

<lang lisp>(defun preorder (node f)

 (when node
   (funcall f (first node))
   (preorder (second node) f)
   (preorder (third node)  f)))

(defun inorder (node f)

 (when node
   (inorder (second node) f)
   (funcall f (first node))
   (inorder (third node)  f)))

(defun postorder (node f)

 (when node
   (postorder (second node) f)
   (funcall f (first node))
   (postorder (third node)  f)))

(defun level-order (node f)

 (loop with level = (list node)
       while level
       do
   (setf level (loop for node in level
                     when node
                       do (funcall f (first node))
                       and collect (second node)
                       and collect (third node)))))

(defparameter *tree* '(1 (2 (4 (7))

                           (5))
                        (3 (6 (8)
                              (9)))))

(defun show (traversal-function)

 (format t "~&~(~A~):~12,0T" traversal-function)
 (funcall traversal-function *tree* (lambda (value) (format t " ~A" value))))

(map nil #'show '(preorder inorder postorder level-order))</lang>

Output:

preorder:    1 2 4 7 5 3 6 8 9
inorder:     7 4 2 5 1 8 6 9 3
postorder:   7 4 2 5 1 8 6 9 3
level-order: 1 2 3 4 5 6 7 8 9

E

<lang e>def btree := [1, [2, [4, [7, null, null],

                        null],
                    [5, null, null]],
                [3, [6, [8, null, null],
                        [9, null, null]],
                    null]]

def backtrackingOrder(node, pre, mid, post) {

   switch (node) {
       match ==null {}
       match [value, left, right] {
           pre(value)
           backtrackingOrder(left, pre, mid, post)
           mid(value)
           backtrackingOrder(right, pre, mid, post)
           post(value)
       }
   }

}

def levelOrder(root, func) {

   var level := [root].diverge()
   while (level.size() > 0) {
       for node in level.removeRun(0) {
           switch (node) {
               match ==null {}
               match [value, left, right] {
                   func(value)
                   level.push(left)
                   level.push(right)

} } } } }

print("preorder: ") backtrackingOrder(btree, fn v { print(" ", v) }, fn _ {}, fn _ {}) println()

print("inorder: ") backtrackingOrder(btree, fn _ {}, fn v { print(" ", v) }, fn _ {}) println()

print("postorder: ") backtrackingOrder(btree, fn _ {}, fn _ {}, fn v { print(" ", v) }) println()

print("level-order:") levelOrder(btree, fn v { print(" ", v) }) println()</lang>

Erlang

<lang erlang> -module(tree_traversal). -export([main/0]). -export([preorder/2, inorder/2, postorder/2, levelorder/2]). -export([tnode/0, tnode/1, tnode/3]).

-define(NEWLINE, io:format("~n")).

tnode() -> {}. tnode(V) -> {node, V, {}, {}}. tnode(V,L,R) -> {node, V, L, R}.

preorder(_,{}) -> ok; preorder(F,{node,V,L,R}) ->

   F(V), preorder(F,L), preorder(F,R).

inorder(_,{}) -> ok; inorder(F,{node,V,L,R}) ->

   inorder(F,L), F(V), inorder(F,R).
   

postorder(_,{}) -> ok; postorder(F,{node,V,L,R}) ->

   postorder(F,L), postorder(F,R), F(V).

levelorder(_, []) -> []; levelorder(F, [{}|T]) -> levelorder(F, T); levelorder(F, [{node,V,L,R}|T]) ->

   F(V), levelorder(F, T++[L,R]);

levelorder(F, X) -> levelorder(F, [X]).

main() ->

   Tree = tnode(1,
                tnode(2,
                      tnode(4, tnode(7), tnode()),
                      tnode(5, tnode(), tnode())),
                tnode(3,
                      tnode(6, tnode(8), tnode(9)),
                      tnode())),
   F = fun(X) -> io:format("~p ",[X]) end,
   preorder(F, Tree), ?NEWLINE,
   inorder(F, Tree), ?NEWLINE,
   postorder(F, Tree), ?NEWLINE,
   levelorder(F, Tree), ?NEWLINE.

</lang>

Output:

1 2 4 7 5 3 6 8 9 
7 4 2 5 1 8 6 9 3 
7 4 5 2 8 9 6 3 1 
1 2 3 4 5 6 7 8 9 

Forth

<lang forth> \ binary tree (dictionary)

node ( l r data -- node ) here >r , , , r> ;
leaf ( data -- node ) 0 0 rot node ;
>data ( node -- ) @ ;
>right ( node -- ) cell+ @ ;
>left ( node -- ) cell+ cell+ @ ;
preorder ( xt tree -- )
 dup 0= if 2drop exit then
 2dup >data swap execute
 2dup >left recurse
      >right recurse ;
inorder ( xt tree -- )
 dup 0= if 2drop exit then
 2dup >left recurse
 2dup >data swap execute
      >right recurse ;
postorder ( xt tree -- )
 dup 0= if 2drop exit then
 2dup >left recurse
 2dup >right recurse
      >data swap execute ;
max-depth ( tree -- n )
 dup 0= if exit then
 dup  >left recurse
 swap >right recurse max 1+ ;

defer depthaction

depthorder ( depth tree -- )
 dup 0= if 2drop exit then
 over 0=
 if   >data depthaction drop
 else over 1- over >left  recurse
      swap 1- swap >right recurse
 then ;
levelorder ( xt tree -- )
 swap is depthaction
 dup max-depth 0 ?do
   i over depthorder
 loop drop ;

7 leaf 0 4 node

             5 leaf 2 node

8 leaf 9 leaf 6 node

             0      3 node 1 node value tree

cr ' . tree preorder \ 1 2 4 7 5 3 6 8 9 cr ' . tree inorder \ 7 4 2 5 1 8 6 9 3 cr ' . tree postorder \ 7 4 5 2 8 9 6 3 1 cr tree max-depth . \ 4 cr ' . tree levelorder \ 1 2 3 4 5 6 7 8 9 </lang>

Haskell

<lang haskell>data Tree a = Empty

           | Node { value :: a,
                    left  :: Tree a,
                    right :: Tree a }

preorder, inorder, postorder, levelorder :: Tree a -> [a]

preorder Empty = [] preorder (Node v l r) = [v]

                       ++ preorder l
                       ++ preorder r

inorder Empty = [] inorder (Node v l r) = inorder l

                      ++ [v]
                      ++ inorder r

postorder Empty = [] postorder (Node v l r) = postorder l

                        ++ postorder r
                        ++ [v]

levelorder x = loop [x]

   where loop []                = []
         loop (Empty      : xs) = loop xs
         loop (Node v l r : xs) = v : loop (xs ++ [l,r])

tree :: Tree Int tree = Node 1

           (Node 2
                 (Node 4
                       (Node 7 Empty Empty)
                       Empty)
                 (Node 5 Empty Empty))
           (Node 3
                 (Node 6
                       (Node 8 Empty Empty)
                       (Node 9 Empty Empty))
                 Empty)

main :: IO () main = do print $ preorder tree

         print $ inorder tree
         print $ postorder tree
         print $ levelorder tree</lang>

Output:

[1,2,4,7,5,3,6,8,9]
[7,4,2,5,1,8,6,9,3]
[7,4,5,2,8,9,6,3,1]
[1,2,3,4,5,6,7,8,9]


J

<lang J>preorder=: ]S:0 postorder=: ([:; postorder&.>@}.) , >@{. levelorder=: ;@({::L:1 _~ [: (/: #@>) <S:1@{::) inorder=: ([:; inorder&.>@("_`(1&{)@.(1<#))) , >@{. , [:; inorder&.>@}.@}.</lang>

Required example:

<lang J>N2=: conjunction def '(<m),(<n),<y' N1=: conjunction def '(<m),<n' L=: adverb def '<m'

N2=: conjunction def '(<m),(<n),<y' N1=: adverb def '(<m),<y' L=: adverb def '<m'

tree=: 1 N2 (2 N2 (4 N1 (7 L)) 5 L) 3 N1 6 N2 (8 L) 9 L</lang>

This tree is organized in a pre-order fashion

   preorder tree
1 2 4 7 5 3 6 8 9

post-order is not that much different from pre-order, except that the children must extracted before the parent.

   postorder tree
7 4 5 2 9 8 6 3 1

Implementing in-order is more complex because we must sometimes test whether we have any leaves, instead of relying on J's implicit looping over lists

   inorder tree
7 4 2 5 1 9 8 6 3

level-order can be accomplished by constructing a map of the locations of the leaves, sorting these map locations by their non-leaf indices and using the result to extract all leaves from the tree. Elements at the same level with the same parent will have the same sort keys and thus be extracted in preorder fashion, which works just fine.

   levelorder tree
1 2 3 4 5 6 7 8 9


For J novices, here's the tree instance with a few redundant parenthesis:

   tree=: 1 N2 (2 N2 (4 N1 (7 L)) (5 L)) (3 N1 (6 N2 (8 L) (9 L)))

Syntactically, N2 is a binary node expressed as m N2 n y. N1 is a node with a single child, expressed as m N2 y. L is a leaf node, expressed as m L. (And n must be parenthesized if it is not a single word.)

Java

Works with: Java version 1.5+

<lang java5>import java.util.Queue; import java.util.LinkedList; public class TreeTraverse {

   private static class Node<T>{
       public Node<T> left;
       public Node<T> right;
       public T data;
       
       public Node(T data){
           this.data = data;
       }
       public Node<T> getLeft() {
           return left;
       }
       public void setLeft(Node<T> left) {
           this.left = left;
       }
       public Node<T> getRight() {
           return right;
       }
       public void setRight(Node<T> right) {
           this.right = right;
       }
   }
   public static void preorder(Node<?> n){
       if (n != null) {
           System.out.print(n.data + " ");
           preorder(n.getLeft());
           preorder(n.getRight());
       }
   }
   
   public static void inorder(Node<?> n){
       if (n != null) {
           inorder(n.getLeft());
           System.out.print(n.data + " ");
           inorder(n.getRight());
       }
   }
   
   public static void postorder(Node<?> n){
       if (n != null){
           postorder(n.getLeft());
           postorder(n.getRight());
           System.out.print(n.data + " ");
       }
   }
   
   public static void levelorder(Node<?> n) {
       Queue<Node<?>> nodequeue = new LinkedList<Node<?>>();
       if (n != null)
           nodequeue.add(n);
       while (!nodequeue.isEmpty()) {
           Node<?> next = nodequeue.remove();
           System.out.print(next.data + " ");
           if (next.getLeft() != null) {
               nodequeue.add(next.getLeft());
           }
           if (next.getRight() != null) {
               nodequeue.add(next.getRight());
           }
       }
   }
   
   public static void main(String[] args){
       Node<Integer> one = new Node<Integer>(1);
       Node<Integer> two = new Node<Integer>(2);
       Node<Integer> three = new Node<Integer>(3);
       Node<Integer> four = new Node<Integer>(4);
       Node<Integer> five = new Node<Integer>(5);
       Node<Integer> six = new Node<Integer>(6);
       Node<Integer> seven = new Node<Integer>(7);
       Node<Integer> eight = new Node<Integer>(8);
       Node<Integer> nine = new Node<Integer>(9);
       one.setLeft(two);
       one.setRight(three);
       two.setLeft(four);
       two.setRight(five);
       three.setLeft(six);
       four.setLeft(seven);
       six.setLeft(eight);
       six.setRight(nine);
       
       preorder(one);
       System.out.println();
       inorder(one);
       System.out.println();
       postorder(one);
       System.out.println();
       levelorder(one);
       System.out.println();
   }

}</lang> Output:

1 2 4 7 5 3 6 8 9 
7 4 2 5 1 8 6 9 3 
7 4 5 2 8 9 6 3 1 
1 2 3 4 5 6 7 8 9 

<lang logo>

nodes are [data left right], use "first" to get data

to node.left :node

 if empty? butfirst :node [output []]
 output first butfirst :node

end to node.right :node

 if empty? butfirst :node [output []]
 if empty? butfirst butfirst :node [output []]
 output first butfirst butfirst :node

end to max :a :b

 output ifelse :a > :b [:a] [:b]

end to tree.depth :tree

 if empty? :tree [output 0]
 output 1 + max tree.depth node.left :tree  tree.depth node.right :tree

end

to pre.order :tree :action

 if empty? :tree [stop]
 invoke :action first :tree
 pre.order node.left :tree :action
 pre.order node.right :tree :action

end to in.order :tree :action

 if empty? :tree [stop]
 pre.order node.left :tree :action
 invoke :action first :tree
 pre.order node.right :tree :action

end to post.order :tree :action

 if empty? :tree [stop]
 pre.order node.left :tree :action
 pre.order node.right :tree :action
 invoke :action first :tree

end to at.depth :n :tree :action

 if empty? :tree [stop]
 ifelse :n = 1 [invoke :action first :tree] [
   at.depth :n-1 node.left  :tree :action
   at.depth :n-1 node.right :tree :action
 ]

end to level.order :tree :action

 for [i 1 [tree.depth :tree]] [at.depth :i :tree :action]

end

make "tree [1 [2 [4 [7]]

                [5]]
             [3 [6 [8]
                   [9]]]]
 pre.order :tree [(type ? "| |)]  (print)
  in.order :tree [(type ? "| |)]  (print)
post.order :tree [(type ? "| |)]  (print)

level.order :tree [(type ? "| |)] (print) </lang>

OCaml

<lang ocaml>type 'a tree = Empty

            | Node of 'a * 'a tree * 'a tree

let rec preorder f = function

   Empty        -> ()
 | Node (v,l,r) -> f v;
                   preorder f l;
                   preorder f r

let rec inorder f = function

   Empty        -> ()
 | Node (v,l,r) -> inorder f l;
                   f v;
                   inorder f r

let rec postorder f = function

   Empty        -> ()
 | Node (v,l,r) -> preorder f l;
                   preorder f r;
                   f v

let levelorder f x =

 let queue = Queue.create () in
   Queue.add x queue;
   while not (Queue.is_empty queue) do
     match Queue.take queue with
         Empty        -> ()
       | Node (v,l,r) -> f v;
                         Queue.add l queue;
                         Queue.add r queue
   done

let tree =

 Node (1,
       Node (2,
             Node (4,
                   Node (7, Empty, Empty),
                   Empty),
             Node (5, Empty, Empty)),
       Node (3,
             Node (6,
                   Node (8, Empty, Empty),
                   Node (9, Empty, Empty)),
             Empty))

let () =

 preorder   (Printf.printf "%d ") tree; print_newline ();
 inorder    (Printf.printf "%d ") tree; print_newline ();
 postorder  (Printf.printf "%d ") tree; print_newline ();
 levelorder (Printf.printf "%d ") tree; print_newline ()</lang>

Output:

1 2 4 7 5 3 6 8 9 
7 4 2 5 1 8 6 9 3 
2 4 7 5 3 6 8 9 1 
1 2 3 4 5 6 7 8 9 

Python

<lang python> from collections import namedtuple from sys import stdout

Node = namedtuple('Node', 'data, left, right') tree = Node(1,

           Node(2,
                Node(4,
                     Node(7, None, None),
                     None),
                Node(5, None, None)),
           Node(3,
                Node(6,
                     Node(8, None, None),
                     Node(9, None, None)),
                None))

def printwithspace(i):

   stdout.write("%i " % i)

def preorder(node, visitor = printwithspace):

   if node is not None:
       visitor(node.data)
       preorder(node.left, visitor)
       preorder(node.right, visitor)

def inorder(node, visitor = printwithspace):

   if node is not None:
       inorder(node.left, visitor)
       visitor(node.data)
       inorder(node.right, visitor)

def postorder(node, visitor = printwithspace):

   if node is not None:
       postorder(node.left, visitor)
       postorder(node.right, visitor)
       visitor(node.data)

def levelorder(node, more=None, visitor = printwithspace):

   if node is not None:
       if more is None:
           more = []
       more += [node.left, node.right]
       visitor(node.data)
   if more:    
       levelorder(more[0], more[1:], visitor)

stdout.write(' preorder: ') preorder(tree) stdout.write('\n inorder: ') inorder(tree) stdout.write('\n postorder: ') postorder(tree) stdout.write('\nlevelorder: ') levelorder(tree) stdout.write('\n') </lang>

Sample output:

  preorder: 1 2 4 7 5 3 6 8 9 
   inorder: 7 4 2 5 1 8 6 9 3 
 postorder: 7 4 5 2 8 9 6 3 1 
levelorder: 1 2 3 4 5 6 7 8 9 

Ruby

<lang ruby>class BinaryTreeNode

 def initialize(value, left=nil, right=nil)
   @value, @left, @right = value, left, right
 end
 attr_reader :value, :left, :right
 def self.from_array(nested_list)
   value, left, right = nested_list
   if value 
     self.new(value, self.from_array(left), self.from_array(right))
   end
 end

 def walk_nodes(order, &block)
   order.each do |node|
     case node
     when :left  then left && left.walk_nodes(order, &block)
     when :self  then yield self
     when :right then right && right.walk_nodes(order, &block)
     end
   end
 end

 def each_preorder(&b)  ; walk_nodes([:self, :left, :right], &b) ; end
 def each_inorder(&b)   ; walk_nodes([:left, :self, :right], &b) ; end
 def each_postorder(&b) ; walk_nodes([:left, :right, :self], &b) ; end

 def each_levelorder
   queue = [self]
   until queue.empty?
     node = queue.shift
     yield node
     queue << node.left if node.left
     queue << node.right if node.right
   end
 end

end

root = BinaryTreeNode.from_array [1, [2, [4, 7], [5]], [3, [6, [8], [9]]]]

%w{each_preorder each_inorder each_postorder each_levelorder}.each {|mthd|

 printf "%-11s ", mthd[5..-1] + ':'
 root.send(mthd) {|node| print "#{node.value} "}
 puts

}</lang>

Output:

preorder:   1 2 4 7 5 3 6 8 9
inorder:    7 4 2 5 1 8 6 9 3
postorder:  7 4 5 2 8 9 6 3 1
levelorder: 1 2 3 4 5 6 7 8 9

Tcl

Works with: Tcl version 8.6

<lang tcl>oo::class create tree {

   # Basic tree data structure stuff...
   variable val l r
   constructor {value {left {}} {right {}}} {

set val $value set l $left set r $right

   }
   method value {} {return $val}
   method left  {} {return $l}
   method right {} {return $r}
   destructor {

if {$l ne ""} {$l destroy} if {$r ne ""} {$r destroy}

   }
   # Traversal methods
   method preorder {varName script {level 0}} {

upvar [incr level] $varName var set var $val uplevel $level $script if {$l ne ""} {$l preorder $varName $script $level} if {$r ne ""} {$r preorder $varName $script $level}

   }
   method inorder {varName script {level 0}} {

upvar [incr level] $varName var if {$l ne ""} {$l inorder $varName $script $level} set var $val uplevel $level $script if {$r ne ""} {$r inorder $varName $script $level}

   }
   method postorder {varName script {level 0}} {

upvar [incr level] $varName var if {$l ne ""} {$l postorder $varName $script $level} if {$r ne ""} {$r postorder $varName $script $level} set var $val uplevel $level $script

   }
   method levelorder {varName script} {

upvar 1 $varName var set nodes [list [self]]; # A queue of nodes to process while {[llength $nodes] > 0} { set nodes [lassign $nodes n] set var [$n value] uplevel 1 $script if {[$n left] ne ""} {lappend nodes [$n left]} if {[$n right] ne ""} {lappend nodes [$n right]} }

   }

}</lang> Note that in Tcl it is conventional to handle performing something “for each element” by evaluating a script in the caller's scope for each node after setting a caller-nominated variable to the value for that iteration. Doing this transparently while recursing requires the use of a varying ‘level’ parameter to upvar and uplevel, but makes for compact and clear code.

Demo code to satisfy the official challenge instance: <lang tcl># Helpers to make construction and listing of a whole tree simpler proc Tree nested {

   lassign $nested v l r
   if {$l ne ""} {set l [Tree $l]}
   if {$r ne ""} {set r [Tree $r]}
   tree new $v $l $r

} proc Listify {tree order} {

   set list {}
   $tree $order v {

lappend list $v

   }
   return $list

}

  1. Make a tree, print it a few ways, and destroy the tree

set t [Tree {1 {2 {4 7} 5} {3 {6 8 9}}}] puts "preorder: [Listify $t preorder]" puts "inorder: [Listify $t inorder]" puts "postorder: [Listify $t postorder]" puts "level-order: [Listify $t levelorder]" $t destroy</lang> Output:

preorder:    1 2 4 7 5 3 6 8 9
inorder:     7 4 2 5 1 8 6 9 3
postorder:   7 4 5 2 8 9 6 3 1
level-order: 1 2 3 4 5 6 7 8 9

Unix Shell

Bash (also "sh" on most Unix systems) has arrays. We implement a node as an association between three arrays: left, right, and value. <lang bash>left=() right=() value=()

  1. node node#, left#, right#, value
  2. if value is empty, use node#

node() {

 nx=${1:-'Missing node index'}
 leftx=${2}
 rightx=${3}
 val=${4:-$1}
 value[$nx]="$val"
 left[$nx]="$leftx"
 right[$nx]="$rightx"

}

  1. define the tree

node 1 2 3 node 2 4 5 node 3 6 node 4 7 node 5 node 6 8 9 node 7 node 8 node 9

  1. walk NODE# ORDER

walk() {

 local nx=${1-"Missing index"}
 shift
 for branch in "$@" ; do
   case "$branch" in
     left)  if [[ "${left[$nx]}" ]];      then walk ${left[$nx]}  $@ ; fi ;;
     right) if [[ "${right[$nx]}" ]];     then walk ${right[$nx]} $@ ; fi ;;
     self)  printf "%d " "${value[$nx]}"  ;;
   esac
 done

}

apush() {

 local var="$1"
 eval "$var=( \"\${$var[@]}\" \"$2\" )"

}

showname() {

 printf "%-12s " "$1:"

}

showdata() {

 showname "$1"
 shift
 walk "$@"
 echo 

}

preorder() { showdata $FUNCNAME $1 self left right ; } inorder() { showdata $FUNCNAME $1 left self right ; } postorder() { showdata $FUNCNAME $1 left right self ; } levelorder() {

 showname 'level-order'
 queue=( $1 )
 x=0
 while [[ $x < ${#queue[*]} ]]; do
   value="${queue[$x]}"
   printf "%d " "$value"
   for more in "${left[$value]}" "${right[$value]}" ; do
     if -n "$more" ; then

apush queue "$more"

     fi
   done
   : $((x++))
 done
 echo 

}

preorder 1 inorder 1 postorder 1 levelorder 1</lang> The output: <lang "bash">preorder: 1 2 4 7 5 3 6 8 9 inorder: 7 4 2 5 1 8 6 9 3 postorder: 7 4 5 2 8 9 6 3 1 level-order: 1 2 3 4 5 6 7 8 9 </lang>

Ursala

Ursala has built-in notation for trees and is perfect for whipping up little tree walking functions. <lang Ursala> tree =

1^:<

  2^: <4^: <7^: <>, 0>, 5^: <>>,
  3^: <6^: <8^: <>, 9^: <>>, 0>>

pre = ~&dvLPCo post = ~&vLPdNCTo in = ~&vvhPdvtL2CTiQo lev = ~&iNCaadSPfavSLiF3RTaq

  1. cast %nLL

main = <.pre,in,post,lev> tree </lang> output:

<
   <1,2,4,7,5,3,6,8,9>,
   <7,4,2,5,1,8,6,9,3>,
   <7,4,5,2,8,9,6,3,1>,
   <1,2,3,4,5,6,7,8,9>>