辛星Java树算法教程第四篇:二叉树的后序遍历(非递归单栈方式)

对于二叉树的后序遍历,我们前面介绍了一种使用递归的方式,这种比较简单,还有两种使用栈的方式,但是这里都是选择了使用两个栈。
那么能不能使用一个栈来完成呢?显然是可以呢。那么具体怎么操作呢?这里也有很多思路,我们这里介绍两种比较常规的思路。

第一种是用一个临时变量来保存访问过的节点,它的主要目的是判断一个节点的左右子树是否均被访问完成。
如果一个节点的左右子树均被访问了,那么我们就可以访问这个节点,否则就按照右子树、左子树的方式进行压栈,以备后续处理。
我们来看一下具体的实现吧:

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;

/**
 * 根据单栈法来实现二叉树的后序遍历
 * 它这里用一个变量last来保存当前最后访问的节点,它必须在访问后设置
 * 如何来判断一个节点node的左右子树都被访问呢?
 * 使用: (node.right == null && node.left == last) || node.right == last
 *
 * 它的思路就是:
 * 如果一个节点的左右子树均被访问过或者是叶子节点,那么就访问它
 * 否则把右子树和左子树依次压入到栈中
 */
public class PostOrderDemo4 {

    public static void main(String[] args) {
        TreeNode current = TreeNodeHelper.getTreeNode();
        TreeNode last = null;
        Stack<TreeNode> stack = new Stack<>();
        stack.push(current);
        while (!stack.isEmpty()) {
            current = stack.peek();
            boolean emptyNode = current.getRight() == null && current.getLeft() == null;
            boolean visited = (current.getRight() == null && current.getLeft() == last) || current.getRight() == last;
            if (emptyNode || visited) {
                stack.pop();
                System.out.println(current.getValue());
                last = current;
            } else {
                if (current.getRight() != null) {
                    stack.push(current.getRight());
                }
                if (current.getLeft() != null) {
                    stack.push(current.getLeft());
                }
            }
        }

    }
}

第二种就是采用压栈两次的方式,对于某个特定的节点,当它第一次出栈的时候,它会把右子树和左子树给压进去,当它第二次出栈的时候,它会把自己打印出来。
其实它的思想和第一种方法没有本质的区别,我们来看一下代码实现吧:

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;

/**
 * 使用单栈方式的后序遍历
 * 这里使用压栈两次的方法,第一次出栈是把孩子压进去,第二次出栈是访问自己
 */
public class PostOrderDemo5 {

    public static void main(String[] args) {
        TreeNode current = TreeNodeHelper.getTreeNode();
        Stack<TreeNode> stack = new Stack<>();
        stack.push(current);
        stack.push(current);

        while (!stack.isEmpty()) {
            current = stack.pop();
            if (!stack.isEmpty() && current == stack.peek()) {
                if (current.getRight() != null) {
                    stack.push(current.getRight());
                    stack.push(current.getRight());
                }
                if (current.getLeft() != null) {
                    stack.push(current.getLeft());
                    stack.push(current.getLeft());
                }
            } else {
                System.out.println(current.getValue());
            }
        }
    }
}

对于树的后序遍历,我们就介绍到这里啦。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值