算法 非递归中序遍历二叉树总结(2种方法)
@author:Jingdai
@date:2020.12.03
传送门
方法1
先序遍历是第一次遇到该节点遍历;中序是第二次遇到该节点遍历;而后序是第三次遇到该节点遍历。非递归用栈进行遍历,第一次遇到就是压栈时,第二次是弹栈时,所以中序遍历应该弹栈的时候进行遍历。弹栈后代表弹栈节点及其左子树已经遍历完了,所以此时将弹栈节点的右子节点压栈,对其右子树进行同样的操作。代码如下。
public static void inOrderTraverse(TreeNode root) {
TreeNode p = root;
LinkedList<TreeNode> stack = new LinkedList<>();
while (p != null || stack.size() != 0) {
while (p != null) {
stack.push(p);
p = p.left;
}
p = stack.pop();
System.out.println(p.val);
p = p.right;
}
}
其实仔细观察代码的话会发现其实中序和先序代码除了遍历(这里就是输出语句)的位置不一样,其余的代码完全一样,所以先序和中序会一种,另一种也就会了。ps:先序可以看我上一篇的总结。
方法2 Morris方法
Morris方法是为了将遍历的空间复杂度从 O(h)
降为 O(1)
,如果对Morris遍历过程有问题的可以看我前一篇先序遍历的总结,这里直接上代码。
public static void inOrderTraverse(TreeNode root) {
TreeNode cur = root;
TreeNode rightmost = null;
while (cur != null) {
if (cur.left != null) {
rightmost = cur.left;
while (rightmost.right != null && rightmost.right != cur) {
rightmost = rightmost.right;
}
if (rightmost.right == null) {
// first
rightmost.right = cur;
cur = cur.left;
} else {
// second
rightmost.right = null;
System.out.println(cur.val);
cur = cur.right;
}
} else {
System.out.println(cur.val);
cur = cur.right;
}
}
}