avp26/u7/hash_table.py
2026-10-29 14:52:44 +00:00

119 lines
3.4 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
def __delitem__(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:
self.slots[idx] = self.deleted
self._size -= 1
else:
raise KeyError(key)
def __contains__(self, key):
self._check_key(key)
idx = self.probe(key)
slot = self.slots[idx]
return slot is not self.empty and slot is not self.deleted and slot[0] == key
def __len__(self):
return self._size
def __iter__(self):
for slot in self.slots:
if slot is not self.empty and slot is not self.deleted:
yield slot[0]