基于线性探测法的散列表(来自:算法)

下列代码主要实现了调整数组的大小来保证散列表的使用率永远都不会超过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()不一定相同

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值