Sunteți pe pagina 1din 24

--5.

1 --
Cautari dupa cheie
Multimi de elemente in care se efectueaza cautari
frecvente cu "cheie" sir de caractere:
dictionar
agenda telefonica
index de strazi / localitati
Pentru flexibilitate si eficienta operatiilor de
inserare si eliminare se poate utiliza o lista.
Pentru eficienta operatiilor de cautare nu este
indicata utilizarea unei singure liste.
Solutia clasica: utilizarea unui vector de liste, in
care elementele sunt grupate dupa initiala cheii.
--5.2 --
Chei grupate dupa initiala
' j '
' i '
' z'
' a' . . . .
.
.
.
.
.
.
.
. . . .
--5.3 --
Tabele de dispersie
Problema: durata cautarii este dependenta
de lungimea listei in care se cauta, iar in
majoritatea cazurilor lungimile listelor sunt foarte
diferite unele liste pot fi foarte lungi, in timp ce
altele pot fi vide.
Solutie: utilizarea unei functii de dispersie
(hash function).
Functia de dispersie genereaza, pentru orice
sir de caractere, un cod de dispersie dintr-un
domeniu fixat [0,M-1].
--5.4 --
Functie de dispersie
U multimea cheilor posibile
K multimea cheilor stocate
|K| << |U|.
Functia Hash h:
h : U {0,1,, M1}
--5.5 --
Functie de dispersie
0
M1
h(k
1
)
h(k
4
)
h(k
2
)
h(k
3
)
U
K
k
1
k
2
k
3
k
4
--5.6 --
Functie de dispersie - exemplu
/* M numarul de intrari din tabela de dispersie */
int CodDispersie(void *a)
/* intoarce -> sumaCoduriLitere % M */
{
unsigned long suma;
char* x = (char*)a;
for (suma = 0; *x != '\0'; x++)
suma += *x;
return (suma % M);
}
--5.7 --
Tabele de dispersie
Caz extrem:
Meste chiar numarul de total de elemente.
In acest caz functia de dispersie genereaza un cod
distinct pentru fiecare element. Intr-un astfel de caz
elementele pot fi memorate direct intr-un vector numit
tabela de dispersie cu adresare directa, indicele unui
element fiind reprezentat de codul de dispersie
corespunzator.
[ 0] [ k] [ M-1]
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
--5.8 --
Tabele de dispersie
In cazul general numarul de valori distincte ale
codului de dispersie este mult mai mic decat numarul
total de elemente.
In acest caz intre doua elemente cu acelasi cod de
dispersie k se produce o coliziune.
--5.9 --
Functie de dispersie - coliziuni
0
M1
h(k
1
)=h(k
4
)
h(k
2
)=h(k
5
)=h(k
6
)
h(k
3
)=h(k
7
)
U
K
k
1
k
2
k
3
k
5
k
4
k
6
k
7
k
8
h(k
8
)
X
X
X
--5.10 --
Functie de dispersie rezolvarea coliziunilor
k
2
0
M1
U
K
k
1
k
2
k
3
k
5
k
4
k
6
k
7
k
8
k
1
k
4
k
5
k
6
k
7
k
3
k
8
Adresare prin inlantuire
--5.11 --
Tabele de dispersie

[ M-1]
[ 0]


.
.
.


M

f d

v
a
f unct i e de
di sper si e
t ypedef st r uct cel ul a
{
st r uct cel ul a* ur m;
voi d* i nf o;
}TCel ul aG, *TLG, **ALG;
t ypedef i nt ( *TFHash) ( voi d*) ;
t ypedef st r uct
{
si ze_t M;
TFHash f d;
TLG* v;
}TD;
--5.12 --
Tabele de dispersie
Initializare:
TD* IniTD(size_t M, TFHash fd);
parametri:
- dimensiunea tabelei (M)
- functia de dispersie (fd)
-efect: aloca si initializeaza spatiul de
memorie pentru descriptorul tabelei si
vectorul adreselor de liste
rezultat: adresa descriptor sau NULL

[ M-1]
[ 0]


.
.
.


M

f d

v
a
f unct i e de
di sper si e
--5.13 --
Tabele de dispersie
Initializare:
TD* IniTD(size_t M, TFHash fd)
{
TD* at d = ( TD*) mal l oc( si zeof ( TD) ) ;
i f ( ! at d) r et ur n NULL;
adt - >v = ( TLG*) cal l oc( M, si zeof ( TLG) ) ;
i f ( ! at d- >v)
{f r ee( at d) ; r et ur n NULL; }
at d- >M = M;
at d- >f d = f d;
r et ur n at d;
}

[ M-1]
[ 0]


.
.
.


M

f d

v
a
f unct i e de
di sper si e
--5.14 --
Tabele de dispersie operatii specifice
Cautare:
void* ExistaTD(TD* a, void* ae, TFCmp f);
parametri:
- adresa tabela
- adresa element
efect: calculeaza codul
de dispersie k si cauta
elementul in lista [k]
(utilizand o functie parametru)
rezultat: adresa element / NULL

element cautat
. . . [ k]
[ 0]


.
.
.




.
.
M

f d

