from collections.abc import Callable from utils.literal import Literal from utils.memory_array import MemoryArray from utils.memory_cell import MemoryCell from utils.memory_range import mrange UNUSED_MARK = "UNUSED" DELETED_MARK = "DELETED" class HashTableOpenAddressing: def __init__(self, m: Literal, f: Callable[[MemoryCell, Literal, Literal], Literal]): if not isinstance(m, Literal): m = Literal(m) self.m = m self.f = f self.table = MemoryArray(m) for i in mrange(m): self.table[i].value = UNUSED_MARK def insert(self, x: MemoryCell): with MemoryCell(0) as i: while i < self.m: j = self.f(x, i, self.m) if self.is_free(j): self.table[j].set(x) return True i.set(i.succ()) return False def search(self, x: MemoryCell): with MemoryCell(0) as i: while i < self.m: j = self.f(x, i, self.m) if self.is_unused(j): return False if self.table[j] == x: return True i.set(i.succ()) return False def delete(self, x: MemoryCell): with MemoryCell(0) as i: while i < self.m: j = self.f(x, i, self.m) if self.is_unused(j): return False if self.table[j] == x: self.table[j].value = DELETED_MARK return True i.set(i.succ()) return False def __str__(self): return str(self.table) def alpha(self): with MemoryCell(0) as i: used = 0 while i < self.m: used += 0 if self.is_free(i) else 1 i.set(i.succ()) return used / int(self.m) def is_unused(self, i: Literal): if self.table[i].value == UNUSED_MARK: return True return False def is_deleted(self, i: Literal): if self.table[i].value == DELETED_MARK: return True return False def is_free(self, i: Literal): return self.is_unused(i) or self.is_deleted(i)