Java二叉樹

Taxze發表於2020-12-26
package com.company;

public class BinaryTree {
    public class BinaryTreeNode {
        private int data;  //資料
        private BinaryTreeNode leftChirld;  //左孩子
        private BinaryTreeNode rightChirld; //右孩子

        public int getData() {
            return data;
        }

        public void setData(int data) {
            this.data = data;
        }

        public BinaryTreeNode getLeftChirld() {
            return leftChirld;
        }

        public void setLeftChirld(BinaryTreeNode leftChirld) {
            this.leftChirld = leftChirld;
        }

        public BinaryTreeNode getRightChirld() {
            return rightChirld;
        }

        public void setRightChirld(BinaryTreeNode rightChirld) {
            this.rightChirld = rightChirld;
        }
    }

    /**
     * 二叉樹的建立/
     */
    public class Tree {
        private BinaryTreeNode root;

        //初始化二叉樹
        public Tree() {
        }

        public Tree(BinaryTreeNode root) {
            this.root = root;
        }

        public void setRoot(BinaryTreeNode root) {
            this.root = root;
        }

        public BinaryTreeNode getRoot() {
            return root;
        }
    }

    /**
     * 二叉樹的清空:
     * 首先提供一個清空以某個節點為根節點的子樹的方法,既遞迴地刪除每個節點;
     * 接著提供一個刪除樹的方法,直接通過第一種方法刪除到根節點即可
     */
    //清除某個子樹的所有節點
    public void clear(BinaryTreeNode node) {
        if (node != null) {
            clear(node.getLeftChirld());
            clear(node.getRightChirld());
            node = null; //刪除節點
        }
    }
    //    //清空樹
    //    public void clear(){
    //        clear(root);
    //    }

    //判斷二叉樹是否為空
    //public boolean isEmpty(){
    //    return root == null;
    //}

    /**
     * 求二叉樹的高度:
     * 首先要一種獲取以某個節點為子樹的高度的方法,使用遞迴呼叫。
     * 如果一個節點為空,那麼這個節點肯定是一顆空樹,高度為0;
     * 如果不為空,那麼我們要遍歷地比較它的左子樹高度和右子樹高度,
     * 高的一個為這個子樹的最大高度,然後加上自己本身的高度就是了
     * 獲取二叉樹的高度,只需要呼叫第一種方法,即傳入根節點
     */

//    //獲取二叉樹的高度
//    public int heigh(){
//        return heigh(root);
//    }

    //獲取以某節點為子樹的高度
    public int heigh(BinaryTreeNode node) {
        if (node == null) {
            return 0; //遞迴結束,空子樹高度為0
        } else {
            //遞迴獲取左子樹高度
            int l = heigh(node.getLeftChirld());
            //遞迴獲取右子樹高度
            int r = heigh(node.getRightChirld());
            //高度應該算更高的一邊,(+1是因為要算上自身這一層)
            return l > r ? (l + 1) : (r + 1);
        }
    }
    /**
     * 獲取二叉樹的節點數
     */
//    public int size(){
//        return size(root);
//    }


    /**
     * 求二叉樹的節點數:
     * 求節點數時,我們看看獲取某個節點為子樹的節點數的實現。
     * 首先節點為空,則個數肯定為0;
     * 如果不為空,那就算上這個節點之後繼續遞迴所有左右子樹的子節點數,
     * 全部相加就是以所給節點為根的子樹的節點數
     * 如果求二叉樹的節點數,則輸入根節點即可
     */

    public int size(BinaryTreeNode node) {
        if (node == null) {
            return 0;  //如果節點為空,則返回節點數為0
        } else {
            //計算本節點 所以要+1
            //遞迴獲取左子樹節點數和右子樹節點數,最終相加
            return 1 + size(node.getLeftChirld()) + size(node.getRightChirld());
        }
    }

    //node節點在subTree子樹中的父節點
    public BinaryTreeNode getParent(BinaryTreeNode subTree, BinaryTreeNode node) {
        if (subTree == null) {
            return null;   //如果是空子樹,則沒有父節點
        }
        if (subTree.getLeftChirld() == node || subTree.getRightChirld() == node) {
            return subTree;   //如果子樹的根節點的左右孩子之一是待查節點,則返回子樹的根節點
        }
        BinaryTreeNode parent = null;
        if (getParent(subTree.getLeftChirld(), node) != null) {
            parent = getParent(subTree.getLeftChirld(), node);
            return parent;
        } else {
            //遞迴左右子樹
            return getParent(subTree.getRightChirld(), node);
        }
    }

    //查詢node節點在二叉樹中的父節點
//    public BinaryTreeNode getParent(BinaryTreeNode node){
//        return (root==null||root==node)? null:getParent(root,node);
//    }

    /**
     * 返回左右子樹
     */
    //獲取某個節點的左子樹
    public BinaryTreeNode getleftTree(BinaryTreeNode node) {
        return node.getLeftChirld();
    }

    //獲取某個節點的右子樹
    public BinaryTreeNode getrightTree(BinaryTreeNode node) {
        return node.getRightChirld();
    }

    /**
     * 二叉樹的插入
     * 二叉樹的插入分析:
     * <p>
     * 分兩種情況:插入某個節點的左子節點;插入某個節點的右子節點
     * 值得指出的是,當這個節點本身有子節點時,這樣的插入也會覆蓋原來在這個位置上的節點。
     * 另外,雖然插入的是子節點,但是子節點也可以代表一顆子樹。
     * 因為但從這個節點來看並不知道這個節點是否有左右子樹存在,所以雖然插入的是一個節點,但有可能
     * 插入可很多節點(插入的是一顆子樹)
     */
    //給某個節點插入左節點
    public void insertLeft(BinaryTreeNode parent, BinaryTreeNode newnode) {
        parent.setLeftChirld(newnode);
    }

    //給某個節點插入右節點
    public void insertRitht(BinaryTreeNode parent, BinaryTreeNode newnode) {
        parent.setRightChirld(newnode);
    }

    /**
     * 先根遍歷(PreOrder)
     * 若二叉樹為空,則退出,否則進行下面操作
     * 1.訪問根節點
     * 2.先根遍歷左子樹
     * 3.先根遍歷右子樹
     * 退出
     */
    public void PreOrder(BinaryTreeNode node) {
        if (node != null) {
            System.out.println(node.getData()); //先訪問根節點
            PreOrder(node.getLeftChirld());  //先根遍歷左子樹
            PreOrder(node.getRightChirld());  //先根遍歷右子樹
        }
    }

    /**
     * 中根遍歷(InOrder)
     * 若二叉樹為空,則退出,否則進行下面操作
     * <p>
     * 1.中根遍歷左子樹
     * 2.訪問根節點
     * 3.中根遍歷右子樹
     * 4.退出
     */
    public void InOrder(BinaryTreeNode node) {
        if (node != null) {
            InOrder(node.getLeftChirld());  //中根遍歷左子樹
            System.out.println(node);    //訪問根節點
            InOrder(node.getRightChirld());  //中根遍歷右子樹
        }
    }

    /**後根遍歷(PostOrder)
     若二叉樹為空,則退出,否則進行下面操作

     1.後根遍歷左子樹
     2.後根遍歷右子樹
     3.訪問根節點
     4.退出*/

    public void PostOrder(BinaryTreeNode node){
        if(node!=null){
            PostOrder(node.getLeftChirld());  //後根遍歷左子樹
            PostOrder(node.getRightChirld());  //後根遍歷右子樹
            System.out.println(node);   //訪問根節點
        }
    }
}

相關文章