二叉樹的前序、中序、後序遍歷實現(遞歸+非遞歸)

        把LeetCode上二叉樹的三序遍歷做了,有個問題。本來想直接將LinkedList清空再重新放的,結果怎麼搞都不行。還是對C語言指針概念匱乏啊,彙編也沒學過的我哭qq。不過我通過重新new對象還是達到了想要的結果。

        List<Integer> list = new LinkedList<>();
        ......
        list = null;
        list = new LinkedList<>();

        這樣就搞定了。將list指向新的堆空間。




一、二叉樹的前序遍歷

        二叉樹的前序遍歷其實就是先訪問根結點,再前序遍歷根結點的左子樹,最後前序遍歷根結點的右子樹。


Alt

1、遞歸版

        遞歸版很容易想,直接根據定義一步到位。

	private void preOrderTraversal(Node<E> node) {
        if (node == null)
            return;
        System.out.print(node.element + " ");    
        preOrderTraversal(node.left);
        preOrderTraversal(node.right);
    }



2、非遞歸版

        觀察前序遍歷的訪問順序,一路往左訪問,訪問右結點的時候和之前往左遍歷的順序是相反的,可以藉助棧將右子樹入棧,不能往左訪問的時候就出棧,不斷循環,棧爲空則遍歷結束。

	private void preOrder(Node<E> node) {
        Stack<Node<E>> stack = new Stack<>();

        while (true) {
            if (node != null) {
                System.out.print(node.element + " ");
                if (node.right != null)
                    stack.push(node.right);
                node = node.left;
            } else {
                if (!stack.isEmpty())
                    node = stack.pop();
                else
                    break;
            }
        }
    }




二、二叉樹的中序遍歷

        二叉樹的中序遍歷其實就是先中序遍歷根結點的左子樹,再訪問根結點,最後中序遍歷根結點的右子樹。

Alt

1、遞歸版

        根據定義一步到位。

	private void inOrderTraversal(Node<E> node) {
        if (node == null)
            return;
        inOrderTraversal(node.left);
        System.out.print(node.element + " ");     
        inOrderTraversal(node.right);
    }



2、非遞歸版

        觀察中序遍歷的訪問順序,一路往左遍歷,先要訪問的是不能再往左走的結點,訪問左結點的順序和往左遍歷的順序也是相反的,藉助棧將一路往左時候經歷的結點都入棧。不能往左的時候,將棧頂元素彈出並訪問,並看看彈出的結點是否有右結點,不斷循環,棧爲空則遍歷結束。

	private void inOrder(Node<E> node) {
        Stack<Node<E>> stack = new Stack<>();
        while (true) {
            if (node != null) {
                stack.push(node);
                node = node.left;
            } else {
                if (!stack.isEmpty()) {
                    node = stack.pop();
                    System.out.print(node.element + " ");
                } else
                    break;
                node = node.right;
            }
        }
    }




三、二叉樹的後序遍歷

       二叉樹的後序遍歷其實就是先後序遍歷根結點的左子樹,再後序遍歷根結點的右子樹,最後訪問根結點。

Alt

1、遞歸版

       根據定義一步到位。

	private void postOrderTraversal(Node<E> node) {
        if (node == null)
            return;
        postOrderTraversal(node.left);
        postOrderTraversal(node.right);
        System.out.print(node.element + " ");   
    }



2、非遞歸版

       觀察後序遍歷的訪問順序,其實是先某個結點的左結點,再訪問它的右結點,最後訪問自己。藉助棧按照和訪問時候反着的順序將結點依次入棧。當遇到葉子結點或者上次彈出結點的父結點是這次棧頂的結點的時候,就從棧頂彈出元素並訪問。棧爲空,遍歷結束。

	private void postOrder(Node<E> node) {
        Stack<Node<E>> stack = new Stack<>();
        stack.push(node);
        Node<E> prevNode = null;
        while (!stack.isEmpty()) {
            Node<E> top = stack.peek();
            if ((top.left == null && top.right == null) || (prevNode != null && prevNode.parent == top)) {
                prevNode = stack.pop();
                System.out.print(prevNode.element + " ");
            } else {
                if (top.right != null)
                    stack.push(top.right);
                if (top.left != null)
                    stack.push(top.left);
            }
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章