Szoftvertervezés és -fejlesztés II. előadáshttp://nik.uni-obuda.hu/sztf2
Szénási Sá[email protected]
Óbudai Egyetem,Neumann János Informatikai Kar
Hasító táblázatok
Hasító függvények, kulcsütközés kezelése
Felépítése
Tipikus hasító függvények
További megfontolások
Kulcsütközés kezelése
Hasító táblázatok
Szoftvertervezés és -fejlesztés [email protected]
• Amennyiben az elemek kulcsai a {0..m-1} tartományból valók, és m nem túl nagy, alkalmazhatjuk a közvetlen címzést
• Minden elemet egy m elemű A (kivételesen 0-tól indexelt) tömbben tárolunk el, és minden elem tömbbeli indexe egyenlő a kulcsával
• Pl. beszúrás algoritmusa
• Hasonlóan egyszerű a törlés és a kulcs szerinti keresés is
• Bejárás ebben az esetben nem, vagy nehezen értelmezhető
• A fenti műveletek lépésszáma: Ο(1)
• Közvetlen címzés általában nem valósítható meg– A kulcshalmaz nagy mérete kezelhetetlen méretű tárkapacitást igényelne
Pl. kulcs születési dátum: ~ 20M
– Az aktuálisan tárolt elemek száma a -hoz képest kicsi lennePl. fenti példából hány valós születési dátum, név?
3
Közvetlen címzés
eljárás Beszúrás(címsz. A, kulcs, érték)
A[kulcs] érték
eljárás vége
Szoftvertervezés és -fejlesztés [email protected]
• A hasító táblázat hasonló elveken alapul, azonban bevezetünk még egy új függvényt, ami a kulcsokat leképezi tömb indexekre
• Kulcshalmaz (): a lehetséges kulcsok halmaza (minden kulcs egyedi)Legyen n = | |
• Indexhalmaz (): a lehetséges indexek halmazaLegyen m = | |, és legyen = {0..m-1} 0
• Kulcstranszformációs-függvény: h:
Egy leképezés, amely a kulcs alapján megadja az indexet
• Az elemeket fizikailag egy m méretű tömbben tároljuk (A). Példáinkban ezt 0..m-1 között indexelhetőnek tekintjük
• A tárolandó elem felépítése:THasítóElem = Struktúra(kulcs, tartalom)
• Kulcsokkal kapcsolatos megjegyzések– El kell tárolnunk a kulcsot is, hiszen több is leképződhet ugyanoda
– Célszerű a kulcs egy speciális értékével () jelölni, ha egy hely még szabad
4
Hasító táblázat
Szoftvertervezés és -fejlesztés [email protected]
• : nevek halmaza
• I : egész számok halmaza (0 ... abc mérete - 1)
• h : név első karakterének helye az abc-ben - 1
5
Példa nevek leképezésére
Aladár0 ...
1 ...
Cecil2 ...
Dénes3 ...
4 ...
Ferenc5 ...
Aladár
CecilDénes
Ferenc
h(Aladár)
h(Cecil)
h(Dénes)
h(Ferenc)
h A
Szoftvertervezés és -fejlesztés [email protected]
• Tökéletes: nincs benne kulcsütközés (ez ritkán érhető el)
• Beszúrás
• Keresés
• Törlés
6
Tökéletes hasító táblázat alapműveletei
eljárás Beszúrás(címsz. A, h, kulcs, érték)
A[h(kulcs)].kulcs kulcs
A[h(kulcs)].tart érték
eljárás vége
eljárás Törlés(címsz. A, h, kulcs)
A[h(kulcs)].kulcs
eljárás vége
függvény Keresés(A, h, kulcs)
ha A[h(kulcs)].kulcs ≠ akkor
vissza A[h(kulcs)].tart
különben
hiba „nincs ilyen kulcs”
elágazás vége
eljárás vége
Szoftvertervezés és -fejlesztés [email protected]
• Előnye– Nagy méretű kulcshalmaz esetén is használható lehet
– Ha a tényleges elemszám kisebb mint a kulcshalmaz mérete, akkor is hatékony memóriafoglalás érhető el vele
• Hátránya– Fennáll a lehetőség, hogy két (egyébként különböző) kulcs ugyanoda képződik
le, tehát foglalkoznunk kell az esetleges ütközésekkel is
– Nehéz megtalálni a tökéletes hasítófüggvényt
• A választott hasítófüggvénynek mindig az adott feladatnakmegfelelőnek kell lennie, általános megoldásunk nincs
• Azonban megadható néhány általános szabály– Egyenletesen ossza szét a kulcsokat
– Véletlenszerűen ossza szét a hasonló kulcsokat
– Kevés ütközés produkáljon
– Egyszerűen kiszámolható legyen
7
Hasító táblázat elemzése
Felépítése
Tipikus hasító függvények
További megfontolások
Kulcsütközés kezelése
Hasító táblázatok
Szoftvertervezés és -fejlesztés [email protected]
• A választott hasító függvény:h(k) : k mod mahol– k a kulcs, ami csak pozitív egész szám lehet
– m tetszőleges pozitív egész szám
• Az m értelemszerűen az A tömb mérete is egyben
• Az egyenletes szétszórás az m megválasztásától függ
• Tipikusan nem ajánlott 2 vagy 10 hatványait választani, mivel akkoraz eredmény csak az utolsó néhány helyiértéktől függ
• Célszerű m-nek prímszámot választani
9
Osztó módszer
Szoftvertervezés és -fejlesztés [email protected]
• A választott hasító függvény:h(k) : KözepeM(Y * k)ahol– k a kulcs, ami csak pozitív egész szám lehet
– Y egy tetszőleges pozitív egész szám
– KözepeM(x) függvény visszaadja az x középső M darab számjegyét
• A paramétert itt is célszerű prímnek választani
• Nevezetes megoldás a négyzetközép módszerh(k) : KözepeM(k * k)
10
Szorzó módszer
Szoftvertervezés és -fejlesztés [email protected]
• A választott hasító függvény:h(k) : Helyiértéki(k) mod mahol– k a kulcs, ami csak pozitív egész szám lehet
– m tetszőleges pozitív egész szám (tömb mérete is egyben)
– Helyiértéki(x) visszaadja az x szám i. számjegyét
• Hátránya, hogy érzéketlen a számjegyek cseréjére, amely bizonyos kulcsok esetén ütközésekhez vezethet
• Emiatt célszerű lehet súlyozni a helyiértékeketh(k) : Súlyi * Helyiértéki(k) mod mahol– k a kulcs, ami csak pozitív egész szám lehet
– m tetszőleges pozitív egész szám (tömb mérete is egyben)
– Súlyi az i. számjegyhez tartozó súlyozó tényező (pozitív egész szám)
– Helyiértéki(x) visszaadja az x szám i. számjegyét
11
Számjegyes módszer
Felépítése
Tipikus hasító függvények
További megfontolások
Kulcsütközés kezelése
Hasító táblázatok
Szoftvertervezés és -fejlesztés [email protected]
• Az eddigi módszerek mind egész szám típusú kulcsot feltételeztek, ez azonban nem mindig elég (pl. kulcsként személyi igazolvány)
• Ha a kulcs karakter típus, valamilyen számot kell hozzárendelni (pl. ASCII, UniCode, stb.):h(k) : Karakterkód(k)ahol– k a kulcs, ami egy karakter
• Ha nem csak egy karakter, hanem több karakterből álló szöveg, akkor pedig:h(k) : Karakterkód(ki)ahol– k a kulcs, ami egy szöveg
– ki a kulcs i. karaktere
• Előre definiált kulcsok esetén (pl. természetes nyelv szavai) gyakran ismert a karakterek eloszlása, ilyenkor súlyozással lehet finomítani
13
Szöveges típusú kulcsok
Szoftvertervezés és -fejlesztés [email protected]
• Az előzőleg megismert módszerek esetén, ha a paraméter előre rögzített, akkor könnyen megállapíthatók olyan kulcsok, amelyek mind ugyanoda képződnek le (véletlenül, vagy szándékosan)
• Hatásos módszer, ha a hasító függvényt a kulcsoktól független módon véletlenül választjuk ki
• Ez általános esetben kielégítő eredményt ad, és elkerüli a legrosszabb esetet
• Gyakorlatban jól használatható, ha a hasító függvény paramétereit választjuk meg véletlenszerűen (pl. a súlyozási paramétereket tartalmazó függvények esetén a különböző súly értékeket)
14
Univerzális hasítási technika
Szoftvertervezés és -fejlesztés [email protected]
• Összetett kulcs egy személy esetén pl. a személy neve és a születési dátuma együttesen
• Összetett kulcsok esetén általánosan jól használható módszer nem állapítható meg
• Általában célszerű az összetett kulcsot megfelelő byte-méretű darabokra vágni, majd ezeket a darabokat számként kezelve valamelyik előzőleg ismert transzformációt alkalmazni
• Amennyiben ismert a kulcs felépítése (vagy tapasztalati úton megállapítható) célszerű lehet súlyozni az egyes darabokat
15
Összetett kulcsok
Felépítése
Tipikus hasító függvények
További megfontolások
Kulcsütközés kezelése
Hasító táblázatok
Szoftvertervezés és -fejlesztés [email protected]
• Kulcsütközésnek tekintjük, ha a kulcstranszformációs-függvény két különböző kulcsú elemet azonos indexhalmazbeli elemre képez
• A kulcstranszformációs-függvényt próbáljuk úgy megvalósítani, hogy minél kevesebb kulcsütközést okozzon, de nyilvánvaló, hogy ha a kulcshalmaz nagyobb, mint az indexhalmaz, akkor az ütközés elkerülhetetlen
• Ez tehát nem hiba, hanem a hasító táblázat velejárója, amit kezelnünk kell
17
Kulcsütközés
Aladár0 ...
-1 -
Cecil2 ...
Dénes3 ...
-4 -
-5 -
Aladár
CecilDénes
Dalma
h(Aladár)
h(Cecil)
h(Dénes)
h(Dalma)
Szoftvertervezés és -fejlesztés [email protected]
• Túlcsordulási területtel– A hasítótáblázat addig megismert alapvető szerkezetét kiegészítjük egy további
memóriaterülettel
– A kulcsütközés miatt az alap szerkezetbe nem férő elemeket ezen a túlcsordulási területen tároljuk
• Láncolt listával– A hasító táblázatban nem magukat az elemeket, hanem csak egy-egy láncolt
lista fejet tárolunk
– Ezek a láncolt listák tárolják a megadott hasító értékhez tartozó elemeket
• Nyílt címzéssel– A hasító táblázat felépítése itt teljesen megfelel az eddigieknek
– A hasító függvényt azonban kiegészítjük egy további paraméterrel, ami lehetőséget ad az elemek elcsúsztatására
– Ennek megfelelően többszöri próbálkozással más-más helyre próbáljuk meg elhelyezni az elemet
– Értelemszerűen a keresést és törlést is ehhez kell igazítani
• Egyéb megoldások
18
Kulcsütközések kezelése
Szoftvertervezés és -fejlesztés [email protected]
• A hasító tábla adatait tartalmazó tömb mellett lefoglalunk egy másik memóriaterületet (túlcsordulási terület). Műveleteit nem tárgyaljuk:– TúlcsordulásiTerületBeszúr(kulcs, érték)
– TúlcsordulásiTerületKeres(kulcs) : Logikai
– TúlcsordulásiTerületTöröl(kulcs)
• Beszúrás művelete– Ha az A tömb hasító függvény által megadott helye szabad, akkor ide helyezzük
az új elemet
– Ha nem, akkor a túlcsordulási területre
19
Beszúrás hasító táblázatba (túlcsordulási területtel)
eljárás Beszúrás(címsz. A, h, kulcs, érték)
i ← h(kulcs)
ha A[i].kulcs = akkor
A[i].kulcs ← kulcs
A[i].tart ← érték
különben
TúlcsodulásiTerületBeszúr(kulcs,érték)
elágazás vége
eljárás vége
Szoftvertervezés és -fejlesztés [email protected]
• Keresés művelete– Megnézzük, hogy az A tömbben van-e a keresett elem (a „helyén”)
– Ha ott nincs, akkor megvizsgáljuk a túlcsordulási területet
– Ha egyik helyen sincs, akkor hibát jelzünk
• Keresés pszeudokódja
20
Keresés hasító táblázatban (túlcsordulási területtel)
függvény Keresés(A, h, kulcs)
i ← h(kulcs)
ha A[i].kulcs = kulcs akkor
vissza A[i].tart
különben
ha TúlcsodulásiTerületKeres(kulcs) akkor
elem ← TúlcsodulásiTerületOlvas(kulcs)
vissza elem
különben
hiba ”Nincs ilyen kulcs”
elágazás vége
elágazás vége
eljárás vége
Szoftvertervezés és -fejlesztés [email protected]
• Törlés művelete– Ha a keresett elem az A tömbben van, akkor töröljük
– Ha ott nincs, akkor ellenőrizzük a túlcsordulási terüeltet is. Ha ott van, akkor töröljük innen
– Ha egyik helyen sincs, akkor hibát jelzünk
• Törlés pszeudokódja
21
Törlés hasító táblázatból (túlcsordulási területtel)
eljárás Törlés(címsz. A, h, kulcs)
i ← h(kulcs)
ha A[i].kulcs = kulcs akkor
A[i].kulcs ←
különben
ha TúlcsodulásiTerületKeres(kulcs) akkor
TúlcsodulásiTerületTöröl(kulcs)
elágazás vége
elágazás vége
eljárás vége
Szoftvertervezés és -fejlesztés [email protected]
• Ebben az esetben az A tömb nem közvetlenül az eltárolni kívánt elemeket és kulcsokat tartalmazza, hanem csak láncolt listák fejeit
• Beszúrás művelete:A[h(kulcs)] kezdetű listába új elem beszúrása.
• Keresés művelete:A[h(kulcs)] kezdetű listában elem keresése.
• Törlés művelete: A[h(kulcs)] kezdetű listában elem törlése.
• Célszerű lehet rendezni a láncolt listát hozzáférési gyakoriság szerint
• A szükséges műveletek a láncolt listáj témakörben tárgyaltuk22
Láncolt altáblák
Aladár0
1Cecil2
Dénes3 Dalma
Szoftvertervezés és -fejlesztés [email protected]
• Egy előre definiált szisztematikus üres hely keresést végzünk– Tehát ha egy kulcs hasító függvény által megadott helye nem szabad, akkor egy
másik helyet keresünk neki (ugyanezt követjük keresés és törlés során)
– Ezek az úgynevezett kipróbálási stratégiák
• Ehhez bevezetünk egy kétparaméteres hasító függvényt, aminek első paramétere a kulcs, második pedig a próbálkozás száma:– Lineáris próba: h(k, j) : (h(k) + zj) mod m
– Négyzetes próba: h(k, j) : (h(k) + z1j + z2j2) mod m
ahol• k – a hasítani kívánt kulcs• j – az aktuális próbálkozás száma• h(k) – egy már ismert hasító függvény• m – az osztó módszernél már megismert paraméter• z illetve z1,z2 – tetszőleges egész konstansok
• A különféle próbák különféle problémákkal járhatnak– Lineáris próba: egy területen halmozódó kulcsok rontják a futásidőt
– Négyzetes próba: kihagyhat szabad helyeket
• Célszerűen bevezetünk az üres () mellett egy törölt (⊗) állapotot is23
Nyílt címzés
Szoftvertervezés és -fejlesztés [email protected]
• Beszúrás művelete– Első körben j = 0 értékkel vizsgáljuk meg, hogy szabad-e a hasító függvény által
adott hely (tehát üres vagy törölt)
– Ha nem, akkor növeljük a j paraméter értékét, hátha találunk szabad helyet
– Ha találtunk szabad helyet, akkor oda felvesszük az új elemet
– Ha nem (m próbálkozás után ezt valószínűsítjük), akkor hibát jelzünk
• Beszúrás pszeudokódja
24
Beszúrás hasító táblázatba (nyílt címzéssel)
eljárás Beszúrás(címsz. A, h, kulcs, érték)
j ← 0
ciklus amíg j<m ∧ A[h(kulcs,j)].kulcs≠ ∧ A[h(kulcs,j)].kulcs≠⊗
j ← j + 1
ciklus vége
ha j < m akkor
A[h(kulcs,j)].kulcs ← kulcs
A[h(kulcs,j)].tart ← érték
különben
hiba "Nincs hely"
elágazás vége
eljárás vége
Szoftvertervezés és -fejlesztés [email protected]
• Keresés művelete– a beszúráshoz hasonló utat járjuk végig, amíg
• megtaláljuk a keresett kulcsot → megvan a keresett elem• üres helyre lépünk → nincs ilyen kulcs
– törölt elemnél megyünk tovább, hiszen utána még lehet a keresett kulcs
• Keresés pszeudokódja
25
Keresés hasító táblázatban (nyílt címzéssel)
függvény Keresés(A, h, kulcs)
j ← 0
ciklus amíg j<m ∧ A[h(kulcs,j)].kulcs≠ ∧ A[h(kulcs,j)].kulcs≠kulcs
j ← j + 1
ciklus vége
ha j < m ∧ A[h(kulcs,j)].kulcs ≠ akkor
vissza A[h(kulcs,j)].tart
különben
hiba "Nincs ilyen kulcs"
elágazás vége
eljárás vége
Szoftvertervezés és -fejlesztés [email protected]
• Törlés művelete– Az első ciklus azonos a keresésnél látottal (hiszen elsőként meg kell találnunk a
törlendő elemet egy kereséssel)
– Ha a keresés eredményes volt, akkor a vizsgált elemet töröljük. Ez ebben az esetben csak a törölt tulajdonság beállítását jelenti
– Ha nem találtuk meg, akkor hibát jelzünk
• Törlés pszeudokódja
26
Törlés hasító táblázatból (túlcsordulási területtel)
eljárás Törlés(címsz. A, h, kulcs)
j ← 0
ciklus amíg j<m ∧ A[h(kulcs,j)].kulcs≠ ∧ A[h(kulcs,j)].kulcs≠kulcs
j ← j + 1
ciklus vége
ha j < m ∧ A[h(kulcs,j)].kulcs ≠ akkor
A[h(kulcs,j)].kulcs ← ⊗
különben
hiba "Nincs ilyen kulcs"
elágazás vége
eljárás vége
Szoftvertervezés és -fejlesztés [email protected]
• Használjunk két vagy akár több hasító függvényt (h1, h2,…, hr) !
• Ezek lehetnek– egymástól teljesen független hasítófüggvények
– hasonló függvények más-más paramtérekkel, például:
• hj(k) : KözepeM(Y * k * j * j)ahol– k a kulcs, ami csak pozitív egész szám lehet
– j a hasítófüggvény száma
– Y, k, KözepeM a már ismert paraméterek
• Beszúrás:Ha a hi kulcstranszformációs függvény alkalmazásával kulcsütközéslépne fel, próbáljuk a hi+1-el, ami máshova képez (i=1-től indulva)
• Keresés:A beszúráshoz hasonló utat járunk végig itt is
• Törlés:A fenti kereséssel megtalált elemet töröljük
27
Többszörös hasítás
Szoftvertervezés és -fejlesztés [email protected]
• Javasolt/felhasznált irodalom– Cormen, Leiserson, Rivest: Algoritmusok, Műszaki Könyvkiadó, 1997
– Pap, Szlávi, Zsakó: μlógia34 – Módszeres programozás: Adattípusok, ELTE TTK, 1998
– Szénási: Algoritmusok, adatszerkezetek II., Óbudai Egyetem, 2014
28
Irodalomjegyzék
Top Related