Binary tree traversal techniques
Tree traversal is one of the most common operations and one of the easiest to implement by recursion on a binary tree data structure. Implementing a recursive pre-order, in-order and post-order traversal is absolutely straightforward
Implementing pre-order, in-order and post-order iteratively proves to be slightly harder. By using a stack it is possible to implement all three of them with relatively few lines of code. Pseudocode and code follow
Pre-order
push root node
while stack is not empty
print node
pop it
push right and left children
In-order
push root node
while there's a left node
push left node
node = left node
while stack is not empty
print node
pop it
if there's a right node
push right node
while there's a left node
push left node
node = left node
Post-order
root = pointer to root node
while root is not null
push right node
push root
root = root.left
while stack is not empty
if there is no right node
print it
pop it
else
if the right node is on the stack below me
exchange first node with second node in the stack
root = first node (i.e. former right child)
while root is not null
push right node
push root
root = root.left
else
print it
pop it
In-Order Morris traversal
Another \( O(n) \) method of implementing a non-recursive in-order traversal without even using a stack is due to the Morris Traversal algorithm which builds on threaded binary trees by agumenting predecessor nodes with right links to their successors in the first phase and removes these links in the second phase. E.g. given the tree
the algorithm starts from the root and if there’s a left node tries to find the rightmost predecessor of the current node. When it is found, since it features a nullptr
as right child, this pointer is temporarily modified to point to the current node (i.e. its successor)
it then proceeds doing the same until a leftmost node with no left child is found
at this point the second phase starts: the node with no left child is printed out (1 in the example) and the right pointer is used to get to the successor node 2. The algorithm would proceed in the same way as phase 1 by finding again 2’s predecessor, but this time the predecessor has no nullptr
as right child since it was augmented before. Therefore the predecessor was already printed and processed: the current node is printed and the graph restored by deleting the predecessor’s right link and advancing to the next right value (successor)