具体介绍见
MIT算法导论-第7,8讲-哈希表
Java 集合之 HashMap详细介绍(源码解析)和使用示例
HashMap详细介绍(源码解析)和使用示例
下面给出两种实现
1.基于拉链法的散列表
package xwq.dt;
import xwq.util.StdIn;
import xwq.util.StdOut;
public class SeparateChainingHashST<Key,Value>{
private int M;
private SequentialSearchST<Key,Value>[] st;
public SeparateChainingHashST() {
this(997);
}
public SeparateChainingHashST(int M) {
if(M<=0)
throw new IllegalArgumentException("M underflow.");
this.M = M;
st = (SequentialSearchST<Key,Value>[])new SequentialSearchST[M];
for(int i=0;i<M;i++)
st[i] = new SequentialSearchST<Key,Value>();
}
public boolean contains(Key key) {
return get(key)!=null;
}
public Value get(Key key) {
return st[hash(key)].get(key);
}
public void put(Key key,Value val) {
if(key == null) return;
if(val == null) {delete(key); return;}
st[hash(key)].put(key, val);
}
public void delete(Key key) {
st[hash(key)].delete(key);
}
private int hash(Key key) {
return (key.hashCode()&0x7FFFFFFF)%M;
}
public Iterable<Key> keys() {
Queue<Key> q = new Queue<Key>();
for(int i=0;i<M;i++) {
for(Key k:st[i].keys())
q.enqueue(k);
}
return q;
}
public static void main(String[] args) {
SeparateChainingHashST<String, Integer> st = new SeparateChainingHashST<String, Integer>();
for (int i = 0; !StdIn.isEmpty(); i++) {
String key = StdIn.readString();
st.put(key, i);
}
for (String s : st.keys())
StdOut.println(s + " " + st.get(s));
}
}
2.基于线性探测法的散列表
package xwq.dt;
import xwq.util.StdIn;
import xwq.util.StdOut;
public class LinearProbingHashST<Key,Value> {
private Key[] keys;
private Value[] values;
private int N;
private int M;
public LinearProbingHashST() {
this(4);
}
public LinearProbingHashST(int M) {
if(M<=0) throw new IllegalArgumentException("M is underflow");
this.M = M;
this.N = 0;
keys = (Key[])new Object[M];
values = (Value[])new Object[M];
}
public boolean contains(Key key) {
return get(key) != null;
}
public Value get(Key key) {
if(key == null)
return null;
for(int i = hash(key);keys[i]!=null;i=(i+1)%M)
if(keys[i].equals(key))
return values[i];
return null;
}
public void put(Key key,Value val) {
if(key == null) return;
if(val == null) {
delete(key);
return;
}
if (N >= M/2) resize(2*M);
int i;
for(i = hash(key);keys[i]!=null;i=(i+1)%M)
if(key.equals(keys[i])) {
values[i] = val;return;
}
N++;
keys[i] = key;
values[i] = val;
}
public void delete(Key key) {
if(key == null) return;
if(!contains(key))
return;
int i = hash(key);
while (!key.equals(keys[i])) {
i = (i + 1) % M;
}
keys[i] = null;
values[i] = null;
i = (i+1)%M;
while(keys[i] != null) {
N--;
put(keys[i],values[i]);
keys[i] = null;
values[i] = null;
i = (i+1)%M;
}
N--;
if(N > 0 && N <= M/8)
resize(M/2);
}
private int hash(Key key) {
return (key.hashCode() & 0x7FFFFFFF)%M;
}
private void resize(int capacity) {
if(capacity<=0) return;
LinearProbingHashST<Key,Value> copy = new LinearProbingHashST<Key,Value>(capacity);
for(int i=0;i<M;i++)
if(keys[i]!=null)
copy.put(keys[i], values[i]);
this.keys = copy.keys;
this.values = copy.values;
this.M = copy.M;
}
public Iterable<Key> keys() {
Queue<Key> queue = new Queue<Key>();
for(int i=0;i<M;i++)
if(keys[i]!=null)
queue.enqueue(keys[i]);
return queue;
}
public boolean check() {
if (M < 2*N) {
System.err.println("Hash table size M = " + M + "; array size N = " + N);
return false;
}
for (int i = 0; i < M; i++) {
if (keys[i] == null) continue;
else if (get(keys[i]) != values[i]) {
System.err.println("get[" + keys[i] + "] = " + get(keys[i]) + "; vals[i] = " + values[i]);
return false;
}
}
return true;
}
public static void main(String[] args) {
LinearProbingHashST<String, Integer> st = new LinearProbingHashST<String, Integer>();
for (int i = 0; !StdIn.isEmpty(); i++) {
String key = StdIn.readString();
st.put(key, i);
}
for (String s : st.keys())
StdOut.println(s + " " + st.get(s));
}
}