数据结构之哈希表

具体介绍见

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)); 
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值