算法-树(1)—BST(二叉搜索树)

本文基于BST结构主要实现查找,删除功能
此种数据结构较为简单,主要分析添加查找删除功能
后附完整代码

1.BST定义:
1).每个结点均有键值对,其中键值实现排序;
2).每个结点的都大于它的左结点,小于它的右结点。
2. 主要实现(递归)

结点内部类Node:
`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;
    }
}
`

1).添加put
思想:键值不能相同的原则,所以先递归查找是否存在这样的键值,若存在,则更新value值,否则添加相应的键值对到对应的位置。
实现:

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

2).删除deleteMin,delete
1.删除最小值:
查找最小值:递归查找左子树,若左子树为null,则递归右子树,查找Node.left==null的结点,次结点即为树的最小值。
删除最小值:删除最小值后,最小结点的右子树,接到最小值父结点的左子树中。

    private Node deleteMin(Node x)
    {
        if(x.left == null)
            //此处返回需要删除的最小结点的右子树(这样才能保证后面结点不丢失).
            return x.right;
        //递归到最小结点时,返回了x.right,此处令最小结点的父结点的左子树等于返回的x.right.
        //而需要删除的结点,被当成垃圾系统回收.
        x.left = deleteMin(x.left);
        //更新计数器.
        x.N = size(x.left)+size(x.right)+1;
            return x;
    }

2.删除任意结点(传入键值):
思想:首先肯定先递归查找的删除的键值(假设x结点),删除结点x时,我们需要使用到deleteMin,找到以x为父结点的子树的,用于替换x位置的结点

    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
        {
            //此处x为需要删除的结点.判断x是否为单结点,若为单结点,返回x.left或者x.right即能删除x结点.
            if(x.right == null)
                return x.left;
            if(x.left == null)
                return x.right;
            //若不为单结点.创建t结点,保存x的左右连接状态,再查找x右子树的最小结点(此结点即为新的取代x结点的结点).
            Node tmp = x;
            x = min(tmp.right);
            x.right = deleteMin(tmp.right);
            x.left = tmp.left;
        }
        x.N = size(x.left)+size(x.right)+1;
        return x;
    }

3.性能分析:
二分查找法(有序数组):
最坏:查找—lgN。插入—N
平均:查找—lgN。插入—N/2
二叉查找树:
最坏:查找—N。插入—N
平均:查找—1.39lgN。插入—1.39lgN
BST的性能与树的高度成正比。
3. 完整代码

package search;
/**
  * @author : 罗正 
  * @date time:2016年9月7日 下午9:47:08 
**/
public class BSTsearch <Key extends Comparable<Key> ,Value>{

    private Node root;
    /**
     * 内部类:树结点——Node
     * @param args
     */
    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 x)
    {
        if (x == null) 
            return 0;
        else 
            return x.N;
    }

    /**
     * funtion:根据传入的key值,递归查找二叉树,无则返回null.
     * @param key
     * @return
     */

    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);
        else if (cmp>0)
            return get(x.right,key);
        else
            return x.value;
    }

    /**
     * 查找key值,找到则更新,没有则添加.
     * @param key
     * @param value
     */
    public void put(Key key,Value value)
    {

        root = put(root,key,value);
    }

    /**
     * 没有则插入root的子树当中
     * @param x
     * @param key
     * @param value
     * @return
     */
    private Node put(Node x,Key key,Value value)
    {
        if(x == null) 
            return new Node(key,value,1);
        int cmp = key.compareTo(x.key);
        if (cmp<0)
            x.left = put(x.left,key,value);
        else if (cmp>0)
            x.right = put(x.right,key,value);
        else 
            x.value = value;
        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);
    }

    /**
     * 返回小于等于key的最大键.
     * @param key
     * @return
     */
    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 x;
        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;

    }

    /**
     * 根据传入的int k值,查找在树中的key值,并返回
     * @param k
     * @return
     */
    public Key select(int k)
    {
        return select(root,k).key;
    }
    private Node select(Node x,int k)
    {
        if(x == null)
            return null;
        int num = size(x.left);
        if(num > k)
            return select(x.left,k);
        else if(num < k)
            return select(x.right,k-num-1);
        else 
            return x;
    }

    /**
     * 根据传入的key,查找在树中的rank.
     * @param key
     * @return
     */
    public int rank(Key key)
    {
        return rank(root,key);
    }

    private int rank(Node x,Key key)
    {
        if( x == null)
            return 0;
        int cmp = key.compareTo(x.key);
        if(cmp > 0)
            //此处不要忘了加上1+size(x.left)
            return 1+size(x.left)+rank(x.right,key);
        if(cmp < 0)
            return rank(x.left,key);
        else
            return size(x.left);
    }

    /**
     * 以下为较难实现的BST删除操作.
     * 实现步骤如下:
     * 1.保存要删除的结点链接.(如删除A,保存t = B.left).
     * 2.A指向X = min(A.left).<这个结点就是删A后,取代A位置的结点!>
     * 3.X取代A的操作,以及X位置抽取后,树变动的操作
     * 
     * deletemMin().
     * delete().
     */
    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;
    }

    /**
     * 删除给定的键值对key.
     * @param key
     */
    public void delete(Key key)
    {
        root = delete(root,key);
    }

    /**
     * 递归删除key,
     * 返回Node值,便于实现递归而不丢失链接.
     * @param x
     * @param key
     * @return
     */
    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
        {
            //此处x为需要删除的结点.判断x是否为单结点,若为单结点,返回x.left或者x.right即能删除x结点.
            if(x.right == null)
                return x.left;
            if(x.left == null)
                return x.right;
            //若不为单结点.创建t结点,保存x的左右连接状态,再查找x右子树的最小结点(此结点即为新的取代x结点的结点).
            Node tmp = x;
            x = min(tmp.right);
            x.right = deleteMin(tmp.right);
            x.left = tmp.left;
        }
        x.N = size(x.left)+size(x.right)+1;
        return x;
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        BSTsearch bst = new BSTsearch<>();
        bst.put("B", "b");
        bst.put("A", "a");
        bst.put("D", "d");
        bst.put("W", "w");
        bst.put("X", "x");
        bst.put("Z", "z");
        System.out.println(bst.select(0));
        System.out.println("rank A:"+bst.rank("A"));
        System.out.println("bst size :"+bst.size());
        System.out.println("floor:"+bst.floor("Z"));
        System.out.println("min :"+bst.min());
        bst.deleteMin();
        System.out.println("min (mid):"+bst.min());
        bst.delete("B");
        System.out.println("min :"+bst.min());
        System.out.println("bst size:"+bst.size());
    }

}

算法第四版—二叉查找树

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值