如何實現二叉查找樹的創建(分析+代碼詳解)

二叉查找樹的創建

1:二叉樹的結點類:
在這裏插入圖片描述代碼實現如下:

private class Node{
        //存儲鍵
        private Key key;
        //存儲值
        public Value vlaue;
        //記錄左子結點
        public Node left;
        //記錄右子結點
        public Node right;

        //構造函數
        public Node(Key key,Value value,Node left,Node right){
            this.key = key;
            this.vlaue = value;
            this.left = left;
            this.right = right;
        }
    }

2:二叉查找樹API設計:
在這裏插入圖片描述
public void put(Key key,Value value):向樹中添加元素key–value
private Node put(Node x,Key key,Value value):向指定的樹x中添加key-vlaue,並返回添加元素後新的樹

----------------插入方法put實現思想:
1.如果當前樹中沒有任何一個結點,則直接把新結點當做根結點使用;
2:如果當前樹不爲空,則從根結點開始:
··········2.1:如果新結點的key小於當前結點的key,則繼續查找當前結點的左子結點;
··········2.2:如果新結點的key大於當前結點的key,則繼續查找當前結點的右子結點;
··········2.3:如果新結點的key等於當前結點的key,則樹中已經存在這樣的結點,替換該結點的value值即可;
代碼實現入下:

 //向樹中添加元素key--value
    public void put(Key key,Value value){
        root = put(root,key,value);
    }

    //向指定的樹x中添加key-vlaue,並返回添加元素後新的樹
    private Node put(Node x,Key key,Value value){
        //如果x子樹爲空
        if(x == null){
            N++;
            return new Node(key,value,null,null);
        }
        //如果x子樹不爲空
        //比較x結點的鍵和key的大小
        int cmp = key.compareTo(x.key);
        if(cmp > 0){
            //如果key大於x結點的鍵,則繼續找x結點的右子樹
            x.right = put(x.right,key,value);
        }else if(cmp < 0){
            //如果key小於x結點的鍵,則繼續找x結點的左子樹
            x.left = put(x.left,key,value);
        }else {
            //如果key等於x結點的鍵,則替換x結點的值爲value
            x.vlaue = value;
        }
        return x;
    }

public Value get(Key key):查詢樹中指定key對應的value
public Value get(Node x,Key key):從指定的樹x中,查找key對應的值

----------------查找方法get實現思想:
從根節點開始:
·········1:如果要查詢的key小於當前結點的key,則繼續查找當前結點的左子結點;
·········2:如果要查詢的key大於當前結點的key,則繼續查找當前結點的右子結點;
·········3:如果要查詢的Key等於當前結點的key,則樹中返回當前結點的value;
代碼實現入下:

 //查詢樹中指定key對應的value
    public Value get(Key key){
        return get(root,key);
    }

    //從指定的樹x中,查找key對應的值
    public Value get(Node x,Key key){
        //x樹爲Null
        if(x == null){
            return null;
        }

        //x樹不爲null
        //比較key和x結點的鍵的大小
        int cmp = key.compareTo(x.key);
        if(cmp > 0){
            //如果key大於x結點的鍵,則繼續找x結點的右子樹
            return get(x.right,key);
        }else if(cmp < 0){
            //如果key小於x結點的鍵,則繼續找x結點的左子樹
            return get(x.left,key);
        }else {
            //如果key等於x結點的鍵,則替換x結點的值爲value
            return x.vlaue;
        }
    }

public void delete(Key key):刪除樹中key對應的value
public Node delete(Node x,Key key):刪除指定樹x中的key對應的value,並返回刪除後的新樹

----------------刪除方法delete實現思想:
1:找到被刪除的結點;
2:找到被刪除結點右子樹中的最小結點minNode;
3:刪除右子樹中的最小結點;
4:讓被刪除結點的左子樹稱爲最小結點minNode的左子樹,讓被刪除結點的右子樹成爲最小結點minNode的右子樹;
5:讓被刪除結點的父節點指向最小結點minNode;

代碼實現入下:

  //刪除樹中key對應的value
    public void delete(Key key){
        delete(root,key);
    }

    //刪除指定樹x中的key對應的value,並返回刪除後的新樹
    public Node delete(Node x,Key key){
        //x樹爲null
        if(x == null){
            return null;
        }

        //x樹不爲null
        int cmp = key.compareTo(x.key);
        if(cmp > 0){
            //如果key大於x結點的鍵,則繼續找x結點的右子樹
            x.right = delete(x.right,key);
        }else if(cmp < 0){
            //如果key小於x結點的鍵,則繼續找x結點的左子樹
            x.left = delete(x.left,key);
        }else {
            //如果key等於x結點的鍵,完成真正的刪除結點動作,要刪除的結點就是x

            //讓元素個數-1
            N--;

            //得找到右子樹中最小得結點
            if(x.right == null){
                return x.left;
            }

            if(x.left == null){
                return x.right;
            }

            Node minNode = x.right;
            while (minNode.left != null){
                minNode = minNode.left;
            }

            //刪除右子樹中最小得結點
            Node n = x.right;
            while (n.left != null){
                if(n.left.left == null){
                    n.left = null;
                }else {
                    //變換n結點即可
                    n = n.left;
                }
            }
            //讓x結點得左子樹成爲minNode的左子樹
            minNode.left = x.left;
            //讓x結點的右子樹成爲minNode的右子樹
            minNode.right = x.right;
            //讓x結點的父結點指向minNode
            x = minNode;
        }
        return x;
    }

