基於鏈表法解決哈希衝突的實現
該拉鍊發採用了一般性的策略,爲M個元素分別構建符號表來保存散列值到這裏的建。該代碼是摘自算法(第四版)。
public class SequentialSearchST<Key, Value> {
private Node first;//鏈表首結點
private class Node{
//鏈表結點的定義
private final Key key;
private Value val;
private Node next;
public Node(Key key, Value val, Node next) {
this.key = key;
this.val = val;
this.next = next;
}
public Key getKey() {
return key;
}
public Value getVal() {
return val;
}
public void setVal(Value val) {
this.val = val;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
//查找給定的鍵,返回相關聯的值
public Value get(Key key) {
for(Node i = first; i != null; i = i.next) {
if(key.equals(i.key))
return i.val;
}
return null;
}
//查找給定的鍵,找到則更新其值,否則在表中新建結點
public void put(Key key, Value val) {
for(Node i = first; i != null; i = i.next) {
if(key.equals(i.key)) {
i.val = val;
return;
}
}
first = new Node(key, val, first);
}
//刪除結點
public void delete(Key key) {
first = delete(first, key);
}
private Node delete(Node x, Key key) {
if(x == null) {
return null;
}
if(key.equals(x.key)) {
return x.next;
}
x.next = delete(x.next, key);
return x;
}
public Iterable<Key> keys(){
Queue<Key> q = new Queue<Key>();
for(Node i = first; i != null; i = i.next) {
q.enqueue(i.key);
}
return q;
}
public Key getKey() {
return first.key;
}
}
public class SeparateChainingHashST<Key, Value> {
//SequetialSearchST
private int N;//鍵值對總數
private int M;//散列表的大小
private SequentialSearchST<Key, Value>[] st;//存放鏈表對象的數組
public SeparateChainingHashST() {//默認的構造函數會使用997條鏈表
this(997);
}
public SeparateChainingHashST(int M) {
//創建M條鏈表
this.M = M;
//創造一個(SequentialSearchST<Key, Value>[])類型的,長度爲M的數組
st = (SequentialSearchST<Key, Value>[]) new SequentialSearchST[M];
for(int i = 0; i < M; i++) {
//爲每一個數組元素申請一個空間
st[i] = new SequentialSearchST();
}
}
private int hash(Key key) {
return (key.hashCode() & 0x7fffffff) % M;
}
public Value get(Key key) {
return (Value)st[hash(key)].get(key);
}
public void put(Key key, Value val) {
st[hash(key)].put(key, val);
}
public void delete(Key key) {
st[hash(key)].delete(key);
}
public Iterable<Key> keys(){
Queue<Key> queue = new Queue<Key>();
for(int i = 0; i < M; i++) {
System.out.println("第" + i +"個元素的鏈表");
for(Key key : st[i].keys()) {
queue.enqueue(key);
System.out.print(key + " " + get(key) + " ,");
}
System.out.println();
}
return queue;
}
public static void main(String[] args) {
SeparateChainingHashST<String, Integer> st = new SeparateChainingHashST<String, Integer>(5);
for (int i = 0; i < 13; i++) {
String key = StdIn.readString();
st.put(key, i);
}
for (String s : st.keys())
StdOut.println(s + " " + st.get(s));
st.delete("M");
StdOut.println("*************************************");
for (String s : st.keys()) {
StdOut.println(s + " " + st.get(s));
}
}
}
實現一個LRU緩存淘汰算法
採用一個鏈表來保存訪問的數據,每次有新數據時看是否匹配已有的,有則將以保存的數據放到最前端,沒有則將新數據保存至最前端。如果內存滿了則從最末端刪除數據。
public class LRULinkedHashMap<K, V> extends LinkedHashMap<K, V> {
private final int maxCapacity;
private static final float DEFAULT_LOAD_FACTOR = 0.75f;
private final Lock lock = new ReentrantLock();
public LRULinkedHashMap(int maxCapacity) {
super(maxCapacity, DEFAULT_LOAD_FACTOR, true);
this.maxCapacity = maxCapacity;
}
@Override
protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {
return size() > maxCapacity;
}
@Override
public boolean containsKey(Object key) {
try {
lock.lock();
return super.containsKey(key);
} finally {
lock.unlock();
}
}
@Override
public V get(Object key) {
try {
lock.lock();
return super.get(key);
} finally {
lock.unlock();
}
}
@Override
public V put(K key, V value) {
try {
lock.lock();
return super.put(key, value);
} finally {
lock.unlock();
}
}
public int size() {
try {
lock.lock();
return super.size();
} finally {
lock.unlock();
}
}
public void clear() {
try {
lock.lock();
super.clear();
} finally {
lock.unlock();
}
}
public Collection<Map.Entry<K, V>> getAll() {
try {
lock.lock();
return new ArrayList<Map.Entry<K, V>>(super.entrySet());
} finally {
lock.unlock();
}
}
}