散列的基础知识以及分离链式法参考
上一篇 数据结构与算法之散列(分离链接法)<七>
线性探测法
若产生冲突则放入下一个空闲区域 但是当数据多 需要发费很多的时间寻找空单元 更糟糕的是,即使表比较空,占据的单元会出现聚集现象,称之为一次聚集 为了解决一次聚集现象 出现了平方探测法
平方探测法
当出现冲突时 寻找空闲区域的步长以平方长度来计算,i^2 就是 1 4 9 16 25 …..等长度去寻找下一个空白单元,这样的话冲突之间的距离分布相对均匀,解决了一次聚集的现象。但是平方探测法虽然解决了一次聚集的情况但是散列到同一位置的那些元素将探测相同的备选单元(就是冲突占用的单元再发生冲突其寻找空白单元的位置都是一样的,出现了循环) 这就叫做二次聚集
代码实现
/*
* 解决哈希冲突
* 平方探测法
*/
public class QuadraticProbingHashTable<T> {
private static final int DEFAULT_SIZE = 11;
public QuadraticProbingHashTable() {
this(DEFAULT_SIZE);
}
QuadraticProbingHashTable(int DEFAULT_SIZE) {
allocateArray(DEFAULT_SIZE);
}
@SuppressWarnings("unchecked")
private void allocateArray(int arraySize) {
// 根据arraySize的数值获取下一个素数
array = new HashEntry[nextPrime(arraySize)];
}
public void remove(T element) {
// findPos这个位置对象可能为null也可能与element相同
int findPos = findPos(element);
// 找到了与element相同的对象
if (isActive(findPos)) {
// 惰性删除
array[findPos].isActive = false;
// 当前插入数据大小减1
currentSize--;
}
}
// 哈希对象
private static class HashEntry<T> {
// 保存数据
public T element;
// 是否被删除 (惰性删除)
public boolean isActive;
public HashEntry(T element) {
this(element, true);
}
public HashEntry(T element, boolean isActive) {
this.element = element;
this.isActive = isActive;
}
}
// 哈希数组
private HashEntry<T>[] array;
// 数组当前大小
private int currentSize;
// 插入数据
public void insert(T element) {
int findPos = findPos(element);
// 若element已经存在于该hash中返回空
if (isActive(findPos)) {
return;
}
// 若不存在则插入
array[findPos] = new HashEntry<T>(element);
// 插入成功后已插入数据大小加1
currentSize++;
// 如果当前的已插入的数据大小比数组的1/2还要大则要更新数组
// 因为平方探测法只能探索数组大小的1/2