遍历二叉树 非递归 JAVA 实现

Posted 顧棟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了遍历二叉树 非递归 JAVA 实现相关的知识,希望对你有一定的参考价值。

遍历二叉树 非递归

先序遍历

二叉树的先序遍历既可以直接采用递归思想实现,也可以使用栈的存储结构模拟递归的思想实现

中序遍历

中序遍历的非递归方式实现思想是:从根结点开始,遍历左孩子同时压栈,当遍历结束,说明当前遍历的结点没有左孩子,从栈中取出来调用操作函数,然后访问该结点的右孩子,继续以上重复性的操作。

除此之外,还有另一种实现思想:中序遍历过程中,只需将每个结点的左子树压栈即可,右子树不需要压栈。当结点的左子树遍历完成后,只需要以栈顶结点的右孩子为根结点,继续循环遍历即可。

后序遍历

后序遍历是在遍历完当前结点的左右孩子之后,才调用操作函数,所以需要在操作结点进栈时,为每个结点配备一个标志位。当遍历该结点的左孩子时,设置当前结点的标志位为 0,进栈;当要遍历该结点的右孩子时,设置当前结点的标志位为 1,进栈。

这样,当遍历完成,该结点弹栈时,查看该结点的标志位的值:如果是 0,表示该结点的右孩子还没有遍历;反之如果是 1,说明该结点的左右孩子都遍历完成,可以调用操作函数。

Java实现

package tree;

public class TreeNode {
    /**
     * 节点上的值
     */
    private int value;
    /**
     * 左节点
     */
    private TreeNode left;
    /**
     * 右节点
     */
    private TreeNode right;

    public TreeNode() {

    }

    public TreeNode(TreeNode left, TreeNode right, int value) {
        this.left = left;
        this.right = right;
        this.value = value;
    }

    public TreeNode(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public TreeNode getLeft() {
        return left;
    }

    public void setLeft(TreeNode left) {
        this.left = left;
    }

    public TreeNode getRight() {
        return right;
    }

    public void setRight(TreeNode right) {
        this.right = right;
    }
}
package tree;

import org.apache.commons.lang.StringUtils;

import java.util.Stack;

/**
 * 遍历二叉树
 */
public class TraversalBinaryTree {

    public static final StringBuilder VALUES = new StringBuilder();
    public static final String SEPARATOR = "->";
    public static final int SEPARATOR_LENGTH = SEPARATOR.length();

    /**
     * 先序遍历 非递归
     */
    public static String preOrderTraverse(TreeNode treeNode) {
        String result = "";
        Stack<TreeNode> stack = new Stack<>();
        // 树或栈不为空
        while (null != treeNode || !stack.isEmpty()) {
            // 对左子树进行遍历,直到最后没有做子树结点
            while (null != treeNode) {
                VALUES.append(treeNode.getValue()).append(SEPARATOR);
                stack.push(treeNode);
                treeNode = treeNode.getLeft();
            }
            // 栈不为空说明 还没有遍历结束
            if (!stack.isEmpty()) {
                treeNode = stack.pop();
                treeNode = treeNode.getRight();
            }
        }
        if (StringUtils.isNotBlank(VALUES.toString())) {
            result = VALUES.substring(0, VALUES.toString().length() - SEPARATOR_LENGTH);
        }
        return result;
    }

    /**
     * 中序遍历 非递归
     */
    public static String inorderTraverse(TreeNode treeNode) {
        String result = "";
        Stack<TreeNode> stack = new Stack<>();

        while (null != treeNode || !stack.isEmpty()) {
            // 对左子树进行遍历,直到最后没有做子树结点
            while (null != treeNode) {
                stack.push(treeNode);
                treeNode = treeNode.getLeft();
            }

            // 栈不为空说明 还没有遍历结束
            if (!stack.isEmpty()) {
                treeNode = stack.pop();
                VALUES.append(treeNode.getValue()).append(SEPARATOR);
                treeNode = treeNode.getRight();
            }
        }

        if (StringUtils.isNotBlank(VALUES.toString())) {
            result = VALUES.substring(0, VALUES.toString().length() - SEPARATOR_LENGTH);
        }
        return result;
    }

    /**
     * 后序遍历 非递归
     */
    public static String postorderTraverse(TreeNode treeNode) {
        String result = "";
        // 左右结点的标记
        Integer flagLeft = 0;
        Integer flagRight = 1;
        Stack<TreeNode> stack = new Stack<>();
        //辅助栈,用来判断子节点返回父节点时处于左节点还是右节点。
        Stack<Integer> stack2 = new Stack<>();

        while (null != treeNode || !stack.isEmpty()) {

            while (null != treeNode) {
                stack.push(treeNode);
                stack2.push(flagLeft);
                treeNode = treeNode.getLeft();
            }

            // 如果是从右子节点返回父节点,则任务完成,将两个栈的栈顶弹出
            while (!stack.empty() && flagRight.equals(stack2.peek())) {
                stack2.pop();
                VALUES.append(stack.pop().getValue()).append(SEPARATOR);
            }

            // 如果是从左子节点返回父节点,则将标记改为右子节点
            if (!stack.empty() && flagLeft.equals(stack2.peek())) {
                stack2.pop();
                stack2.push(flagRight);
                treeNode = stack.peek().getRight();
            }
        }

        if (StringUtils.isNotBlank(VALUES.toString())) {
            result = VALUES.substring(0, VALUES.toString().length() - SEPARATOR_LENGTH);
        }
        return result;
    }
}
package tree;


import java.util.Stack;

public class Client {

    public static void main(String[] args) {
        String result = "";
        TreeNode treeNode = init();

        System.out.println("===非递归方式===");
        TraversalBinaryTree.VALUES.delete(0, result.length() + 2);
        result = TraversalBinaryTree.preOrderTraverse(treeNode);
        System.out.println("先序结果=" + result);

        TraversalBinaryTree.VALUES.delete(0, result.length() + 2);
        result = TraversalBinaryTree.inorderTraverse(treeNode);
        System.out.println("中序结果=" + result);

        TraversalBinaryTree.VALUES.delete(0, result.length() + 2);
        result = TraversalBinaryTree.postorderTraverse(treeNode);
        System.out.println("后序结果=" + result);
    }

    /**
     * 构建如下的二叉树,同时是个满二叉树
     * 1
     * /  \\
     * 2    3
     * /  \\  / \\
     * 4   5 6   7
     */
    public static TreeNode init() {
        TreeNode root = new TreeNode(1);
        TreeNode treeNode2 = new TreeNode(2);
        TreeNode treeNode3 = new TreeNode(3);
        root.setLeft(treeNode2);
        root.setRight(treeNode3);
        TreeNode treeNode4 = new TreeNode(4);
        TreeNode treeNode5 = new TreeNode(5);
        TreeNode treeNode6 = new TreeNode(6);
        TreeNode treeNode7 = new TreeNode(7);
        treeNode2.setLeft(treeNode4);
        treeNode2.setRight(treeNode5);
        treeNode3.setLeft(treeNode6);
        treeNode3.setRight(treeNode7);
        return root;
    }


}
===非递归方式===
先序结果=1->2->4->5->3->6->7
中序结果=4->2->5->1->6->3->7
后序结果=4->5->2->6->7->3->1

以上是关于遍历二叉树 非递归 JAVA 实现的主要内容,如果未能解决你的问题,请参考以下文章

遍历二叉树 非递归 JAVA 实现

超强二叉树解析.必收藏!(数组,链表实现,8种遍历方法,前,中,后序线索化二叉树及其遍历)---风之java

非递归遍历二叉树Java实现

(Java)二叉树的三种遍历(非递归实现)

遍历二叉树的递归与非递归代码实现

C++实现二叉树 前中后序遍历(递归与非递归)非递归实现过程最简洁版本