天天看點

二叉樹的周遊

所謂周遊(Traversal)是指沿着某條搜尋路線,依次對樹中每個結點均做一次且僅做一次通路。通路結點所做的操作依賴于具體的應用問題。周遊是二叉樹上最重要的運算之一,是二叉樹上進行其它運算之基礎。周遊方式分别為:先序周遊、中序周遊、後序周遊。二叉樹前序周遊:根-> 左-> 右;二叉樹中序周遊:左-> 根-> 右;二叉樹後序周遊:左-> 右-> 根

二叉樹的周遊

所謂周遊(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();
                }

            }
        }
    }

}
           

__EOF__

歡迎轉載,但請注明出處!

歡迎大家一起交流學習!如果有什麼疑問,大家可以在評論區一起交流!

如果您覺得文章對您有幫助,可以點選文章右下角【推薦】一下。您的鼓勵是我的最大動力!