u7
This commit is contained in:
parent
eba8134ee2
commit
c9dd473355
@ -0,0 +1,94 @@
|
||||
"""Hash tabuľka s lineárnym sondovaním a reťazcovými kľúčmi."""
|
||||
|
||||
_DELETED = object()
|
||||
|
||||
class HashTable:
|
||||
def __init__(self, capacity=10):
|
||||
if type(capacity) is not int:
|
||||
raise TypeError("Kapacita musí byť celé číslo.")
|
||||
if capacity <= 0:
|
||||
raise ValueError("Kapacita musí byť kladné číslo.")
|
||||
self._slots = [None] * capacity
|
||||
self._size = 0
|
||||
|
||||
pass
|
||||
|
||||
@property
|
||||
def capacity(self):
|
||||
return len(self._slots)
|
||||
|
||||
@staticmethod
|
||||
def _check_key(key):
|
||||
if not isinstance(key, str):
|
||||
raise TypeError("Klúč musí byť typu string.")
|
||||
|
||||
def _is_active(self, index, key):
|
||||
slot = self._slots[index]
|
||||
return slot is not None and slot is not _DELETED and slot[0] == key
|
||||
|
||||
def hash(self, key):
|
||||
self._check_key(key)
|
||||
h = 0
|
||||
for char in key:
|
||||
h = (31 * h + ord(char)) % self.capacity
|
||||
return h
|
||||
|
||||
def probe(self, key):
|
||||
"""Vráť index kľúča alebo miesta na vloženie bez zmeny tabuľky."""
|
||||
start = self.hash(key)
|
||||
first_deleted = None
|
||||
for step in range(self.capacity):
|
||||
index = (start + step) % self.capacity
|
||||
slot = self._slots[index]
|
||||
if slot is None:
|
||||
return first_deleted if first_deleted is not None else index
|
||||
if slot is _DELETED:
|
||||
if first_deleted is None:
|
||||
first_deleted = index
|
||||
elif slot[0] == key:
|
||||
return index
|
||||
if first_deleted is not None:
|
||||
return first_deleted
|
||||
raise RuntimeError("Tabuľka je plná.")
|
||||
|
||||
def _resize(self, new_capacity):
|
||||
old_slots = self._slots
|
||||
self._slots = [None] * new_capacity
|
||||
for slot in old_slots:
|
||||
if slot is not None and slot is not _DELETED:
|
||||
self._slots[self.probe(slot[0])] = slot
|
||||
|
||||
def __getitem__(self, key):
|
||||
index = self.probe(key)
|
||||
if not self._is_active(index, key):
|
||||
raise KeyError(key)
|
||||
return self._slots[index][1]
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
index = self.probe(key)
|
||||
if self._is_active(index, key):
|
||||
self._slots[index] = (key, value)
|
||||
return
|
||||
if (self._size + 1) / self.capacity > 0.7:
|
||||
self._resize(self.capacity * 2)
|
||||
index = self.probe(key)
|
||||
self._slots[index] = (key, value)
|
||||
self._size += 1
|
||||
|
||||
def __delitem__(self, key):
|
||||
index = self.probe(key)
|
||||
if not self._is_active(index, key):
|
||||
raise KeyError(key)
|
||||
self._slots[index] = _DELETED
|
||||
self._size -= 1
|
||||
|
||||
def __contains__(self, key):
|
||||
return self._is_active(self.probe(key), key)
|
||||
|
||||
def __len__(self):
|
||||
return self._size
|
||||
|
||||
def __iter__(self):
|
||||
for slot in self._slots:
|
||||
if slot is not None and slot is not _DELETED:
|
||||
yield slot[0]
|
||||
Loading…
Reference in New Issue
Block a user