Sunteți pe pagina 1din 7

-- Tabele de dispersie .

1 --

E.Kalisz - Structuri de date

Cautri dup cheie


Mulimi de elemente n care se efectueaz cutri
frecvente cu "cheie ir de caractere:
 dicionar
 agend telefonic
 index de strzi / localiti
Pentru flexibilitate i eficiena operaiilor de
inserare i eliminare se poate utiliza o list.
Pentru eficiena operaiilor de cutare nu este
indicat utilizarea unei singure liste.
Soluia clasic
Solu
clasic
: utilizarea unui vector de liste,
liste n
care elementele sunt grupate dup iniiala cheii.

-- Tabele de dispersie .2 --

E.Kalisz - Structuri de date

Chei grupate dup iniial


'a'

....
.
.
.

'i'

....

'j'
.
.
.
.

'z'

-- Tabele de dispersie .3 --

E.Kalisz - Structuri de date

Tabele de dispersie
Problem: durata cutrii este dependent
de lungimea listei n care se caut, iar n
majoritatea cazurilor lungimile listelor sunt foarte
diferite unele liste pot fi foarte lungi, n timp ce
altele pot fi vide.
Soluie: utilizarea unei funcii de dispersie
(hash function).
Funcia de dispersie genereaz, pentru orice
ir de caractere, un cod de dispersie dintr-un
domeniu fixat [0,M-1].

E.Kalisz - Structuri de date

-- Tabele de dispersie .4 --

Functie de dispersie - exemplu


int CodDispersie(void *a,...)
/* apel cu (NULL,M) -> fixeaza valoarea M
apel cu (adrSir) -> sumaCoduriLitere % M */
{ static size_t M = 256;
unsigned long suma;
va_list ap;
char* x = (char*)a;
if (a) /* apel uzual -> calcul cod */
{ for (suma = 0; *x != '\0'; x++)
suma += *x;
return (suma % M); /* intoarce cod dispersie */
}
/* apel de initializare -> preia valoare M */
va_start(ap, a);
M = va_arg(ap, size_t);
va_end(ap);
return 0;
}

-- Tabele de dispersie .5 --

E.Kalisz - Structuri de date

Tabele de dispersie
Caz extrem:
M este chiar numrul de total de elemente.
In acest caz funcia de dispersie genereaz un cod
distinct pentru fiecare element. Intr-un astfel de caz
elementele pot fi memorate direct ntr-un vector numit
tabela de dispersie cu adresare direct, indicele unui
element fiind reprezentat de codul de dispersie
corespunztor.
[0]

[k]
........

[M -1]
.....................

-- Tabele de dispersie .6 --

E.Kalisz - Structuri de date

Tabele de dispersie
In cazul general numrul de
[0]
valori distincte ale codului de
dispersie este mult mai mic dect
numrul total de elemente.
In acest caz ntre dou elemente
[k]
cu acelai cod de dispersie k se
produce o coliziune.
Cea mai simpl metod de
rezolvare a coliziunilor const n
combinarea celor dou variante
[M-1]
prezentate anterior.

...
.
.
.

...
.
.
.
.
.
.

...

-- Tabele de dispersie .7 --

E.Kalisz - Structuri de date

Tabele de dispersie
Elementele tabelei de dispersie sunt adrese de liste, n
fiecare list fiind memorate adresele elementelor cu
acelai cod de dispersie k [0,M-1].
Pentru eficiena cutrii oricruia dintre cele N
elemente este de dorit ca lungimile celor M liste s fie
ct mai apropiate de valoarea N/M = factor de ncrcare
(load factor) al tabelei de dispersie.
[0 ]

. . .
.
.
.

[k ]

. . .
.
.

-- Tabele de dispersie .8 --

E.Kalisz - Structuri de date

Tabele de dispersie operaii specifice


Iniializare:
 parametri:
- dimensiunea tabelei (M)
- funcia de dispersie (fd)
- alte elemente, specifice
implementrii

 efect: aloc i iniializeaz spaiul