v
a
. . . .
. .
f unct i e de
di sper si e
--5.15 --
Tabele de dispersie operatii specifice
Cautare:
void* ExistaTD(TD* a, void* ae, TFCmp f)
{
i nt cod = a- >f d( ae) ;
TLG p;
i nt r ez;
f or ( p = a- >v[ cod] ; p ! = NULL; p = p- >ur m)
{
r ez = f ( ae, p- >i nf o) ;
i f ( r ez == 0) r et ur n p- >i nf o;
i f ( r ez < 0) br eak;
}
r et ur n NULL;
}
--5.16 --
Tabele de dispersie operatii specifice
Inserare:
int InsTD(TD* a, void* ae, size_t d, TFCmp f)
parametri:
- adresa tabela
- adresa element
- dimensiune element
- functie de test
efect: calculeaza codul de dispersie si actualizeaza lista
corespunzatoare, daca elementul nu exista deja
rezultat:
1 daca inserarea a reusit
0 daca elementul exista deja
-1 daca nu exista spatiu pentru o noua celula de lista
--5.17 --
Tabele de dispersie operatii specifice
Inserare:
i nt ( *TFCmp) ( voi d*, voi d*) ;
int InsTD(TD* a, void* ae, size_t d, TFCmp f)
{
i nt cod = a- >f d( ae) ;
TLG aux, *aL;
i nt r ez;
f or ( aL = a- >v+cod; *aL ! = NULL; aL = &( *aL) - >ur m)
{
r ez = f ( ae, ( *aL) - >i nf o) ;
i f ( r ez == 0) r et ur n 0;
i f ( r ez < 0) br eak;
}
--5.18 --
Tabele de dispersie operatii specifice
Inserare:
/ * i nser ar e */
aux = ( TLG) mal l oc( si zeof ( TCel ul G) ) ;
i f ( ! aux) r et ur n - 1;
aux- >i nf o = mal l oc( d) ;
memcpy( aux- >i nf o, ae, d) ;
aux- >ur m= *aL;
*aL = aux;
r et ur n 1;
}
--5.19 --
Tabele de dispersie operatii specifice
Extragere element:
int ExtrTD(TabDisp* a, void*ae, TFCmp f);
parametri: adresa tabelei, adresa element, functie test
efect: calculeaza codul de dispersie k si actualizeaza
lista [k], daca elementul este gasit (spatiul ocupat de
element nu este afectat, eventuala eliberare a acestuia
fiind responsabilitatea utilizatorului)
rezultat: 0 / 1 (element inexistent / element gasit)
--5.20 --
Tabele de dispersie operatii specifice
Extragere element:
int ExtrTD(TabDisp* a, void*ae, TFCmp f)
{
i nt cod = a- >f d( ae) ;
TLG aux, *aL;
i nt r ez;
voi d* aee; / * adr esa el ement ext r as */
f or ( aL=a- >v+cod; *aL ! = NULL; aL=&( *aL) - >ur m)
{
r ez = f ( ae, ( *aL) - >i nf o) ;
i f ( r ez < 0) r et ur n 0;
--5.21 --
Tabele de dispersie operatii specifice
Extragere element:
i f ( r ez == 0)
{
aux = *aL;
*aL = aux- >ur m;
aee = aux- >i nf o;
f r ee( aux) ;
r et ur n 1;
}
} / * f or par cur ger e l i st a */
r et ur n 0;
}

rezultat
element cautat
. . .
[k]
.
.



.
.
. . . .
. . . .
--5.22 --
Tabele de dispersie operatii specifice
Eliberare spatiu ocupat:
t ypedef voi d ( *TF) ( voi d*) ;
void DistrTD(TabDisp**aa, TF fe);
parametri:
- adresa tabelei
- adresa functiei de eliberare
a spatiului ocupat de un element
efect: elibereaza mai intai tot spatiul
ocupat de liste si apoi spatiul alocat la
initializare

DistrTD(&a,ElibElem);
[ M-1]
[ 0]


.
.
.


M

f d

v
a
. .
. .
a
f unct i e de
di sper si e
--5.23 --
Tabele de dispersie operatii specifice
Eliberare spatiu ocupat:
void DistrTD(TabDisp**aa, TF fe)
{
TLG p, aux;
i nt cod;
f or ( cod = 0; cod < M; cod++)
f or ( p=( *aa) - >v[ cod] ; p ! =NULL; )
{
aux = p;
p = p- >ur m;
f e( aux- >i nf o) ;
f r ee( aux) ;
}
f r ee( ( *aa) - >v) ;
f r ee( *aa) ;
*aa = NULL;
}

DistrTD(&a,ElibElem);
[ M-1]
[ 0]


.
.
.


M

f d

v
a
. .
. .
a
f unct i e de
di sper si e
--5.24 --
Tabele de dispersie operatii specifice
Afisare continut:
void AfiTD(TabDisp* a, TF afiEl)
{
i nt cod;
TLG p;
f or ( cod = 0; cod < M; cod++)
i f ( a- >v[ cod] )
{
pr i nt f ( [ %d] : , cod) ;
f or ( p=a- >v[ cod] ; p! =NULL; p=p- >ur m)
af i El ( p- >i nf o) ;
pr i nt f ( \ n) ;
}
}

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