今天刚好想到这个问题,但是不太会,就查询后记录一下。
首先是节点类:
没有进行一些属性的封装,见谅!
class TreeNode{
int val;
TreeNode left;
TreeNode right;
public TreeNode(int val, TreeNode leftNode, TreeNode rightNode){
this.val = val;
this.left = leftNode;
this.right = rightNode;
}
public TreeNode() {
}
}
后序遍历的递归方法:没什么可说的,大家都知道
List<Integer> Diguires = new ArrayList<>();
//递归进行后序遍历:直接就先左,右,中顺序递归调用即可
public List<Integer> Digui(TreeNode root){
if(root.left != null) Digui(root.left);
if(root.right != null) Digui(root.right);
Diguires.add(root.val);
return Diguires;
}
后序遍历的非递归方法:
List<Integer> Notdiguires = new ArrayList<>();
//因为要使用非递归的方法来进行遍历,后序遍历正常是左右中:
//这里就是利用栈来存储,用中右左的顺序来存放节点,哪出栈顺序就是正常的后序顺序
public List<Integer> NotDigui(TreeNode root){
Stack<TreeNode> stack = new Stack<TreeNode>();
Stack<TreeNode> output = new Stack<TreeNode>();//构造一个中间栈来存储逆后序遍历的结果
TreeNode now = root;
//直到将节点全部放入到output栈中
while(now != null || stack.size() > 0) {
if (now != null) { //当前node有值,就存放在两个栈中,指向右边
output.push(now); //当前节点
stack.push(now);
now = now.right; //右节点
} else { //node没有值,当时栈不为空,node指向栈顶,在指向左边
now = stack.pop();
now = now.left; //左节点
}
}
while (output.size() > 0) { //output的顺序是最终的输出顺序
Notdiguires.add(output.pop().val);
}
return Notdiguires;
}
注解写的已经差不多了,这里总结一下:
就是当前节点有值就放入到栈中/中/,然后看右子节点是否有值/右/,如果有就放入栈中,没有就说明已经到叶子节点了,然后就取出栈里面的顶节点(也就是上一个放入的节点),操作左子节点/左/,继续上面的步骤,直到最左边的子节点为空(也就是最左边的叶子节点)。
也就是按照后序相反的顺序存放于栈中,从栈里面取出的就是正常的后序遍历
具体还无法理解可以画个树来按照步骤操作一下!