forked from Dstar4/Hash-Tables
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhashtable.py
More file actions
141 lines (97 loc) · 3.1 KB
/
hashtable.py
File metadata and controls
141 lines (97 loc) · 3.1 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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import hashlib
# '''
# Linked List hash table key/value pair
# Singly linked list -- LinkedPair'''
class LinkedPair:
def __init__(self, key, value):
self.key = key
self.value = value
self.next = None
class HashTable:
'''
A hash table that with `capacity` buckets
that accepts string keys
'''
def __init__(self, capacity):
self.capacity = capacity # Number of buckets in the hash table
self.storage = [None] * capacity
def _hash(self, key):
'''
Hash an arbitrary key and return an integer.
You may replace the Python hash with DJB2 as a stretch goal.
'''
return hashlib.sha256(key.encode())
def _hash_djb2(self, key):
'''
Hash an arbitrary key using DJB2 hash
OPTIONAL STRETCH: Research and implement DJB2
'''
pass
def _hash_mod(self, key):
'''
Take an arbitrary key and return a valid integer index
within the storage capacity of the hash table.
'''
return self._hash(key) % self.capacity
def insert(self, key, value):
'''
Store the value with the given key.
Hash collisions should be handled with Linked List Chaining.
Fill this in.
'''
index = self._hash_mod(key)
if self.storage[index] is not None:
print("error: key in use")
else:
self.storage[index] = value
def remove(self, key):
'''
Remove the value stored with the given key.
Print a warning if the key is not found.
Fill this in.
'''
index = self._hash_mod(key)
if self.storage[index] is not None:
self.storage[index] = None
else:
print('warning key not found')
def retrieve(self, key):
'''
Retrieve the value stored with the given key.
Returns None if the key is not found.
Fill this in.
'''
index = self._hash_mod(key)
# if its none it meets spec, still works
return self.storage[index]
def resize(self):
'''
Doubles the capacity of the hash table and
rehash all key/value pairs.
Fill this in.
'''
old_storage = self.storage.copy()
self.capacity = self.capacity * 2
self.storage = [None] * self.capacity
for bucket_item in old_storage:
self.insert(bucket_item)
if __name__ == "__main__":
ht = HashTable(2)
ht.insert("line_1", "Tiny hash table")
ht.insert("line_2", "Filled beyond capacity")
ht.insert("line_3", "Linked list saves the day!")
print("")
# Test storing beyond capacity
print(ht.retrieve("line_1"))
print(ht.retrieve("line_2"))
print(ht.retrieve("line_3"))
# Test resizing
old_capacity = len(ht.storage)
ht.resize()
new_capacity = len(ht.storage)
print(f"\nResized from {old_capacity} to {new_capacity}.\n")
# Test if data intact after resizing
print(ht.retrieve("line_1"))
print(ht.retrieve("line_2"))
print(ht.retrieve("line_3"))
print("")