1. 程式人生 > >基於線性探測法的散列表(來自:演算法)

基於線性探測法的散列表(來自:演算法)

下列程式碼主要實現了調整陣列的大小來保證散列表的使用率永遠都不會超過1/2resize(),插入鍵put(),查詢鍵get(),查詢鍵線上性表中的位置getplace(),刪除鍵delete(),遍歷線性表keys()等方法

package cn.edu.zzuli.api;

import edu.princeton.cs.algs4.Queue;
import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdOut;

public class LPHST<Key, Value> {
	private int N;//符號表中鍵值對的總數
	private int M;//線性探測表的大小
    private Key[] keys;//鍵
    private Value[] vals;//值
    public LPHST(int capacity){
    	N = 0;
    	M = capacity;
    	keys = (Key[]) new Object[M];
    	vals = (Value[]) new Object[M];
    }
    private int hash(Key key) {
    	return (key.hashCode() & 0xfffffff) % M;
    }
    //通過調整陣列的大小來保證散列表的使用率永遠都不會超過1/2
    private void resize(int capacity) {
    	LPHST<Key, Value> temp = new LPHST<Key, Value>(capacity); 
    	for(int i = 0; i < M; i++) {
    		if(keys[i] != null)
    			temp.put(keys[i], vals[i]);
    	}
    	M = temp.M;
    	keys = temp.keys;
    	vals = temp.vals;
    }
    public void put(Key key, Value val) {
    	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])) {
    			vals[i] = val;
    			return;
    		}
    	}
    	keys[i] = key;
    	vals[i] = val;
    	N++;
    }
    //刪除鍵時,我們需要將簇中被刪除鍵右邊的所有鍵重新插入散列表
    public void delete(Key key) {
    	if(get(key) == null) {
    		return;
    	}
    	int i = hash(key);
    	while(!key.equals(keys[i])) {
    		i = (i + 1) % M;
    	}
    	keys[i] = null;
    	vals[i] = null;
    	i = (i + 1) % M;
    	while(keys[i] != null) {
    		Key keyToRedo = keys[i];
    		Value valToRedo = vals[i];
    		keys[i] = null;
    		vals[i] = null;
    		N--;
    		put(keyToRedo, valToRedo);
    		i = (i + 1) % M;
    	}
    	N--;
    	if(N > 0 && N <= M/8) {
    		resize(M / 2);
    	}
    }
    //將鍵線上性表中的位置返回,如果鍵線上性表中找不到,則返回(M + 1)
    public int getpalce(Key key) {
    	for(int i = hash(key); keys[i] != null; i = (i + 1) % M) {
    		if(key.equals(keys[i])) {
    			return i;
    		}
    	}
    	return M + 1;
    }
    //查詢與鍵對應的值
    public Value get(Key key) {
    	for(int i = hash(key); keys[i] != null; i = (i + 1) % M) {
    		if(key.equals(keys[i])) {
    			return vals[i];
    		}
    	}
    	return null;
    }
    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 static void main(String[] args) {
    	LPHST<String, Integer> st = new LPHST<String, Integer>(16);
        for (int i = 0; i < 13; i++) {
            String key = StdIn.readString();
            st.put(key, i);
        }
        for (String s : st.keys()) {
       	     StdOut.print(s + " " + st.get(s));
       	     StdOut.println(", " + st.getpalce(s));
        }
        st.delete("M");
        StdOut.println("*************************************");
        for (String s : st.keys()) {
        	 StdOut.print(s + " " + st.get(s));
        	 StdOut.println(", " + st.getpalce(s));
        }
        StdOut.println("*************************************");
    }
}

測試用例

S E A R C H E X A M P L E

不同的機器的hashCode()不一定相同