Il dizionario è una struttura dati dinamica che prevede tre operazioni: inserimento di una coppia key-value, ricerca di una value in base alla key e cancellazione di una coppia key-value.
- Implementato con le hash table, il costo delle operazioni sarà , il caso migliore sarà e il caso medio è .
- Implementato con gli alberi di ricerca, il costo delle operazioni sarà , il caso migliore sarà , ma non è garantito che il caso medio sia .
Implementazione con albero di ricerca
Con gli alberi, si può fare in modo che i nodi siano al massimo a distanza dalla radice. Inoltre le chiavi dei nodi dell’albero di ricerca sono univoche ed è facile navigarci, quindi la ricerca di una valore da una chiave si può fare in .
Implementazione con hash table (indirizzamento aperto)
class Nodo:
def __init__(self, key, value = None, next = None):
self.key = key
self.value = value
self.next = next
class LinkedList:
def __init__(self):
self.testa = None
def get_nodo_da_chiave(self, key) -> Nodo:
try:
nodo = self.testa
while nodo is not None:
if nodo.key == key:
return nodo
nodo = nodo.next
except AttributeError:
raise KeyError(f'la chiave {key} non è presente')
def inserisci_pair(self, key, value=None) -> None:
if not self.get_nodo_da_chiave(key):
self.testa = Nodo(key, value, self.testa)
def rimuovi_pair(self, key) -> None:
if self.testa == None:
raise KeyError(f'la chiave {key} non è presente')
if self.testa.key == key:
self.testa = self.testa.next
return self.testa
nodo = self.testa
while nodo.next is not None:
if nodo.next.key == key:
nodo.next = nodo.next.next
return self.testa
nodo = nodo.next
raise KeyError(f'la chiave {key} non è presente')
class DizionarioHashAperto:
def __init__(self, HASH_POSITIONS=100):
self.HASH_POSITIONS = HASH_POSITIONS
self.positions = [
LinkedList() for _ in range(self.HASH_POSITIONS)
]
def _my_hash(self, value) -> int:
try:
if type(value) is str:
value = sum(ord(char) for char in value)
return value % self.HASH_POSITIONS
except TypeError:
raise ValueError(f'il tipo {type(value).__name__} non è hashable dalla funzione my_hash')
def __contains__(self, key: int) -> bool:
nodo = self.positions[self._my_hash(key)].get_nodo_da_chiave(key)
return bool(nodo)
def __getitem__(self, key) -> int:
return self.positions[self._my_hash(key)].get_nodo_da_chiave(key).value
def __setitem__(self, key, value):
self.rimuovi(key)
self.inserisci(key, value)
def inserisci(self, key, value=None) -> None:
self.positions[self._my_hash(key)].inserisci_pair(key, value)
def rimuovi(self, key: int) -> None:
self.positions[self._my_hash(key)].rimuovi_pair(key)