布谷鸟散列的学习笔记1

布谷鸟散列接口:

public interface HashFamily<E> {
    int getNumOfFunctions();

    void generateNewFunctions();

    int hash(E e, int which);
}

布谷鸟散列的类的框架

public class CuckooHashTable<E> {
    private static final float LOAD_FACTOR = 0.4f;

    private static final int ALLOWED_REHASHES = 1;

    private static final int DEFAULT_TABLE_SIZE = 101;

    private final HashFamily<? super E> hashFunctions;

    private final int numHashFunctions;

    private Object[] array;

    private int currentSize;

    public CuckooHashTable(HashFamily<? super E> hashFunctions) {
        this(hashFunctions, DEFAULT_TABLE_SIZE);
    }

    public CuckooHashTable(HashFamily<? super E> hashFunctions, int size) {
        allocateArray(nextPrime(size));
        currentSize = 0;
        this.hashFunctions = hashFunctions;
        numHashFunctions = hashFunctions.getNumOfFunctions();
    }

    private void allocateArray(int arraySize) {
        array = new Object[arraySize];
    }

    // 清空
    private void doClear() {
        currentSize = 0;
        for (int i = 0; i < array.length; i++)
            array[i] = null;
    }

    // 大小
    public int size() {
        return currentSize;
    }

    // 是否为空
    public boolean isEmpty() {
        return currentSize == 0;
    }

    public void clear() {
        doClear();
    }

    // 是否包含
    public boolean contains(E e) {
        return findPos(e) != -1;
    }

    /**
     * 布谷鸟散列的插入
     * 
     * @param e
     */
    public boolean add(E e) {
        if (contains(e))
            return false;
        if (currentSize >= array.length * LOAD_FACTOR)
            expand();
        return addHelper(e);
    }

    private int rehashes = 0;

    private Random r = new Random();

    private boolean addHelper(E e) {
        final int COUNT_LIMIT = 100;
        while (true) {
            int lastPos = -1;
            int pos;
            for (int count = 0; count < COUNT_LIMIT; count++) {
                for (int i = 0; i < numHashFunctions; i++) {
                    pos = myHash(e, i);
                    if (array[pos] == null) {
                        array[pos] = e;
                        currentSize++;
                        return true;
                    }
                }
                int i = 0;
                do {
                    pos = myHash(e, r.nextInt(numHashFunctions));
                } while (pos == lastPos && i++ < 5);
                E tmp = array(lastPos = pos);
                array[pos] = e;
                e = tmp;
            }
            if (++rehashes > ALLOWED_REHASHES) {
                expand();
                rehashes = 0;
            } else
                rehash();
        }
    }

    // 扩展
    private void expand() {
        rehash((int) (array.length / LOAD_FACTOR));
    }

    // 再散列
    private void rehash() {
        hashFunctions.generateNewFunctions();
        rehash(array.length);
    }

    private void rehash(int newLength) {
        E[] oldArray = (E[]) array;
        allocateArray(nextPrime(newLength));
        currentSize = 0;
        for (E e : oldArray) {
            if (e != null)
                add(e);
        }
    }

    private E array(int index) {
        return (E) array[index];
    }

    // 删除
    public boolean remove(E e) {
        int pos = findPos(e);
        if (pos != -1) {
            array[pos] = null;
            currentSize--;
        }
        return pos != -1;
    }

    // 在布谷列表中查找某项的位置
    private int findPos(E e) {
        for (int i = 0; i < numHashFunctions; i++) {
            int pos = myHash(e, i);
            if (array[pos] != null && array[pos].equals(e))
                return pos;
        }

        return -1;
    }

    private int myHash(E e, int which) {
        int hashVal = hashFunctions.hash(e, which);
        hashVal %= array.length;
        if (hashVal < 0)
            hashVal += array.length;
        return hashVal;
    }

    @Override
    public String toString() {
        StringJoiner joiner = new StringJoiner(null);
        for (int i = 0; i < array.length; i++) {
            if (array[i] != null)
                joiner.add((CharSequence) array[i]);
        }
        return joiner.toString();
    }

    private int nextPrime(int n) {
        if (n % 2 == 0)
            n++;
        while (!isPrime(n))
            n += 2;
        return n;
    }

    private boolean isPrime(int n) {
        if (n == 2 || n == 3)
            return true;
        if (n == 1 || n % 2 == 0)
            return false;
        for (int i = 3; i * i <= n; i += 2)
            if (n % i == 0)
                return false;
        return true;
    }
}

猜你喜欢

转载自blog.csdn.net/bushanyantanzhe/article/details/80181579