-
Notifications
You must be signed in to change notification settings - Fork 88
/
Copy pathhashTable.py
131 lines (114 loc) · 3.58 KB
/
hashTable.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
''' mbinary
#########################################################################
# File : hashTable.py
# Author: mbinary
# Mail: [email protected]
# Blog: https://mbinary.xyz
# Github: https://github.com/mbinary
# Created Time: 2018-07-08 16:39
# Description:
#########################################################################
'''
class item:
def __init__(self, key, val, nextItem=None):
self.key = key
self.val = val
self.next = nextItem
def to(self, it):
self.next = it
def __eq__(self, it):
'''using keyword <in> '''
return self.key == it.key
def __bool__(self):
return self.key is not None
def __str__(self):
li = []
nd = self
while nd:
li.append(f'({nd.key}:{nd.val})')
nd = nd.next
return ' -> '.join(li)
def __repr__(self):
return f'item({self.key},{self.val})'
class hashTable:
def __init__(self, size=100):
self.size = size
self.slots = [item(None, None) for i in range(self.size)]
def __setitem__(self, key, val):
nd = self.slots[self.myhash(key)]
while nd.next:
if nd.key == key:
if nd.val != val:
nd.val = val
return
nd = nd.next
nd.next = item(key, val)
def myhash(self, key):
if isinstance(key, str):
key = sum(ord(i) for i in key)
if not isinstance(key, int):
key = hash(key)
return key % self.size
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
while nd:
yield nd.key
nd = nd.next
def __getitem__(self, key):
nd = self.slots[self.myhash(key)].next
while nd:
if nd.key == key:
return nd.val
nd = nd.next
raise Exception(
f'[KeyError]: {self.__class__.__name__} has no key {key}')
def __delitem__(self, key):
'''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:
self.slots[n] = item(None, None) # be careful
else:
self.slots[n] = nd.next
return
while nd:
if nd.next is None:
break # necessary
if nd.next.key == key:
nd.next = nd.next.next
nd = nd.next
def __str__(self):
li = ['\n\n'+'-'*5+'hashTable'+'-'*5]
for i, nd in enumerate(self.slots):
li.append(f'{i}: '+str(nd.next))
return '\n'.join(li)
if __name__ == '__main__':
from random import randint
dic = hashTable(16)
n = 100
li = [1, 2, 5, 40, 324, 123, 6, 22, 18, 34, 50]
print(f'build hashTable using {li}')
for i in li:
dic[i] = '$'+str(i)
print(dic)
for i in [1, 34, 45, 123]:
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)