二叉树的遍历

二叉树

所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问。访问结点所做的操作依赖于具体的应用问题。遍历是二叉树上最重要的运算之一,是二叉树上进行其它运算之基础。

遍历方式分别为:先序遍历、中序遍历、后序遍历。

遍历之前,我们先来创建一棵树。
首先要声明结点TreeNode类,代码如下:

public class TreeNode {
    private int val;
    private TreeNode left;
    private TreeNode right;
    public TreeNode() {
    }

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

    public TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
     
    // 省略get、set
}

随机创建一个tree

public class TreeBuilder {

    /**
     *                      1
     *                  /       \
     *                 2            3
     *              /   \           /   \
     *             4     5         6     7
     *             /                \
     *             8                 9
     * @return
     */
    public static TreeNode randomBuild() {
        TreeNode node8 = new TreeNode(8);
        TreeNode node9 = new TreeNode(9);
        TreeNode node7 = new TreeNode(7);
        TreeNode node6 = new TreeNode(6, null, node9);
        TreeNode node5 = new TreeNode(5);
        TreeNode node4 = new TreeNode(4, node8, null);
        TreeNode node3 = new TreeNode(3, node6, node7);
        TreeNode node2 = new TreeNode(2, node4, node5);
        TreeNode node1 = new TreeNode(1, node2, node3);

        return node1;
    }

}

使用递归的方式进行遍历

public class TreePrint1 {

    public static void main(String[] args) {
        TreeNode head = TreeBuilder.randomBuild();

        System.out.println("preorderTraversal");
        preorderTraversal(head);

        System.out.println("\n\ninorderTraversal");
        inorderTraversal(head);

        System.out.println("\n\npostorderTraversal");
        postorderTraversal(head);
    }

    /**
     * 二叉树前序遍历   根-> 左-> 右
     */
    private static void preorderTraversal(TreeNode head) {
        if (head == null) {
            return;
        }
        System.out.print(head.getVal() + " ");
        preorderTraversal(head.getLeft());
        preorderTraversal(head.getRight());
    }

    /**
     *  二叉树中序遍历   左-> 根-> 右
     */
    private static void inorderTraversal(TreeNode head) {
        if (head == null) {
            return;
        }
        inorderTraversal(head.getLeft());
        System.out.print(head.getVal() + " ");
        inorderTraversal(head.getRight());
    }

    /**
     * 二叉树后序遍历   左-> 右-> 根
     */
    private static void postorderTraversal(TreeNode head) {
        if (head == null) {
            return;
        }
        postorderTraversal(head.getLeft());
        postorderTraversal(head.getRight());
        System.out.print(head.getVal() + " ");
    }

}

使用非递归的方式进行遍历

public class TreePrint2 {

    public static void main(String[] args) {
        TreeNode head = TreeBuilder.randomBuild();

        System.out.println("preorderTraversal");
        preorderTraversal(head);

        System.out.println("\n\ninorderTraversal");
        inorderTraversal(head);

        System.out.println("\n\npostorderTraversal");
        postorderTraversal(head);
    }

    /**
     * 二叉树前序遍历   根-> 左-> 右
     */
    private static void preorderTraversal(TreeNode head) {
        if (head == null) {
            return;
        }
        Stack<TreeNode> stack = new Stack<>();
        TreeNode node = head;
        while (node != null || !stack.isEmpty()) {
            while (node != null) {
                System.out.print(node.getVal() + " ");
                stack.push(node);
                node = node.getLeft();
            }
            if (!stack.isEmpty()) {
                node = stack.pop().getRight();
            }
        }
    }

    /**
     *  二叉树中序遍历   左-> 根-> 右
     */
    private static void inorderTraversal(TreeNode head) {
        if (head == null) {
            return;
        }
        Stack<TreeNode> stack = new Stack<>();
        TreeNode node = head;
        while (node != null || !stack.isEmpty()) {
            while (node != null) {
                stack.push(node);
                node = node.getLeft();
            }
            if (!stack.isEmpty()) {
                node = stack.pop();
                System.out.print(node.getVal() + " ");
                node = node.getRight();
            }
        }
    }

    /**
     * 二叉树后序遍历   左-> 右-> 根
     */
    private static void postorderTraversal(TreeNode head) {
        if (head == null) {
            return;
        }
        Stack<TreeNode> stack = new Stack<>();
        TreeNode node = head;   // 当前根节点
        TreeNode last = null;   // 上一次打印的节点
        while (node != null || !stack.isEmpty()) {
            while (node != null) {
                stack.push(node);
                node = node.getLeft();
            }
            if (!stack.isEmpty()) {
                node = stack.pop();
                /*
                没有右节点,当前节点可以打印了
                当前节点的右节点就是上一次打印的节点,当前节点可以打印了
                “node = null”表示当前节点的这个分支不能再处理了,因为外层循环是“node = node.getLeft()”
                 */
                if (node.getRight() == null || node.getRight() == last) {
                    System.out.print(node.getVal() + " ");
                    last = node;
                    node = null;
                }else {
                    stack.add(node);
                    node = node.getRight();
                }

            }
        }
    }

}
posted @ 2021-02-01 00:23  狼爷  阅读(97)  评论(0编辑  收藏  举报