有序符号表(数组实现,JAVA,算法(四),二分法)

来源:互联网 发布:ubuntu安装到虚拟机 编辑:程序博客网 时间:2024/06/06 00:12

数组实现的有序符号表介绍:
两个平行数组,相同的下标分别是键和值,由于查入和删除需要调整数组大小,所以和无序链表一样,这两个操作仍然是线性的。但是符号表最为频繁的操作应该是查询的,查询操作可以使用二分法实现,达到了logN的复杂度。二分法的实现需要排好序的键,所以有了泛型的存在,需要实现Comparable接口。rank函数用二分法查找键,在很多函数里面我们都会使用这个函数以达到快速查找的能力。由于有序符号表的实现可以基于多种数据结构,但是它们的操作都是符号表常见操作,故在这里抽象出一个SymbolTable类,包装好以后的符号表使用的函数声明原型。

Comparable:为了使任意类型可比较,JAVA包装好的Integer,Double..这些类都实现了这个接口。当前类的函数接受一个Comparable类型的参数,只要实现了这个接口的类都可以作为参数传递,这就是接口回调,类似于上转型对象。

有序符号表基类:

package com.lizi.datastructure.symboltable;//有序符号表基类public abstract class SymbolTable<Key extends Comparable<Key>,Value> {    //将键值对存入表中(若值为空则将建key从表中删除)    public abstract void put(Key key,Value value);    //获取键Key对应的值(若键key不存在返回空)    public abstract Value get(Key key);    //从表中删去键key(及其对应的值)    public abstract Value delete(Key key);    //表中是否存在该键    public boolean contains(Key key){        return get(key)!=null;    }    //表是否为空    public boolean isEmpty(){        return size()==0;    }    //表中的键值对数量    public abstract int size();    //最小的键    public abstract Key min();    //最大的键    public abstract Key max();    //小于等于Key的最大键    public abstract Key floor(Key key);    //大于等于Key的最小键    public abstract Key ceiling(Key key);    //小于key的键的数量    public abstract int rank(Key key);    //删除最小的键    public void deleteMin(){        delete(min());    }    //删除最大的键    public void deleteMax(){        delete(max());    }    //返回下标为index的键    public abstract Key select(int index);    //[low....high]之间键的数量,包括相等元素    public int size(Key low,Key high){        if (high.compareTo(low)<0)            return 0;        else if (contains(high))            return rank(high)-rank(low)+1;        else             return rank(high)-rank(low);    }    //[low....high]之间键的集合,已经排序    public abstract Iterable<Key> keys(Key low,Key high);    //表中所有键的集合,已经排序    public Iterable<Key> keys(){        return keys(min(),max());    }}

以下是数组实现的符号表:

package com.lizi.datastructure.symboltable;import java.util.ArrayList;import java.util.List;//二分搜索,基于排序数组public class BinarySearchST<Key extends Comparable<Key>,Value> extends SymbolTable<Key, Value> {    private Key[] keys;    private Value[] values;    private int size=0;    @SuppressWarnings("unchecked")    public BinarySearchST(int capacity) {        keys=(Key[]) new Comparable[capacity];        values=(Value[]) new Object[capacity];//java不允许泛型数组,只能创建Object再强制转换类型        this.size=0;    }    @Override    public void put(Key key, Value value) {        if(value==null) {delete(key); return;}        //如果键存在,则修改键值        int pos=rank(key);        if (pos<size&&keys[pos].compareTo(key)==0) {            values[pos]=value;            return;        }        //键值不存在,判断数组是否越界并将数组扩容        if(size==keys.length) resize(2*keys.length);        for (int i =size; i>pos; i--) {            keys[i]=keys[i-1];            values[i]=values[i-1];        }        keys[pos]=key;        values[pos]=value;        size++;     }    @Override    public Value get(Key key) {        if(isEmpty()) return null;        int pos=rank(key);        if (pos<size&&keys[pos].compareTo(key)==0)             return values[pos];        else return null;    }    @Override    public Value delete(Key key) {        int pos=rank(key);        //没找到则返回空        if (pos<size&&keys[pos].compareTo(key)!=0) {            return null;        }        Value value = values[pos];        if(size<keys.length/2) resize(keys.length/2);        for (int i = pos; i < size - 1; i++) {            keys[i] = keys[i + 1];            values[i] = values[i + 1];        }        size--;        return value;    }    @Override    public int size() {        return size;    }    @Override    public Key min() {        return keys[0];    }    @Override    public Key max() {        return keys[size-1];    }    @Override    public Key floor(Key key) {        int pos=rank(key);        if (pos<size&&keys[pos].compareTo(key)==0) {            return keys[pos];        }        return keys[pos-1];    }    @Override    public Key ceiling(Key key) {        int pos=rank(key);        return keys[pos];    }    //非递归的二分查找    @Override    public int rank(Key key) {        int low=0;        int high=size-1;        while (low<=high) {            int middle=low+(high-low)/2;            int cmp=key.compareTo(keys[middle]);            if (cmp<0) high=middle-1;            else if(cmp>0) low=middle+1;            else return middle;        }        return low;    }    //递归的二分查找    public int rank(Key key,int low,int high) {        if(low>high) return low;        int pos=rank(key);        int cmp=key.compareTo(keys[pos]);        if (cmp>0) return rank(key, pos+1, high);        else if(cmp<0) return rank(key,low,pos-1);        else return pos;    }    @Override    public Key select(int index) {        return keys[index];    }    @Override    public Iterable<Key> keys(Key low, Key high) {        List<Key> keys=new ArrayList<Key>(size);        for (int i = 0; i <size; i++) {            keys.add(this.keys[i]);        }        return keys;    }    //该函数仅仅将容量扩大,但是有效元素数量并未改变,所以大小还是size    @SuppressWarnings("unchecked")    public void resize(int capacity) {        Key[] newKeys=(Key[]) new Comparable[capacity];        Value[] newValues=(Value[]) new Object[capacity];        for (int i = 0; i < size; i++) {            newKeys[i]=keys[i];            newValues[i]=values[i];        }        keys=newKeys;        values=newValues;    }}
原创粉丝点击