Java實現二叉排序樹的插入查詢與遍歷

二叉排序樹的非遞歸插入,非遞歸查詢,尋找最大值,尋找最小值java

package whut.tree;
//二叉排序樹的非遞歸插入,非遞歸查詢,尋找最大值,尋找最小值
class Node {
    private int data;
    private Node left;
    private Node right;
    public Node(int data) {
        this.data = data;
    }
    public int getData() {
        return data;
    }
    public Node getLeft() {
        return left;
    }
    public void setLeft(Node left) {
        this.left = left;
    }
    public Node getRight() {
        return right;
    }
    public void setRight(Node right) {
        this.right = right;
    }
    // 展現節點數據
    public void displayNode() {
        System.out.println(" " + data + " ");
    }
}
// 樹
public class BinaryTree {
    private Node root;// 樹根
    // 非遞歸方式插入新的節點數據,
    public void insert(int data) {
        Node newNode = new Node(data);
        if (root == null) {
            root = newNode;
        } else {
            // 子節點,當前節點
            Node current = root;
            // 父節點
            Node parent;
            while (true)// 尋找插入的位置
            {
                parent = current;
                // 當小於根節點,插入到左邊
                if (data < current.getData()) {
                    current = current.getLeft();
                    // 跳出循環
                    if (current == null) {
                        parent.setLeft(newNode);
                        return;
                    }
                } else {
                    current = current.getRight();
                    if (current == null) {
                        parent.setRight(newNode);
                        return;
                    }
                }
            }
        }
    }
    // 非遞歸方式實現查詢
    public Node find(int data) {
        Node current = root;
        while (current.getData() != data) {
            if (current.getData() < data)
                current = current.getLeft();
            else
                current = current.getRight();
            // 當一個元素不在一個二叉樹中,確定爲null了
            if (current == null)
                return null;
        }
        // 跳出循環說明找到了那個相等的
        return current;
    }
    // 找二叉樹最小的節點,一直遍歷左孩子,直到其左孩子爲null
    public Node findMinNode() {
        Node current;
        Node parent;
        //
        if (root == null) {
            return null;
        } else {
            parent = root;
            current = parent.getLeft();
            while (current != null) {
                parent = current;
                current = current.getLeft();
            }
            return parent;
        }
    }
    // 找到二叉排序樹的最大值,也就是最右邊的孩子
    public Node findMaxNode() {
        Node current;
        Node parent;
        //
        if (root == null) {
            return null;
        } else {
            parent = root;
            current = parent.getRight();
            while (current != null) {
                parent = current;
                current = current.getRight();
            }
            return parent;
        }
    }
    // 先要找到節點,而後根據要刪除節點的位置進行刪除
    // 刪除的節點有三種,葉子節點,有一個節點的節點,有兩個節點的節點
    public boolean delete(int key) {
        Node current = root;
        Node parent = root;
        // 這裏主要是爲了區分刪除的是左孩子仍是右孩子
        boolean isLeftChild = false;
        // 顯然,當current.iData == key 時,current就是須要刪除的節點
        // 在循環中利用parent保存了父類節點
        while (current.getData() != key) {
            parent = current;
            if (key < current.getData()) {
                isLeftChild = true;
                current = current.getLeft();
            } else {
                isLeftChild = false;
                current = current.getRight();
            }
            if (current == null)// 找不到key時返回false
                return false;
        }
        // 當節點爲葉子節點的時候
        if (current.getLeft() == null && current.getRight() == null) {
            if (current == root)
                root = null;
            else if (isLeftChild)
                parent.setLeft(null);
            else
                parent.setRight(null);
        }
        // 當刪除的節點爲含有一個子節點的節點
        // 刪除的節點只有一個左子節點時
        // 必需要考慮被刪除的節點是左節點仍是右節點
        else if (current.getRight() == null) {
            if (current == root)// 要刪除的節點爲根節點
                root = current.getLeft();
            else if (isLeftChild)// 要刪除的節點是一個左子節點
                parent.setLeft(current.getLeft());
            else
                parent.setRight(current.getLeft());// 要刪除的節點是一個右子節點
        }
        // 當刪除的節點爲含有一個子節點的節點
        // 刪除的節點只有一個右子節點時
        // 必需要考慮被刪除的節點是左節點仍是右節點
        else if (current.getLeft() == null) {
            if (current == root)// 要刪除的節點爲根節點
                root = current.getRight();
            else if (isLeftChild)// 要刪除的節點是一個左子節點
                parent.setLeft(current.getRight());
            else
                parent.setRight(current.getRight());// 要刪除的節點是一個右子節點
        }
        // 當要刪除的節點是含有兩個節點的時候
        else
         {
            //首先要獲取被刪除節點的後繼節點,current
             Node successor = getSuccessor(current);
             if(current == root)
                root = successor ;
             //這裏已經屏蔽了後繼節點是葉子和非葉子節點
             else if(isLeftChild)
                    parent.setLeft(successor);
             else
                    parent.setRight(successor);
             successor.setLeft(current.getLeft());
         }
        return true;
    }
    // 尋找後記節點,主要是當要刪除的節點包含了兩個子節點的時候
    // 返回後繼節點,後繼節點就是比要刪除的節點的關鍵值要大的節點集合中的最小值。
    //後繼節點要麼是被刪除節點的不包含左子節點的右節點,要麼就是包含左子節點的右節點的子節點
    private Node getSuccessor(Node delNode)
    {
        // 後繼節點的父節點
        Node successorParent = delNode;
        // 後繼節點
        Node successor = delNode.getRight();
        //判斷後繼節點是否有左孩子
        Node current = successor.getLeft();
        while (current != null) {
            successorParent = successor;
            successor = current;
            current = current.getLeft();
        }
        //當該後繼節點是屬於包含左子節點的右節點的子節點
        if (successor != delNode.getRight())
        {
            successorParent.setLeft(successor.getRight());
            //鏈接被刪除節點的右孩子
            successor.setRight(delNode.getRight());
        }
        return successor;
    }
    // 下面三種遍歷樹
    // 三種遍歷均是採用遞歸實現的
    // 前序遍歷
    public void preOrder(Node localRoot) {
        if (localRoot != null) {
            localRoot.displayNode();// 訪問這個節點
            preOrder(localRoot.getLeft());// 調用自身來遍歷左子樹
            preOrder(localRoot.getRight());// 調用自身來遍歷右子樹
        }
    }
    // 中序遍歷
    public void midOrder(Node localRoot) {
        if (localRoot != null) {
            preOrder(localRoot.getLeft());// 調用自身來遍歷左子樹
            localRoot.displayNode();// 訪問這個節點
            preOrder(localRoot.getRight());// 調用自身來遍歷右子樹
        }
    }
    // 後續遍歷
    public void lastOrder(Node localRoot) {
        if (localRoot != null) {
            preOrder(localRoot.getLeft());// 調用自身來遍歷左子樹
            preOrder(localRoot.getRight());// 調用自身來遍歷右子樹
            localRoot.displayNode();// 訪問這個節點
        }
    }
}


