Add u7/hash_table.py
This commit is contained in:
parent
7df331772b
commit
8a0ad1092a
127
u7/hash_table.py
Normal file
127
u7/hash_table.py
Normal file
@ -0,0 +1,127 @@
|
||||
class HashTable:
|
||||
def __init__(self, capacity=10):
|
||||
if type(capacity) is not int or isinstance(capacity, bool):
|
||||
raise TypeError("Kapacita musí byť celé číslo.")
|
||||
if capacity <= 0:
|
||||
raise ValueError("Kapacita musí byť kladné celé číslo.")
|
||||
|
||||
self._capacity = capacity
|
||||
self.empty = object()
|
||||
self.deleted = object()
|
||||
self.slots = [self.empty] * capacity
|
||||
self.count = 0
|
||||
|
||||
@property
|
||||
def capacity(self):
|
||||
return self._capacity
|
||||
|
||||
def hash(self, key):
|
||||
if not isinstance(key, str):
|
||||
raise TypeError("Kľúč musí byť reťazec.")
|
||||
h = 0
|
||||
for znak in key:
|
||||
h = (31 * h + ord(znak)) % self._capacity
|
||||
return h
|
||||
|
||||
def probe(self, key):
|
||||
if not isinstance(key, str):
|
||||
raise TypeError("Kľúč musí byť reťazec.")
|
||||
|
||||
start_idx = self.hash(key)
|
||||
first_deleted = None
|
||||
|
||||
for krok in range(self._capacity):
|
||||
idx = (start_idx + krok) % self._capacity
|
||||
slot = self.slots[idx]
|
||||
|
||||
if slot is self.empty:
|
||||
return first_deleted if first_deleted is not None else idx
|
||||
elif slot is self.deleted:
|
||||
if first_deleted is None:
|
||||
first_deleted = idx
|
||||
elif slot[0] == key:
|
||||
return idx
|
||||
|
||||
if first_deleted is not None:
|
||||
return first_deleted
|
||||
raise RuntimeError("Tabuľka je plná a nemá žiadne voľné ani vymazané miesto.")
|
||||
|
||||
def load_factor(self):
|
||||
return self.count / self._capacity
|
||||
|
||||
def __getitem__(self, key):
|
||||
if not isinstance(key, str):
|
||||
raise TypeError("Kľúč musí byť reťazec.")
|
||||
idx = self.probe(key)
|
||||
slot = self.slots[idx]
|
||||
if slot is not self.empty and slot is not self.deleted and slot[0] == key:
|
||||
return slot[1]
|
||||
raise KeyError(key)
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
if not isinstance(key, str):
|
||||
raise TypeError("Kľúč musí byť reťazec.")
|
||||
|
||||
start_idx = self.hash(key)
|
||||
existing_idx = None
|
||||
for krok in range(self._capacity):
|
||||
idx = (start_idx + krok) % self._capacity
|
||||
slot = self.slots[idx]
|
||||
if slot is self.empty:
|
||||
break
|
||||
if slot is not self.deleted and slot[0] == key:
|
||||
existing_idx = idx
|
||||
break
|
||||
|
||||
if existing_idx is not None:
|
||||
self.slots[existing_idx] = (key, value)
|
||||
return
|
||||
|
||||
if (self.count + 1) / self._capacity > 0.7:
|
||||
self._resize(self._capacity * 2)
|
||||
|
||||
idx = self.probe(key)
|
||||
self.slots[idx] = (key, value)
|
||||
self.count += 1
|
||||
|
||||
def _resize(self, new_capacity):
|
||||
old_slots = self.slots
|
||||
self._capacity = new_capacity
|
||||
self.slots = [self.empty] * new_capacity
|
||||
self.count = 0
|
||||
|
||||
for slot in old_slots:
|
||||
if slot is not self.empty and slot is not self.deleted:
|
||||
k, v = slot
|
||||
idx = self.probe(k)
|
||||
self.slots[idx] = (k, v)
|
||||
self.count += 1
|
||||
|
||||
def __delitem__(self, key):
|
||||
if not isinstance(key, str):
|
||||
raise TypeError("Kľúč musí byť reťazec.")
|
||||
idx = self.probe(key)
|
||||
slot = self.slots[idx]
|
||||
if slot is not self.empty and slot is not self.deleted and slot[0] == key:
|
||||
self.slots[idx] = self.deleted
|
||||
self.count -= 1
|
||||
return
|
||||
raise KeyError(key)
|
||||
|
||||
def __contains__(self, key):
|
||||
if not isinstance(key, str):
|
||||
raise TypeError("Kľúč musí byť reťazec.")
|
||||
try:
|
||||
idx = self.probe(key)
|
||||
except RuntimeError:
|
||||
return False
|
||||
slot = self.slots[idx]
|
||||
return slot is not self.empty and slot is not self.deleted and slot[0] == key
|
||||
|
||||
def __len__(self):
|
||||
return self.count
|
||||
|
||||
def __iter__(self):
|
||||
for slot in self.slots:
|
||||
if slot is not self.empty and slot is not self.deleted:
|
||||
yield slot[0]
|
||||
Loading…
Reference in New Issue
Block a user