线性探针法哈希表

线性探针法哈希表

2019-07-03  11:40:23

import java.io.ObjectInputStream;
import java.util.ArrayList;

/**
 * @ClassName LinearProbeHashST
 * @Author wangyudi
 * @Date 2019/7/3 10:53
 * @Version 1.0
 * @Description 用线性试探法实现哈希表
 */
public class LinearProbeHashST<Key, Value> {
    private int m; //数组大小
    private int n;//键值对数量
    private Key[] keys;//键数组
    private Value[] values;//值数组
    private ArrayList<Key> arr;//用于迭代的集合

    /**
     * 构造函数
     * 初始化数组对
     */
    public LinearProbeHashST() {
        this(16);
    }
    public LinearProbeHashST(int m) {
        this.m = m;
        this.n = 0;
        this.keys = (Key[]) new Object[m];
        this.values = (Value[]) new Object[m];
    }

    /**
     * 调整数组的大小(对于线性探针哈希表而言,该数组大小调整时必须的)
     * 需要新建一个哈希表,将源哈希表的数据PUT到新哈希表中,然后把新建符号表的成员给原表
     * @param size
     */
    private void resize(int size) {
        LinearProbeHashST<Key, Value> linearProbeHashST = new LinearProbeHashST<>(size);//新建符号表
        for (int i = 0; i < m; i++) {//将源表中所有键值对插入到新建符号表中
            if (keys[i] != null) {
                linearProbeHashST.put(keys[i], values[i]);
            }
        }
        this.m = size;//调整源表大小,重新指向数组
        this.values = linearProbeHashST.values;
        this.keys = linearProbeHashST.keys;
    }

    /**
     * 获取散列值
     * @param key
     * @return
     */
    private int hash(Key key) {
        return (key.hashCode() & 0x7FFFFFFF) % m; //舍去了最高位(符号位)
    }

    /**
     * 向哈希表中添加键值对
     *
     * @param key
     * @param value
     */
    public void put(Key key, Value value) {
        if (n > m / 2) resize(m * 2);//调整大小
        int i = hash(key);
        while (keys[i] != null) {//循环移动
            if (keys[i].equals(key)) {//在空位前遇到相同的键,则更新对应的值
                values[i] = value;
                return;
            }
            i = (i + 1) % m;
        }
        keys[i] = key;//遇到空位,将键值对放入数组中
        values[i] = value;
        n++;
    }

    /**
     * 根据键获取值
     *
     * @param key
     * @return
     */
    public Value get(Key key) {
        int i = hash(key);
        while (keys[i] != null) {//从散列值开始遍历直到遇到空位
            if (keys[i].equals(key)) {//空位前遇到相同的键,则说明找到了对应的键
                return values[i];
            }
            i = (i + 1) % m;
        }
        return null;//空位前没有找到对应的键,则返回null
    }

    /**
     * 从哈希表中删除键值对
     *
     * @param key
     * @return
     */
    public Value delete(Key key) {
        int i = hash(key);
     Value t = null;
while (keys[i] != null) {//从散列值开始遍历直到遇到空位(在null前遍历所有键值对) if (keys[i].equals(key)) { //找到该键 t = values[i]; keys[i] = null; //删除找到的键 values[i] = null;
          n--; i
= (i + 1) % m; //将删除键后面的键值对重新PUT到哈希表中
}
while (keys[i] != null) { //先保存键值,然后删除键值,再插入键值对 Key k = keys[i]; Value v = values[i]; keys[i] = null; //必须置为null,不然在键的索引正好是散列值的情况下会出问题 values[i] = null;
            n--; put(k, v); //会 n++ i
= (i + 1) % m; }
if (n > 0 && n < m / 8) resize(m / 2);return t;//未找到该键,则返回null } /** * 返回迭代器 * @return */ public Iterable<Key> keys() { arr = new ArrayList<>(); for (int i = 0; i < m; i++) { if (keys[i] != null) { arr.add(keys[i]); } } return arr; } }
public static void main(String[] args) {
    LinearProbeHashST<Integer, String> linearProbeHashST = new LinearProbeHashST<>();
    linearProbeHashST.put(12,"12..");
    linearProbeHashST.put(2,"2..");
    linearProbeHashST.put(34,"34..");
    linearProbeHashST.put(17,"17..");
    linearProbeHashST.put(55,"55..");
    linearProbeHashST.put(214,"214..");
    for(Integer i : linearProbeHashST.keys()){
        System.out.println(i);
    }
    System.out.println("===============================================");
    System.out.println(linearProbeHashST.delete(34));
    for(Integer i : linearProbeHashST.keys()){
        System.out.println(i);
    }
    System.out.println("===============================================");
    System.out.println(linearProbeHashST.get(55));
}

//结果
17
2
34
214
55
12
===============================================
34..
17
2
214
55
12
===============================================
55..
原文地址:https://www.cnblogs.com/youzoulalala/p/11125492.html