Morris traversal: traverse binary tree inorder with no recursion and O(1) space

参考:http://pthread.blog.163.com/blog/static/169308178201210112045787/

 

Most textbooks mention that binary tree can be traversed using recursion or , using stack without recursion. The recursive procedure is simple to write, and the stack version use extra space. 

There's also a very well designed algorithm that traverse a binary tree inorder without recursion and yet use only O(1) space -- Morris Traversal.  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
The algorithm is also very easy to implementation:

template<typename T>
void morris_traversal(bst_node_t<T>* root)
{
bst_node_t<T>* current = root;
while (current) {
if (!current->left) {
std::cout << current->data << " ";
current = current->right;
} else {
bst_node_t<T>* it = current->left;
while (it->right && it->right != current) {
it = it->right;
}
if (!it->right) {
it->right = current;
current = current->left;
} else {
std::cout << current->data << " ";
it->right = NULL;
current = current->right;
}
}
}
}

 
But however, this algorithm is not so easy to understand. Why every time we encounter a node that has both right child and left child, we have to set current node as right child of the right most node of the current's left subtree? How does this algorithm restore the tree after we  temporarily change the tree structure?
 
Here we give some pictures to demonstrate this process:
 
Morris traversal: traverse binary tree inorder with no recursion and O(1) space - pthread - pthread的博客
 
 At the beginning, we start from the root node of the tree as current.
 
 
 
 
 
 
 
 
 
Morris traversal: traverse binary tree inorder with no recursion and O(1) space - pthread - pthread的博客
 
Second, we find that node 8(current) has both left and right child, so we set node 8 as right child of the right most node of the left subtree, that's node 7.
 

/*

    here current points to node 8,it to node 3
*/
bst_node_t<T>* it = current->left;
/*
    go to che right most child of node 3 that is node 7
*/
while (it->right && it->right != current) {
    it = it->right;
}
/*
    here it points to node 7, current to node 8
*/
if (!it->right) {
    /*
        set current(node 8) as right child of node 7, notice
        that node 8's left child pointer still points to node 3
     */
    it->right = current;
    /*
        current goes left, that is, current points to node 3
    */
    current = current->left;
}
 
Morris traversal: traverse binary tree inorder with no recursion and O(1) space - pthread - pthread的博客
 

Repeat the process above, with current node 3, go left child of current node, that is node 1. Then we find that node 1 has no right child. 

 
So we set node 3 as node 1's left right child and set current as node 1.Node 1 has no left child, so we goes into this piece of code, and set current as node 3
 

if (!current->left) {
std::cout << current->data << " ";
current = current->right;
}

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Morris traversal: traverse binary tree inorder with no recursion and O(1) space - pthread - pthread的博客
As node 3 goes to its left most child and find itself, which means that we visit node 3 in the second time, so here we restore the tree by set node 1's right child to NULL, and visit node 3.
 
 

/*
current => node 3
it => node 1
*/
bst_node_t<T>* it = current->left;
/*
here we find that it->right = node 3 = current
so break the loop
*/
while (it->right && it->right != current) {
it = it->right;
}
if (!it->right) {
it->right = current;
current = current->left;
} else {
/*
we visit node 3 in the second time, thus print data
*/
std::cout << current->data << " ";
/*
adjust node 1's right child pointer to null as it originally be
*/
it->right = NULL;
/*
we complete traversal left child of node 3, current goes right, that is node 5
*/
current = current->right;
}

 

 

Here we have covered each condition of Morris Traversal. The loop continues and the whole tree will be traversed and restored.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值