データ構造-5-ハッシュテーブル

5、ハッシュテーブル

1.コンセプト

ハッシュテーブルは、マッピング関係を持つデータ構造です。つまり、KEYを指定すると、対応するVALUEを見つけることができます。KEYとVALUEは、エントリ(またはノード)を形成します。

KEYはユニークです。後で追加されたエントリが前のエントリのKEYと等しい場合、新しいVALUEのみが古いVALUEを上書きし、新しいエントリは作成されません。

すべてのエントリを維持するために、配列構造を使用できます。同時に、占有を減らすために连续的内存空间、単一リンクリスト構造を使用して、同じhashCode値のKEYに対応するエントリを維持できます(パフォーマンスを向上させるために、単一のリンクリストへの変換をバイナリツリーに変更するか、バイナリツリーを単一リンクリストに復元することもできます)

2.一般的な方法

  1. putは要素をハッシュテーブルに追加します(等しいKEYのエントリは、新しいVALUEが古いVALUEを上書きすることに注意してください)
  2. 与えられたキーに従って対応する値を見つけます
  3. 削除指定されたキーに従って、対応するエントリを削除します

3.例

class HashTable<K, V> {
    
    
    private Entry<K, V>[] table;
    private final int length;
    private int size;

    public HashTable(int length) {
    
    
        this.length = length;
        this.size = 0;
    }

    public void put(K key, V value) {
    
    
        if (null == key || null == value) {
    
    
            throw new NullPointerException();
        }

        if (null == table) {
    
    
            @SuppressWarnings("unchecked")
            Entry<K, V>[] table = (Entry<K, V>[])new Entry[this.length];
            this.table = table;
        }

        int hash = hash(key);
        Entry<K, V> entry = table[hash];
        while (null != entry) {
    
    
            if (entry.key.equals(key)) {
    
    
                entry.value = value;
                return;
            }
            entry = entry.prev;
        }

        entry = table[hash];
        Entry<K, V> put = new Entry<K, V>(key, value);
        table[hash] = put;
        put.prev = entry;

        this.size++;
    }

    public V get(K key) {
    
    
        if (null == key) {
    
    
            throw new NullPointerException();
        }

        int hash = hash(key);
        Entry<K, V> entry = table[hash];
        while (null != entry) {
    
    
            if (entry.key.equals(key)) {
    
    
                return entry.value;
            }
            entry = entry.prev;
        }

        return null;
    }

    public boolean remove(K key) {
    
    
        if (null == key) {
    
    
            throw new NullPointerException();
        }

        int hash = hash(key);
        Entry<K, V> entry = table[hash];
        boolean first = true;
        Entry<K, V> next = table[hash];
        while (null != entry) {
    
    
            if (entry.key.equals(key)) {
    
    
                if (first) {
    
    
                    table[hash] = entry.prev;
                } else {
    
    
                    next.prev = entry.prev;
                }

                this.size--;
                return true;
            }

            entry = entry.prev;
            if (first) {
    
    
                first = false;
            } else {
    
    
                next = next.prev;
            }
        }

        return false;
    }

    public int size() {
    
    
        return this.size;
    }

    private int hash(K key) {
    
    
        return key.hashCode() % this.length;
    }

    private static class Entry<K, V> {
    
    
        private final K key;
        private V value;
        private Entry<K, V> prev;

        private Entry(K key, V value) {
    
    
            this.key = key;
            this.value = value;
        }

        @Override
        public String toString() {
    
    
            return this.key + "=" + this.value;
        }
    }

    @Override
    public String toString() {
    
    
        if (null == table) {
    
    
            return "{}";
        }

        StringBuilder sBuilder = new StringBuilder("{");
        for (int i = 0; i < this.length; i++) {
    
    
            Entry<K, V> entry = table[i];
            while (null != entry) {
    
    
                sBuilder.append(entry.toString()).append(',').append(' ');
                entry = entry.prev;
            }
        }

        return sBuilder.substring(0, sBuilder.length() - 2) + '}';
    }

}

おすすめ

転載: blog.csdn.net/adsl624153/article/details/103866147