94 lines
2.7 KiB
Python
94 lines
2.7 KiB
Python
class HashTable:
|
|
|
|
def __init__(self, capacity=10):
|
|
if type(capacity) is not int:
|
|
raise TypeError("Kapacita musí byť celé číslo (int)")
|
|
if capacity <= 0:
|
|
raise ValueError("Kapacita musí byť kladné číslo")
|
|
self.__capacity = capacity
|
|
self._size = 0
|
|
|
|
self.empty = object()
|
|
self.deleted = object()
|
|
self.slots = [self.empty] * self.__capacity
|
|
|
|
@property
|
|
def capacity(self):
|
|
return self.__capacity
|
|
|
|
def _check_key(self, key):
|
|
if not isinstance(key, str):
|
|
raise TypeError("Kľúč musí byť reťazec (str)")
|
|
|
|
def hash(self, key):
|
|
self._check_key(key)
|
|
h = 0
|
|
for char in key:
|
|
h = (31 * h + ord(char)) % self.__capacity
|
|
return h
|
|
|
|
def probe(self, key):
|
|
self._check_key(key)
|
|
start_index = self.hash(key)
|
|
first_deleted = None
|
|
|
|
for krok in range(self.__capacity):
|
|
index = (start_index + krok) % self.__capacity
|
|
slot = self.slots[index]
|
|
|
|
if slot is self.empty:
|
|
if first_deleted is not None:
|
|
return first_deleted
|
|
return index
|
|
|
|
elif slot is self.deleted:
|
|
if first_deleted is None:
|
|
first_deleted = index
|
|
|
|
else:
|
|
if slot[0] == key:
|
|
return index
|
|
|
|
if first_deleted is not None:
|
|
return first_deleted
|
|
|
|
raise RuntimeError("Tabuľka je plná")
|
|
def load_factor(self):
|
|
return self._size / self.__capacity
|
|
def _resize(self):
|
|
old_slots = self.slots
|
|
self.__capacity *= 2
|
|
self.slots = [self.empty] * self.__capacity
|
|
self._size = 0
|
|
|
|
|
|
for slot in old_slots:
|
|
if slot is not self.empty and slot is not self.deleted:
|
|
key, value = slot
|
|
index = self.probe(key)
|
|
self.slots[index] = (key, value)
|
|
self.size += 1
|
|
def __getitem__(self, key):
|
|
self._check_key(key)
|
|
idx = self.probe(key)
|
|
slot = self.slots[idx]
|
|
|
|
if slot is not self.empty and slot is not self.deleted and slot[0] == key:
|
|
return slot[1]
|
|
raise KeyError(key)
|
|
|
|
def __setitem__(self, key, value):
|
|
self._check_key(key)
|
|
idx = self.probe(key)
|
|
slot = self.slots[idx]
|
|
|
|
if slot is not self.empty and slot is not self.deleted and slot[0] == key:
|
|
self.slots[idx] = (key, value)
|
|
return
|
|
|
|
if (self._size + 1) / self.__capacity > 0.7:
|
|
self._resize()
|
|
idx = self.probe(key)
|
|
|
|
self.slots[idx] = (key, value)
|
|
self._size += 1 |