hash表是怎么生成的?哈希表浅析

本文深入浅出地介绍了哈希表的工作原理,包括如何通过哈希函数存储和检索数据,以及在Python中实现简单哈希表的过程。从基本的LineMap到更复杂的HashMap,逐步展示了哈希表的优化过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

hash表的用途十分广泛,通俗来讲,hash表是一个用来存储key-value键值对的集合。
每一个键值对也叫做Entry,这些Entry会分散的储存在一个数组当中,这个数组就是HashMap的主干
python中有许多数据类型都是使用hash表实现的,比如字典,集合,计数器等。

接下来我们来实现一个简单的hash表,在写代码之前,我们先大致了解一下hash表是怎么储存数据的

例如有一个数据{‘a’:1},一个数组n
我们hash(a)得到一个key的hash值
这时候我们需要将value存储在数组中,于是
index = hash(a)%len(n)
通过用hash(a)得到一个整数类型,对数组长度取余,余数就是我们把value存在数组中位置的下表值。
当我们查询key为‘a’的value时,直接重复上面的公式就能得到value的下标,直接进行取值操作。

class LineMap(object):

    def __init__(self):
        self.items = []  #使用列表当做储存键值对的数组

    def add(self,k,v):  #定义添加键值对的方法
        self.items.append((k,v))  #使用元组模拟键值对的映射关系
        return self.items

    def get(self,k):  #定义取值操作的方法
        for key,value in self.items:
            if key == k:
                return value
        raise KeyError  #如果没有这个键,则抛出错误


class BetterMap(object):  #新建一个类进行优化查询定位,将原来的一个表分为多个子表进行查询

    def __init__(self,n):  #初始化方法
        self.maps = []  #定义一个主表maps
        for i in range(n):  #将之前的items作为子表,将其对象LineMap添加进主表
            self.maps.append(LineMap())

    def find_map(self,k):  #根据hash函数生成键的hash值,并通过公式确定键对应的值应该存在于哪一个子表中
        index = hash(k) % len(self.maps)
        print(index)  #打印一下value的下标值,存在哪个子表中
        return self.maps[index]  #返回键所对应的值的下标

    def add(self,k,v): #定义添加方法
        map = self.find_map(k)  #调用find_map获得子表对象
        map.add(k,v)  #调用子表的add方法插入数据

    def get(self,k):  #定义取值方法
        map = self.find_map(k)
        map.get(k)


class HashMap(object):  #进一步优化总表
    def __init__(self):  
        self.maps = BetterMap(2) #初始化一个子表数为2的总表
        self.num = 0  #初始化表中数据总计为0

    def get(self,k):  #定义取值方法,直接调用Bettermap的get方法即可
        self.maps.get(k)

    def add(self,k,v):  
        if self.num == len(self.maps.maps):  #这里需要比较一下是否插入数据的数量达到了子表数量
        ““”
		如果达到了子表数量,我们需要添加新的子表,因为是通过对表长度取余
		分配value位置的,所以我们表的子表数量需要随着数据数量的增加而增加,
		比如当数据数量为15时,可能index就等于14,如果不增加子表,则取不到
		index对应的存储位置,就会报错
        “”“”
            self.resize() 
        self.maps.add(k,v)  #插入数据
        self.num += 1  #数据量+1
        return self.maps.maps #这里没必要返回,我返回来就是看看数据是否插进来了

    def resize(self):
        new_maps = BetterMap(self.num*2)  #生成一个新的总表对象,容量依旧为2
        for map in self.maps.maps:  #遍历旧的总表中的总表数组,得到子表对象
            for k,v in map.items:  #遍历子表的数组,取得key与value值
                new_maps.add(k,v)  #把key和value值新增到新的总表中,用总表的add方法分配存储位置
        self.maps = new_maps  #用新的总表替换旧表


h = HashMap()  #实例化一个hashmap
f = h.add('a',1)  #插入一个数据
print(f[0].items)
print(f[1].items)

结果

1
[]
[('a', 1)]

可以看到,hash表生成了一个1的index,为数据的下标
通过下标去获得对应子表,成功取出数据
而另一个子表没有数据

好了,hash表就先分享到这里了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值