# 映射数据类型在查找这一操作时的复杂度为O(1),要实现这样的快速查找,必须有一个结可以快速查找到key的结构,这可以用哈希表实现
class Map:
"""映射数据类型"""
def __init__(self, size):
"""初始化映射"""
# 维护一个hash表和一个与之对应的列表
self.size = size # size是hash表的大小,一般取素数
self.slots = [None] * self.size
self.values = [None] * self.size
self._step = 1 # 再散列时探测空槽的步长。不能设置为size的倍数,否者形成周期,永远无法探测到空槽
def hash_function(self, key):
"""散列函数,将key转换为hash值"""
return key % self.size
def rehash_function(self, hash_value):
"""再散列函数,防止散列冲突"""
return (hash_value + self._step) % self._step
def __getitem__(self, item):
"""此特殊方法实现用[]对键值的访问"""
return self.get(item)
def __setitem__(self, key, value):
return self.put(key,value)
def put(self, key, value):
"""添加键值到映射中"""
hash_value = self.hash_function(key) # 理论上应该存放key的槽号
if self.slots[hash_value] is None: # 检查槽是不是空
self.slots[hash_value] = key
self.values[hash_value] = value
elif self.slots[hash_value] == key:
self.values[hash_value] = value
else:
new_hash_value = self.rehash_function(hash_value)
while self.slots[new_hash_value] is not None and self.slots[new_hash_value] != key: # 如果槽不空且槽不是存的key
# ,那么都还要继续rehash
new_hash_value = self.rehash_function(new_hash_value)
if self.slots[new_hash_value] is None:
self.slots[new_hash_value] = key
self.values[new_hash_value] = value
else:
self.values[hash_value] = value
def get(self, key): # 实现逻辑是,由于两个表是并行的,找到key的位置也就找到value的位置了,再返回value就好
"""通过键查找键值"""
theoretic_position = self.hash_function(key) # key的理论槽号
position = theoretic_position
if self.slots[position] == key:
return self.values[position]
else:
new_position = self.rehash_function(position)
while self.slots[new_position] != key and self.slots[new_position] is not None: # 没找到继续找,找了一轮没找到就不用找了
new_position = self.rehash_function(position)
if new_position == position:
return None
else:
return self.values[new_position]
#创建空映射
map=Map(4)
#添加键值对到映射中
map[1]=12
map[3]=14
map[21]=7
#查看映射
print(map[1],map[3],map[21])