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

来源:互联网 发布:ipv6 无网络访问权限 编辑:程序博客网 时间:2024/06/07 15:00

本文基于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());    }}

算法第四版—二叉查找树

0 0