Aktualizovat u7/hash_table.py

This commit is contained in:
Oleksandr Mateshchuk 2026-10-29 18:20:23 +00:00
parent fa20d2ae88
commit 375babbc41

View File

@ -15,24 +15,27 @@ class HashTable:
def capacity(self): def capacity(self):
return self._capacity return self._capacity
def hash(self, key): def _validate_key(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")
def hash(self, key):
self._validate_key(key)
h = 0 h = 0
for znak in key: for char in key:
h = (31 * h + ord(znak)) % self.capacity h = (31 * h + ord(char)) % self.capacity
return h return h
def probe(self, key): def probe(self, key):
if not isinstance(key, str): self._validate_key(key)
raise TypeError("Key must be a string")
start = self.hash(key) start = self.hash(key)
first_deleted = None first_deleted = None
for krok in range(self.capacity): for step in range(self.capacity):
index = (start + krok) % self.capacity index = (start + step) % self.capacity
item = self._table[index] item = self._table[index]
if item is None: if item is None:
@ -52,87 +55,52 @@ class HashTable:
raise RuntimeError("Hash table is full") raise RuntimeError("Hash table is full")
def __setitem__(self, key, value): def __setitem__(self, key, value):
if not isinstance(key, str): self._validate_key(key)
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) index = self.probe(key)
item = self._table[index]
# Existujúci kľúč: prepíš hodnotu.
if item is not None and item is not self._DELETED:
if item[0] == key:
self._table[index] = (key, value)
return
# Nový kľúč: skontroluj zaplnenie.
if (self._size + 1) / self.capacity > 0.7:
self._resize(self.capacity * 2)
index = self.probe(key)
self._table[index] = (key, value) self._table[index] = (key, value)
self._size += 1 self._size += 1
def __getitem__(self, key): def __getitem__(self, key):
if not isinstance(key, str): self._validate_key(key)
raise TypeError("Key must be a string")
try:
index = self.probe(key)
except RuntimeError:
raise KeyError(key)
index = self.probe(key)
item = self._table[index] item = self._table[index]
if item is None or item is self._DELETED: if item is None or item is self._DELETED or item[0] != key:
raise KeyError(key)
if item[0] != key:
raise KeyError(key) raise KeyError(key)
return item[1] return item[1]
def __delitem__(self, key): def __delitem__(self, key):
if not isinstance(key, str): self._validate_key(key)
raise TypeError("Key must be a string")
try:
index = self.probe(key)
except RuntimeError:
raise KeyError(key)
index = self.probe(key)
item = self._table[index] item = self._table[index]
if item is None or item is self._DELETED: if item is None or item is self._DELETED or item[0] != key:
raise KeyError(key)
if item[0] != key:
raise KeyError(key) raise KeyError(key)
self._table[index] = self._DELETED self._table[index] = self._DELETED
self._size -= 1 self._size -= 1
def __contains__(self, key): def __contains__(self, key):
if not isinstance(key, str): self._validate_key(key)
raise TypeError("Key must be a string")
try:
index = self.probe(key)
except RuntimeError:
return False
index = self.probe(key)
item = self._table[index] item = self._table[index]
return ( return (
@ -148,3 +116,20 @@ class HashTable:
for item in self._table: for item in self._table:
if item is not None and item is not self._DELETED: if item is not None and item is not self._DELETED:
yield item[0] yield item[0]
def load_factor(self):
return self._size / self.capacity
def _resize(self, new_capacity):
old_table = self._table
self._capacity = new_capacity
self._table = [None] * new_capacity
self._size = 0
for item in old_table:
if item is not None and item is not self._DELETED:
key, value = item
index = self.probe(key)
self._table[index] = (key, value)
self._size += 1