下面爲完整代碼(附帶檢測):

public class BinaryTree<Key extends Comparable<Key>,Value> {
    //記錄根節點
    private Node root;
    //記錄樹中元素的個數
    private int N;

    private class Node{
        //存儲鍵
        private Key key;
        //存儲值
        public Value vlaue;
        //記錄左子結點
        public Node left;
        //記錄右子結點
        public Node right;

        //構造函數
        public Node(Key key,Value value,Node left,Node right){
            this.key = key;
            this.vlaue = value;
            this.left = left;
            this.right = right;
        }
    }

    //獲取樹中元素的個數
    public int size(){
        return N;
    }

    //向樹中添加元素key--value
    public void put(Key key,Value value){
        root = put(root,key,value);
    }

    //向指定的樹x中添加key-vlaue,並返回添加元素後新的樹
    private Node put(Node x,Key key,Value value){
        //如果x子樹爲空
        if(x == null){
            N++;
            return new Node(key,value,null,null);
        }
        //如果x子樹不爲空
        //比較x結點的鍵和key的大小
        int cmp = key.compareTo(x.key);
        if(cmp > 0){
            //如果key大於x結點的鍵,則繼續找x結點的右子樹
            x.right = put(x.right,key,value);
        }else if(cmp < 0){
            //如果key小於x結點的鍵,則繼續找x結點的左子樹
            x.left = put(x.left,key,value);
        }else {
            //如果key等於x結點的鍵,則替換x結點的值爲value
            x.vlaue = value;
        }
        return x;
    }

    //查詢樹中指定key對應的value
    public Value get(Key key){
        return get(root,key);
    }

    //從指定的樹x中,查找key對應的值
    public Value get(Node x,Key key){
        //x樹爲Null
        if(x == null){
            return null;
        }

        //x樹不爲null
        //比較key和x結點的鍵的大小
        int cmp = key.compareTo(x.key);
        if(cmp > 0){
            //如果key大於x結點的鍵,則繼續找x結點的右子樹
            return get(x.right,key);
        }else if(cmp < 0){
            //如果key小於x結點的鍵,則繼續找x結點的左子樹
            return get(x.left,key);
        }else {
            //如果key等於x結點的鍵,則替換x結點的值爲value
            return x.vlaue;
        }
    }

    //刪除樹中key對應的value
    public void delete(Key key){
        delete(root,key);
    }

    //刪除指定樹x中的key對應的value,並返回刪除後的新樹
    public Node delete(Node x,Key key){
        //x樹爲null
        if(x == null){
            return null;
        }

        //x樹不爲null
        int cmp = key.compareTo(x.key);
        if(cmp > 0){
            //如果key大於x結點的鍵,則繼續找x結點的右子樹
            x.right = delete(x.right,key);
        }else if(cmp < 0){
            //如果key小於x結點的鍵,則繼續找x結點的左子樹
            x.left = delete(x.left,key);
        }else {
            //如果key等於x結點的鍵,完成真正的刪除結點動作,要刪除的結點就是x

            //讓元素個數-1
            N--;

            //得找到右子樹中最小得結點
            if(x.right == null){
                return x.left;
            }

            if(x.left == null){
                return x.right;
            }

            Node minNode = x.right;
            while (minNode.left != null){
                minNode = minNode.left;
            }

            //刪除右子樹中最小得結點
            Node n = x.right;
            while (n.left != null){
                if(n.left.left == null){
                    n.left = null;
                }else {
                    //變換n結點即可
                    n = n.left;
                }
            }
            //讓x結點得左子樹成爲minNode的左子樹
            minNode.left = x.left;
            //讓x結點的右子樹成爲minNode的右子樹
            minNode.right = x.right;
            //讓x結點的父結點指向minNode
            x = minNode;
        }
        return x;
    }
}


//主程序
public class TestBinaryTree {
    public static void main(String[] args) {
        //創建二叉查找樹對象
        BinaryTree<Integer, String> tree = new BinaryTree<>();

        //測試插入
        tree.put(3,"張三");
        tree.put(2,"李四");
        tree.put(1,"王五");
        tree.put(4,"趙六");
        tree.put(5,"楊七");
        System.out.println("插入完畢後元素的個數:"+tree.size());

        //測試獲取
        System.out.println("鍵5對應的元素是:"+tree.get(5));//楊七

        //測試刪除
        tree.delete(2);
        System.out.println("刪除後的元素個數:"+tree.size());
        System.out.println("刪除後鍵2對應的元素;"+tree.get(2));
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章