de memorie pentru descriptorul tabelei
i vectorul adreselor de liste

M
fd

functie de
disp ersie

v
.
.
.
.

[0]
.
.
.

[M-1]

 rezultat: adresa descriptor sau NULL


Prototip:
TabDisp* IniTD(size_t M, TF1 fd,...);

E.Kalisz - Structuri de date

-- Tabele de dispersie .9 --

Tabele de dispersie operaii specifice


Inserare:
 parametri:
- adres tabel
- adres element
 efect: calculeaz codul de dispersie i actualizeaz
lista corespunztoare, dac elementul nu exist deja
 rezultat:
1 dac inserarea a reuit
0 dac elementul exist deja
-1 dac nu exist spaiu pentru o nou celul de list
Prototip:
int InsTD(TabDisp* a, void* e);

E.Kalisz - Structuri de date

-- Tabele de dispersie .10 --

Tabele de dispersie operaii specifice


Precondiie inserare: utilizatorul a alocat i completat
corect spaiul ocupat de element.
Observaii:
- noua celul poate fi inserat n list la nceput, la sfrit
sau pe baza unei relaii de ordine, n funcie de varianta
de implementare aleas; n ultima variant adresa
funciei care verific relaia de ordine trebuie memorat
n descriptorul tabelei.
- dac pentru verificarea identitii a doua elemente se
utilizeaz o funcie special, atunci adresa sa trebuie
memorat n descriptorul tabelei; de obicei aceast
funcie se refer strict la irul cheie

-- Tabele de dispersie .11 --

E.Kalisz - Structuri de date

Tabele de dispersie operaii specifice


Cutare:
a
 parametri:
- adresa tabelei
- adresa elementului

M
fd

functie de
dispersie

[0]
....
ft
 efect: calculeaz codul
.
.
.
de dispersie k i caut
.
.
.
elementul n lista [k]
[k]
...
. .
(utiliznd funcia de test
.
.
functie test
din descriptor sau o
relatie elem
element cautat
funcie parametru)
 rezultat: adres element / NULL
Prototipuri posibile:
void* ExistaTD(TabDisp* a, void* e);
void* CautaTD(TabDisp* a, void* e, TF2 f);

E.Kalisz - Structuri de date

-- Tabele de dispersie .12 --

Tabele de dispersie operaii specifice


Afiare continut:
 parametri:
- adresa tabelei
- funcia de afiare a unui element
 algoritm:
pentru fiecare valoare a codului de dispersie
daca exista lista atunci
{ afiseaza codul
parcurge lista, afisand fiecare element
}

Prototip:
void AfiTD(TabDisp* a, TF1 afiEl);

-- Tabele de dispersie .13 --

E.Kalisz - Structuri de date

Tabele de dispersie operaii specifice


Extragere element:
 parametri: adresa tabelei i adresa elementului
 efect: calculeaz codul de dispersie k i actualizeaz
lista [k], dac elementul este gsit (spaiul ocupat de
element nu este afectat, eventuala eliberare a acestuia
fiind responsabilitatea utilizatorului)
 rezultat: adresa element / NULL
Prototip: void* ExtrTD(TabDisp* a, void*e);
....

.
.

...

[k]

....

.
.

element cautat
rezultat

-- Tabele de dispersie .14 --

E.Kalisz - Structuri de date

Tabele de dispersie operaii specifice


a

Eliberare spaiu ocupat:


 parametri:
- adresa tabelei
- adresa funciei de eliberare
a spaiului ocupat de un
element
 efect: elibereaz mai nti tot
spaiul ocupat de liste i apoi
spaiul alocat la iniializare

fd

functie de
dispersie

v
.
.
.
.

[0]

..
.
.
.

[M-1]

..

DistrTD(&a,ElibElem);

Prototip:
void DistrTD(TabDisp**aa, TF1 fe);

S-ar putea să vă placă și