二叉树的非递归遍历
二叉树的递归遍历对于我们程序猿来说简单易懂,代码量较少,但是相对来讲比较浪费空间。所以用非递归法来实现一下。
前序遍历
前序遍历使用一个栈来解决,从根节点开始,到左子树,先让根节点入栈,之后左子树,然后是右子树。
先来看代码实现:
public void preorder(Node root) {
Stack<Node> stack = new Stack<>();
Node cur = root;
while (!stack.isEmpty() || cur != null) {
while (cur != null) {
System.out.print(cur.value);
stack.push(cur);
cur = cur.left;
}
Node top = stack.pop();
cur = top.right;
}
}
首先把结点ABD依次入栈,因为把D入栈之后,cur.left为空了,内层循环结束。之后把DBA依次出栈,当吧A出栈之后,cur.left不再为空,而是c,于是再按照内层循环把CE依次打印并入栈
之后把EC依次出栈,C出栈之后,cur.left为F,F打印并入栈。至此循环结束。
中序遍历
中序遍历和前序遍历基本差不多,只是打印的地方有些差距。
先看代码:
public void inorder(Node root) {
Stack<Node> stack = new Stack<>();
Node cur = root;
while (!stack.isEmpty() || cur != null) {
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
Node top = stack.pop();
System.out.println(cur.value);
cur = top.right;
}
}
同样的,内层循环先把ABD依次入栈,但不打印
之后依次出栈并打印,当出到A的时候,cur不再为空,把CE依次入栈。
然后EC出栈,当C出栈之后,cur更新为F,F出栈并打印。
后序遍历
后序遍历想对特殊一些,想要打印根节点的值,必须保证根节点的right已经打印过了。
先看代码:
public void postorder(Node root) {
Stack<Node> stack = new Stack<>();
Node cur = root;
Node last = null;
while (!stack.isEmpty() || cur != null) {
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
Node top = stack.peek();
if (top.right == null || top.right == last) {
System.out.print(top.value);
stack.pop();
last = top;
} else {
cur = top.right;
}
}
}
}
}
会发现代码多了一个last变量,我们具体来看看用法。
跟着代码,首先把ABD依次入栈,之后依次判断栈顶元素的right是否为空或者等于之前遍历过得last,发现吧D的right都为空,所以依次出栈。
当出到A的时候,发现不满足栈顶元素的right是否为空或者等于之前遍历过得last,所以当前的值更新为A的right,把CE依次入栈。
当把E出完之后发现C不符合出栈的条件,于是当前值更新为F,把F入栈
F打印并出栈。
当判断C的时候,会发现此时满足C的right等于last也就是上一次的栈顶元素F,于是先打印后出栈,A亦是如此。