java學習之—二叉樹

package com.data.java.towtree;

import java.io.IOException;

/**
 * 二叉樹
 * @Title: uminton
 */

class Node{
    public int iData; //數據用做關鍵值
    public double dData; //其餘數據
    public Node leftChild; //左子節點
    public Node rightChild; //右子節點

    public Node() {
    }

    public Node(int iData, double dData) {
        this.iData = iData;
        this.dData = dData;
    }

    public void displayNode(){
        System.out.print("{");
        System.out.print(iData);
        System.out.print(", ");
        System.out.print(dData);
        System.out.print("} ");
    }
}

public class Tree {

    private Node root; //根節點

    public Node getRoot() {
        return root;
    }

    /**
     * 查找一個數據
     * @param key
     * @return
     */
    public Node find(int key){
        Node current = root;                 //把跟節點設置爲當前節點
        while (current.iData != key){        //循環查找
            if(key < current.iData){         //若是小於就去當前樹的左邊子節點
                current = current.leftChild; //把子節點賦給當前節點
            }else {                          //若是大於就去當前樹的右邊子節點
                current = current.rightChild;//把子節點賦給當前節點
            }
            if(current == null){             //到達序列的末端沒有找到節點,代表他不存在,返回空
                return current;
            }
        }
        return current;                      //循環條件相等,循環結束,找到結果。
    }

    /**
     * 添加一個數據
     * @param id
     * @param dd
     */
    public void insert(int id, double dd) {
        Node newNode = new Node(id, dd);            //先建立一個新節點
        if(root == null){                           //若是跟節點爲空,表示樹,沒有數據,直接賦值給根節點
            root = newNode;
        }else {
            Node current = root;                    //根節點賦值給當前節點,用於查找
            Node parent;                            //父節點,用來存儲遇到的最後一個不是null的節點,由於curent在查找的過程當中會變成null,
                                                    // 才能發現發現查找過得上一個節點沒有子節點
            while (true){                           //循環查找
                parent = current;                   //用來存儲遇到的最後一個不是null的節點
                if (id < current.iData){            //若是小於就去當前樹的左邊子節點
                    current = current.leftChild;
                    if(current == null){            //到達序列的末端沒有找到節點,代表他不存在
                        parent.leftChild = newNode; //把新的節點賦值給父節點的左子節點
                        return;                     //直接返回,結束循環
                    }
                }else {
                    current = current.rightChild;
                    if(current == null){
                        parent.rightChild = newNode;
                        return;
                    }
                }
            }
        }
    }

    /**
     * 刪除一個數據
     * @param key
     * @return
     *
     * 刪除節點要考慮的三種狀況
     * 1,該節點是葉節點
     * 2,該節點有一個子節點
     * 3,該節點有二個子節點
     */
    public boolean delete(int key){
        Node current = root;
        Node parent = root;
        boolean isLeftChild = true;             //記錄是左節點仍是右節點
        while(current.iData != key){            //循環爲了找到要刪除的節點,循環條件若是相等就是找到了,退出循環
            parent = current;                   //保存要刪除的父節點
            if(key < current.iData){
                isLeftChild = true;
                current = current.leftChild;
            }else {
                isLeftChild = false;
                current = current.rightChild;
            }
            if(current == null){                //查找到末端,都沒有找到,返回false
                return false;
            }
        }
        /**************************狀況1開始*********************************/
        if(current.leftChild == null && current.rightChild == null) {  //判斷是否沒有子節點,也就是該節點是葉節點
            if (current == root) {              //若是是根節點,直接賦值爲null
                root = null;
            } else if (isLeftChild) {           //判斷是不是左節點
                parent.leftChild = null;        //用上面保存的父節點找子節點,直接賦值爲null
            } else {
                parent.rightChild = null;
            }
        /**************************狀況1結束*********************************/

        /**************************狀況2開始*********************************/
        }else if (current.rightChild == null){      //判斷左邊等null或右邊等於null
            if(current == root){                    //若是是根節點,直接賦值爲null
                root = current.leftChild;
            }else if (isLeftChild){                 //判斷是不是左節點
                parent.leftChild = current.leftChild;//用上面保存的父節點找子節點,直接賦值爲null
            }else {
                parent.rightChild = current.leftChild;
            }
        }else if (current.leftChild == null){       //下面同理
            if(current == root){
                root = current.rightChild;
            }else if (isLeftChild){
                parent.leftChild = current.rightChild;
            }else {
                parent.rightChild = current.rightChild;
            }
        /**************************狀況2結束*********************************/

        /**************************狀況3開始*********************************/
        }else {                                     //上面都不成立,代表該節點有兩個子節點。
            Node successor = getSuccessor(current); //取得後繼者
            if(current == root){                    //若是是根節點,直接賦值爲後繼者
                root = successor;
            }else if (isLeftChild){                 //判斷是不是左節點
                parent.leftChild = successor;       //用上面保存的父節點找子節點,直接賦值爲後繼者
            }else {
                parent.rightChild = successor;
            }
            successor.leftChild = current.leftChild;
        }
        /**************************狀況3結束*********************************/
        return true;
    }

    /**
     * 中序遍歷樹
     * @param localRoot
     */
    public void inOrder(Node localRoot){
        if(localRoot != null){
            inOrder(localRoot.leftChild);
            System.out.println(localRoot.iData);
            inOrder(localRoot.rightChild);
        }
    }

    /**
     * 查找最小值
     * @return
     */
    public Node minNumber(){
        Node current = root;
        Node last = null;
        while (current != null){
            last = current;
            current = current.leftChild;
        }
        return last;
    }

    /**
     * 獲取刪除節點的後繼者
     * @param delNode
     * @return
     * 算法:程序找到要刪除的節點的右子節點,(它的關鍵字值必定比要刪除的節點的值大)而後轉到右子節點的左子節點(若果有的話)
     * 而後到這個左子節點的左子節點,以此類推,這個路徑的最後一個左子節點就是要刪除節點的後繼者
     * 若果刪除節點右子節點沒有左子節點,它就是後繼者
     */
    private Node getSuccessor(Node delNode) {
        Node successorParent = delNode;
        Node successor = delNode;
        Node current = delNode.rightChild;          //刪除節點右子節點
        while (current != null){
            successorParent = successor;            //保留後繼者的父節點
            successor = current;                    //後繼者
            current = current.leftChild;            //循環查找左子節點
        }
        if(successor != delNode.rightChild){
            successorParent.leftChild = successor.rightChild;
            successor.rightChild = delNode.rightChild;
        }
        return successor;
    }
}

class TreeApp{
    public static void main(String[] args) throws IOException {
        Tree treTree = new Tree();
        treTree.insert(38,1.5);
        treTree.insert(65,1.5);
        treTree.insert(40,1.5);
        treTree.insert(50,1.5);
        treTree.insert(55,1.5);
        treTree.insert(30,1.5);
        treTree.insert(90,1.5);
        treTree.insert(25,1.6);
        treTree.insert(70,1.7);
        treTree.insert(20,1.7);
        treTree.insert(80,1.7);

        treTree.delete(65);

    }
}

  

最後刪除有點複雜,沒怎麼搞懂見諒。java

相關文章
相關標籤/搜索