A taula hash és una estructura de dades que permet la inserció, la supressió i la recuperació ràpides de dades. Funciona utilitzant una funció hash per assignar una clau a un índex d'una matriu. En aquest article, implementarem una taula hash a Python mitjançant un encadenament separat per gestionar les col·lisions.

Components del hashing
L'encadenament separat és una tècnica utilitzada per gestionar col·lisions en una taula hash. Quan dues o més claus es mapegen al mateix índex de la matriu, les emmagatzemem en una llista enllaçada a aquest índex. Això ens permet emmagatzemar diversos valors al mateix índex i encara poder recuperar-los amb la seva clau.

Manera d'implementar la taula hash mitjançant l'encadenament separat
Manera d'implementar la taula hash mitjançant l'encadenament separat:
Crea dues classes: ‘ Node 'i' HashTable ‘.
El ' Node 'class representarà un node en una llista enllaçada. Cada node contindrà un parell clau-valor, així com un punter al següent node de la llista.
Python 3
canviar el nom d'un directori linux
class> Node:> >def> __init__(>self>, key, value):> >self>.key>=> key> >self>.value>=> value> >self>.>next> => None> |
>
>
La classe 'HashTable' contindrà la matriu que conté les llistes enllaçades, així com mètodes per inserir, recuperar i eliminar dades de la taula hash.
Python 3
class> HashTable:> >def> __init__(>self>, capacity):> >self>.capacity>=> capacity> >self>.size>=> 0> >self>.table>=> [>None>]>*> capacity> |
>
>
El ' __calent__ El mètode ' inicialitza la taula hash amb una capacitat determinada. Estableix el ' capacitat 'i' mida ' variables i inicialitza la matriu a 'Cap'.
El següent mètode és el _haix ‘mètode. Aquest mètode pren una clau i retorna un índex a la matriu on s'ha d'emmagatzemar la parella clau-valor. Utilitzarem la funció hash integrada de Python per hash la clau i després utilitzarem l'operador mòdul per obtenir un índex a la matriu.
Python 3
def> _hash(>self>, key):> >return> hash>(key)>%> self>.capacity> |
>
>
El 'inserir' El mètode inserirà un parell clau-valor a la taula hash. Pren l'índex on s'ha d'emmagatzemar la parella utilitzant el ' _haix ‘mètode. Si no hi ha cap llista enllaçada en aquest índex, es crea un nou node amb el parell clau-valor i el defineix com a cap de llista. Si hi ha una llista enllaçada en aquest índex, itereu per la llista fins que es trobi l'últim node o la clau ja existeix i actualitzeu el valor si la clau ja existeix. Si troba la clau, actualitza el valor. Si no troba la clau, crea un nou node i l'afegeix a la capçalera de la llista.
Python 3
def> insert(>self>, key, value):> >index>=> self>._hash(key)> >if> self>.table[index]>is> None>:> >self>.table[index]>=> Node(key, value)> >self>.size>+>=> 1> >else>:> >current>=> self>.table[index]> >while> current:> >if> current.key>=>=> key:> >current.value>=> value> >return> >current>=> current.>next> >new_node>=> Node(key, value)> >new_node.>next> => self>.table[index]> >self>.table[index]>=> new_node> >self>.size>+>=> 1> |
javascript onclick
>
>
El cerca El mètode recupera el valor associat a una clau determinada. Primer obté l'índex on s'ha d'emmagatzemar el parell clau-valor mitjançant l' _haix mètode. A continuació, cerca la clau a la llista enllaçada en aquest índex. Si troba la clau, retorna el valor associat. Si no troba la clau, planteja a KeyError .
Python 3
def> search(>self>, key):> >index>=> self>._hash(key)> >current>=> self>.table[index]> >while> current:> >if> current.key>=>=> key:> >return> current.value> >current>=> current.>next> >raise> KeyError(key)> |
>
>
El 'eliminar' El mètode elimina un parell clau-valor de la taula hash. Primer obté l'índex on s'ha d'emmagatzemar la parella utilitzant el ` _haix ` mètode. A continuació, cerca la clau a la llista enllaçada en aquest índex. Si troba la clau, elimina el node de la llista. Si no troba la clau, aixeca un ` KeyError `.
Python 3
java per tipus de bucle
def> remove(>self>, key):> >index>=> self>._hash(key)> > >previous>=> None> >current>=> self>.table[index]> > >while> current:> >if> current.key>=>=> key:> >if> previous:> >previous.>next> => current.>next> >else>:> >self>.table[index]>=> current.>next> >self>.size>->=> 1> >return> >previous>=> current> >current>=> current.>next> > >raise> KeyError(key)> |
>
>
'__str__' mètode que retorna una representació de cadena de la taula hash.
Python 3
mylivecricket.in
def> __str__(>self>):> >elements>=> []> >for> i>in> range>(>self>.capacity):> >current>=> self>.table[i]> >while> current:> >elements.append((current.key, current.value))> >current>=> current.>next> >return> str>(elements)> |
>
>
Aquí teniu la implementació completa de la classe 'HashTable':
Python 3
class> Node:> >def> __init__(>self>, key, value):> >self>.key>=> key> >self>.value>=> value> >self>.>next> => None> > > class> HashTable:> >def> __init__(>self>, capacity):> >self>.capacity>=> capacity> >self>.size>=> 0> >self>.table>=> [>None>]>*> capacity> > >def> _hash(>self>, key):> >return> hash>(key)>%> self>.capacity> > >def> insert(>self>, key, value):> >index>=> self>._hash(key)> > >if> self>.table[index]>is> None>:> >self>.table[index]>=> Node(key, value)> >self>.size>+>=> 1> >else>:> >current>=> self>.table[index]> >while> current:> >if> current.key>=>=> key:> >current.value>=> value> >return> >current>=> current.>next> >new_node>=> Node(key, value)> >new_node.>next> => self>.table[index]> >self>.table[index]>=> new_node> >self>.size>+>=> 1> > >def> search(>self>, key):> >index>=> self>._hash(key)> > >current>=> self>.table[index]> >while> current:> >if> current.key>=>=> key:> >return> current.value> >current>=> current.>next> > >raise> KeyError(key)> > >def> remove(>self>, key):> >index>=> self>._hash(key)> > >previous>=> None> >current>=> self>.table[index]> > >while> current:> >if> current.key>=>=> key:> >if> previous:> >previous.>next> => current.>next> >else>:> >self>.table[index]>=> current.>next> >self>.size>->=> 1> >return> >previous>=> current> >current>=> current.>next> > >raise> KeyError(key)> > >def> __len__(>self>):> >return> self>.size> > >def> __contains__(>self>, key):> >try>:> >self>.search(key)> >return> True> >except> KeyError:> >return> False> > > # Driver code> if> __name__>=>=> '__main__'>:> > ># Create a hash table with> ># a capacity of 5> >ht>=> HashTable(>5>)> > ># Add some key-value pairs> ># to the hash table> >ht.insert(>'apple'>,>3>)> >ht.insert(>'banana'>,>2>)> >ht.insert(>'cherry'>,>5>)> > ># Check if the hash table> ># contains a key> >print>(>'apple'> in> ht)># True> >print>(>'durian'> in> ht)># False> > ># Get the value for a key> >print>(ht.search(>'banana'>))># 2> > ># Update the value for a key> >ht.insert(>'banana'>,>4>)> >print>(ht.search(>'banana'>))># 4> > >ht.remove(>'apple'>)> ># Check the size of the hash table> >print>(>len>(ht))># 3> |
>
>Sortida
True False 2 4 3>
Complexitat temporal i complexitat espacial:
- El complexitat temporal del inserir , cerca i eliminar Els mètodes en una taula hash que utilitzen un encadenament separat depèn de la mida de la taula hash, el nombre de parells clau-valor a la taula hash i la longitud de la llista enllaçada a cada índex.
- Suposant una bona funció hash i una distribució uniforme de claus, la complexitat temporal esperada d'aquests mètodes és O(1) per a cada operació. Tanmateix, en el pitjor dels casos, la complexitat del temps pot ser O(n) , on n és el nombre de parells clau-valor a la taula hash.
- Tanmateix, és important escollir una bona funció hash i una mida adequada per a la taula hash per minimitzar la probabilitat de col·lisions i garantir un bon rendiment.
- El complexitat espacial d'una taula hash utilitzant un encadenat separat depèn de la mida de la taula hash i del nombre de parells clau-valor emmagatzemats a la taula hash.
- La pròpia taula hash pren O(m) espai, on m és la capacitat de la taula hash. Cada node de llista enllaçada pren O(1) espai, i pot haver-hi com a màxim n nodes a les llistes enllaçades, on n és el nombre de parells clau-valor emmagatzemats a la taula hash.
- Per tant, la complexitat espacial total és O(m + n) .
Conclusió:
A la pràctica, és important triar una capacitat adequada per a la taula hash per equilibrar l'ús d'espai i la probabilitat de col·lisions. Si la capacitat és massa petita, augmenta la probabilitat de col·lisions, cosa que pot provocar una degradació del rendiment. D'altra banda, si la capacitat és massa gran, la taula hash pot consumir més memòria de la necessària.