Aktualizovat u7/hash_table.py
This commit is contained in:
parent
375babbc41
commit
60f922f2ef
@ -2,10 +2,11 @@ class HashTable:
|
|||||||
_DELETED = object()
|
_DELETED = object()
|
||||||
|
|
||||||
def __init__(self, capacity=10):
|
def __init__(self, capacity=10):
|
||||||
|
"""Vytvor prázdnu tabuľku s kladnou celočíselnou kapacitou."""
|
||||||
if type(capacity) is not int:
|
if type(capacity) is not int:
|
||||||
raise TypeError("Capacity must be an integer")
|
raise TypeError("It's not integer")
|
||||||
if capacity <= 0:
|
if capacity <= 0:
|
||||||
raise ValueError("Capacity must be positive")
|
raise ValueError("Capacity > 0")
|
||||||
|
|
||||||
self._capacity = capacity
|
self._capacity = capacity
|
||||||
self._table = [None] * capacity
|
self._table = [None] * capacity
|
||||||
@ -13,29 +14,30 @@ class HashTable:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def capacity(self):
|
def capacity(self):
|
||||||
|
"""Vráť aktuálny počet pozícií v poli."""
|
||||||
return self._capacity
|
return self._capacity
|
||||||
|
|
||||||
def _validate_key(self, key):
|
def hash(self, key):
|
||||||
|
"""Vráť polynomiálny hash kľúča modulo aktuálna kapacita."""
|
||||||
if not isinstance(key, str):
|
if not isinstance(key, str):
|
||||||
raise TypeError("Key must be a string")
|
raise TypeError("Key must be a string")
|
||||||
|
|
||||||
def hash(self, key):
|
|
||||||
self._validate_key(key)
|
|
||||||
|
|
||||||
h = 0
|
h = 0
|
||||||
for char in key:
|
for znak in key:
|
||||||
h = (31 * h + ord(char)) % self.capacity
|
h = (31 * h + ord(znak)) % self.capacity
|
||||||
|
|
||||||
return h
|
return h
|
||||||
|
|
||||||
def probe(self, key):
|
def probe(self, key):
|
||||||
self._validate_key(key)
|
"""Vráť index kľúča alebo miesta na vloženie bez zmeny tabuľky."""
|
||||||
|
if not isinstance(key, str):
|
||||||
|
raise TypeError("Key must be a string")
|
||||||
|
|
||||||
start = self.hash(key)
|
start = self.hash(key)
|
||||||
first_deleted = None
|
first_deleted = None
|
||||||
|
|
||||||
for step in range(self.capacity):
|
for krok in range(self.capacity):
|
||||||
index = (start + step) % self.capacity
|
index = (start + krok) % self.capacity
|
||||||
item = self._table[index]
|
item = self._table[index]
|
||||||
|
|
||||||
if item is None:
|
if item is None:
|
||||||
@ -54,28 +56,13 @@ class HashTable:
|
|||||||
|
|
||||||
raise RuntimeError("Hash table is full")
|
raise RuntimeError("Hash table is full")
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
def load_factor(self):
|
||||||
self._validate_key(key)
|
"""Vráť podiel počtu aktívnych položiek a kapacity."""
|
||||||
|
return self._size / self.capacity
|
||||||
index = self.probe(key)
|
|
||||||
item = self._table[index]
|
|
||||||
|
|
||||||
# Existujúci kľúč: prepíš hodnotu.
|
|
||||||
if item is not None and item is not self._DELETED:
|
|
||||||
if item[0] == key:
|
|
||||||
self._table[index] = (key, value)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Nový kľúč: skontroluj zaplnenie.
|
|
||||||
if (self._size + 1) / self.capacity > 0.7:
|
|
||||||
self._resize(self.capacity * 2)
|
|
||||||
index = self.probe(key)
|
|
||||||
|
|
||||||
self._table[index] = (key, value)
|
|
||||||
self._size += 1
|
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
self._validate_key(key)
|
if not isinstance(key, str):
|
||||||
|
raise TypeError("Key must be a string")
|
||||||
|
|
||||||
index = self.probe(key)
|
index = self.probe(key)
|
||||||
item = self._table[index]
|
item = self._table[index]
|
||||||
@ -85,8 +72,30 @@ class HashTable:
|
|||||||
|
|
||||||
return item[1]
|
return item[1]
|
||||||
|
|
||||||
|
def __setitem__(self, key, value):
|
||||||
|
if not isinstance(key, str):
|
||||||
|
raise TypeError("Key must be a string")
|
||||||
|
|
||||||
|
index = self.probe(key)
|
||||||
|
item = self._table[index]
|
||||||
|
|
||||||
|
# Ak kľúč existuje, prepíš iba jeho hodnotu.
|
||||||
|
if item is not None and item is not self._DELETED:
|
||||||
|
if item[0] == key:
|
||||||
|
self._table[index] = (key, value)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Ak nový kľúč prekročí zaplnenie 0.7, zväčši tabuľku.
|
||||||
|
if (self._size + 1) / self.capacity > 0.7:
|
||||||
|
self._resize(self.capacity * 2)
|
||||||
|
index = self.probe(key)
|
||||||
|
|
||||||
|
self._table[index] = (key, value)
|
||||||
|
self._size += 1
|
||||||
|
|
||||||
def __delitem__(self, key):
|
def __delitem__(self, key):
|
||||||
self._validate_key(key)
|
if not isinstance(key, str):
|
||||||
|
raise TypeError("Key must be a string")
|
||||||
|
|
||||||
index = self.probe(key)
|
index = self.probe(key)
|
||||||
item = self._table[index]
|
item = self._table[index]
|
||||||
@ -98,9 +107,14 @@ class HashTable:
|
|||||||
self._size -= 1
|
self._size -= 1
|
||||||
|
|
||||||
def __contains__(self, key):
|
def __contains__(self, key):
|
||||||
self._validate_key(key)
|
if not isinstance(key, str):
|
||||||
|
raise TypeError("Key must be a string")
|
||||||
|
|
||||||
|
try:
|
||||||
|
index = self.probe(key)
|
||||||
|
except RuntimeError:
|
||||||
|
return False
|
||||||
|
|
||||||
index = self.probe(key)
|
|
||||||
item = self._table[index]
|
item = self._table[index]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -117,10 +131,8 @@ class HashTable:
|
|||||||
if item is not None and item is not self._DELETED:
|
if item is not None and item is not self._DELETED:
|
||||||
yield item[0]
|
yield item[0]
|
||||||
|
|
||||||
def load_factor(self):
|
|
||||||
return self._size / self.capacity
|
|
||||||
|
|
||||||
def _resize(self, new_capacity):
|
def _resize(self, new_capacity):
|
||||||
|
"""Zväčši tabuľku a vlož všetky aktívne položky nanovo."""
|
||||||
old_table = self._table
|
old_table = self._table
|
||||||
|
|
||||||
self._capacity = new_capacity
|
self._capacity = new_capacity
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user