class HashTable: def __init__(self, capacity=10): if type(capacity) is not int or isinstance(capacity, bool): raise TypeError("Kapacita musí byť celé číslo.") if capacity <= 0: raise ValueError("Kapacita musí byť kladné celé číslo.") self._capacity = capacity self.empty = object() self.deleted = object() self.slots = [self.empty] * capacity self.count = 0 @property def capacity(self): return self._capacity def hash(self, key): if not isinstance(key, str): raise TypeError("Kľúč musí byť reťazec.") h = 0 for znak in key: h = (31 * h + ord(znak)) % self._capacity return h def probe(self, key): if not isinstance(key, str): raise TypeError("Kľúč musí byť reťazec.") start_idx = self.hash(key) first_deleted = None for krok in range(self._capacity): idx = (start_idx + krok) % self._capacity slot = self.slots[idx] if slot is self.empty: return first_deleted if first_deleted is not None else idx elif slot is self.deleted: if first_deleted is None: first_deleted = idx elif slot[0] == key: return idx if first_deleted is not None: return first_deleted raise RuntimeError("Tabuľka je plná a nemá žiadne voľné ani vymazané miesto.") def load_factor(self): return self.count / self._capacity def __getitem__(self, key): if not isinstance(key, str): raise TypeError("Kľúč musí byť reťazec.") 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): if not isinstance(key, str): raise TypeError("Kľúč musí byť reťazec.") start_idx = self.hash(key) existing_idx = None for krok in range(self._capacity): idx = (start_idx + krok) % self._capacity slot = self.slots[idx] if slot is self.empty: break if slot is not self.deleted and slot[0] == key: existing_idx = idx break if existing_idx is not None: self.slots[existing_idx] = (key, value) return if (self.count + 1) / self._capacity > 0.7: self._resize(self._capacity * 2) idx = self.probe(key) self.slots[idx] = (key, value) self.count += 1 def _resize(self, new_capacity): old_slots = self.slots self._capacity = new_capacity self.slots = [self.empty] * new_capacity self.count = 0 for slot in old_slots: if slot is not self.empty and slot is not self.deleted: k, v = slot idx = self.probe(k) self.slots[idx] = (k, v) self.count += 1 def __delitem__(self, key): if not isinstance(key, str): raise TypeError("Kľúč musí byť reťazec.") 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.count -= 1 return raise KeyError(key) def __contains__(self, key): if not isinstance(key, str): raise TypeError("Kľúč musí byť reťazec.") try: idx = self.probe(key) except RuntimeError: return False 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.count def __iter__(self): for slot in self.slots: if slot is not self.empty and slot is not self.deleted: yield slot[0]