【数据结构和算法】—— 哈希表

CodeAdventurerX
• 阅读 976

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;
    }


}
点赞
收藏
评论区
推荐文章
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
4年前
java容器之HashMap
HashMap采用了数组和链表的数据结构,能在查询和修改方便继承了数组的线性查找和链表的寻址修改,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的。解决哈希冲突的三个方法:a.开放定址法  又被称为再散列法,包括线性探测再散列、二次探测再散列、伪随机探测再散列b.再哈希法  地址冲突后,对哈希结果再次进行哈希,直到
Wesley13 Wesley13
4年前
15.链地址法
同样是为了解决哈希表中索引重复问题的算法,基本思路为将哈希表中维护的数组改成存储链表的数组,将数据存在链表中。也可以用数组但是数组的插入和删除的效率较低,故采用链表。实现:链表的实现:/链结点,相当于是车厢/publicclassNode{//数据域publi
Stella981 Stella981
4年前
Consistent hashing一致性算法原理
最近在整理redis分布式集群,首先就整理一下分布式算法原理。常见的分区规则有哈希分区和顺序分区两种,Redis采用的是哈希分区规则。节点取余分区使用特定的数据,如Redis的键或用户ID为key,节点数量为N,则:hash(key)%N,计算出哈希值,然后决定映射到哪个节点上,如节点数为4时,哈希值的结果可能为0、1、2,3.现假
Stella981 Stella981
4年前
Redis哈希对象的ziplist编码实现了O(1)复杂度吗
问题:Redis中哈希对象有两种编码方式,分别是ziplist、hashtable方式。哈希对象,总得体现哈希算法,使得基本操作达到O(1)的效率。hashtable编码方式使用字典,也即是Java中hashMap的方式,这个我可以理解。但是,ziplist方式所有元素都是紧挨的,它是怎么实现hash,并使得查询等操作有O(1)的时间效率的呢?让我们
Wesley13 Wesley13
4年前
Java数据结构和算法(四)——栈
前面我们讲解了数组,数组更多的是用来进行数据的存储,纯粹用来存储数据的数据结构,我们期望的是插入、删除和查找性能都比较好。对于无序数组,插入快,但是删除和查找都很慢,为了解决这些问题,后面我们会讲解比如二叉树、哈希表的数据结构。  而本篇博客讲解的数据结构和算法更多是用作程序员的工具,它们作为构思算法的辅助工具,而不是完全的数据存储工具。这些数据结构的生
Wesley13 Wesley13
4年前
Java学习系列——第3课Java 高级教程
java数据结构  1)【概述】  Java的工具包提供了强大的数据结构在的Java中的数据结构主要包括以下几种接口和类:枚举(枚举)位集合(位集合)向量(矢量)栈(栈)字典(词典)哈希表(哈希表)属性(属性)
Wesley13 Wesley13
4年前
MySQL索引初探
一、什么是索引?帮助数据库系统实现高效获取数据的数据结构索引可以帮助我们快速地定位到数据而不需要每次搜索的时候都遍历数据库中的每一行。二、常见实现方式有哪些?常见索引模型有三种:哈希表、有序数组、搜索树1.哈希表(1)使用哈希表实现的索引称为哈希索引。!(https://os
贾蔷 贾蔷
8个月前
哈希表实现指南:从原理到C++实践
一、简介和应用哈希表(HashTable)是一种高效的数据结构,通过键值对(keyvalue)存储数据,提供快速的插入、删除和查找操作。它使用哈希函数将键映射到表中的位置,使得平均时间复杂度可以达到O(1)。‌应用场景‌:数据库索引、缓存实现(如Redis
贾蔷 贾蔷
8个月前
手把手教你实现哈希表:从代码到原理的新手友好指南
一、简介和应用哈希表(HashTable)是一种高效的数据结构,通过哈希函数将键(Key)映射到存储位置,实现O(1)时间复杂度的查找、插入和删除操作。它广泛应用于缓存系统、数据库索引、字典查询等场景。例如,在编程中需要快速根据用户ID查找信息时,哈希表能
京东云开发者 京东云开发者
7个月前
缓存之美:从根上理解 ConcurrentHashMap
作者:京东科技王奕龙本文将详细介绍ConcurrentHashMap构造方法、添加值方法和扩容操作等源码实现。ConcurrentHashMap是线程安全的哈希表,此哈希表的设计主要目的是在最小化更新操作对哈希表的占用,以保持并发可读性,次要目的是保持空间
CodeAdventurerX
CodeAdventurerX
Lv1
春眠不觉晓,处处闻啼鸟。夜来风雨声,花落知多少!
文章
5
粉丝
0
获赞
0