标签:直接 OLE contain resize arch 不能 缓存 hash ==
散列表类似于数组,可以把散列表的散列值看成数组的索引值。访问散列表和访问数组元素一样快速,它可以在常数时间内实现查找和插入操作。
由于无法通过散列值知道键的大小关系,因此散列表无法实现有序性操作。
散列函数应该满足以下三个条件:
如果散列值的计算很耗时,那么我们或许可以将每个键的散列值缓存起来
基于拉链法的散列表
拉链法使用链表来存储 hash 值相同的键,从而解决冲突。
查找需要分两步,首先查找 Key 所在的链表,然后在链表中顺序查找。
基于线性探测法的散列表
线性探测法使用空位来解决冲突,当冲突发生时,向前探测一个空位来存储冲突的键。
使用线性探测法,数组的大小 M 应当大于键的个数 N(M>N)。
public class SeparateChainingHashST<Key, Value> {
private static final int INIT_CAPACITY = 4;
private int n;//键值对总数
private int m;//散列表大小
private SequentialSearchST<Key, Value>[] st;//这里使用了之前实现的[无序链表](https://www.cnblogs.com/aiguozou/p/11420339.html)
public SeparateChainingHashST() {
this(INIT_CAPACITY);
}
public SeparateChainingHashST(int m) {
this.m = m;
st = (SequentialSearchST<Key, Value>[]) new SequentialSearchST[m];
for (int i = 0; i < m; i++)
st[i] = new SequentialSearchST<Key, Value>();
}
private void resize(int chains) {
SeparateChainingHashST<Key, Value> temp = new SeparateChainingHashST<Key, Value>(chains);
for (int i = 0; i < m; i++) {
for (Key key : st[i].keys()) {
temp.put(key, st[i].get(key));
}
}
this.m = temp.m;
this.n = temp.n;
this.st = temp.st;
}
private int hash(Key key) {
return (key.hashCode() & 0x7fffffff) % m;
}
public int size() {
return n;
}
public boolean isEmpty() {
return size() == 0;
}
public boolean contains(Key key) {
if (key == null) throw new IllegalArgumentException("argument to contains() is null");
return get(key) != null;
}
public Value get(Key key) {
if (key == null) throw new IllegalArgumentException("argument to get() is null");
int i = hash(key);
return st[i].get(key);
}
public void put(Key key, Value val) {
if (key == null) throw new IllegalArgumentException("first argument to put() is null");
//如果值为Null删除
if (val == null) {
delete(key);
return;
}
if (n >= 10 * m) resize(2 * m);
int i = hash(key);
if (!st[i].contains(key)) n++;
st[i].put(key, val);
}
public void delete(Key key) {
if (key == null) throw new IllegalArgumentException("argument to delete() is null");
int i = hash(key);
if (st[i].contains(key)) n--;
st[i].delete(key);
if (m > INIT_CAPACITY && n <= 2 * m) resize(m / 2);
}
public Iterable<Key> keys() {
LinkedList<Key> queue = new LinkedList<>();
for (int i = 0; i < m; i++) {
for (Key key : st[i].keys())
queue.add(key);
}
return queue;
}
}
标签:直接 OLE contain resize arch 不能 缓存 hash ==
原文地址:https://www.cnblogs.com/aiguozou/p/11460879.html