Hash查找
-
分析表
- 哈希表: 是一个很容易就能便捷的定位到元素的一个集合,通常会被称为槽,每个槽都可以存放一个元素。
- hash函数: 元素与元素所属的槽之间的映射关系称为hash函数。
item % len(list)
,集合的元素乘除哈希表的长度。 - 哈希值计算方法
- 余除法: 使用元素整除于hash表的长度得到的值
- 分组求和法: 假设现在有一串字符串
11-22-33-44-55
,可以将它们理解为11+22+33+44+55
得到165,在将这个值整除于hash表的长度得到想要值。 - 平方取中法: 将元素进行平方,再取器中间的数值,整除于hash表的长度。
-
案例
- 假设哈希表的长度为6,也就是哈希表初始值为
[None, None, None, None, None, None]
- 此时想要存入一个值,例如11=‘dog’,通过hash函数的计算,也就是11%6=5,将dog放置,哈希表的第五个位置。
- 然后现在又想存入一个17=‘cat’,通过hash函数的计算,发现17%6=5,此时发现哈希表的第五个位置已经有了元素,并且11!=17,所以会将指针向后偏移,来到hash表的第0个位置,并且发现第0个位置为空,于是就将cat放置第0个位置。
- 最终结果为:
['cat', None, None, None, None, 'dog']
- 假设哈希表的长度为6,也就是哈希表初始值为
-
代码实现
-
Map() 创建一个新的 map 。它返回一个空的 map 集合
-
put(key,value) 向 map 中添加一个新的键值对。如果键已经在 map 中,那么用新值替换旧值。
-
get(key) 给定一个键,返回存储在 map 中的值或 None。
-
del_data(key)方法,使用
del map[key]
形式的语句从 map 中删除键值对。 -
len_data()方法,使用
len()
返回存储在 map 中的键值对的数量。 -
in_data()方法,返回 True 对于
key in map
语句,如果给定的键在 map 中,否则为False。 -
class Map: def __init__(self, size=11): self.size = size self.slots = [None] * self.size # 存放key self.data = [None] * self.size # 存放value def hash_func(self, key, size): return key % size def re_hash(self, old_hash, size): return (old_hash + 1) % size def put(self, key, value): start_slot = self.hash_func(key, len(self.slots)) if self.slots[start_slot] is None: """ 没有冲突 """ self.slots[start_slot] = key self.data[start_slot] = value else: """ 存在冲突 """ if self.slots[start_slot] == key: """ 已存在,而非冲突 """ self.data[start_slot] = value else: """ 存在冲突 """ next_slot = self.re_hash(start_slot, len(self.slots)) while self.slots[next_slot] is not None and self.slots[next_slot] != key: """ 当没有找到空槽或者找到相同key的时候,执行循环 """ next_slot = self.re_hash(next_slot, len(self.slots)) if next_slot == start_slot: # raise IndexError("hash表已满") print("hash表已满") return # 走到这边说明已经找到了空槽或者找到了相同的key if self.slots[next_slot] is None: # 说明找到了空槽 self.slots[next_slot] = key self.data[next_slot] = value else: # 说明已存在,而非冲突 self.data[next_slot] = value def get(self, key): start_slot = self.hash_func(key, len(self.slots)) # 获取该key%11 data = None stop = False found = False position = start_slot while self.slots[position] is not None and not found and not stop: # 没有找到空槽并且没有找到并且没有停止就继续循环 if self.slots[position] == key: # 说明找到了 found = True data = self.data[position] else: position = self.re_hash(position, len(self.slots)) # 依次向后 if position == start_slot: # 说明找了一圈 stop = True return data def del_data(self, key): start_slot = self.hash_func(key, len(self.slots)) stop = False found = False position = start_slot while not found and not stop: """ 没有找到并且没有停止 """ if self.slots[position] == key: self.slots[position] = None self.data[position] = None found = True else: position = self.re_hash(position, len(self.slots)) if position == start_slot: stop = True def len_data(self): count = 0 for i in self.slots: if i is not None: count += 1 return count def in_data(self, key): start_slot = self.hash_func(key, len(self.slots)) found = False stop = False position = start_slot while not found and not stop: if self.slots[position] == key: found = True else: position = self.re_hash(position, len(self.slots)) if position == start_slot: stop = True return found def __getitem__(self, item): return self.get(item) def __setitem__(self, key, value): self.put(key, value) def __delitem__(self, key): self.del_data(key) def __len__(self): return self.len_data() def __contains__(self, item): return self.in_data(item) h = Map() h[1] = 'cat' h[2] = 'people' h[3] = 'people' h[4] = 'people' h[5] = 'people' h[6] = 'people' h[7] = 'people' h[8] = 'people' h[9] = 'people' h[10] = 'people' h[11] = 'people' h[12] = 'people' del h[1] print(2 in h) print(1 in h) print(len(h)) print(h.slots) print(h.data)
-