06.Java數據結構與算法之~二叉樹的基本概念及遍歷

06.Java數據結構與算法之~二叉樹

       樹(Tree)是n(n >= 0)個結點的有限集。n = 0時稱爲空樹。

       在任意一顆非空樹中,有且僅有一個特定的稱爲根(Root)的結點。

       其餘結點可分爲m(m > 0)個互不相交的有限集 T1、T2、、、Tm,其中每一個集合本身又是一棵樹,並且稱爲根的子樹(SubTree)

以下不是樹

原因: E既是D的子集又是C的子集,違反了樹的概念!

結點的度

       結點擁有的子樹數稱爲結點的度。度爲0的結點稱爲葉子結點或終端結點。度不爲0的結點稱爲非終端結點或分支結點。除根結點以外,分支結點也稱爲內部結點。樹的度是樹內各結點的度的最大值。

層次與深度

       結點的層次(Level)從根開始定義起,根爲第一層,根的孩子爲第二層。若某結點在第1層,則其子樹的根就在 i + 1 層。其雙親在同一層的結點互爲堂兄弟。顯然圖中的D、E、F是堂兄弟,而G、H、I、J也是。樹中結點的最大層次稱爲樹的深度(Deph)或高度,當前樹的深度爲4。

有序與無序樹

       如果將樹中結點的各子樹看成從左至右是有次序的,不能互換的,則稱該樹爲有序樹,否則稱無序樹。

二叉樹

爲什麼需要樹這種數據結構?

數組存儲方式的分析:

       優點:通過下標方式訪問元素,速度快。對於有序數組,還可以用二分查找提高檢索速度

       缺點:如果要檢索某個具體值,或者插入刪除值會整體移動,效率較低

鏈式存儲方式的分析:

       優點:在一定程度上對數組存儲方式有優化,比如,插入一個數值結點只需要將插入結點連接到鏈表中即可,刪除也只需要將前一個結點指向後一個結點不需要整體移動,因此效率好

       缺點:在進行檢索時,效率依然很低。因爲需要從頭遍歷

樹存儲方式分析:

       比如二叉排序樹(Binary sort tree)既可以保證數據的檢索速度,又可以保證插入、刪除、修改的速度

什麼是二叉樹?

       每個節點最多只能有兩個子節點的一種形式稱爲二叉樹

       二叉樹的子節點分爲左節點和右節點

斜樹

       所有節點都只有左子樹的二叉樹稱爲左斜樹,只有右子樹的二叉樹稱爲右斜樹。總之統稱爲斜樹

滿二叉樹

       在一顆二叉樹中,如果所有分支節點都存在左子樹和右子樹,並且所有葉子都在同一層上,這樣的二叉樹稱爲滿二叉樹。

二叉樹遍歷代碼實現

定義Tree接口

public interface Tree {
    //構建樹
    void CreateBinaryTree(Object tree, Object left, Object right);
    //先序遍歷
    void PreOrder();
    //中序遍歷
    void InfixOrder();
    //後序遍歷
    void PostOrder();
}

編寫BinaryTree二叉樹實現類

public class BinaryTree implements Tree{
    private BinaryTree left;    //左子樹
    private BinaryTree right;   //右子樹
    private Object root;        //根節點

    //-------構造傳值-------
    public BinaryTree(Object data){
        root =  data;
    }
    @Override
    //-------構建樹-------         爲了兼容接口統一Object
    public void CreateBinaryTree(Object tree, Object left, Object right){
        //強制轉換
        BinaryTree Tree = (BinaryTree) tree;
        Tree.left = (BinaryTree)left;
        Tree.right = (BinaryTree)right;
    }

    //-------先序遍歷-------
    @Override
    public void PreOrder() {
        //判斷二叉樹是否爲空
        if(root != null){
            System.out.print(root + " ");
            //判斷左子節點是否爲空
            if(left != null){
                left.PreOrder();
            }
            if(right != null){
                right.PreOrder();
            }
        }else{
            //說明樹爲空,空指針異常
            throw new NullPointerException();
        }
    }
    //-------中序遍歷-------
    @Override
    public void InfixOrder() {
        //判斷二叉樹是否爲空
        if(root != null){
            //判斷左子節點是否爲空
            if(left != null){
                left.InfixOrder();
            }
            System.out.print(root + " ");
            if(right != null){
                right.InfixOrder();
            }
        }else{
            //說明樹爲空,空指針異常
            throw new NullPointerException();
        }
    }
    //-------後序遍歷-------
    @Override
    public void PostOrder() {
        //判斷二叉樹是否爲空
        if(root != null){
            //判斷左子節點是否爲空
            if(left != null){
                left.PostOrder();
            }
            if(right != null){
                right.PostOrder();
            }
            System.out.print(root + " ");
        }else{
            //說明樹爲空,空指針異常
            throw new NullPointerException();
        }
    }
}

測試:

    public static void main(String[] args) {
        Tree A = new BinaryTree("A");
        Tree B = new BinaryTree("B");
        Tree C = new BinaryTree("C");
        Tree D = new BinaryTree("D");
        Tree E = new BinaryTree("E");
        Tree F = new BinaryTree("F");
        Tree G = new BinaryTree("G");

        A.CreateBinaryTree(A,B,C);  //定義A的兩個子節點
        A.CreateBinaryTree(B,D,E);  //定義B的兩個子節點
        A.CreateBinaryTree(C,F,G);  //定義C的兩個子節點

        System.out.println("先序遍歷");
        A.PreOrder();
        System.out.println("\n中序遍歷");
        A.InfixOrder();
        System.out.println("\n後序遍歷");
        A.PostOrder();      
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章