关于数据结构和算法:数据结构和算法-哈希表

1.什么是哈希表

哈希表是联合哈希算法联合其余数据结构形成的一种数据结构。

为什么会产生这样的数据结构呢?

次要起因是在现实状况下,取出和放入元素所耗费的工夫复杂度为

\( O(1) \)

比方咱们看一种常见的实现形式,哈希算法+数组+链表形成的哈希表:

假如数组index从1开始,那么依据哈希算法,元素1就放在数组下标为1的中央,元素3就放在数组下标为3的中央,元素5放在数组下标为1的中央,然而因为元素1曾经在数组中了,对于这种状况,咱们的一种解决形式就是元素1和元素5通过链表连贯,元素1依然在数组中,新退出的元素5放在元素1前面,元素1的next节点指向元素5.

2. java实现

哈希表的用处很广,比方java的HashMap、HashSet。

对于哈希表,咱们的操作次要是PUT和GET操作。

上面就来看看怎么实现繁难版本的HashMap。

import java.util.Arrays;
import java.util.Objects;

/**
 * key and value are not permitted null
 * @author bennetty74
 * @since 2021.10.24
 */
public class HashMap <K,V> implements Map<K,V>{
    // 申明一个ENTRY数组用于寄存元素
    private Entry<K,V>[] entries;
    private final double loadFactor = 0.75d;
    private int capacity = 8;
    private int size = 0;

    @SuppressWarnings("unchecked")
    public HashMap() {
        entries = new Entry[this.capacity];
    }

    @SuppressWarnings("unchecked")
    public HashMap(int capacity) {
        this.capacity = capacity;
        entries = new Entry[capacity];
    }

    @Override
    public boolean contains(K key) {
        int idx = getIndex(key);
        if (entries[idx] == null) {
            return false;
        }
        Entry<K, V> entry = entries[idx];
        while (entry != null) {
            if (entry.key.equals(key)) {
                return true;
            }
            entry = entry.next;
        }
        return false;
    }
    // put操作,不容许key和value为null
    public boolean put(K key, V value) {
        if (Objects.isNull(key) || Objects.isNull(value)) {
            throw new IllegalArgumentException("Key or value is null");
        }
        int idx = getIndex(key);
        // if null, put in entries array
        if (Objects.isNull(entries[idx])) {
            entries[idx] = new Entry<>(key, value);
        } else {
            // else put at the head of Entry list
            Entry<K, V> newEntry = new Entry<>(key, value);
            newEntry.next = entries[idx];
            entries[idx] = newEntry;
        }
        // if load factor greater than 0.75, then rehash
        if (size++ / (double) capacity > 0.75f) {
            rehash();
        }
        return true;
    }

    private void rehash() {
        capacity = 2 * capacity;
        Entry<K, V>[] oldEntries = Arrays.copyOf(this.entries, capacity);
        entries = new Entry[capacity];
        for (Entry<K, V> oldEntry : oldEntries) {
            if (oldEntry != null) {
                put(oldEntry.key, oldEntry.value);
            }
        }
    }

    public V get(K key) {
        if (Objects.isNull(key)) {
            throw new IllegalArgumentException("Key is null");
        }
        // get idx by key's hashCode
        int idx = getIndex(key);
        Entry<K, V> entry = entries[idx];
        if (!Objects.isNull(entry)) {
            while (!Objects.isNull(entry)) {
                if (key.equals(entry.key)) {
                    return entry.value;
                }
                entry = entry.next;
            }
        }
        // not found the specific key, return null
        return null;
    }
    // 此处的hash算法很简略,就是依据key的hashCode除以entry数组的容量的余数作为数组下标寄存元素
    private int getIndex(K key) {
        return key.hashCode() % capacity;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("HashMap { ");
        for (int i = 0; i < capacity; i++) {
            if (entries[i] != null) {
                Entry<K, V> entry = entries[i];
                while (entry != null) {
                    sb.append(entry.key).append("=").append(entry.value).append(",");
                    entry = entry.next;
                }
            }
        }
        sb.replace(sb.length() - 1, sb.length(), "").append(" }");
        return sb.toString();
    }

    // Entry类,蕴含HashMap的key和value
    private static class Entry<K,V> {
        K key;
        V value;

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

        Entry<K,V> next;
    }


}

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理