From 2dc15997744cdc2c71f85c179122d6108edd2d20 Mon Sep 17 00:00:00 2001 From: Arina Dohadailo Date: Fri, 30 Oct 2026 01:20:20 +0000 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20u7/hash=5Ftable.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- u7/hash_table.py | 104 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/u7/hash_table.py b/u7/hash_table.py index e69de29..853c97e 100644 --- a/u7/hash_table.py +++ b/u7/hash_table.py @@ -0,0 +1,104 @@ +class HashTable: + _DELETED = object() + def __init__(self, capacity=10): + if type(capacity) != int: + raise TypeError("Capacity must be an integer") + if capacity <= 0: + raise ValueError("Capacity must be positive") + self._capacity = capacity + self._table = [None] * capacity + self._size = 0 + @property + def capacity(self): + return self._capacity + def hash(self, key): + if type(key) != str: + raise TypeError + h = 0 + for char in key: + h = (31 * h + ord(char)) % self.capacity + return h + def probe(self, key): + if type(key) != str: + raise TypeError + start = self.hash(key) + deleted = None + for i in range(self.capacity): + index = (start + i) % self.capacity + item = self._table[index] + if item is None: + if deleted is not None: + return deleted + return index + if item is self._DELETED: + if deleted is None: + deleted = index + elif item[0] == key: + return index + if deleted is not None: + return deleted + raise RuntimeError + def __setitem__(self, key, value): + if type(key) != str: + raise TypeError + try: + index = self.probe(key) + 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 + except RuntimeError: + pass + if (self._size + 1) / self.capacity > 0.7: + old_table = self._table + self._capacity = 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: + index = self.probe(item[0]) + self._table[index] = item + self._size += 1 + index = self.probe(key) + self._table[index] = (key, value) + self._size += 1 + def __getitem__(self, key): + if type(key) != str: + raise TypeError + index = self.probe(key) + item = self._table[index] + if item is None or item is self._DELETED: + raise KeyError(key) + return item[1] + def __delitem__(self, key): + if type(key) != str: + raise TypeError + index = self.probe(key) + item = self._table[index] + if item is None or item is self._DELETED: + raise KeyError(key) + self._table[index] = self._DELETED + self._size -= 1 + def __contains__(self, key): + if type(key) != str: + raise TypeError + try: + index = self.probe(key) + item = self._table[index] + if item is not None and item is not self._DELETED: + if item[0] == key: + return True + return False + except RuntimeError: + return False + def __len__(self): + return self._size + def __iter__(self): + keys = [] + for item in self._table: + if item is not None and item is not self._DELETED: + keys.append(item[0]) + return iter(keys) + def load_factor(self): + return self._size / self.capacity