6
Tabele de dispersie Ne punem problema ment ¸inerii unui set finit de date, fiecare dintre ele identifi- cat˘ a printr-o cheie unic˘ a, ¸ si not˘ am cu K mult ¸imea cheilor din acest set, numit˘ a mult ¸imea cheilor actuale. Prin natura lor, fie c˘ a sunt ˆ ıntregi de lungime fix˘ a, dar mare, fie c˘ a sunt stringuri de caractere, cheile actuale K fac parte dintr-o mult ¸ime U , de cardinalitate mult mai mare decˆ at K, numit˘ a universul cheilor, lucru pe care ˆ ıl not˘ am |K| << |U |. Pe aceast˘ a mult ¸ime dorim s˘ a facem operat ¸ii de inserare ¸ si ¸ stergere, ¸ si, de asemenea, foarte frecvent, operat ¸ii de c˘ autare. Ideal ar fi ca operat ¸ia de c˘ autare s˘ a aib˘ a timp O(1) sau apropiat de el, ˆ ın orice caz timp constant (¸ si mic) ˆ ın raport cu cheile din U . Structura de date care ne permite accesul ˆ ın timp O(1) la orice component˘ a este vectorul. Dac˘ a ne-am putea permite ment ¸inerea ˆ ın memorie a unui vector T a c˘ arui mult ¸ime de indici a fie chiar U , atunci pentru orice cheie actual˘ a k Kın locat ¸ia T [k] am putea ment ¸ine data identificat˘ a de cheia k. Un asemenea T se nume¸ ste tabel cu adresare direct˘ a. Din p˘ acate, pentru multe probleme concrete nu ne putem permite aceast˘ a solut ¸ie deoarece ar conduce la o risip˘ a de spat ¸iu. D˘ am mai jos ateva exemple. 1. Vrem s˘ a ment ¸inem ˆ ınregistr˘ ari cu date despre cei 68 de angajat ¸i ai unei firme. Fiecare angajat este identificat cu ajutorul unui num˘ ar de cod compus din 4 cifre. Cardinalul mult ¸imii cheilor actuale este |K| = 68, dar universul cheilor U este format din mult ¸imea tuturor ˆ ıntregilor cu 4 cifre ˆ ın scriere zecimal˘ a, deci |U | = 10 4 = 10000. Un tabel cu adresare direct˘ a ar ˆ ınsemna s˘ a ment ¸inem ˆ ın memorie un vector cu 10000 de componente, dintre care doar 68 ar fi efectiv folosite. 2. Vrem s˘ a ment ¸inem ˆ ınregistr˘ ari cu date despre populat ¸ia Romˆ aniei. Fiecare locuitor este identificat cu ajutorul unor chei unice, codul numeric per- sonal, un ˆ ıntreg compus din 12 cifre. Cardinalul mult ¸imii cheilor ac- tuale este aproximativ 22 de milioane, |K| = 22 · 10 6 . Universul cheilor va fi mult ¸imea tuturor ˆ ıntregilor de 12 cifre, deci va avea dimensiunea |U | = 10 12 . 3. Anuarul telefonic al unei localit˘ at ¸i ment ¸ine informat ¸ii despre abonat ¸ii identificat ¸i cu ajutorul numelui ¸ si prenumelui, deci un ¸ sir de maximum 20 de caractere deci va avea dimensiunea |U | = 26 20 . ˆ In toate situat ¸iile descrise mai sus este nerealist˘ a folosirea unui tabel cu adresare direct˘ a, adic˘ a a unui tabel T indexat chiar dup˘ a U . Trebuie s˘ a g˘ asim o mult ¸ime de indici pentru T , de cardinal m, mult mai mic decˆ at |U |, eventual apropiat de cardinalul lui Ksi o metod˘ a de a dispersa cheile din K pe mult ¸imea de indici {0, 1, ..., m - 1}. Cu alte cuvinte, avem nevoie de o funct ¸ie, definit˘ a pe universul cheilor ¸ si cu valori ˆ ın mult ¸imea indicilor T : h : U →{0, 1, ..., m - 1} 1

Hash Tables

Embed Size (px)

DESCRIPTION

