Morris 二叉树遍历
对于二叉树遍历有很多的方法,先序遍历,中序遍历,后序遍历,层次遍历等等。但是这些遍历方法每个节点至少访问一次并且需要记录上一次访问的节点。因此时间复杂度为O(n),空间复杂度为O(n)或O(log(n))。下面介绍的Morris 二叉树遍历方法 时间复杂度为O(n),空间复杂度为O(1)。
Morris遍历优点是空间复杂度为O(1),并且遍历完后不改变树的结构。缺点是时间会增长,因为大部分节点会访问两次。这是典型的时间换取空间的例子。这个算法空间复杂度能做到O(1)精妙之处在于它利用叶子节点的左右指针指向该叶子节点在某种遍历顺序下的前驱节点或后继节点。下面以中序遍历为例,介绍Morris算法。
算法步骤
- 如果当前节点的左孩子为空,输出当前节点,并将当前节点的右孩子设置为当前节点。
- 如果当前节点的左孩子不为空,则在当前节点的左子树上寻找当前节点在中序遍历下的前驱节点。
a) 如果当前节点的前驱节点的右孩子为空,则将前驱节点的右孩子指向当前节点。将当前节点的左孩子设置为当前节点。
b) 如果当前节点的前驱节点的右孩子指向当前节点,则将前驱节点的右孩子设置为NULL(恢复树的结构),输出当前节点,并将当前节点的右孩子设置为当前节点。
图示过程如下:
算法流程图
java 代码
public void MorrisTraverse(TreeNode root) {
TreeNode cur = root;
TreeNode prev = null;
while(cur != null){
if(cur.left == null){
System.out.prinln(cur.val);
cur = cur.right;
}
else{
prev = cur.left;
while(prev.right != null && prev.right != cur){
prev = prev.right;
}
if(prev.right == null){
prev.right = cur;
cur = cur.left;
}
else{
System.out.println(cur.val);
prev.right = null;
cur = cur.right;
}
}
}
}
参考资料:
http://www.cnblogs.com/AnnieKim/archive/2013/06/15/MorrisTraversal.html