59 lines
1.8 KiB
Python
59 lines
1.8 KiB
Python
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)
|