Tree traversal
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
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>
ALGOL 68
- note the strong code structural similarities with C.
Note the changes from the original translation from C in this diff. It contains examples of syntactic sugar available in ALGOL 68.
<lang algol68>MODE VALUE = INT; PROC value repr = (VALUE value)STRING: whole(value, 0);
MODE NODES = STRUCT ( VALUE value, REF NODES left, right); MODE NODE = REF NODES;
PROC tree = (VALUE value, NODE left, right)NODE:
HEAP NODES := (value, left, right);
PROC preorder = (NODE node, PROC (VALUE)VOID action)VOID:
IF node ISNT NODE(NIL) THEN action(value OF node); preorder(left OF node, action); preorder(right OF node, action) FI;
PROC inorder = (NODE node, PROC (VALUE)VOID action)VOID:
IF node ISNT NODE(NIL) THEN inorder(left OF node, action); action(value OF node); inorder(right OF node, action) FI;
PROC postorder = (NODE node, PROC (VALUE)VOID action)VOID:
IF node ISNT NODE(NIL) THEN postorder(left OF node, action); postorder(right OF node, action); action(value OF node) FI;
PROC destroy tree = (NODE node)VOID:
postorder(node, (VALUE skip)VOID: # free(node) - PR garbage collect hint PR # node := (SKIP, NIL, NIL) );
- helper queue for level order #
MODE QNODES = STRUCT (REF QNODES next, NODE value); MODE QNODE = REF QNODES;
MODE QUEUES = STRUCT (QNODE begin, end);
MODE QUEUE = REF QUEUES;
PROC enqueue = (QUEUE queue, NODE node)VOID: (
HEAP QNODES qnode := (NIL, node); IF end OF queue ISNT QNODE(NIL) THEN next OF end OF queue ELSE begin OF queue FI := end OF queue := qnode
);
PROC queue empty = (QUEUE queue)BOOL:
begin OF queue IS QNODE(NIL);
PROC dequeue = (QUEUE queue)NODE: (
NODE out := value OF begin OF queue; QNODE second := next OF begin OF queue;
- free(begin OF queue); PR garbage collect hint PR #
QNODE(begin OF queue) := (NIL, NIL); begin OF queue := second; IF queue empty(queue) THEN end OF queue := begin OF queue FI; out
);
PROC level order = (NODE node, PROC (VALUE)VOID action)VOID: (
HEAP QUEUES queue := (QNODE(NIL), QNODE(NIL)); enqueue(queue, node); WHILE NOT queue empty(queue) DO NODE next := dequeue(queue); IF next ISNT NODE(NIL) THEN action(value OF next); enqueue(queue, left OF next); enqueue(queue, right OF next) FI OD
);
PROC print node = (VALUE value)VOID:
print((" ",value repr(value)));
main: (
NODE node := tree(1, tree(2, tree(4, tree(7, NIL, NIL), NIL), tree(5, NIL, NIL)), tree(3, tree(6, tree(8, NIL, NIL), tree(9, NIL, NIL)), NIL));
MODE TEST = STRUCT( STRING name, PROC(NODE,PROC(VALUE)VOID)VOID order );
PROC test = (TEST test)VOID:( STRING pad=" "*(12-UPB name OF test); print((name OF test,pad,": ")); (order OF test)(node, print node); print(new line) ); []TEST test list = ( ("preorder",preorder), ("inorder",inorder), ("postorder",postorder), ("level order",level order) );
FOR i TO UPB test list DO test(test list[i]) OD;
destroy tree(node)
)</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
AutoHotkey
<lang AutoHotkey>AddNode(Tree,1,2,3,1) ; Build global Tree AddNode(Tree,2,4,5,2) AddNode(Tree,3,6,0,3) AddNode(Tree,4,7,0,4) AddNode(Tree,5,0,0,5) AddNode(Tree,6,8,9,6) AddNode(Tree,7,0,0,7) AddNode(Tree,8,0,0,8) AddNode(Tree,9,0,0,9)
MsgBox % "Preorder: " PreOrder(Tree,1) ; 1 2 4 7 5 3 6 8 9 MsgBox % "Inorder: " InOrder(Tree,1) ; 7 4 2 5 1 8 6 9 3 MsgBox % "postorder: " PostOrder(Tree,1) ; 7 4 5 2 8 9 6 3 1 MsgBox % "levelorder: " LevOrder(Tree,1) ; 1 2 3 4 5 6 7 8 9
AddNode(ByRef Tree,Node,Left,Right,Value) {
if !isobject(Tree) Tree := object()
Tree[Node, "L"] := Left Tree[Node, "R"] := Right Tree[Node, "V"] := Value
}
PreOrder(Tree,Node) { ptree := Tree[Node, "V"] " "
. ((L:=Tree[Node, "L"]) ? PreOrder(Tree,L) : "") . ((R:=Tree[Node, "R"]) ? PreOrder(Tree,R) : "")
return ptree } InOrder(Tree,Node) {
Return itree := ((L:=Tree[Node, "L"]) ? InOrder(Tree,L) : "") . Tree[Node, "V"] " " . ((R:=Tree[Node, "R"]) ? InOrder(Tree,R) : "")
} PostOrder(Tree,Node) {
Return ptree := ((L:=Tree[Node, "L"]) ? PostOrder(Tree,L) : "") . ((R:=Tree[Node, "R"]) ? PostOrder(Tree,R) : "") . Tree[Node, "V"] " "
} LevOrder(Tree,Node,Lev=1) {
Static ; make node lists static i%Lev% .= Tree[Node, "V"] " " ; build node lists in every level If (L:=Tree[Node, "L"]) LevOrder(Tree,L,Lev+1) If (R:=Tree[Node, "R"]) LevOrder(Tree,R,Lev+1) If (Lev > 1) Return While i%Lev% ; concatenate node lists from all levels t .= i%Lev%, Lev++ Return t
}</lang>
C
<lang c>#include <stdlib.h>
- 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))
<lang cpp>#include <boost/scoped_ptr.hpp>
- include <iostream>
- 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>
C#
<lang csharp>using System; using System.Collections.Generic;
namespace TreeTraversal {
class Program { class Tree<Type> { public Tree<Type> Left { get; private set; } public Tree<Type> Right { get; private set; } public Type Value { get; set; }
public Tree(Type value, Tree<Type> left, Tree<Type> right) { Value = value; Left = left; Right = right; }
public IEnumerable<Type> PreorderIterator() { yield return Value; if (Left != null) foreach (Type val in Left.PreorderIterator()) yield return val; if (Right != null) foreach (Type val in Right.PreorderIterator()) yield return val; }
public IEnumerable<Type> InorderIterator() { if (Left != null) foreach (Type val in Left.InorderIterator()) yield return val; yield return Value; if (Right != null) foreach (Type val in Right.InorderIterator()) yield return val; }
public IEnumerable<Type> PostorderIterator() { if (Left != null) foreach (Type val in Left.PostorderIterator()) yield return val; if (Right != null) foreach (Type val in Right.PostorderIterator()) yield return val; yield return Value; }
public IEnumerable<Type> LevelOrderIterator() { Queue<Tree<Type>> queue = new Queue<Tree<Type>>(); queue.Enqueue(this); while (queue.Count > 0) { Tree<Type> node = queue.Dequeue(); yield return node.Value; if (node.Left != null) queue.Enqueue(node.Left); if (node.Right != null) queue.Enqueue(node.Right); } } }
static private void ShowTree<Type>(string label,IEnumerable<Type> enumerable) { Console.Write(label); foreach (Type val in enumerable) { Console.Write(" {0}", val); } Console.WriteLine(); }
static void Main(string[] args) { Tree<int> tree = new Tree<int>(1, new Tree<int>(2, new Tree<int>(4, new Tree<int>(7, null, null), null), new Tree<int>(5, null, null)), new Tree<int>(3, new Tree<int>(6, new Tree<int>(8, null, null), new Tree<int>(9, null, null)), null)); ShowTree("preorder: ", tree.PreorderIterator()); ShowTree("inorder: ", tree.InorderIterator()); ShowTree("postorder: ", tree.PostorderIterator()); ShowTree("level-order:", tree.LevelOrderIterator()); } }
}</lang>
Clojure
<lang clojure>(defn walk [node f order]
(when node (doseq [o order] (if (= o :visit) (f (:val node)) (walk (node o) f order)))))
(defn preorder [node f]
(walk node f [:visit :left :right]))
(defn inorder [node f]
(walk node f [:left :visit :right]))
(defn postorder [node f]
(walk node f [:left :right :visit]))
(defn queue [& xs]
(when (seq xs) (apply conj clojure.lang.PersistentQueue/EMPTY xs)))
(defn level-order [root f]
(loop [q (queue root)] (when-not (empty? q) (if-let [node (first q)] (do (f (:val node)) (recur (conj (pop q) (:left node) (:right node)))) (recur (pop q))))))
(defn vec-to-tree [t]
(if (vector? t) (let [[val left right] t] {:val val :left (vec-to-tree left) :right (vec-to-tree right)}) t))
(let [tree (vec-to-tree [1 [2 [4 [7]] [5]] [3 [6 [8] [9]]]])
fs '[preorder inorder postorder level-order] pr-node #(print (format "%2d" %))] (doseq [f fs] (print (format "%-12s" (str f ":"))) ((resolve f) tree pr-node) (println)))</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) (postorder (third node) f) (funcall f (first node))))
(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
D
Code for D V.2. This code is very generic, if you need it less generic it can be shortened. <lang d>import std.stdio: write, writeln;
class Node(T) {
T data; Node left, right; this(T data, Node left=null, Node right=null) { this.data = data; this.left = left; this.right = right; }
}
// static templated opCall can't be used in Node auto node(T)(T data, Node!T left=null, Node!T right=null) {
return new Node!T(data, left, right);
}
void show(T)(T x) {
write(x, " ");
}
enum Visit { pre, inv, post }
// visitor can be any kind of callable or it uses a default visitor. // TNode can be any kind of Node, with data, left and right fields, // so this is more generic than a member function of Node. void backtrackingOrder(Visit v, TNode, TyF=void*)(TNode node, TyF visitor=null) {
static if (is(TyF == void*)) auto truevisitor = &show!(typeof(node.data)); else auto truevisitor = visitor; if (node !is null) { static if (v == Visit.pre) truevisitor(node.data); backtrackingOrder!v(node.left, visitor); static if (v == Visit.inv) truevisitor(node.data); backtrackingOrder!v(node.right, visitor); static if (v == Visit.post) truevisitor(node.data); }
}
void levelOrder(TNode, TyF=void*)(TNode node, TyF visitor=null, TNode[] more=[]) {
static if (is(TyF == void*)) auto truevisitor = &show!(typeof(node.data)); else auto truevisitor = visitor; if (node !is null) { more ~= [node.left, node.right]; truevisitor(node.data); } if (more.length) levelOrder(more[0], truevisitor, more[1..$]);
}
void main() {
auto tree = node(1, node(2, node(4, node(7)), node(5)), node(3, node(6, node(8), node(9))));
write(" preOrder: "); backtrackingOrder!(Visit.pre)(tree); write("\n inorder: "); backtrackingOrder!(Visit.inv)(tree); write("\n postOrder: "); backtrackingOrder!(Visit.post)(tree); write("\nlevelorder: "); levelOrder(tree); writeln();
}</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
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
Factor
<lang factor>USING: accessors combinators deques dlists fry io kernel math.parser ; IN: rosetta.tree-traversal
TUPLE: node data left right ;
CONSTANT: example-tree
T{ node f 1 T{ node f 2 T{ node f 4 T{ node f 7 f f } f } T{ node f 5 f f } } T{ node f 3 T{ node f 6 T{ node f 8 f f } T{ node f 9 f f } } f } }
- preorder ( node quot: ( data -- ) -- )
[ [ data>> ] dip call ] [ [ left>> ] dip over [ preorder ] [ 2drop ] if ] [ [ right>> ] dip over [ preorder ] [ 2drop ] if ] 2tri ; inline recursive
- inorder ( node quot: ( data -- ) -- )
[ [ left>> ] dip over [ inorder ] [ 2drop ] if ] [ [ data>> ] dip call ] [ [ right>> ] dip over [ inorder ] [ 2drop ] if ] 2tri ; inline recursive
- postorder ( node quot: ( data -- ) -- )
[ [ left>> ] dip over [ postorder ] [ 2drop ] if ] [ [ right>> ] dip over [ postorder ] [ 2drop ] if ] [ [ data>> ] dip call ] 2tri ; inline recursive
- (levelorder) ( dlist quot: ( data -- ) -- )
over deque-empty? [ 2drop ] [ [ dup pop-front ] dip { [ [ data>> ] dip call drop ] [ drop left>> [ swap push-back ] [ drop ] if* ] [ drop right>> [ swap push-back ] [ drop ] if* ] [ nip (levelorder) ] } 3cleave ] if ; inline recursive
- levelorder ( node quot: ( data -- ) -- )
[ 1dlist ] dip (levelorder) ; inline
- levelorder2 ( node quot: ( data -- ) -- )
[ 1dlist ] dip [ dup deque-empty? not ] swap '[ dup pop-front [ data>> @ ] [ left>> [ over push-back ] when* ] [ right>> [ over push-back ] when* ] tri ] while drop ; inline
- main ( -- )
example-tree [ number>string write " " write ] { [ "preorder: " write preorder nl ] [ "inorder: " write inorder nl ] [ "postorder: " write postorder nl ] [ "levelorder: " write levelorder nl ] [ "levelorder2: " write levelorder2 nl ] } 2cleave ;</lang>
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>
Go
<lang go>package main
import (
"container/list" "fmt"
)
type T int
type Node struct {
Value T Left, Right *Node
}
func (n *Node) IterPreorder() (<-chan T) {
out := make(chan T) var recursive func(*Node) recursive = func(node *Node) { out <- node.Value if node.Left != nil { recursive(node.Left) } if node.Right != nil { recursive(node.Right) } } go func() { recursive(n) close(out) }() return out
}
func (n *Node) IterInorder() (<-chan T) {
out := make(chan T) var recursive func(*Node) recursive = func(node *Node) { if node.Left != nil { recursive(node.Left) } out <- node.Value if node.Right != nil { recursive(node.Right) } } go func() { recursive(n) close(out) }() return out
}
func (n *Node) IterPostorder() (<-chan T) {
out := make(chan T) var recursive func(*Node) recursive = func(node *Node) { if node.Left != nil { recursive(node.Left) } if node.Right != nil { recursive(node.Right) } out <- node.Value } go func() { recursive(n) close(out) }() return out
}
func (n *Node) IterLevelorder() (<-chan T) {
out := make(chan T,20) pop := func(lst *list.List) *Node { elm := lst.Front() val := elm.Value.(*Node) lst.Remove(elm) return val } go func() { queue := list.New() queue.PushBack(n) for queue.Len() > 0 { node := pop(queue) out <- node.Value if node.Left != nil { queue.PushBack(node.Left) } if node.Right != nil { queue.PushBack(node.Right) } } close(out) }() return out
}
func main() {
tree := &Node{1, &Node{2, &Node{4, &Node{7,nil,nil}, nil}, &Node{5,nil,nil}}, &Node{3, &Node{6, &Node{8,nil,nil}, &Node{9,nil,nil}}, nil}} fmt.Printf("%-12s", "preorder:") for val := range tree.IterPreorder() { fmt.Printf(" %d", val) } fmt.Printf("\n%-12s", "inorder:") for val := range tree.IterInorder() { fmt.Printf(" %d", val) } fmt.Printf("\n%-12s", "postorder:") for val := range tree.IterPostorder() { fmt.Printf(" %d", val) } fmt.Printf("\n%-12s", "level-order:") for val := range tree.IterLevelorder() { fmt.Printf(" %d", val) } fmt.Println()
}</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
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]
Icon and Unicon
Icon
<lang Icon>procedure main()
bTree := [1, [2, [4, [7]], [5]], [3, [6, [8], [9]]]] showTree(bTree, preorder|inorder|postorder|levelorder)
end
procedure showTree(tree, f)
writes(image(f),":\t") every writes(" ",f(tree)[1]) write()
end
procedure preorder(L)
if \L then suspend L | preorder(L[2|3])
end
procedure inorder(L)
if \L then suspend inorder(L[2]) | L | inorder(L[3])
end
procedure postorder(L)
if \L then suspend postorder(L[2|3]) | L
end
procedure levelorder(L)
if \L then { queue := [L] while nextnode := get(queue) do { every put(queue, \nextnode[2|3]) suspend nextnode } }
end</lang>
Output:
->bintree procedure preorder: 1 2 4 7 5 3 6 8 9 procedure inorder: 7 4 2 5 1 8 6 9 3 procedure postorder: 7 4 5 2 8 9 6 3 1 procedure levelorder: 1 2 3 4 5 6 7 8 9 ->
Unicon
This Icon solution works in Unicon. A solution that uses Unicon extensions has not been provided.
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
<lang J> preorder tree
1 2 4 7 5 3 6 8 9</lang>
post-order is not that much different from pre-order, except that the children must extracted before the parent.
<lang J> postorder tree
7 4 5 2 9 8 6 3 1</lang>
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
<lang J> inorder tree
7 4 2 5 1 9 8 6 3</lang>
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.
<lang J> levelorder tree
1 2 3 4 5 6 7 8 9</lang>
For J novices, here's the tree instance with a few redundant parenthesis:
<lang J> tree=: 1 N2 (2 N2 (4 N1 (7 L)) (5 L)) (3 N1 (6 N2 (8 L) (9 L)))</lang>
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
. In all three cases, the parent value (m
) for the node appears on the left, and the child tree(s) appear on the right. (And n
must be parenthesized if it is not a single word.)
Java
<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
JavaScript
inspired by Ruby <lang javascript>function BinaryTree(value, left, right) {
this.value = value; this.left = left; this.right = right;
} BinaryTree.prototype.preorder = function(f) {this.walk(f,['this','left','right'])} BinaryTree.prototype.inorder = function(f) {this.walk(f,['left','this','right'])} BinaryTree.prototype.postorder = function(f) {this.walk(f,['left','right','this'])} BinaryTree.prototype.walk = function(func, order) {
for (var i in order) switch (order[i]) { case "this": func(this.value); break; case "left": if (this.left) this.left.walk(func, order); break; case "right": if (this.right) this.right.walk(func, order); break; }
} BinaryTree.prototype.levelorder = function(func) {
var queue = [this]; while (queue.length != 0) { var node = queue.shift(); func(node.value); if (node.left) queue.push(node.left); if (node.right) queue.push(node.right); }
}
// convenience function for creating a binary tree function createBinaryTreeFromArray(ary) {
var left = null, right = null; if (ary[1]) left = createBinaryTreeFromArray(ary[1]); if (ary[2]) right = createBinaryTreeFromArray(ary[2]); return new BinaryTree(ary[0], left, right);
}
var tree = createBinaryTreeFromArray([1, [2, [4, [7]], [5]], [3, [6, [8],[9]]]]);
print("*** preorder ***"); tree.preorder(print); print("*** inorder ***"); tree.inorder(print); print("*** postorder ***"); tree.postorder(print); print("*** levelorder ***"); tree.levelorder(print);</lang>
Logo
<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] in.order node.left :tree :action invoke :action first :tree in.order node.right :tree :action
end to post.order :tree :action
if empty? :tree [stop] post.order node.left :tree :action post.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) -> postorder f l; postorder 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
Oz
<lang oz>declare
Tree = n(1 n(2 n(4 n(7 e e) e) n(5 e e)) n(3 n(6 n(8 e e) n(9 e e)) e))
fun {Concat Xs} {FoldR Xs Append nil} end
fun {Preorder T} case T of e then nil [] n(V L R) then {Concat [[V] {Preorder L} {Preorder R}]} end end
fun {Inorder T} case T of e then nil [] n(V L R) then {Concat [{Inorder L} [V] {Inorder R}]} end end
fun {Postorder T} case T of e then nil [] n(V L R) then {Concat [{Postorder L} {Postorder R} [V]]} end end
local fun {Collect Queue} case Queue of nil then nil [] e|Xr then {Collect Xr} [] n(V L R)|Xr then V|{Collect {Append Xr [L R]}} end end in fun {Levelorder T} {Collect [T]} end end
in
{Show {Preorder Tree}} {Show {Inorder Tree}} {Show {Postorder Tree}} {Show {Levelorder Tree}}</lang>
PicoLisp
<lang PicoLisp>(de preorder (Node Fun)
(when Node (Fun (car Node)) (preorder (cadr Node) Fun) (preorder (caddr Node) Fun) ) )
(de inorder (Node Fun)
(when Node (inorder (cadr Node) Fun) (Fun (car Node)) (inorder (caddr Node) Fun) ) )
(de postorder (Node Fun)
(when Node (postorder (cadr Node) Fun) (postorder (caddr Node) Fun) (Fun (car Node)) ) )
(de level-order (Node Fun)
(for (Q (circ Node) Q) (let N (fifo 'Q) (Fun (car N)) (and (cadr N) (fifo 'Q @)) (and (caddr N) (fifo 'Q @)) ) ) )
(setq *Tree
(1 (2 (4 (7)) (5)) (3 (6 (8) (9))) ) )
(for Order '(preorder inorder postorder level-order)
(prin (align -13 (pack Order ":"))) (Order *Tree printsp) (prinl) )</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
PureBasic
<lang PureBasic>Structure node
value.i *left.node *right.node
EndStructure
Structure queue
List q.i()
EndStructure
DataSection
tree: Data.s "1(2(4(7),5),3(6(8,9)))"
EndDataSection
- Convenient routine to interpret string data to construct a tree of integers.
Procedure createTree(*n.node, *tPtr.Character)
Protected num.s, *l.node, *ntPtr.Character Repeat Select *tPtr\c Case '0' To '9' num + Chr(*tPtr\c) Case '(' *n\value = Val(num): num = "" *ntPtr = *tPtr + 1 If *ntPtr\c = ',' ProcedureReturn *tPtr Else *l = AllocateMemory(SizeOf(node)) *n\left = *l: *tPtr = createTree(*l, *ntPtr) EndIf Case ')', ',', #Null If num: *n\value = Val(num): EndIf ProcedureReturn *tPtr EndSelect If *tPtr\c = ',' *l = AllocateMemory(SizeOf(node)): *n\right = *l: *tPtr = createTree(*l, *tPtr + 1) EndIf *tPtr + 1 ForEver
EndProcedure
Procedure enqueue(List q.i(), element)
LastElement(q()) AddElement(q()) q() = element
EndProcedure
Procedure dequeue(List q.i())
Protected element If FirstElement(q()) element = q() DeleteElement(q()) EndIf ProcedureReturn element
EndProcedure
Procedure onVisit(*n.node)
Print(Str(*n\value) + " ")
EndProcedure
Procedure preorder(*n.node) ;recursive
onVisit(*n) If *n\left preorder(*n\left) EndIf If *n\right preorder(*n\right) EndIf
EndProcedure
Procedure inorder(*n.node) ;recursive
If *n\left inorder(*n\left) EndIf onVisit(*n) If *n\right inorder(*n\right) EndIf
EndProcedure
Procedure postorder(*n.node) ;recursive
If *n\left postorder(*n\left) EndIf If *n\right postorder(*n\right) EndIf onVisit(*n)
EndProcedure
Procedure levelorder(*n.node)
Dim q.queue(1) Protected readQueue = 1, writeQueue, *currNode.node enqueue(q(writeQueue)\q(),*n) ;start queue off with root Repeat readQueue ! 1: writeQueue ! 1 While ListSize(q(readQueue)\q()) *currNode = dequeue(q(readQueue)\q()) If *currNode\left enqueue(q(writeQueue)\q(),*currNode\left) EndIf If *currNode\right enqueue(q(writeQueue)\q(),*currNode\right) EndIf onVisit(*currNode) Wend Until ListSize(q(writeQueue)\q()) = 0
EndProcedure
If OpenConsole()
Define root.node createTree(root,?tree) Print("preorder: ") preorder(root) PrintN("") Print("inorder: ") inorder(root) PrintN("") Print("postorder: ") postorder(root) PrintN("") Print("levelorder: ") levelorder(root) PrintN("") Print(#CRLF$ + #CRLF$ + "Press ENTER to exit") Input() CloseConsole()
EndIf</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
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
or
<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
}
- 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=()
- node node#, left#, right#, value
- 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"
}
- 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
- 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. This source listing shows the tree depicted above declared as a constant, followed by declarations of four functions applicable to trees of any type. The main program applies all four of them to the tree and makes a list of their results, each of which is a list of natural numbers. The compiler directive #cast %nLL induces the compile-time side effect of displaying the result on standard output as a list of lists of naturals. <lang Ursala>tree =
1^:<
2^: <4^: <7^: <>, 0>, 5^: <>>, 3^: <6^: <8^: <>, 9^: <>>, 0>>
pre = ~&dvLPCo post = ~&vLPdNCTo in = ~&vvhPdvtL2CTiQo lev = ~&iNCaadSPfavSLiF3RTaq
- 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>>