二叉查找树

2016-09-22  本文已影响68人  sleepyjoker

定义: 一棵二叉查找树是一棵二叉树,其中每个结点都含有一个Comparable的键(以及相关联的值)且每个结点的键都大于其左子树中的任意结点的键而小于右子树中的任意结点的键。

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 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.val;
    }
    public void put(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;
    }
}

我们嵌套了一个私有类来表示二叉树上的一个结点,每个结点都含有一个键,一个值,一个左链接,一个右链接和一个统计结点计数器。算法中的size()方法将空链接的值当做0,从而保证有size(x) = size(x.left) + size(x.right) + 1
使用二叉查找树的算法的运行时间取决于树的形状。最好的情况下,一棵含有N个结点的树是完全平衡的,每条空链接和根结点的距离均为~lgN。一般情况下,树的情况与此相接近。

在N个随机键构造的二叉查找树中,查找命中平均比较的次数为2lgN;查找未命中和插入操作的平均比较次数为2lgN。


二叉查找树中max(), min(), floor(), ceiling()方法的实现:

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;
    else if(cmp <0)  return floor(x.left, key);
    Node t = floor(x.right, key);
    if (t != null)  return t;
    else  return x;
}

二叉查找树中select()和rank()方法的实现:

public Key select(int k){
    return select(root, k).key;
}
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);
    else if (t <k)  return select(x.right, k-t-1);
    else return x;
}
public int rank(Key key){
    return rank(key, root);
}
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);
}

二叉查找树中delete()方法的实现:

public void deleteMin(){
    root = deleteMin(root);
}
private Node deleteMin(Node x){
    if (x == 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{
        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;
}

二叉查找树的范围查找操作

public Iterable<Key> keys(){
    return keys(min(), max());
}
public Iterable<Key> keys(){
    Queue<Key> queue = new Queue<Key>();
    keys(root, queue, lo, hi);
    return queue;
}
private void keys(Node x, Queue<Key> queue, Key lo, Key hi){
    if( x = null)  return;
    int cmplo = lo.compareTo(x.key);
    int cmphi = hi.compareTo(x.key);
    if( cmplo < 0) keys(x.left, queue, lo, hi);
    if( cmp <=0 && cmphi >= 0) queue.enqueue(x.key);
    if(cmphi > 0) keys(x.right, queue, lo, hi);
}
上一篇下一篇

猜你喜欢

热点阅读