Notatii:
tipElement - tipul elementelor tabelei
tipCheie - tipul cheii
t - tabela
e - valoare a lui tipElement
k - valoare a lui tipCheie
b - valoare booleana
contor - valoare intreaga
Operatori:
CreazaTabelaVida(t)
- procedura care face pe t vid
TabelaVida(t) -> b
- functie booleana care returneaza "true" daca tabela e goala
TabelaPlina(t) -> b
- functie booleana care returneaza "true" daca tabela e plina
CheieElemTabela(e) -> k
- functie ce returneaza cheia elementului e
CheieGasita(t,k) -> b
- functie ce returneaza "true" daca cheia k se gaseste in t
InserElemTabela(t,e)
- procedura care insereaza pe e in t, presupunind ca acesta nu exista
SuprimaElemTabela(t,k)
- procedura ce suprima din tabela t elementul cu cheia k, presupunind
ca acest element exista
FurnizeazaElemTabela(t,k) -> e
- functie care returneaza elementul cu cheia k, presupunind ca
elementul exista
TraverseazaTabela(t,Vizitare(ListaArgumente)
- procedura ce executa procedura Vizitare pentru fiecare element al
tabelei t
DimensTabela(t) -> contor
- functie ce returneaza numarul de elemente din tabela; se poate
actualiza o variabila contor la fiecare insertie si suprimare
Actualizare(t,e)
- procedura ce actualizeaza intrarea din tabela ce contine elementul
e; se poate scrie prin apelul operatorilor anterior definiti :
SuprimaElemTabela(t,CheieElemTabela(e)) si InserElemTabela(t,e)
Ca un dezavantaj apare si faptul ca pentru rezervarea spatiului de memorie statica al tabloului, trebuie evaluat numarul de insertii ce se vor face.
Implementarea este avantajoasa cind se realizeaza traversari frecvente in ordinea cheilor si cind nu se cunoaste numarul maxim de elemente.
Se defineste o functie de asociere H, care e de fapt o functie de
dispersie:
H : tipCheie -> 0_p-1,
ce asociaza fiecarei chei cite un indice de tablou.
Prin metoda dispersiei, care se mai numeste si "transformarea cheilor" sau "hashing" ( amestecare ), pentru inregistrarea unui element cu cheia k, se determina indicele l=H(k), apoi se depune elementul la intarea l. Pentru o alta cheie k_prim, avind acelasi indice asociat l=H(k)=H(k_prim), se ajunge la "situatia de coliziune", care se poate rezolva prin mai multe metode.
Pentru cautarea unei chei k, se verifica daca elementul de la intrarea H(k) are cheia cautata, in caz negativ, s-a ajuns la coliziune.
Pentru aplicarea tehnicii dispersiei, care duce la performante foarte bune,
trebuie solutionate doua probleme:
- definirea functiei de dispersie H
- rezolvarea situatiilor de coliziune.
Foarte des se foloseste functia: H(k)=ord(k) mod p, unde ord(k) precizeaza numarul de ordine al cheii k in multimea tuturor cheilor.
In cazul cheilor siruri de caractere se pot folosi functiile:
H(k)=( suma(i=1,length(k)) 2^i * ord(k[i]) ) mod p, sau
H(k)=( suma(i=1,length(k)) ord(k[i]) ) mod p.
Se demonstreaza ca pentru repartitia cit mai uniforma a cheilor, dimensiu- nea p a tabloului trebuie sa fie numar prim. Daca p e o putere a lui 2, calculul indicelui l s-ar face mai rapid, dar posibilitatea de aparitie a coliziunilor ar fi mult mai mare.
l:=H(k); nr_incercari:=0;
repeat
if t[l].cheie=k then
{element gasit}
else
if t[l].cheie=liber then
{elementul nu e in tablou, se introduce}
else
begin {tratarea coliziunii}
inc(nr_incercari);
l:=H(k)+g(nr_incercari)
end
until *gasit or *s-a introdus or *tabela e plina;
O varianta pentru functia g(nr_incercari) este cea care duce la testarea
indicilor consecutivi din tablou, acesta fiind exploatat circular, deci
indicele testat la pasul nr_incercari este: Dezavantajul acestei adresari liniare este ca are tendinta de a ingramadi nodurile in continuarea celor existente, coliziunile aparind mai des.
Adresarea patratica cu indicele la pasul nr_incercari:
l=(H(k)+nr_incercari^2) mod p,
elimina dezavantajul anterior, dar conduce la probabilitatea ( mica ) de a nu
se putea gasi nici o intrare libere, desi tabele nu e plina.
Formula ilustreaza performantele foarte bune ale metodei dispersiei, de exemplu 2.56 incercari la un factor de umplere de 0.9.
Daca rezolvarea coliziunilor se face prin adresare directa, formula devine:
E=(1-f/2)/(1-f),
pastrind inca performante bune, de exemplu 5.5 incercari la un factor de
umplere de 0.9.
In ciuda performantelor bune, metoda dispersiei are dezavantajele:
- dimensiunea tabloului trebuie estimata anterior, lucru ce nu e posibil
intotdeauna ( caz in care se folosesc liste sau arbori ), ajungindu-se fie la
risipa, fie la depasirea memoriei alocate; in plus, pentru performante bune,
alocarea initiala trebuie facuta cu 10% mai mult decit e necesar;
- suprimarea cheilor este dificila, mai putin in cazul inlantuirii directe.