diff --git a/u7/hash_table.py b/u7/hash_table.py index e69de29..7ab59e9 100644 --- a/u7/hash_table.py +++ b/u7/hash_table.py @@ -0,0 +1,94 @@ +"""Hash tabuľka s lineárnym sondovaním a reťazcovými kľúčmi.""" + +_DELETED = object() + +class HashTable: + def __init__(self, capacity=10): + if type(capacity) is not int: + raise TypeError("Kapacita musí byť celé číslo.") + if capacity <= 0: + raise ValueError("Kapacita musí byť kladné číslo.") + self._slots = [None] * capacity + self._size = 0 + + pass + + @property + def capacity(self): + return len(self._slots) + + @staticmethod + def _check_key(key): + if not isinstance(key, str): + raise TypeError("Klúč musí byť typu string.") + + def _is_active(self, index, key): + slot = self._slots[index] + return slot is not None and slot is not _DELETED and slot[0] == key + + 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): + """Vráť index kľúča alebo miesta na vloženie bez zmeny tabuľky.""" + start = self.hash(key) + first_deleted = None + for step in range(self.capacity): + index = (start + step) % self.capacity + slot = self._slots[index] + if slot is None: + return first_deleted if first_deleted is not None else index + if slot is _DELETED: + if first_deleted is None: + first_deleted = index + elif slot[0] == key: + return index + if first_deleted is not None: + return first_deleted + raise RuntimeError("Tabuľka je plná.") + + def _resize(self, new_capacity): + old_slots = self._slots + self._slots = [None] * new_capacity + for slot in old_slots: + if slot is not None and slot is not _DELETED: + self._slots[self.probe(slot[0])] = slot + + def __getitem__(self, key): + index = self.probe(key) + if not self._is_active(index, key): + raise KeyError(key) + return self._slots[index][1] + + def __setitem__(self, key, value): + index = self.probe(key) + if self._is_active(index, key): + self._slots[index] = (key, value) + return + if (self._size + 1) / self.capacity > 0.7: + self._resize(self.capacity * 2) + index = self.probe(key) + self._slots[index] = (key, value) + self._size += 1 + + def __delitem__(self, key): + index = self.probe(key) + if not self._is_active(index, key): + raise KeyError(key) + self._slots[index] = _DELETED + self._size -= 1 + + def __contains__(self, key): + return self._is_active(self.probe(key), key) + + def __len__(self): + return self._size + + def __iter__(self): + for slot in self._slots: + if slot is not None and slot is not _DELETED: + yield slot[0] \ No newline at end of file