-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhash_table.py
More file actions
110 lines (100 loc) · 3.35 KB
/
hash_table.py
File metadata and controls
110 lines (100 loc) · 3.35 KB
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
'''
Hash Table Implementation
'''
# Optimizations
# i. Open Addressing
# ii. Double Hashing (Collision Resolution)
class HashTable:
def __init__(self, size=256, max_tries=3):
self.size = size
self.table = [None] * size
self.removed = [False] * size
self.max_tries = 3
def add(self, key: str):
assert isinstance(key, str)
hash_pri = hash(key) % self.size
if self.table[hash_pri] == None or self.removed[hash_pri]:
self.table[hash_pri] = key
else:
hash_sec = hash(key + '@@@') % self.size
tries = 0
while tries < self.max_tries:
tries += 1
addr = (hash_pri + hash_sec * tries) % self.size
if self.table[addr] == None or self.removed[addr]:
self.table[addr] = key
break
else:
print(f'ERROR: Cannot add {key}, table full!')
return False
# print()
return True
def remove(self, key: str):
hash_pri = hash(key) % self.size
if self.table[hash_pri] == key:
self.removed[hash_pri] = True
elif self.table[hash_pri] == None:
raise ValueError(f'ERROR: Key {key} not found!')
else:
hash_sec = hash(key + '@@@') % self.size
tries = 0
while tries < self.max_tries:
tries += 1
addr = (hash_pri + hash_sec * tries) % self.size
if self.table[addr] == key:
self.removed[addr] = True
break
elif self.table[addr] == None:
raise ValueError(f'ERROR: Key {key} not found!')
else:
raise ValueError(f'ERROR: Key {key} not found!')
# print()
return
def is_in(self, key: str):
hash_pri = hash(key) % self.size
if self.table[hash_pri] == None:
return False
elif self.table[hash_pri] == key and not self.removed[hash_pri]:
return True
else:
hash_sec = hash(key + '@@@') % self.size
tries = 0
while tries < self.max_tries:
tries += 1
addr = (hash_pri + hash_sec * tries) % self.size
if self.table[addr] == None:
return False
elif self.table[addr] == key and not self.removed[addr]:
return True
else:
# print()
return False
def hash_check1():
t = HashTable()
t.add('A')
print(t.is_in('A'))
print(t.is_in('B'))
t.remove('A')
print(t.is_in('A'))
from random import randint, choice
def hash_check():
for _ in range(100):
print('.', end='')
l = [str(randint(0, 250)) for _ in range(40)]
t_check = set(l)
t = HashTable()
for key in t_check:
assert t.add(key)
# print(t_check)
t_len = len(t_check)
for _ in range(randint(t_len // 4, t_len // 3)):
key = choice(list(t_check))
t_check.remove(key)
t.remove(key)
for key in t_check:
assert t.is_in(key), key
for x in [randint(1000, 1250) for _ in range(len(l))]:
assert not t.is_in(str(x))
if __name__ == '__main__':
hash_check1()
hash_check()