Aktualizovat u7/hash_table.py

This commit is contained in:
Oleksandr Mateshchuk 2026-10-27 14:12:11 +00:00
parent 961d49c532
commit fa20d2ae88

View File

@ -1,24 +1,21 @@
class HashTable: class HashTable:
_DELETED = object()
def __init__(self, capacity=10): def __init__(self, capacity=10):
"""Vytvor prázdnu tabuľku s kladnou celočíselnou kapacitou."""
if type(capacity) is not int: if type(capacity) is not int:
raise TypeError("It's not integer") raise TypeError("Capacity must be an integer")
if capacity <= 0: if capacity <= 0:
raise ValueError("Capacity > 0") raise ValueError("Capacity must be positive")
self._capacity = capacity self._capacity = capacity
self._table = [None] * capacity self._table = [None] * capacity
self._size = 0 self._size = 0
@property @property
def capacity(self): def capacity(self):
"""Vráť aktuálny počet pozícií v poli.""" return self._capacity
return self.kapacity
def hash(self, key): def hash(self, key):
"""Vráť polynomiálny hash kľúča modulo aktuálna kapacita."""
if not isinstance(key, str): if not isinstance(key, str):
raise TypeError("Key must be a string") raise TypeError("Key must be a string")
@ -28,30 +25,105 @@ class HashTable:
return h return h
def probe(self, key): def probe(self, key):
"""Vráť index kľúča alebo miesta na vloženie bez zmeny tabuľky."""
if not isinstance(key, str): if not isinstance(key, str):
raise TypeError("Key must be a string") raise TypeError("Key must be a string")
start = self.hash(key) start = self.hash(key)
first_deleted = None first_deleted = None
def load_factor(self): for krok in range(self.capacity):
"""Vráť podiel počtu aktívnych položiek a kapacity.""" index = (start + krok) % self.capacity
if not isinstance(key, str): item = self._table[index]
raise TypeError("Key must be a string")
def __getitem__(self, key): if item is None:
if not isinstance(key, str): if first_deleted is not None:
raise TypeError("Key must be a string") return first_deleted
return index
if item is self._DELETED:
if first_deleted is None:
first_deleted = index
elif item[0] == key:
return index
if first_deleted is not None:
return first_deleted
raise RuntimeError("Hash table is full")
def __setitem__(self, key, value): def __setitem__(self, key, value):
if not isinstance(key, str): if not isinstance(key, str):
raise TypeError("Key must be a string") raise TypeError("Key must be a string")
try:
index = self.probe(key)
except RuntimeError:
index = None
if index is not None:
item = self._table[index]
if item is not None and item is not self._DELETED:
if item[0] == key:
self._table[index] = (key, value)
return
if (self._size + 1) / self.capacity > 0.7:
old_table = self._table
self._capacity *= 2
self._table = [None] * self._capacity
self._size = 0
for item in old_table:
if item is not None and item is not self._DELETED:
old_key, old_value = item
new_index = self.probe(old_key)
self._table[new_index] = (old_key, old_value)
self._size += 1
index = self.probe(key)
self._table[index] = (key, value)
self._size += 1
def __getitem__(self, key):
if not isinstance(key, str):
raise TypeError("Key must be a string")
try:
index = self.probe(key)
except RuntimeError:
raise KeyError(key)
item = self._table[index]
if item is None or item is self._DELETED:
raise KeyError(key)
if item[0] != key:
raise KeyError(key)
return item[1]
def __delitem__(self, key): def __delitem__(self, key):
if not isinstance(key, str): if not isinstance(key, str):
raise TypeError("Key must be a string") raise TypeError("Key must be a string")
try:
index = self.probe(key)
except RuntimeError:
raise KeyError(key)
item = self._table[index]
if item is None or item is self._DELETED:
raise KeyError(key)
if item[0] != key:
raise KeyError(key)
self._table[index] = self._DELETED
self._size -= 1
def __contains__(self, key): def __contains__(self, key):
if not isinstance(key, str): if not isinstance(key, str):
raise TypeError("Key must be a string") raise TypeError("Key must be a string")
@ -62,11 +134,13 @@ class HashTable:
return False return False
item = self._table[index] item = self._table[index]
return ( return (
item is not None item is not None
and item is not self._DELETED and item is not self._DELETED
and item[0] == key and item[0] == key
) )
def __len__(self): def __len__(self):
return self._size return self._size