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表就先分享到这里了