7. Tördelőtáblák (Hasítótáblák) Legye U az Elemtip, uiverzum, H = {a,,a } U Vegyük egy T:Array[0..M-] of Elemtip tömbböt, amelybe a H halmazt tároli akarjuk. Válasszuk egy h : U {0,,M } függvéyt, amely mide a i halmazelemre megadja azt a táblázat idexet, ahol az elemet tároli akrajuk, T [h(a i )] := a i. Ha a i a j és h(a i ) = h(a j ) ütközés. 7.. Ütközésfeloldás lácolással Legye T:Array[0..M-] of Lac, és legye T [ j] a {x : x H h(x) = j} elemek láca. 0 T... j... M.... ábra. Adatszerkezet ütközésfelodás lácolással módszerhez. Cost Meret =??? ;(* a tördelőtábla mérete *) Type Kulcstip=??? ;(* a halmaz elemeiek kulcstípusa *) Adattip =??? ;(* a halmaz elemeiek adattípusa *) Elemtip = Record kulcs : Kulcstip; adat : Adattip Idex = 0.. Meret; Lac = ^Cella; Cella = Record adat : Elemtip; csat : Lac Tabla = Array[Idex] Of Lac; Fuctio H(K:Kulcstip):Idex; { a tördelőfüggvéy }??? Procedure Letesit(Var T:Tabla); Var i : Idex; {Letesit} For i := 0 To Meret Do H.T[i]:=Nil;
Ed{Letesit}; Fuctio Keres(T:Tabla; K:Kulcstip):Lac; Var i:idex; P:Lac; P:=T[H[K]]; While (P<>Nil) Ad (P^.adat.kulcs<>K) Do P:=P^.csat; Keres := P; Ed{Keres}; Procedure Bovit(Var T:Tabla; X:Elemtip); Var P : Lac; {Bovit} i:=h(x.kulcs); New(P); P^.adat:=X; P^.csat:=T[i]; T[i]:=P; Ed{Bovit}; Procedure Torol(Var T:Tabla; K:Kulcstip); Var i:idex; P,P0 : Lac; i:=h(k); P:=T[i]; P0:=P; While (P<>Nil) Ad (K<>P^.adat.kulcs) Do P0:=P; P:=P^.csat; If P<>Nil The If P=P0 The T[i]:=P^.csat Else P0^.csat := P^.csat; Dispose(P) Ed Ed{Torol}; 7.2. Ütközésfeloldás yílt címzéssel Pótvizsgálat (próbasorozat) h : U {0,,m } {0,,m } h(k,0),,h(k,m ) 0,,m egy permutációja mide k kulcsra. A k kulcsú elem helye a táblázatba az a j = h(k,i), amelyre Mi{i : T [h(k,i)] = Szabad} Ekkor a próbák száma i +. Például, ha U = Iteger, h(x,i) = (x + i)modm. Ezt a tördelőfüggvéyt alkalmazva bővítsük a kezdetbe üres táblát egymás utá a 5, 30, 6, 35, 20, és 28 elemekkel. Majd töröljük a táblából a 6-os elemet. Ha ezt követőe a 28 elemet keressük a táblába, 2
akkor a 2,3,4,5,... próbasorozat kell alkalmazi, de a keresés em állhat meg a 3 idexű törölt táblaelemél. Tehát a táblába a törölt helyeket em tekithetjük üresek. Választauk kell egy Ures és egy ettől külöböző Torolt kostas kulcs értéket az üres, illetve a törölt táblaelemek jelölésére. T 0 2 3 4 5 6 7 8 9 0 2 5 6 30 28 20 35 2. ábra. Tördelőtábla a 5, 30, 6, 35, 20, és 28 elemekkel való bővítés utá. T 0 2 3 4 5 6 7 8 9 0 2 5 30 28 20 35 3. ábra. Tördelőtábla a 6 elem törlése utá. {Tördelőtábla, ütközésfeloldás yílt címzéssel} Cost M =??? ;{ a tördelötábla mérete} Ures =??? ;{ Kulcstípusú kostas, az üres hely jele } Torolt =??? ;{ Kulcstípusú kostas, a törölt hely jele } Type Kulcstip=??? ;{ a halmaz elemeiek kulcstípusa} Adattip =??? ;{ a halmaz elemeiek adattípusa } Elemtip = Record kulcs : Kulcstip; adat : Adattip Idex = 0.. M-; Tabla = Array[Idex] Of Elemtip; Fuctio H(K:Kulcstip; i:idex) : Idex; { a tördelőfüggvéy } {???} Fuctio TKeres(Cost T : Tabla; K : Kulcstip) : Word; Var i, {a próbaszám} j : Word;{táblaidex} i:=0; Repeat j:=h(k,i); Ic(i); Util (i=m) Or (K=T[j].kulcs) Or (T[j].kulcs=Ures); If (K=T[j].kulcs) The TKeres:=j Else TKeres:=M Ed{TKeres}; 3
Procedure TBovit(Var T:Tabla; X:Elemtip); Var i, j : Word; K:Kulcstip; {Bovit} K:=X.kulcs; i := 0; Repeat j:=h(k,i); Ic(i); Util (i=m) Or (T[j].kulcs=Torolt) Or (T[j].kulcs=Ures); If (T[j].kulcs<>Torolt) Ad (T[j].kulcs<>Ures) The Exit; {ics szabad hely a táblába} T[j].kulcs:=K; T[j].adat:=X.adat Ed {Bovit }; Procedure TTorol(Var T : Tabla; K : Kulcstip); Var i, j : Word; {Torol} ; i := 0; Repeat j:=h(k,i); Ic(i); Util (i=m) Or (T[j].kulcs=K) Or (T[j].kulcs=Ures); If (T[j].kulcs<>K) The Exit {ics K kulcsú elem a táblába} T[j].kulcs:=Torolt Ed{Torol}; 7.3. Pótvizsgálatok (próbasorozatok). Lieáris pótvizsgálat h(k,i) = (h 0 (k) + i) mod m, h 0 : U {0,,m } Négyzetes pótvizsgálat h(k,i) = (h 0 (k) + c i + c 2 i 2 ) mod m, h 0 : U {0,,m } Dupla tördelés h(k,i) = (h (k) + i h 2 (k)) mod m, h,h 2 : U {0,,m } A h 2 (k) értékekek relatív prímek kell lei a táblázat m méretéhez. Pl. h (k) = k mod m és h 2 (k) = + (k mod m ), ahol m = m. 7.4. Tördelőfüggvéyek Az osztás módszere: h(k) = k mod m A szorzás módszere: h(k) = m(k Amod ) ahol k Amod = k A k A 4
0 < A <, pl. A = ( 5 )/2 = 0.680 7.5. Tördelőtáblák hatékoysági elemzése Legye h : U {0,...,m } a tördelőfüggvéy. α = m a tábla telítettségi téyezője. Egyeletességi feltétel: Pr(k) = m k:h(k)= j ( j = 0,,m ) Feltesszük, hogy h(k) olcsó, azaz Θ() időbe kiszámítható. Ütközésfeloldás lácolással A BOVIT futási ideje legrossabb esetbe is O(). A KERES és TOROL futási ideje legrossabb esetbe O(). (Mide elem egyetle lácba va és a keresés szekveciális.) Ha a T [ j] lác hossza j, akkor = 0 + + + m és j várható értéke /m = α. Így egy k kulcsú elem kereséséek ideje lieárisa függ a T [h(k)] lác h(k) hosszától. A T [h(k)] lác azo elemeiek számát tekitsük, amelyekkel a keresés sorá összehasolítódik a keresett k kulcs. Két esetet kell tekiteük, az első az, amikor a keresés sikeres, a másik pedig a sikertele keresés. 7.. tétel. Ha teljesül az egyeletességi feltétel, akkor lácolással törtéő ütközésfeloldás eseté a sikertele keresés átlagos ideje Θ( + α). Bizoyítás. Az egyeletességi feltétel miatt bármely k kulcsra, ami még ics a tábláa, egyforma valószíűséggel adódik bármely j = h(k) táblaidex. Ezért egy k kulcs sikertele kereséséek átlagos ideje megegyezik aak átlagos idejével, hogy a T [h(k)] lácot végigkeressük. Eek a lácak az átlagos hossza α, tehát h(k) kiszámításával együtt az átlagos futási idő Θ( + α). Sikertele keresés eseté aak valószíűsége, hogy egy adott lácba keresük, azoos a lác hossszával. 7.2. tétel. Ha teljesül az egyeletességi feltétel, akkor lácolással törtéő ütközésfeloldás eseté a sikeres keresés átlagos ideje Θ( + α). Bizoyítás. Az x elem sikeres keresése eseté megvizsgált elemek várható száma eggyel agyobb, mit azokak az elemekek a várható száma, amelyek megelőzik x-et az x-et tartalmazó lácba. Az x-et megelőző elemeket x beszúrása utá szúrtuk be, mivel új elemet midig a lác elejéhez illesztük. Tehát átlagoli kell a táblázat elemére az +azo elemek várható száma értékeket, amelyeket x utá adtuk x lácához. Legye x i a táblázatba i-edikkét beszúrt elem és legye k i = x i.kulcs. Az egyeletességi feltétel miatt Pr{h(k i ) = h(k j )} = /m. Ezért a sikeres keresés sorá vizsgált elemek számáak várható értéke ( ) + = + i= j=i+ m m ( i) i= ) = + i = + m Tehát a sikeres keresés futási ideje, beszámítva h(k) kiszámítását is m ( i= = + 2m ( 2 = + α 2 α 2. T a () = Θ(2 + α 2 α ) = Θ( + α) 2 i= ( + ) 2 ) 5
A yílt címzés hatékoyságáak elemzése A legjobb eset KERES, BÖVIT, TOROL : O() A legrosszabb eset BÖVIT: O() KERES, TOROL : O() Átlagos eset 7.3. tétel. Nyílt címzés eseté a sikertele keresés sorá a próbák számáak várható értéke α. Bizoyítás. p i = Pr{potosa i táblaelem foglalt} azaz, i a legkisebb idex, amelyre T [h(k,i)] = Szabad} Ekkor a próbák számáak várható értéke: Jelölje q i aak valószíűségét, hogy legfeljebb i próbát kell végezi. Tehát q = m q 2 = m m q i = m m + i m+ i ( m )i = α i. Tehát + + i p i = i p i + i p i i(q i q i ) = α i q i α i α A BOVIT algoritmus átlagos futási ideje : O( α ). 7.4. tétel. Nyílt címzés eseté a sikeres keresés sorá a próbák számáak várható értéke α l ( α). Bizoyítás. Sikeres keresés ugyaazo próbasorozatot hajtja végre, mit amikor az elemet beraktuk a táblázatba. Ha a k kulcsú elem i-edikkét került a táblázatba, akkor a próbák száma m i m. Tehát a próbák számáak várható értéke: m m i = m m i = α (H m H m ), ahol H i = i j= j az i. harmoikus szám. /x csökkeő, így α (H m H m ) = α α m m m k=m + /k (/x)dx = α l m m = α l α Tehát a Torol algoritmus átlagos futási ideje (= sikeres kerersés) O( α l α ) Pl. ha α = 0.5 akkor.387, ha α = 0.9 akkor 2.559 próba kell átlagosa a törléshez. 6
7.6. Az UioHolva adattípus megvalósítása Az UioHolva absztrakt adattípus. Értékhalmaz: UioHolva = {{H,...,H k } : H i E,i =,...,k,i j H i H j = /0} Műveletek: S : UioHolva, X : Elemtip,N,N,N2 : NevTip {Igaz} Letesit(S) {S = /0} {S = S} Megszutet(S) {Igaz} {S = S} Uresit(S) {S = /0} {S = {H,...,H k } X H i } Holva(S,X,N) {N = Y (X H i Y H i )} {S = {H,...,H k } X / H i } Holva(S,X,N) {N = X S = Pre(S) {{X}} {S = {H,...,H k } N H i N2 H j } Uio(S,N,N2) {S = Pre(S) H i H j {H i H j }} {S = {H,...,H k }} Elemszam(S) {= k S = Pre(S)} {S = {H,...,H k }} ReszElemszam(S,N) {= H i N H i S = Pre(S)} {S = S} IterKezd(S,I) {} {I = I} IterAd(I,x) {} {I = I} IterVege(I) {} {S = {H,...,H k } ( i)(n H i )} ReszIterKezd(S,N,I) {} {I = I} ReszIterAd(I, x) {} {I = I} ReszIterVege(I) {} Adatszerkezet választása. A diszjukt részhalmazok ábrázolhatók olya Rep : {,...,} {,...,} függvéyel, hogy bármely x,y {,...,}-re Rep(x) = Rep(y) akkor és csak akkor, ha x és y ugyaazo részhalmazhoz tartozik. Ezt szemlélteti a 4. ábra. Ekkor a HOLVAN művelet kostas időbe megvalósítható, az UNIO azoba az egyik részhalmaz elemszámával aráyos idejű lesz. Egy másik lehet- 4. ábra. Egyszerű adatszerkezet az UioHolva adattípushoz. 5. ábra. Az UNIO művelet megvalósítása egyszerű adatszerkezet eseté. séges adatszerkezet a megvalósításhoz a kétdimeziós lác, amit a a 6. ábra mutat. Ekkor az UNIO művelet kostas időbe megvalósítható, a HOLVAN művelet azoba csak O() időbe. Tehát egymásak elletmodó követelméyeket kellee kielégítei, amelyik adatszerkezet jó a HOLVAN művelethez, az em jó az UNIO-hoz. Kevesebbet követeljük a HOLVAN hatékoy, azaz kostas idejű megvalósításáál. Ábrázoljuk a részhalmazokat fával, mit azt a 7. ábra mutatja. Ekkor az UNIO kostas időbe egvalósítható. A HOLVAN futási idejéek felső korlátja a fa magassága, tehát arra kell törekedi, hogy fa magassága e legye agy. Két heurisztokát haszáluk eek elérésére: 7
6. ábra. Kétdimeziós lác az UNIOHOLVAN típus megvalósításához. 7. ábra. Halmazerdő adatszerkezet az UNIOHOLVAN adattípus megvalósításához. x x 8. ábra. Úttömörítés HOLVAN művelet sorá. 8
.Egyesítés a agyobbikhoz: Az UNIO művelet midig a agyobb elemszámú részhalmaz gyökeréhez kapcsolja a kisebb elemszámú részhalmaz gyökerét. 2. Úttömörítés: Mide HOLVAN művelet sorá a fáak midazo potjait, amelye a keresés áthalad a gyökérhez kapcsoljuk. Az iterátor műveletek hatékoy megvalósításához ábrázoljuk a részhalmazokat körlácba, továbbá kétiráyú körlácba a részhalmazok gyökereit. Tehát az adatszerkezet: (M, Adat, R); ahol az R szerkezeti kapcsolatok: R = {Apa,Csat, Elore,Vissza}, Apa,Csat, Elore,Vissza : M M. Az Apa kapcsolat fa, a Csat kapcsolat körlác, az (Elore,Vissza) kapcsolatpár pedig kétiráyú körlác. A részhalmazok elemszámát em tároljuk, haem Apa(x) = E legye, ha x gyökér és az x-gyökerű részhalmaz elemszáma E. Két körlác kostas időbe egyesíthető, amit a 0. ábra mutat. 9. ábra. Adatszerkezet az UNIOHOLVAN adattípus megvalósításához. q p p2 0. ábra. Két körlác egyesítése:q := Csat(p);Csat(p) := Csat(p2);Csat(p2) := q. Cost MaxN=0000; Null=0; Type Adattip =??? ;(* a felhaszáló defiiálja *) Idex=..MaxN; Kulcstip = Idex; Elemtip = Record kulcs : Kulcstip; adat : Adattip Nevtip = Kulcstip; Tartip = Array[Idex] Of Record adat:adattip; apa:iteger; csat:idex; 9
elore,vissza:idex; RepTip = Record Fa : Tartip; Fej: 0..MaxN; Eszam : 0..MaxN; UioHol = RepTip ;(* az UioHolva adattipus tipusa *) Iterator=^IterRep; IterRep = Record Hra: ^TarTip; kezd,pot: Iteger ReszIterator=Record Hra: ^TarTip; kezd,pot: Iteger Procedure Letesit(Var S:UioHol; N:Idex); Var i:idex; S.Eszam:=0; S.Fej:=0; For i:= To N Do S.Fa[i].apa:=0; Procedure Uresit(Var S:UioHol); Var i:idex; S.Eszam:=0; S.Fej:=0; For i:= To MaxN Do S.Fa[i].apa:=0; Ed{Uresit}; Procedure Holva(Var S : UioHol; X : Elemtip; Var N : Nevtip); Var j,k:idex; j:=x.kulcs; N:=j; If S.Fa[j].apa=Null The Ic(S.Eszam); S.Fa[j].adat:=X.adat; S.Fa[j].apa:=-; S.Fa[j].csat:=j; {egyelemű körlác} If S.Fej=0 The {az első részhalmaz} S.Fej:=N; S.Fa[N].elore:=N; S.Fa[N].vissza:=N; Ed Else k:=s.fa[s.fej].elore; {az új részhalmaz bekötése a kettős körlácba} S.Fa[j].elore:=k; S.Fa[k].vissza:=j; S.Fa[j].vissza:=S.Fej; S.Fa[S.Fej].elore:=j; Ed Ed Else 0
While S.Fa[N].apa > 0 Do N:=S.Fa[N].apa; While j <> N Do { úttömörítés } k:=s.fa[j].apa; S.Fa[j].apa:=N; j:=k Ed Ed{Holva}; Procedure Uio(Var S : UioHol; N,M : Nevtip); Var k:nevtip; p:idex; If (N<>M) Ad (S.Fa[N].apa<0) Ad (S.Fa[M].apa<0) The Dec(S.Eszam); If S.Fa[N].apa > S.Fa[M].apa The {egyesítés a agyobbikhoz} k:=n; N:=M; M:=k S.Fa[N].apa:=S.Fa[N].apa + S.Fa[M].apa; S.Fa[M].apa:=N; p:=s.fa[n].csat; {a két körlác egyesítése} S.Fa[N].csat:=S.Fa[M].csat; S.Fa[M].csat:=N; k:=s.fa[m].vissza; S.Fa[M].vissza:=S.Fa[M].elore; S.Fa[S.Fa[M].elore].vissza:= K; Ed Ed{Uio}; Procedure Eleme( S : UioHol; K : Kulcstip; Var Va : Boolea; Var N : Nevtip ); Var i,j:idex; j:=k; Va:=S.Fa[j].apa<>Null; If Va The N:=j; While S.Fa[N].apa > 0 Do N:=S.Fa[N].apa; While j <> N Do { úttömörítés } i:=s.fa[j].apa; S.Fa[j].apa:=N; j:=i Ed Ed{Eleme}; Fuctio Elemszam(S : UioHol) : Iteger; Elemszam:=S.Eszam
Fuctio ReszElemszam(S : UioHol; N : Nevtip) : Iteger; ReszElemszam:=-S.fa[N].apa Procedure IterKezd(S : UioHol; Var I: Iterator); New(I); I^.kezd:= S.Fej; I^.Hra:= @S.Fa; I^.pot:= S.Fej; Procedure IterAd(Var I:Iterator; Var X: NevTip); With I^ Do If pot = Null The exit; X:= pot; pot:= Hra^[pot].elore; If pot=kezd The pot:= 0 Fuctio IterVege(I: Iterator): Boolea; IterVege:= I^.pot =Null; Procedure ReszIterKezd(S : UioHol; N: Nevtip; Var I: Iterator); New(I); I^.kezd:= N; I^.Hra:= @S.Fa; I^.pot:= N; Procedure ReszIterAd(Var I: Iterator; Var X: Elemtip); With I^ Do If pot = Null The exit; X.kulcs:= pot; X.adat:= Hra^[pot].adat; pot:= Hra^[pot].csat; If pot=kezd The pot:= Null Fuctio ReszIterVege(I: Iterator): Boolea; ReszIterVege:= I^.pot = Null; 2
Az UNIOHOL adattípus megvalósításáak hatékoysági elemzése. Összesítéses elemzés. Egy műveletegyüttes, mit az absztrakt adattípusok hatékoysági elemzését megadhatjuk úgy is, hogy em külö-külö vizsgáljuk az egyes műveletek futási idejét, haem müveletsorok összesített futási idejét mérjük. Ha egy P = P ;...;P m műveltsor összesített futási ideje T (P), akkor a T (P)/m háyadost az egyes műveletek amortizált futási idejéek evezzük. ha i = 0, lg (i) = lg(lg (i ) ) ha i > 0és lg (i ) > 0, emdef egyébkét lg = mi{i 0 : lg (i) } P = P ; ;P m műveletsorozat, ahol P i {UNIO, HOLVAN} és azo HOLVAN műveletek száma, amelyek új elemet adak a halmazredszerhez, azaz a részhalmazok elemszámáak összege a műveletsor végé, akkor a műveletsor futási ideje: T (P) = O(mlg ) lg mide gyakorlatba előforduló -re 5, mivel lg (2 65536 ) = 5. Tehát az HOLVAN műveletek amortizált futási ideje praktikusa kostas. 3