第三章--基于二叉查找树的符号表

/**
 * 基于二叉查找树的符号表。
 * @param <Key>
 * @param <Value>
 */
public class BTS <Key extends Comparable<Key>,Value> {
    private Node root;
    private class Node {
        private Key key;
        private Value value;
        private Node left, right;
        private int N;

        public Node(Key key, Value value, int n) {
            this.key = key;
            this.value = value;
            this.N = n;
        }
    }
    public int size(){
        return size(root);
    }
    private int size(Node node) {
        if (node == null) {
            return 0;
        } else return node.N;
    }
    private Value get(Node node,Key key){
        if (node==null)return null;
        int cmp=key.compareTo(node.key);
        if (cmp<0)return get(node.left,key);
        else if (cmp>0)return get(node.right,key);
        else return node.value;
    }
    public Value get(Key key){
        return get(root,key);
    }
    //put方法里使用了递归,从上往下不断搜索节点,直到node==null,则递归结束并返回一个新的node,并将这个node赋给当前node的left或者right,最后返回当前node(这个node在下面的put方法中被赋给root)。
    private Node put(Node node,Key key,Value value){
        if (node==null)return new Node(key,value,1);
        int cmp=key.compareTo(node.key);
        if (cmp<0)node.left=put(node.left,key,value);
        else if (cmp>0)node.right=put(node.right,key,value);
        else node.value=value;
        //node.N等于左右两个节点数的N值加一(加一是因为要算上该节点自身)
        node.N=size(node.right)+size(node.left)+1;
        return node;

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

    //以node x为根节点向下寻找最小的key。
    private  Node min(Node x){
        if (x.left==null)return x;
        return min(x.left);
    }

    public Key min(){
        return min(root).key;
    }
//以node x为根节点向下寻找key所对应的node。
    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 Key floor(Key key){
        Node x=floor(root,key);
        if (x==null)return null;
        return x.key;
    }

    //选出二叉排序树中排名第k个key,两个if判断挺好理解的,不再赘述。
    private  Node select(Node x,int k){
        if (x==null)return  null;
        int t=size(x.left);
        if (t>k)return select(x.left,k);
        if (t<k)return select(x.right,k-t-1);
        else return x;
    }
    public Key select(int k){
        return select(root,k).key;
    }
    //返回以node x为节点的子树中小于key的键的数量。else if部分加一是因为小于给定key的元素有左边的诸多节点+当前节点以及右边部分节点,因为当前节点的存在,故需要加一。
    private int rank(Key key,Node x){
        if (x==null){
            return 0;
        }
        int cmp=key.compareTo(x.key);
        if (cmp<0)return rank(key,x.left);
        else if (cmp>0)return 1+size(x.left)+rank(key,x.right);
        else return size(x.left);
    }
    public int rank(Key key){
        return rank(key,root);
    }  
    //画图可以看出来,下面的delete方法也对deleteMin方法进行了分析
    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 deleteMin(){
        root=deleteMin(root);
    }
    
    //delete方法将某一节点删掉后,用该节点右边的最小节点来替代原有节点的位置(因为右边最小节点小于右边左右节点,而大于左边所有节点)
    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);//1处
        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);
          /*  
               S 
       E               X
   A        R     
     C    H
            M
       假设要删除的元素是E,则deleteMin(t.right);相当于将H删除,将M和R连接, x.right = deleteMin(t.right);则将H和R连接。
            x.left = t.left;相当于将H和A连接。   1处那行代码将S与H相连。 
        */
            x.right = deleteMin(t.right);
            x.left = t.left;
        }
        x.N=size(x.left)+size(x.right)+1;
        return x;
        }
        public void delete(Key key){
        root=delete(root,key);
        }
      
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值