二叉排序樹的遞歸插入,遞歸遍歷,遞歸查詢app

package whut.tree;
//二叉樹的存儲,這裏會創建一個二叉排序樹,遞歸方式
public class NodeTree {
    public int value;
    public NodeTree left;
    public NodeTree right;
    //遞歸實現存儲
    public void store(int value) {
        if (value < this.value) {
            if (left == null) {
                left = new NodeTree();
                left.value = value;
            } else {
                left.store(value);
            }
        } else if (value > this.value) {
            if (right == null)
            {
                right = new NodeTree();
                right.value = value;
            } else {
                right.store(value);
            }
        }
    }
    public boolean find(int value) {
        System.out.println("find happen " + this.value);
        if (value == this.value) {
            return true;
        } else if (value > this.value) {
            if (right == null)
                return false;
            return right.find(value);
        } else {
            if (left == null)
                return false;
            return left.find(value);
        }
    }
    //前序遍歷
    public void preList() {
        System.out.print(this.value + ",");
        if (left != null)
            left.preList();
        if (right != null)
            right.preList();
    }
            
    //中序遍歷
    public void middleList() {
        if (left != null)
            left.middleList();
        System.out.print(this.value + ",");
        if (right != null)
            right.middleList();
    }
     //後續遍歷
    public void afterList() {
        if (left != null)
            left.afterList();
        if (right != null)
            right.afterList();
        System.out.print(this.value + ",");
    }
    public static void main(String[] args) {
        int[] data = new int[20];
        for (int i = 0; i < data.length; i++) {
            data[i] = (int) (Math.random() * 100) + 1;
            System.out.print(data[i] + ",");
        }
        System.out.println();
        NodeTree root = new NodeTree();
        root.value = data[0];
        for (int i = 1; i < data.length; i++) {
            root.store(data[i]);
        }
        //查詢
        root.find(data[19]);
        //先序
        root.preList();
        System.out.println();
        //中序
        root.middleList();
        System.out.println();
        //後續
        root.afterList();
    }
}
相關文章
相關標籤/搜索