class HashTableEntry: def __init__(self, key: str, value: str): self.key = key self.value = value self.deleted = False class HashTable: def __init__(self, capacity: int = 100): self.capacity = capacity self.size = 0 self.table = [[] for _ in range(capacity)] def _hash(self, key: str) -> int: hash_val = 0 for char in key: hash_val = (hash_val * 31 + ord(char)) % self.capacity return hash_val def insert(self, key: str, value: str) -> None: if self.size / self.capacity > 0.75: self._resize() index = self._hash(key) bucket = self.table[index] for entry in bucket: if entry.key == key and not entry.deleted: entry.value = value return bucket.append(HashTableEntry(key, value)) self.size += 1 def _resize(self) -> None: old_table = self.table self.capacity *= 2 self.table = [[] for _ in range(self.capacity)] self.size = 0 for bucket in old_table: for entry in bucket: if not entry.deleted: self.insert(entry.key, entry.value) def search(self, key: str): index = self._hash(key) bucket = self.table[index] for entry in bucket: if entry.key == key and not entry.deleted: return entry.value return None def delete(self, key: str) -> bool: index = self._hash(key) bucket = self.table[index] for entry in bucket: if entry.key == key and not entry.deleted: entry.deleted = True self.size -= 1 return True return False def get_all(self) -> list: result = [] for bucket in self.table: for entry in bucket: if not entry.deleted: result.append({'name': entry.key, 'phone': entry.value}) return result def clear(self) -> None: self.table = [[] for _ in range(self.capacity)] self.size = 0 def get_size(self) -> int: return self.size def is_empty(self) -> bool: return self.size == 0