tabele de dispersie

Citation preview

  • Tabele de dispersie

    Ne punem problema mentinerii unui set finit de date, fiecare dintre ele identifi-cata printr-o cheie unica, si notam cu K multimea cheilor din acest set, numitamultimea cheilor actuale. Prin natura lor, fie ca sunt ntregi de lungime fixa,dar mare, fie ca sunt stringuri de caractere, cheile actuale K fac parte dintr-omultime U , de cardinalitate mult mai mare decat K, numita universul cheilor,lucru pe care l notam |K|

  • cu ajutorul careia sa gasim locul fiecarei date din multimea noastra: dataidentificata printr-o cheie k, k K, sa se afle n locatia T [h(k)] a tabelului T .

    O asemenea functie se numeste functie de dispersie. Pentru a fi o functiebuna de dispersie, functia h trebuie sa ndeplineasca anumite cerinte, si anume:

    1. Sa se poata calcula rapid. Timpul de calcul al lui h(k) ne va da timpul deacces la componenta T [h(k)].

    2. Codomeniul ei sa fie cat mai mic. Este dezirabil ca m sa fie cat maiapropiat de |K|, n orice caz diferenta dintre ele sa fie acceptabila cadimensiune.

    3. h sa fie cat mai aproape de o functie surjectiva, adica sa avem cat maiputine locatii goale. Aceasta cerinta se leaga de precedenta.

    4. h sa fie cat mai aproape de o functie injectiva pe K. Cu alte cuvinte,pentru chei k1, k2 K, k1 6= k2 sa avem h(k1) 6= h(k2).

    Numim coliziune a cheilor k1 si k2 situatia n care h(k1) = h(k2). Cerinta4 se exprima si sub forma ,,ne dorim sa avem cat mai putine coliziuni. Dinpacate coliziunile nu pot fi evitate complet si trebuie gasite metode de rezolvarea lor.

    Pentru a folosi un tabel de dispersie programatorul trebuie sa rezolve douaprobleme: sa aleaga o functie de dispersie si sa opteze pentru o metoda derezolvare a coliziunilor. Aceasta din urma se mparte n doua mari clase :

    rezolvarea coliziunilor prin nlantuire(cand locatia T [h(k)] contine o listanlantuita a tuturor nregistrarilor cu chei ce au colizionat cu k ) si

    rezolvarea coliziunilor prin adresare directa, cand se folosesc metode maisofisticate de cautare a unei locatii libere n T pentru o cheie care col-izioneaza.

    Ne vom ocupa pe rand de cele 2 tipuri de probleme.

    U

    K

    0

    1

    ..

    h(k2)=0

    h(k3)=1

    h(k4)=h(k6)coliziune

    ..

    h(k1)=h(k5)=h(k7)coliziune

    ..

    m-1

    k2 k3

    k1 k4 k6

    k5 k7

    2

  • Functii de dispersie

    Ne ocupam n acest paragraf de prezentarea catorva tehnici euristice de crearea unor functii de dispersie bune. Am exprimat informal n paragraful precedentcateva cerinte pentru o asemenea functie

    h : U {0, 1, ...,m 1}.

    Vom lucra la ipoteza hashingului simplu uniform (HSU), care, infor-mal, spune ca orice cheie este distribuita prin functia h cu probabilitate egalan oricare din locatiile {0, . . . ,m 1}. Mai precis, pentru oricare h K proba-bilitatea ca h(k) = i este 1m pentru orice i [0 . . .m 1], si este independentade restul cheilor. Daca P este probabilitatea de distrubutie a cheilor din K nU , adica daca P (k)=probabilitatea de a extrage cheia k din U , atunci ipotezaHSU se formuleaza:

    {k|h(k)=i}P (k) =

    1

    m, i = 0, 1, . . . ,m 1

    Deoarece P este de obicei necunoscuta, nu este n general posibil sa verificamca ipoteza HSU este satisfacuta .

    In cele ce urmeaza vom interpreta cheile si numerele naturale, adica vomconsidera ca U < N . Atunci cand cheile sunt stringuri, metoda folosita pentrua le converti la numere naturale este urmatoarea: se nlocuieste fiecare caractercu codul sau ASCII si se calculeaza valoarea sirului rezultat ca ntreg n baza128.

    De exemplu: AB se scrie 6566128 = 65 128 + 66 = 8386 ABC se scrie656667128 = 65 1282 + 66 128 + 67 = 1073605

    Metoda diviziuni

    Se numesc functii de dispersie obtinute prin metoda diviziunii functiile de forma

    h : U {0, . . . ,m 1}, h(k) = kmodm.Ele sunt printre cele mai comune pentru ca sunt usor de calculat.Alegerea unei astfel de functii revine practic la alegerea lui m, dimensiunea

    tabelului de dispersie. Deci, ea va fi guvernata, pe de o parte, de dimensiunilelui K si de modul n care rezolvam coliziunile. De exemplu, daca ne propunemsa le rezolvam prin inlantuire si sa mentinem n medie 3 date ntr-o locatie,

    m ar putea fi apropiat de |K|3 . Daca nsa vrem ca toate elementele din K sa-sigaseasca locul n tabel, atunci am putea alege un m apropiat de 3|K|2 , acceptanddeci o risipa de spatiu egala cu |K|2 .

    Dar acestea nu sunt singurele considerente care guverneaza alegerea lui m.Important este ca cheile sa fie bine dispersate pe multimea {0, 1, . . . ,m 1}si sa avem cat mai putine coliziuni. Vom evita valori pentru m de forma lui2, deoarece, daca m = 2, atunci h(k) = kmod2p reprezinta doar ultimii p biti

    3

  • din scrierea binara a lui k. Am pierdut n felul acesta informatia continuta nceilalti biti, lucru nerecomandabil: daca nu avem indicatii contrare, trebuie safacem ca h(k) sa depinda de toti bitii lui k. Numerele apropiate de puteri alelui 2 sunt si ele de evitat. Un exemplu de rezultat care ne conduce la aceastadecizie este urmatorul: daca m = 2p 1 si cheile k sunt siruri de caractere nbaza 2p, atunci 2 siruri care difera doar printr-o transpozitie a doua caractereadiacente vor avea aceeasi valoare prin h.

    Vom evita si valori pentru m de forma puterilor lui 10 , caci daca am alegeun asemenea m, atunci h(k) nu ar ? decat de o parte a caracterelor ce apar nscrierea lui k n baza 10. Valori bune pentru aceasta metoda sunt m, un numarprim si cat mai departe de puteri ale lui 2. Evident, ne putem propune saindexam tabelul dupa multimea de indici {1, 2, . . . ,m}, n caz n care functiiledin aceasta clasa vor fi de forma h(k) = kmodm + 1.

    Sa consideram exemplul firmei cu 68 de angajati, identificati cu chei ntregicu 4 cifre n scrierea n baza 10. Sa presupunem ca alegem pentru tabel o

    dimensiune apropiata de 3|K|2 =32 68. O buna alegere pentru m ar fi m = 97,

    deoarece este prim , apropiat de 32 68 si destul de departe de puteri ale lui 2.Sa consideram cheile k1 = 3205, k2 = 7148 si k3 = 2345.Cu functia de dispersie data de metoda diviziunii

    h(k) = kmod97

    Obtinem pentru aceste chei urmatoarele adrese din tabel : h(k1) = 3205mod97 =4 h(k2) = 7148mod97 = 67 h(k3) = 2345mod97 = 17

    Metoda multiplicarii

    Fie A o constanta pozitiva subunitara, 0 < A < 1. Sa consideram functia datade

    h(k) = bm(kAmod1)ckAmod1 reprezinta partea fractionara a lui kA, kA[kA], care se inmulteste

    cu m, iar rezultatul se trunchiaza la cel mai apropiat ntreg. Observam cavaloarea lui m nu e critica pentru aceasta metoda, iar puterile lui 2 sunt alegeribune pentru m, pentru ca functia se va calcula usor. Fie m = 2p. Atunci

    h(k) = b2p(kA [kA])c = bkA2p 2p[kA]c

    Fie w lungimea unui cuvant masina n biti si presupunem ca k se poate reprezentape w biti de forma

    4

  • r1 r0

    bA2wc

    k

    w p biti

    w

    K bA2wc = r12w + r0Deoarece kA2p = (kA2w) 2pw nseamna ca h(k) = (r12w + r0)2pw.Knuth recomanda pentru A numarul de aur,

    5+12 , a carui valoare aprox-

    imata cu 7 zecimale este 1, 6180339. Revenind la exemplul nostru, sa alegempentru aceasta metoda A = 0, 61803391 si m = 26 = 64. Atunci, pentru cele 3chei din exemplu si functia h(k) = bm(kAmod1)c, avem: h(k1) = h(3205) = 51deoarece partea fractionala a lui 3205 A este 0, 7986, care, nmultit cu 64 ne da51, 1107, a carui parte ntreaga este 51. Analog, obtinem h(k2) = h(7148) = 45si h(k3) = h(2345) = 18.

    Metoda mpachetarii

    Metoda mpachetarii sau folding genereaza functii de dispersie n felul urmator.Fiecare cheie k, despre care am facut presupunerea ca este ntreg, este partitionatan bucati de lungimi egale (eventual cu exceptia ultimei), k1, k2, . . . , kr. Dacak este un ntreg scris n baza 10 bucatile vor fi siruri de caractere n baza 10, deaceeasi lungime fixa, l, pe care din nou le putem considera ntregi. O functie dedispersie

    h : U [0 . . . 102 1]este data de formula:

    h(k) = (k1 + k2 + + kr)mod10l

    ceea ce nseamna ca se aduna cele r bucati, ca ntregi, si din suma se pastreazadoar l cifre, cele mai putin semnificative. Alte functii de dispersie se obtininversand ordinea cifrelor n toate bucatile pare sau n toate bucatile impare.De exemplu:

    h(k) = (k1 + k2 + k3 + . . .)mod10l

    unde k este ntregul obtinut prin inversarea ordinii caracterelor. Pe exemplulnostru metoda mpachetarii se aplica n felul urmator: spargem fiecare cheie de

    1Pentru calcularea valorii h(k) nu pastram decat partea fractionara a produsului kA.

    Prin urmare, este suficient sa alegem A ca fiind partea fractionara a numarului5+12

    , adica

    0, 6180339, care este chiar5+12

    .

    5

  • 4 caractere n 2 bucati de cate 2 caractere, pe care le adunam si omitem, dacae cazul, cifra cea mai nesemnificativa pentru ca rezultatul sa aiba lungimea totde 2 caractere. Avem deci h(k1) = h(3205) = 32 + 5 = 37 h(k2) = h(7148) =(71 + 48)mod100 = 19 h(k3) = h(2345) = 23 + 45 = 68 Pentru functia h

    (k) =k1+k2, n care a doua functie o inversam n oglinda nainte de adunare, obtinemh(3205) = 32 + 05 = 32 + 50 = 82 h(7148) = 71 + 48 = (71 + 84)mod100 = 55h(2345) = 23 + 45 = 23 + 54 = 77

    Metoda patratului

    Presupunem ca l este lungimea fixata a lui h(k) ca ntreg n baza 10. Fie

    h : U [0 . . . 10l], h(k) = (k2div10c1)mod10c2 .Se ridica la patrat, iar din ntregul lung astfel obtinut se elimina c1 cifre

    dintre cele mai putin semnificative si c2 cifre dintre cele mai semnificative,pastrandu-se exact l cifre din ,,centrul lui k2. Cu alte cuvinte c1 si l suntfixate, iar c@ se obtine din formula:

    l = lung(k2) c1 c2.

    Sa aplicam aceasta metoda exemplului nostru. O cheie de 4 cifre va avea patratulde 7 sau 8 cifre, dintre care sa eliminam c1 = 3 dintre cele din dreapta, sapastram l = 2 cifre, si sa eliminam si restul de cifre ,,centrale, adica a 4-a si a5-a din stanga. k1 = 3205 : k1

    2 = 32052 = 10272025 si h(k1) = 72 k2 = 7148 :k2

    2 = 71482 = 51093904 si h(k2) = 93 k3 = 2345 : k32 = 23452 = 5499025 si

    h(k3) = 99

    6