二叉树的遍历

二叉树

所谓遍历(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();
                }

            }
        }
    }

}

相关文章

背景:计算机内部用补码表示二进制数。符号位1表示负数,0表...
大家好,我们现在来讲解关于加密方面的知识,说到加密我认为不...
相信大家在大学的《算法与数据结构》里面都学过快速排序(Qui...
加密在编程中的应用的是非常广泛的,尤其是在各种网络协议之...
前言我的目标是写一个非常详细的关于diff的干货,所以本文有...
对称加密算法 所有的对称加密都有一个共同的特点:加密和...