圖解二叉樹的創建和遍歷

二叉樹定義:二叉樹是每個結點最多有兩個子樹的樹結構。

二叉樹的特點:

  1. 每個節點最多有兩個子節點,即二叉樹不存在大於2的節點;
  2. 二叉樹的子樹有左右之分,其子樹的次序不能顛倒。

二叉樹的結構:

二叉樹

二叉樹的性質:

  1. 在非空二叉樹中,第 i 層的節點總數不超過 2 i-1,i >= 1;
  2. 深度爲 h 的二叉樹最多有 2 h - 1 個節點(h>=1),最少有 h 個節點;
  3. 對於任意一棵二叉樹,如果其葉節點總數爲 n1,而度數爲2的節點總數爲 n2,則 n1 = n2+1;
  4. 具有 n 個節點的完全二叉樹的深度爲 (Log2n) +1;
  5. 對於任意一個根節點,如果根節點的下標爲n,那麼它的左節點下標爲 2n+1,右節點下標爲 2n+2,根據這點可以很方便的用數組來保存二叉樹的節點。

實現二叉樹:

import java.util.ArrayList;
import java.util.List;

class BinaryTree<E> {
    // 根節點
    private Node<E> _root;
    // 用列表暫時保存下節點
    private List<Node<E>> nodes = new ArrayList<>();

    public void createTree(E[] array) {
        if (array.length == 0) {
            return;
        }
        for (E e : array) {
            nodes.add(new Node<>(null, null, null, e));
        }
        // 獲取根節點
        if (nodes.get(0) != null) {
            _root = nodes.get(0);
        }
        // 根據二叉樹的特性5來確定每個節點的左右子節點
        for (int i = 0; i < nodes.size(); i++) {
            if ((i * 2 + 1) < nodes.size() && nodes.get(i * 2 + 1) != null) {
                nodes.get(i).left = nodes.get(i * 2 + 1);
            }
            if ((i * 2 + 2) < nodes.size() && nodes.get(i * 2 + 2) != null) {
                nodes.get(i).right = nodes.get(i * 2 + 2);
            }
        }
    }

    // 節點類
    static class Node<E> {
        // 父節點暫時沒有用到
        Node<E> parent;
        // 左節點
        Node<E> left;
        // 右節點
        Node<E> right;
        // 節點中存儲的數據
        E data;

        Node(Node<E> parent, Node<E> left, Node<E> right, E data) {
            this.data = data;
            this.parent = parent;
            this.left = left;
            this.right = right;
        }

        @Override
        public String toString() {
            return data.toString();
        }
    }

    public static void main(String[] args) {
        Integer[] array = {0, 1, 2, 3, 4, 5, 6, 7, 8};
        BinaryTree<Integer> binaryTree = new BinaryTree<>();
        binaryTree.createTree(array);
    }
}

實現二叉樹的代碼很簡單,主要就是通過上述的性質5來確定每一個節點的左右子節點,一層一層的綁定關係,最終就可以將所有的節點聯繫完整。下面是二叉樹生成的整個順序:二叉樹生成過程

二叉樹的遍歷:

前面我們生成了一棵二叉樹,雖然生成了,但是卻不知道如果去遍歷二叉樹輸出每個節點對應的數據,那就等於拿到了某件東西卻不會使用,這也是不希望看到的一種情況,下面就看看如果遍歷一棵二叉樹吧!

  1. 先序遍歷: 首先訪問根節點,這也就是爲什麼上面創建二叉樹的時候要保存根節點的用處,根節點訪問之後在訪問其左子樹,最後再訪問右子樹;在訪問左右子樹的時候依舊是按照先根然左後右的順序。文字想必大家都看的模棱兩可的,下面看順序圖吧,更直觀,更清晰:image.png
    以上就是整個先序遍歷的流程,這九個步驟大家應該一眼就能看的懂,用代碼更加容易實現:
    /**
     * 先序遍歷,訪問根節點的操作發生在遍歷其左右節點之前
     *
     * @param node 某個根節點
     */
    public void preOrder(Node<E> node) {
        if (node == null) {
            return;
        }
        System.out.print(node + " ");
        preOrder(node.left);
        preOrder(node.right);
    }
  1. 中序遍歷:首先訪問根節點的左子樹,直到左子樹訪問完,回過頭來訪問根節點,最後訪問左子樹,這裏便不在貼流程圖了,簡單的把實現代碼貼出來:
    /**
     * 中序遍歷,訪問根節點的操作發生在遍歷左右節點中間
     *
     * @param node 某個根節點
     */
    public void inOrder(Node<E> node) {
        if (node == null) {
            return;
        }
        inOrder(node.left);
        System.out.print(node + " ");
        inOrder(node.right);
    }
  1. 後序遍歷:首先訪問根節點的左子樹,直到左子樹訪問完,回到根節點的右子樹,訪問完,最後訪問根節點,照樣貼上實現代碼:
    /**
     * 後序遍歷,訪問根節點的操作發生在遍歷左右節點之後
     *
     * @param node 某個根節點
     */
    public void postOrder(Node<E> node) {
        if (node == null) {
            return;
        }
        postOrder(node.left);
        postOrder(node.right);
        System.out.print(node + " ");
    }

至此爲止,二叉樹的內容就結束了,整個的源碼可以掃描下方的二維碼,我會將源碼奉上,切記多敲幾遍,這樣就才能在腦海中加深印象,不然看過覺得理解了,三天之後就又拋之腦後了!

如果本文章你發現有不正確或者不足之處,歡迎你在下方留言或者掃描下方的二維碼留言也可!

公衆號.png

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