您的位置:首页 > 理论基础 > 数据结构算法

数据结构之哈希表

2016-02-10 23:38 639 查看

具体介绍见

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);//默认散列表的大小设为997
}

public SeparateChainingHashST(int M) {
if(M<=0)
throw new IllegalArgumentException("M underflow.");
this.M = M;
//Java不允许泛型的数组
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);
}

// print keys
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;
}
// double table size if 50% full
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;
// find position i of key
int i = hash(key);
while (!key.equals(keys[i])) {
i = (i + 1) % M;
}
// delete key and associated value
keys[i] = null;
values[i] = null;

// rehash all keys in same cluster
i = (i+1)%M;
while(keys[i] != null) {
// delete keys[i] an vals[i] and reinsert
N--;
put(keys[i],values[i]);
keys[i] = null;
values[i] = null;
i = (i+1)%M;
}
N--;
// halves size of array if it's 12.5% full or less
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;
}

// integrity check - don't check after each put() because
// integrity not maintained during a delete()
public boolean check() {

// check that hash table is at most 50% full
if (M < 2*N) {
System.err.println("Hash table size M = " + M + "; array size N = " + N);
return false;
}

// check that each key in table can be found by get()
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;
}

/**
* Unit tests the <tt>LinearProbingHashST</tt> data type.
*/
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);
}
// print keys
for (String s : st.keys())
StdOut.println(s + " " + st.get(s));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: