import sys, os _root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) _l07 = os.path.join(_root, 'vorlesung', 'L07_hashtable') if _l07 not in sys.path: sys.path.insert(0, _l07) if _root not in sys.path: sys.path.insert(0, _root) from collections.abc import Callable from utils.algo_context import AlgoContext from utils.algo_int import Int class HashTableChaining: """Hashtabelle mit Verkettung (Chaining) zur Kollisionsauflösung.""" def __init__(self, m: int, h_func: Callable, ctx: AlgoContext): self.ctx = ctx self.m = Int(m, ctx) self.h = h_func self.table = [[] for _ in range(m)] self._n = 0 def _slot(self, x: Int) -> int: return int(self.h(x, self.m)) def insert(self, x: Int) -> bool: j = self._slot(x) for elem in self.table[j]: if elem == x: # Duplikat – Vergleich wird gezählt return False self.table[j].append(x) self._n += 1 return True def search(self, x: Int) -> bool: j = self._slot(x) for elem in self.table[j]: if elem == x: # Vergleich wird gezählt return True return False def delete(self, x: Int) -> bool: j = self._slot(x) for i, elem in enumerate(self.table[j]): if elem == x: # Vergleich wird gezählt self.table[j].pop(i) self._n -= 1 return True return False def __str__(self): rows = [] for i, chain in enumerate(self.table): vals = ' -> '.join(str(e.value) for e in chain) if chain else '—' rows.append(f'[{i:2d}] {vals}') return '\n'.join(rows) def alpha(self) -> float: return self._n / int(self.m)