二叉查找树

二叉查找树
也称为有序二叉树,或者已排序二叉树,是指一根空树或者具有下列性质的二叉树:
  • 若任意结点的左子树不空,则左子树上所有结点的值均小于它的根节点的值
  • 若任意结点的右子树不空,则右子树上所有结点的值均大于它的根节点的值
  • 任意结点的左右子树也分别为二叉查找树
  • 没有键值相等的节点
因为一颗由n个结点随机构造的二叉查找树的高度为lgn,所以顺理成章,二叉查找树的一般操作的执行时间为O(lgn)。但二叉查找树若退化成了一颗具有n个结点的线性链后,则这些操作的最坏运行时间为O(n)。

1.查找的递归算法
  • 如果树是空的,则查找未命中;
  • 如果被查找的键和根结点的键相等,查找命中,否则我们就递归地在适当的子树中查找;
  • 如果被查找的键较小选择左子树,较大则选择右子树。
package cn.chen.tree;

public 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 k){
        if (x == null ) return null ;
        int cmp = k.compareTo(x. key );
        if (cmp < 0 ) return get(x. left , k);
        else if (cmp > 0 ) return get(x. right , k);
        else return x. val ;
    }

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

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

    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. right ) + 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 );
    }
}

2.删除
在删除结点x后用它的后继结点填补它的位置。因为x有一个右子节点,因此它的后继结点就是其右子树中的最小结点。这样替换仍旧可以保持树的有序性。
  1. 将指向即将被删除的结点的链接保存为t;
  2. 将x指向它的后继结点min(t.right);
  3. 将x的右链接指向deleteMin(t.right);
  4. 将x的左链接设为t.left。
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 ;
        // 将指向即将被删除的结点的链接保存为t;
        Node t = x;
        // 将x指向它的后继结点min(t.right);
        x = min(t. right );
        // 将x的右链接指向deleteMin(t.right);
        x. right = deleteMin(t. right );
        // 将x的左链接设为t.left。
        x. left = t. left ;
    }
    x. N = size(x. left ) + size(x. right ) + 1 ;
    return x;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值