二叉查找树(BST)

class BST<Key extends Comparable<Key>, Value>{

    private Node root;

    private class Node{
        private Key key;
        private Value val;
        private Node left, right;
        private int N;

        public Node(Key key, Value val, int N){
            this.key = key;
            this.val = val;
            this.N = N;
        }
    }

    public int size(){
        return size(root);
    }

    private int size(Node x){
        if(x == null) return 0;
        else          return x.N;
    }

    public Value get(Key key){
        return get(root, key);
    }

    private Value get(Node x, Key key){
        if(x == null) return null;
        int cmp = key.compareTo(x.key);
        if(cmp < 0) return get(x.left, key);
        if(cmp > 0) return get(x.right, key);
        else return x.val;
    }

    public void put(Key key, Value value){
        root = put(root, key, value);
    }

    private Node put(Node x, Key key, Value val){
        if(x == null) return new Node(key, val, 1);
        int cmp = key.compareTo(x.key);
        if(cmp < 0)      x.left = put(x.left, key, val);              //更新
        else if(cmp > 0)    x.right = put(x.right, key, val);
        else x.val = val;
        x.N = size(x.left) + size(x.left) + 1;             //更新
        return x;
    }

    public Key min(){
        return min(root).key;
    }
    
    private Node min(Node x){
        if(x.left == null) return x;
        return min(x.left);
    }

    public Key floor(Key key){
        Node x = floor(root ,key);
        if( x == null) return null;
        return x.key;
    }

    private Node floor(Node x, Key key){
        if(x == null) return null;
        int cmp = key.compareTo(x.key);
        if(cmp == 0) return x;
        if(cmp < 0) return floor(x.left, key);
        Node t = floor(x.right, key);
        if (t != null ) return t;
        else return x;
    }

    public void deleteMin(){
        root = deleteMin(root);
    }

    private Node deleteMin(Node x){
        if(x.left == null) return x.right;
        x.left = deleteMin(x.left);
        x.N = size(x.left) + size(x.right) + 1;
        return x;
    }

    public void delete(Key key){
        root = delete(root, key);
    }

    private Node delete(Node x, Key key){
        if(x == null) return null;
        int cmp = key.compareTo(x.key);
        if(cmp < 0) x.left = delete(x.left, key);
        else if(cmp > 0) x.right = delete(x.right, key);
        else {
            if(x.right == null) return x.left;
            if(x.left == null) return x.right;
            Node t = x;                          //删除的节点有左右孩子
            x = min(t.right);
            x.right = deleteMin(t.right);
            x.left = t.left;
        }
        x.N = size(x.left) + size(x.right) + 1;
        return x;
    }
}     

  对于二叉查找树,删除一个节点时,当这个节点没有左右孩子时,或者只有左孩子或右孩子时,删除比较简单,当这个节点有左右两个孩子时,删除需要4个步骤,假设要删除的节点为x:

1.将指向即将被删除的节点的连接保存为t,即t=x

2.将x指向它左孩子树中的最小一个节点 ,即x=min(t.min)

3.将x的右连接(原本指向一棵所有节点都大于x.key的二叉查找树)指向deleteMin(t.right),也就是在删除后所有节点仍然都大于x.key的子二叉查找树

4.将x的左链接(本为空)设为t.left(其下所有的键都小于被删除的节点和它的后继节点)

猜你喜欢

转载自blog.csdn.net/qq_27469549/article/details/80625753