algorithm-in-python/dataStructure/hashTable.py

132 lines
3.6 KiB
Python
Raw Normal View History

2018-07-08 23:28:29 +08:00
''' mbinary
#########################################################################
# File : hashTable.py
# Author: mbinary
# Mail: zhuheqin1@gmail.com
2019-01-31 12:09:46 +08:00
# Blog: https://mbinary.xyz
2018-07-08 23:28:29 +08:00
# Github: https://github.com/mbinary
# Created Time: 2018-07-08 16:39
# Description:
#########################################################################
'''
2020-04-15 12:28:20 +08:00
2018-07-08 16:41:55 +08:00
class item:
2020-04-15 12:28:20 +08:00
def __init__(self, key, val, nextItem=None):
2018-07-08 16:41:55 +08:00
self.key = key
self.val = val
self.next = nextItem
2020-04-15 12:28:20 +08:00
def to(self, it):
2018-07-08 16:41:55 +08:00
self.next = it
2020-04-15 12:28:20 +08:00
def __eq__(self, it):
2018-07-08 16:41:55 +08:00
'''using keyword <in> '''
return self.key == it.key
2020-04-15 12:28:20 +08:00
2018-07-08 16:41:55 +08:00
def __bool__(self):
return self.key is not None
2020-04-15 12:28:20 +08:00
2018-07-08 16:41:55 +08:00
def __str__(self):
li = []
nd = self
while nd:
li.append(f'({nd.key}:{nd.val})')
nd = nd.next
return ' -> '.join(li)
2020-04-15 12:28:20 +08:00
2018-07-08 16:41:55 +08:00
def __repr__(self):
return f'item({self.key},{self.val})'
2020-04-15 12:28:20 +08:00
2018-07-08 16:41:55 +08:00
class hashTable:
2020-04-15 12:28:20 +08:00
def __init__(self, size=100):
2018-07-08 16:41:55 +08:00
self.size = size
2020-04-15 12:28:20 +08:00
self.slots = [item(None, None) for i in range(self.size)]
def __setitem__(self, key, val):
2018-07-08 16:41:55 +08:00
nd = self.slots[self.myhash(key)]
while nd.next:
2020-04-15 12:28:20 +08:00
if nd.key == key:
if nd.val != val:
nd.val = val
2018-07-08 16:41:55 +08:00
return
2020-04-15 12:28:20 +08:00
nd = nd.next
nd.next = item(key, val)
2018-07-08 16:41:55 +08:00
2020-04-15 12:28:20 +08:00
def myhash(self, key):
if isinstance(key, str):
2018-07-08 16:41:55 +08:00
key = sum(ord(i) for i in key)
2020-04-15 12:28:20 +08:00
if not isinstance(key, int):
2018-07-08 16:41:55 +08:00
key = hash(key)
return key % self.size
2020-04-15 12:28:20 +08:00
2018-07-08 16:41:55 +08:00
def __iter__(self):
'''when using keyword <in>, such as ' if key in dic',
the dic's __iter__ method will be called,(if hasn't, calls __getitem__
then ~iterate~ dic's keys to compare whether one equls to the key
'''
for nd in self.slots:
nd = nd.next
2020-04-15 12:28:20 +08:00
while nd:
2018-07-08 16:41:55 +08:00
yield nd.key
nd = nd.next
2020-04-15 12:28:20 +08:00
def __getitem__(self, key):
nd = self.slots[self.myhash(key)].next
2018-07-08 16:41:55 +08:00
while nd:
2020-04-15 12:28:20 +08:00
if nd.key == key:
2018-07-08 16:41:55 +08:00
return nd.val
nd = nd.next
2020-04-15 12:28:20 +08:00
raise Exception(
f'[KeyError]: {self.__class__.__name__} has no key {key}')
2018-07-08 16:41:55 +08:00
2020-04-15 12:28:20 +08:00
def __delitem__(self, key):
2018-07-08 16:41:55 +08:00
'''note that None item and item(None,None) differ with each other,
which means you should take care of them and correctly cop with None item
especially when deleting items
'''
n = self.myhash(key)
nd = self.slots[n].next
if nd.key == key:
if nd.next is None:
2020-04-15 12:28:20 +08:00
self.slots[n] = item(None, None) # be careful
else:
self.slots[n] = nd.next
2018-07-08 16:41:55 +08:00
return
while nd:
2020-04-15 12:28:20 +08:00
if nd.next is None:
break # necessary
if nd.next.key == key:
2018-07-08 16:41:55 +08:00
nd.next = nd.next.next
nd = nd.next
2020-04-15 12:28:20 +08:00
2018-07-08 16:41:55 +08:00
def __str__(self):
li = ['\n\n'+'-'*5+'hashTable'+'-'*5]
2020-04-15 12:28:20 +08:00
for i, nd in enumerate(self.slots):
2018-07-08 16:41:55 +08:00
li.append(f'{i}: '+str(nd.next))
return '\n'.join(li)
2020-04-15 12:28:20 +08:00
if __name__ == '__main__':
2018-07-08 16:41:55 +08:00
from random import randint
dic = hashTable(16)
n = 100
2020-04-15 12:28:20 +08:00
li = [1, 2, 5, 40, 324, 123, 6, 22, 18, 34, 50]
2018-07-08 16:41:55 +08:00
print(f'build hashTable using {li}')
for i in li:
dic[i] = '$'+str(i)
print(dic)
2020-04-15 12:28:20 +08:00
for i in [1, 34, 45, 123]:
2018-07-08 16:41:55 +08:00
if i in dic:
print(f'{i} in dic, deleting it')
del dic[i]
else:
print(f'{i} not in dic, ignore it')
print(dic)
print(f'dic[2] is {dic[2]}')
try:
dic[-1]
except Exception as e:
print(e)