配合前置文章食用更佳,传送门如下:
实现Hash表(一)----手写一个简单hash表
问题描述
我们已经完成了hash表的基本操作,插入、删除、更新、遍历等,并且解决了冲突问题,接下来让我们手动实现以下python中的字典结构
补充以及更新
- 这次获取hash值的方法,不再采用最简单的ASCII码相加的方式,而是采用python的内置函数
hash
- 用了很多___xxx___的方法,为了更好的接近内置的dictionary
- 最后遍历的时候,由于MAX_HASH_TABLE_SIZE的不同,可能遍历会出现不同的顺序,但是内容相同
python的实现
MAX_HASH_TABLE_SIZE = 4096
class DictByHash:
def __init__(self, max_size=MAX_HASH_TABLE_SIZE):
self.max_size = max_size
self.data_list = [None] * max_size
def get_valid_index(self, key):
"""
:param key:
:return: hash 返回一个hash值
e.g hash('test') ---> 9223025588143776724
hash(1) --->1
"""
index = hash(key) % self.max_size
while True:
if self.data_list[index] is None:
return index
key_value = self.data_list[index]
if key_value[0] == key:
return index
index += 1
if index == len(self.data_list):
index = 0
def __getitem__(self, item):
"""
:param item: hash表中存储的key
:return: 查找到的值
"""
return self.data_list[self.get_valid_index(item)][1]
def __setitem__(self, key, value):
"""
:param key:
:param value:
:return:
实现更新/插入的逻辑
"""
index = self.get_valid_index(key)
self.data_list[index] = (key, value)
def __iter__(self):
"""
遍历时候调用这个
"""
return (x for x in self.data_list if x is not None)
def __len__(self):
return len([x for x in self])
def __repr__(self):
"""
:return:print的时候会调用这个
"""
from textwrap import indent
pairs = [indent("{} : {}".format(repr(kv[0]), repr(kv[1])), ' ') for kv in self]
return "{\n" + "{}".format(',\n'.join(pairs)) + "\n}"
def __str__(self):
return repr(self)
if __name__ == '__main__':
# Create a hash table
table = DictByHash()
# Insert some key-value pairs
table['a'] = 1
table['b'] = 34
# Retrieve the inserted values
print(table['a'] == 1 and table['b'] == 34)
# Update a value
table['a'] = 99
# Check the updated value
print(table['a'] == 99)
# Get a list of key-value pairs
# 这里可能会不一样,如果取1024就是对的,默认值会得到[('b', 34), ('a', 99)]
print(list(table) == [('a', 99), ('b', 34)])
print(len(table))
总结
至此一个类似于python内置的dictionary就已经实现了,当然,真正的内部肯定要比这复杂的多,这里就是为了让你明白原理。
一个基本的数据结构可以完成增删改查,在我们目前的实现中,还没有牵扯到"删",这个操作,其实现是否是通过get_valid_index
获取对应的index,之后将对应的数据变为None就行了呢?