二叉樹的遍歷以及遞歸、非遞歸實現 / 層次遍歷

二叉樹的遍歷

二叉樹遍歷的經典方法有四種,前序遍歷、中序遍歷、後序遍歷和層次遍歷。

其中,前、中、後序,表示的是節點與它的左右子樹節點遍歷打印的先後順序。

 

前序遍歷是指,對於樹中的任意節點來說,先打印這個節點,然後再打印它的左子樹,最後打印它的右子樹。

中序遍歷是指,對於樹中的任意節點來說,先打印它的左子樹,然後再打印它本身,最後打印它的右子樹。

後序遍歷是指,對於樹中的任意節點來說,先打印它的左子樹,然後再打印它的右子樹,最後打印這個節點本身。

 

前中後序是DFS(深度優先算法)的思想

 

 

實際上,二叉樹的前、中、後序遍歷就是一個遞歸的過程。

前序遍歷,其實就是先打印根節點,然後再遞歸地打印左子樹,最後遞歸地打印右子樹。 

前序遍歷的遞推公式:
preOrder(r) = print r->preOrder(r.left)->preOrder(r.right)

中序遍歷的遞推公式:
inOrder(r) = inOrder(r.left)->print r->inOrder(r.right)

後序遍歷的遞推公式:
postOrder(r) = postOrder(r.left)->postOrder(r.right)->print r

 

遞歸實現

    /**
     * 先序遍歷
     */
    public static void preOrder(Node root) {
        if (root == null) {
            return;
        }
        System.out.print(root.value + " -> ");
        preOrder(root.left);
        preOrder(root.right);
    }

    /**
     * 中序遍歷
     */
    public static void inOrder(Node root) {
        if (root == null) {
            return;
        }
        inOrder(root.left);
        System.out.print(root.value + " -> ");
        inOrder(root.right);
    }

    /**
     * 後序遍歷
     */
    public static void postOrder(Node root) {
        if (root == null) {
            return;
        }
        postOrder(root.left);
        postOrder(root.right);
        System.out.print(root.value + " ->  ");
    }

非遞歸實現

遞歸本身是藉助棧實現的,所以非遞歸的實現也需要棧來實現,本質上實際變成了我們“手動遞歸”

    /**
     * 前序遍歷
     */

    public static void preOrder2(Node root) {
        if (root == null) {
            return;
        }
        Stack<Node> s = new Stack<>();
        s.push(root);
        Node curNode;
        while (!s.isEmpty()) {
            curNode = s.pop();
            System.out.print(curNode.data + "->");
            // 棧先進後出,所以先加入右側節點,這樣輸出的時候,先輸出左側節點
            if (curNode.right != null) {
                s.push(curNode.right);
            }
            if (curNode.left != null) {
                s.push(curNode.left);
            }
        }
    }


    /**
     * 中序遍歷
     */

    public static void inOrder2(Node root) {
        if (root == null) {
            return;
        }
        Stack<Node> s = new Stack<>();
        Node curNode = root;
        while (!s.isEmpty() || curNode != null) {
            // 入棧所有左節點並輸出左節點
            while (curNode != null) {
                s.push(curNode);
                curNode = curNode.left;
            }

            // 彈出左節點
            curNode = s.pop();
            System.out.print(curNode.data + "->");
            // 彈出後,指向當前節點的右節點
            curNode = curNode.right;
        }
    }

     /**
     * 後序遍歷
     */
    public static void postOrder2(Node root) {
        if (root == null) {
            return;
        }

        Stack<Node> s1 = new Stack<>();
        Stack<Node> s2 = new Stack<>();

        s1.push(root);

        Node curNode;
        while (!s1.isEmpty()) {

            curNode = s1.pop();
            // 中、右、左順序壓入棧中
            s2.push(curNode);

            // 壓入s1爲先左後右,保證中、右、左順序壓入s2中
            if (curNode.left != null) {
                s1.push(curNode.left);
            }
            if (curNode.right != null) {
                s1.push(curNode.right);
            }
        }
        while (!s2.isEmpty()) {
            System.out.print(s2.pop().data + "->");
        }

    }

層次遍歷

層次遍歷是BFS(廣度優先算法)的思想。

一般藉助於隊列來實現二叉樹的層次遍歷。

 

層次遍歷的步驟是:

1.對於不爲空的結點,先把該結點加入到隊列中

2.從隊中拿出結點,如果該結點的左孩子不爲空,就分別把左孩子加入到隊列中,否則什麼都不做。右孩子同理

3.重複以上操作直到隊列爲空,層次遍歷結束

 

    public static void LevelTraversal(Node root) {
        if (root == null) {
            return;
        }
        Queue<Node> queue = new LinkedList<Node>();
        Node curNode = null;
        queue.offer(root);//將根節點入隊
        while (!queue.isEmpty()) {
            curNode = queue.poll();//出隊隊頭元素並訪問
            System.out.print(curNode.data + "->");
            if (curNode.left != null)//如果當前節點的左節點不爲空入隊
            {
                queue.offer(curNode.left);
            }
            if (curNode.right != null)//如果當前節點的右節點不爲空,把右節點入隊
            {
                queue.offer(curNode.right);
            }
        }
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章