Inorder Tree Traversal without recursion and without stack!
Using Morris Traversal, we can traverse the tree without using stack and recursion. The idea of Morris Traversal is based on Threaded Binary Tree. In this traversal, we first create links to Inorder successor and print the data using these links, and finally revert the changes to restore original tree.
1. Initialize current as root
2. While current is not NULL
If current does not have left child
a) Print current’s data
b) Go to the right, i.e., current = current->right
Else
a) Make current as right child of the rightmost node in current's left subtree
b) Go to this left child, i.e., current = current->left
Although the tree is modified through the traversal, it is reverted back to its original shape after the completion. Unlike Stack based traversal, no extra space is required for this traversal.
#include<stdio.h>
#include<stdlib.h>
/* A binary tree tNode has data, pointer to left child
and a pointer to right child */
struct tNode
{
int data;
struct tNode* left;
struct tNode* right;
};
/* Function to traverse binary tree without recursion and
without stack */
void MorrisTraversal(struct tNode *root)
{
struct tNode *current,*pre;
if(root == NULL)
return;
current = root;
while(current != NULL)
{
if(current->left == NULL)
{
printf(" %d ", current->data);
current = current->right;
}
else
{
/* Find the inorder predecessor of current */
pre = current->left;
while(pre->right != NULL && pre->right != current)
pre = pre->right;
/* Make current as right child of its inorder predecessor */
if(pre->right == NULL)
{
pre->right = current;
current = current->left;
}
/* Revert the changes made in if part to restore the original
tree i.e., fix the right child of predecssor */
else
{
pre->right = NULL;
printf(" %d ",current->data);
current = current->right;
} /* End of if condition pre->right == NULL */
} /* End of if condition current->left == NULL*/
} /* End of while */
}
/* UTILITY FUNCTIONS */
/* Helper function that allocates a new tNode with the
given data and NULL left and right pointers. */
struct tNode* newtNode(int data)
{
struct tNode* tNode = (struct tNode*)
malloc(sizeof(struct tNode));
tNode->data = data;
tNode->left = NULL;
tNode->right = NULL;
return(tNode);
}
/* Driver program to test above functions*/
int main()
{
/* Constructed binary tree is
1
/ \
2 3
/ \
4 5
*/
struct tNode *root = newtNode(1);
root->left = newtNode(2);
root->right = newtNode(3);
root->left->left = newtNode(4);
root->left->right = newtNode(5);
MorrisTraversal(root);
getchar();
return 0;
}
References:
www.liacs.nl/~deutz/DS/september28.pdf
http://comsci.liu.edu/~murali/algo/Morris.htm
www.scss.tcd.ie/disciplines/software_systems/…/HughGibbonsSlides.pdf
Please write comments if you find any bug in above code/algorithm, or want to share more information about stack Morris Inorder Tree Traversal.
You may also like following posts
Morris Traversal might HANG in infinite loop for certain TREE structure.
Try running given code for below tree:
[You will see it printing wrong data and infinitely looping]
[Code]
A
B C
D E F
G K
[/Code]
Morris traversal gets stuck , after visiting left subtree of A and then while traversing A onwards.
It will try to reLink E->A continously and gets shifted to left subtree of A (which is already traversed)
May be the method works fine for 'complete trees'. But I am not sure, haven't tested it.
May be the method works fine only for 'complete trees'. But I am not sure, haven't tested it.
Here's a challenge: How can you do that with O(1) space complexity without changing the tree in the process when in addition to the regular operations you can do with trees, you can also go to a parent node (parent of root is NULL). Is it possible?
See page 298 Data structures using C and C++ Tanenbaum Threaded binary Trees
@karthik whats d time complexcity of morris algo , pls explain in detail ?
Are there similar methods for preorder and postorder traversals?
In order, post order and pre order traversal without recursion.
http://anandtechblog.blogspot.com/2011/07/iterative-method-for-inorder-and-pre.html
I don't understand how you can revert the changes !!!
Where do you put that code to change the pointers back to NULL.
one more thing .. why we have changed pre->right=NULL before currrent=current->right .. ?? can anybody explain ??
You have answered your own question. pre->right=NULL is done to revert the changes done int the tree.
Draw a tree. Trace the code. Its really simple.
converting the above code into java...thanks dude
public static void inOrderTraversal(Node root) { if (root == null) { return; } Node prev, current; current = root; while (current != null) { if (current.left == null) { System.out.println(current.value); current = current.right; } else { for (prev = current.left; (prev.right != null && prev.right != current); prev = prev.right) ; if (prev.right == null) { prev.right = current; current = current.left; } else { prev.right = null; System.out.println(current.value); current = current.right; } } } }@SANDEEP, GEEKSFORGEEKS, KARTIK.....CAN ANY ONE OF YOU PROOVE TEH TIM E COMPLEXITY OF MORRIS TRAVESRAL IS O(NLOGN)...???
Algorithm:
1. Traverse LEFT until the left child is null and push the current node into stack. (This loop continues until the stack is empty)
2. Pop the stack and process the current node.
3. Go to the right child.
You can find a working Java program at the below link.
http://cslabprograms.blogspot.com/2011/02/non-recursive-tree-traversal-using.html
Morris algorithm runs at O(nlgn) not O(n). I could not think how it runs in O(n) time. Any idea? Thanks
dude, any algortithm which does tree traversal will definitely take at least O(n) time.
Kunal, my pointer is not saying tree traveral takes at least O(n) time. My question is the complexity of the Morris Algorithm. I think it runs at O(nlgn), which is slower than recursive traversal except Morris approach has space advantage.
it takes O(n) time. reference : adam drozdek (data structures)
this part is duplicated when backing from left child to its parent
while(pre->right != NULL && pre->right != current)
pre = pre->right;
Any idea how to remove the duplication finding the right most child when backing from left child to its parent? Thanks
Alternative algorithm also with O(n) time complexity and O(1) space complexity: http://groups.google.com/group/algogeeks/msg/d2f519d74e821963