到现在,树的深度遍历方式中就剩下树的后序遍历方式了,后序遍历也是三种遍历方式里面相对比较难的一个,也是思路相对比较多的一个。
对于后序遍历,我们先给出一个递归的解法:
package com.mengzhidu.teach.algorithm.tree.demo.traversal;
import com.mengzhidu.teach.algorithm.tree.demo.TreeNode;
import com.mengzhidu.teach.algorithm.tree.demo.TreeNodeHelper;
/**
* Created by xinxing on 2019/3/20
*/
public class PostOrderDemo1 {
public static void main(String[] args) {
postOrder(TreeNodeHelper.getTreeNode());
}
private static void postOrder(TreeNode treeNode) {
if (treeNode == null) {
return;
}
postOrder(treeNode.getLeft());
postOrder(treeNode.getRight());
System.out.println(treeNode.getValue());
}
}
递归的解法是比较简单的,然后我们来思考一下非递归方式的实现,有很多种实现方式,比较常见的方式有两种,第一种是使用两个栈来实现,第二种是使用一个栈来实现。
其实使用两个栈来实现,也有两种常见的实现方式。我们分别来看一下:
我们来看一下使用两个栈来实现的方式,它的思考机制为:
(1).一个栈用来标记当前处理的节点,我们不妨记做栈1,一个栈我们用来存储所有的结果,它这里的存储是反向的结果。
(2).我们在处理一个节点的时候,首先把它的根节点压到两个栈里面,然后压入右子树的根节点,接下来就一直压入右子树。
(3).直到没有右子树可以压了,我们就弹出栈1的元素,把它的左子树的根节点压到栈1和栈2里面,直到它的右子树也被压完。
(4).这样,我们用栈1来标识当前的临时节点,我们用栈2来标识整个的结果集。
我们来看一下具体的结果实现吧:
package com.mengzhidu.teach.algorithm.tree.demo.traversal;
import com.mengzhidu.teach.algorithm.tree.demo.TreeNode;
import com.mengzhidu.teach.algorithm.tree.demo.TreeNodeHelper;
import java.util.Stack;
/**
* 基于双栈法实现的后序遍历
* Created by xinxing on 2019/3/20
*/
public class PostOrderDemo2 {
public static void main(String[] args) {
Stack <TreeNode> stack1 = new Stack<>();
Stack <TreeNode> stack2 = new Stack< >();
TreeNode cur = TreeNodeHelper.getTreeNode();
while(cur != null || !stack1.isEmpty()) {
while (cur != null) {
stack1.push(cur);
stack2.push(cur);
cur = cur.getRight();
}
cur = stack1.pop();
cur = cur.getLeft();
}
while(!stack2.isEmpty()) {
System.out.println(stack2.pop().getValue());
}
}
}
第二种思路也是使用两个栈,它也是使用一个栈来保存当前的指向,用一个栈来保存结果集,只不过这个结果集是和后序遍历是反着的,比如后序遍历最后保存根节点,它就先存储根节点,后序遍历倒数第二个元素是根节点的右子树的元素,它就第二个保存根节点的右子树的元素。
如果把树做一个镜像,也就是所有的节点的左右子树都进行一次交换的话,那么后序遍历可以看做是前序遍历的反过程。
说了这么多,还是来看一段代码吧:
package com.mengzhidu.teach.algorithm.tree.demo.traversal;
import com.mengzhidu.teach.algorithm.tree.demo.TreeNode;
import com.mengzhidu.teach.algorithm.tree.demo.TreeNodeHelper;
import java.util.Stack;
/**
* 基于双栈实现的方法
* Created by xinxing on 2019/3/22
*/
public class PostOrderDemo3 {
public static void main(String[] args) {
Stack<TreeNode> stack1 = new Stack<>();
Stack<TreeNode> stack2 = new Stack<>();
TreeNode root = TreeNodeHelper.getTreeNode();
stack1.push(root);
while (!stack1.isEmpty()) {
root = stack1.pop();
if (root == null) {
continue;
}
stack2.push(root);
stack1.push(root.getLeft());
stack1.push(root.getRight());
}
while (!stack2.isEmpty()) {
System.out.println(stack2.pop().getValue());
}
}
}
至此,我们使用两个栈来进行后序遍历的方式就介绍完了。