adatstrukturak

89

Upload: api-3760752

Post on 07-Jun-2015

117 views

Category:

Documents


1 download

DESCRIPTION

AdatstruktúrákKirály Zoltánel®adásai alapjánlejegyezte: Susztár Zoltán2005/2006-os tanév tavaszi szemesztere2.2 verzió2007. szeptember 25.AdatstruktúrákKirály Zoltánel®adásai alapjánlejegyezte: Susztár Zoltán2005/2006-os tanév tavaszi szemesztere2.2 verzió2007. szeptember 25.

TRANSCRIPT

Page 1: Adatstrukturak

Adatstruktúrák

Király Zoltán

el®adásai alapjánlejegyezte: Susztár Zoltán

2005/2006-os tanév tavaszi szemesztere

2.2 verzió

2007. szeptember 25.

Page 2: Adatstrukturak

Tartalomjegyzék

1. Alapvet® adatszerkezetek 4

1.1. Adatstruktúrák tervezése . . . . . . . . . . . . . . . . . . . . . . 4

1.2. Láncolt lista . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

1.3. Sor és verem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

1.4. Gráfok . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

2. Gráfok bejárása: szélességi keresés 10

2.1. Összefügg®-e a gráf? . . . . . . . . . . . . . . . . . . . . . . . . . 12

2.2. Gráfok komponensekre bontása . . . . . . . . . . . . . . . . . . . 12

2.3. Legrövidebb utak . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

2.4. Adott gráf kétszínezhet®-e? . . . . . . . . . . . . . . . . . . . . . 15

2.5. Irányított gráfok . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

3. Kupac 16

4. Minimális költség¶ feszít®fa és legrövidebb út keresése 21

4.1. Kruskal algoritmusa . . . . . . . . . . . . . . . . . . . . . . . . . 21

4.2. DISZJUNKT-UNIÓ�HOLVAN adatstruktúrák . . . . . . . . . . 23

4.3. Prim algoritmusa . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

4.4. Dijkstra algoritmusa . . . . . . . . . . . . . . . . . . . . . . . . . 33

4.5. d-edfokú kupacok . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

5. Amortizációs elemzés 37

5.1. Konvex burok keresése . . . . . . . . . . . . . . . . . . . . . . . . 37

5.2. Az amortizációs elemzés . . . . . . . . . . . . . . . . . . . . . . . 38

5.3. Példa: a konvex burok keresés amortizációs elemzése . . . . . . . 39

6. Fejlettebb kupacok 39

6.1. Fibonacci kupac . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

6.1.1. Amortizációs id® és a strigulázás kapcsolata . . . . . . . . 45

6.2. Párosítós kupacok . . . . . . . . . . . . . . . . . . . . . . . . . . 46

6.2.1. A párosítós kupacok legjobb változata . . . . . . . . . . . 50

2

Page 3: Adatstrukturak

6.3. r-kupacok . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50

7. Szótárak 53

7.1. Bináris keres®fa . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

7.1.1. Optimális bináris keres®fa . . . . . . . . . . . . . . . . . . 56

7.1.2. M¶veletek általános bináris keres®fában . . . . . . . . . . 58

7.2. 2-3 fák . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

7.3. B-fák . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63

7.4. Piros-fekete fák . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63

7.5. AVL-fák (Adelszon-Velszkij és Landisz) . . . . . . . . . . . . . . 66

7.6. Önkiegyensúlyozó fák (Splay-tree; Sleator és Tarjan) . . . . . . . 68

8. Hashelés 71

8.1. Hash függvények . . . . . . . . . . . . . . . . . . . . . . . . . . . 72

8.2. Ütközések feloldása . . . . . . . . . . . . . . . . . . . . . . . . . . 73

8.2.1. Láncolt hash-elés . . . . . . . . . . . . . . . . . . . . . . . 73

8.3. Nyílt címzés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74

8.4. Lineáris hash-elés . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

8.5. Dupla hash-elés . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76

8.6. A dupla hash-elés Brent-féle változata . . . . . . . . . . . . . . . 77

8.7. Univerzális hash-elés . . . . . . . . . . . . . . . . . . . . . . . . . 78

9. Geometriai adatstruktúrák 78

9.1. Egy dimenziós feladatok . . . . . . . . . . . . . . . . . . . . . . . 79

9.2. Két dimenziós feladatok . . . . . . . . . . . . . . . . . . . . . . . 81

9.2.1. Kaszkád tárolás . . . . . . . . . . . . . . . . . . . . . . . . 82

9.3. Egy téglalapot metsz® szakaszok lekérdezése . . . . . . . . . . . . 83

9.3.1. Kupacos keres®fák . . . . . . . . . . . . . . . . . . . . . . 84

9.4. Ferde szakaszok lekérdezése . . . . . . . . . . . . . . . . . . . . . 86

9.4.1. Szakasz-fa . . . . . . . . . . . . . . . . . . . . . . . . . . . 87

9.4.2. Egy függ®leges szakaszt metsz® ferde szakaszok . . . . . . 88

3

Page 4: Adatstrukturak

1. Alapvet® adatszerkezetek

1.1. Adatstruktúrák tervezése

Programozási feladatok megoldása: A programozási feladatok általános megol-dása során el®ször az algoritmus vázlatát készítjük el, majd az adatstruktúrade�nícióját: milyen objektumokat akarunk tárolni, és ezekkel milyen m¶velete-ket akarunk végezni.

Ezután az algoritmust fokozatosan pontosítjuk, egyre részletesebben kidol-gozzuk. A �nomítások során készítjük el az eljárásokat, amelyek el®állítása sorána fenti lépések ismétl®dnek meg. Ehhez hasonló módon de�niáljuk és �nomítjukaz adatstruktúrákat is. Az, hogy milyen adatokat akarunk tárolni az adott adat-struktúrában és milyen m¶veleteket akarunk végezni rajtuk, fogja meghatározni,hogy milyet választunk. Az adatstruktúrák tervezésének lépései :

Speci�káció :

� Milyen objektumokat akarunk tárolni

� Milyen m¶veleteket akarunk végezni ezeken az objektumokon, ezek a m¶-veletek általában:

o Üres adatstruktúra létrehozásao Elem berakása az adatstruktúrábao Speciális m¶veletek (pld. a legkisebb kulcsú elem kivétele)

Ezután az adatsruktúrát az algoritmushoz ill. az eljárásokhoz hasonlóan egy-re pontosabban megtervezzük/megvalósítjuk.

A gyakorlatban nincs �univerzálisan legjobb� adatstruktúra, a felhasználáshatározza meg, hogy melyik lesz a legmegfelel®bb (pld. : a gyakorlatban nemfeltétlenül az az adatstruktúra lesz a legjobb, amelyben a leglassabb m¶veletelvégzésének ideje minimális). Azt a megvalósítást érdemes választani, ahol azalgoritmus által leggyakrabban használt m¶veletek a leggyorsabban valósíthatókmeg.

Ha rendelkezésünkre áll már egy jó adatstruktúra, akkor az is el®fordulhat,hogy érdemesebb az algoritmuson változtatni.

1.2. Láncolt lista

Tulajdonságai :

� Az elemek a memóriában szétszórtan helyezkedhetnek el.

4

Page 5: Adatstrukturak

� Minden elem két részb®l áll : egy mutatóból (pointerb®l), amely a követ-kez® elem memóriacímét mutatja, valamint egy, az adato(ka)t tartalmazórészb®l.

� A lista els® elemére a listafej mutat, a lista utolsó elmének mutatója pedignem mutat sehová (nil mutató).

Kés®bb fogunk egyéb láncolt listákkal is találkozni, pl.

� kétszeresen láncolt listával, ahol egy listaelemhez két pointer tartozik, azegyik a következ®, a másik a megel®z® listaelemre mutat,

� ciklikusan láncolt listával, ahol az utolsó elem pointere nem nil, hanem alegels® elemre mutat,

� illetve ezek kombinációjával.

nil

listafej

1.3. Sor és verem

Tulajdonságai :

� Tetsz®leges típusú objektumok tárolására alkalmas

� Ha egy sorból kiveszünk egy elemet, akkor a legrégebben berakott ele-met kapjuk vissza. A verem annyiban különbözik a sortól, hogy ebbenaz esetben elem-kivétel esetén az utolsónak berakott objektumot kapjukvissza.

M¶veletek :

� Új, üres sor létrehozása (S névvel n méret¶t) : Újsor(S, n)

� Üres-e a sor? : S =?∅

� Új elem berakása a sorba : S ← v

� Elem kivétele a sorból : u← S

M¶veletek megvalósítása : Cél, hogy konstans id®ben el tudjunk végezniminden m¶veletet.A sor méretét meghatározó n érték két jelentéssel bírhat:

5

Page 6: Adatstrukturak

1. Ha n fels® becslés az S ← v m¶veletek számára:ELEJE,VÉGE: pointer

ST1 n

ELEJE

VÉGE

3 6 1

Újsor(S, n) :Újtömb(ST,n)ELEJE:=1; VÉGE:=0

S =?∅ : ELEJE > VÉGE

S ← v :VÉGE++ST(VÉGE):=v

u← S :u:=ST(ELEJE)ELEJE++

2. Ha csak n ≥ |S| teljesül mindig:n + 1 méret¶ tömbben ciklikusan oldjuk meg a m¶veleteket.

A verem megvalósítása hasonló, itt a második eset is könnyen megvalósíthatóés nem kell az ELEJE mutató.

1.4. Gráfok

Cél : adatstruktúra egy V = {1,2, . . . n} csúcshalmazú gráf tárolására. (Ha agráfunk nem ilyen módon adott, akkor feltesszük, hogy létezik egy olyan bi-jektív függvényünk, ami ilyen csúcshalmazúvá számozza át � és vissza � a gráfcsúcsait.)

1. Szomszédsági mátrix : n×n-es A = {ai,j}mátrixban tároljuk az éleket:

ai,j ={

1 ha ij ∈ E0 ha ij /∈ E

6

Page 7: Adatstrukturak

j

ia ij

Ha a gráf irányítatlan, akkor a mátrix szimmetrikus lesz. Ekkor a f®átlófeletti részt elég tárolni.

Tárhely : n2 (bit) (kevés programnyelv támogatja a bit mátrixot, ezért agyakorlatban sokszor n2 rövid egészet használunk.)

M¶veletek :

� Új (csupa-0) mátrix létrehozása

� A gráf egy élének behúzása vagy törlése : ai,j := 01 (általában inputként

kapjuk)

� ij ∈?E : ez itt 1 lépésben megy

� Adott i csúcsból kimen® élek felsorolása : FOR ij ∈ E . . .Végigmegyünk a mátrix i-edik során

Megjegyzés :

Multigráf (olyan gráf, amelyben lehetnek hurokélek is, és a csúcsok közt többpárhuzamos él is mehet):

� ai,j = k, ha i-b®l j-be k db párhuzamos él megy

� ai,i = k, ha az i-dik csúcson k darab hurokél van (vagy aii = 2k, így azi-edik sor összege a csúcs fokszáma lesz).

Súlyozott gráfok :

Két esetet különböztetünk meg:

� A 0 súly nem megengedett: Ebben az esetben nincs probléma: a 0 értékazt jelenti, hogy a két csúcs közt nem megy él, a nem nulla érték pedig akét csúcsot összeköt® él súlyát jelenti.

� A 0 súly is megengedett: Ekkor több információra van szükségünk: ismer-nünk kell például a legkisebb súlyt. (ha például a súlyok nemnegatívak,akkor −1 jelentheti azt, hogy az adott csúcsok közt nem megy él.)

7

Page 8: Adatstrukturak

2. Éllista : Egy L tömbben tároljuk a csúcsokból kiinduló éleket felsorolóláncolt listák listafejeit.

nil

LISTAFEJEK

L1

n

i 2 5 8

Az i. csúcsból legalább 3 él megy ki: pl. a 2-es,. . . , az 5-ös és a 8-as számúcsúcsba.

Tárhely : n + e mutató (irányítatlan esetben n + 2e, mivel minden él kétszerszerepel) és e (ill. 2e) szám.

M¶veletek :

� Üres struktúra létrehozása : A listafej-tömböt nil-ekkel töltjük fel.

� Új él beszúrása (ij irányított él beszúrása):p := L(i); L(i) := beszúrt új (j, p) listaelem címe a memóriában.(Érdemes mindig a láncolt lista elejére beszúrni.) Lépésszám: O(1).

� ij ∈?E : Legrosszabb esetben végig kell menni a láncolt listán. Ez d(i) ≤≤ n−1 lépést jelent. (Irányított gráf esetén a fels® korlát az adott csúcsraa dki(i) kifok.)

� Adott i csúcsból kimen® élek felsorolása : A lépésszám ebben az esetben isd(i) vagy dki(i)

� ij él törlése : Az i-edik és a j-edik listában meg kell keresni, ez d(i)+d(j)lépés, utána kitörölni már konstans.

Megjegyzések :

� Az élfelsorolás (általában a leggyakrabban használt) m¶velet ideje kis fok-szám esetén sokkal jobb, mint a szomszédsági mátrixnál.

8

Page 9: Adatstrukturak

� Megfordított gráf generálása: végigmegyünk az éleken és egy új éllistábaátmásoljuk a fordítottjukat, ez O(e) id®ben megoldható.

� Irányított gráfból a megfelel® irányítatlan gráf generálása: végigmegyünkaz éleken és egy új éllistába átmásoljuk az éleket is és a fordítottjukat is,ez O(e) id®ben megoldható.

� Multi- és súlyozott gráfok esetén: A láncolt listában minden gond nélkültárolható. Mivel egy listaelem adatrésze akárhány adatból állhat, még azse gond, ha az élekhez több szám (kapacitás, súly és hossz) is tartozik.

3. Mátrixban tárolt éllista (egyszer¶ gráfokra)

Egy n×D méret¶ mátrixot használunk. A mátrix i-edik sorában felsoroljukaz i-edik csúcsból kiinduló élek végpontjait. Ha k darab él megy ki, akkor amátrix i-edik sorában a k + 1-ik oszloptól a D-ik oszlopig nullák szerepelnek.

i 2 5 8 0 00

D

n

Az i. csúcsból 3 él megy ki: a 2-es az 5-ös és a 8-as számú csúcsba.

D megválasztása :

� Ha a fokszámokról semmit nem tudunk: D := n.

� Ha ∆= maxfok(G) ismert, akkor D := ∆ + 1 (azért érdemes ∆ + 1-etválasztani, hogy minden sor 0-val végz®djön, így az i. csúcsból akkor nemindul ki több él, ha az i. soron végigmenve 0-hoz értünk).

Nyereség:

� Nem kell pointereket használni

Veszteség:

9

Page 10: Adatstrukturak

� Tárhelyet veszthettünk is: a tárhely mérete n× maxfok, n× átlagfok he-lyett (és ez még a jobb eset: ha ismerjük ∆-t, ha ∆-ról nem tudunk semmit,akkor n× (n + 1) hely kell).

M¶veletek ideje : Ugyanaz, mint az éllista esetén, s®t, egy kicsit még gyorsabbis, mivel nem kell pointerekkel dolgoznunk.Összefoglalva: ez a megoldás a gyakorlatban is egy jó megoldásnak tekinthet®,ha vagy ismerünk egy n-nél kisebb fels® korlátot ∆-ra, vagy a tárfoglalás nemnagyon érdekel minket (hiszen az egy csúcsból kiinduló éleket itt is fel tudjuksorolni fokszám id®ben).

Speciális esetek Páros gráfok: elég n2

4 hely.

a f

a

f

Fák tárolása:

� Éllista

� Prüfer kód: Egy n csúcsú gráf esetén n − 2 darab szám (abban az eset-ben, ha a gráf csúcsai 1-t®l n-ig számozottak). Ez az n − 2 darab számbijektíven (F fa ↔ a1, a2, . . . an−2, ahol 1 ≤ ai ≤ n) írja le a fát. Ez atárolás nagyon alkalmas véletlen fák generálására (ami egyébként nem egyegyszer¶ feladat).

� Pointerekkel (gyökeres fáknál alkalmazzuk, ahol a felfelé men® élet megakarjuk különböztetni a többit®l ; lásd kés®bb). Ha a gyerekek számáranincs jó fels® korlát, akkor a csúcsban az els® gyerekre mutat csak pointer,és a gyerekek egy láncolt listában vannak.

� Kupacoknál (teljesen kiegyensúlyozott fák) tömbben

2. Gráfok bejárása: szélességi keresés

Szélességi keresés esetén egy adott pillanatban minden egyes csúcs 3 féle álla-potban lehet:

a) Az algoritmus során eddig még nem látott

b) Látott, de még nem átvizsgált

10

Page 11: Adatstrukturak

c) Látott és átvizsgált

Egy u csúcs átvizsgálása azt jelenti, hogy végigmegyünk a bel®le kimen®éleken, és ha a) típusú csúcsot találunk, azt átsoroljuk b) típusúvá; végül u-tmagát pedig c) típusúvá.

A szélességi keresésnél a b) állapotú csúcsok közül a legrégebbit vizsgáljukát.

Egy L bittömböt (L(i) = 1⇔ ha i-t már láttuk az algoritmus során) és egyS sort ( ez fogja tartalmazni a b) állapotú csúcsokat) használunk.

Az algoritmus :

INIT:Újsor(S, n) ; Újtömb(L, n)FOR i := 1 . . . n L(i) := 0L(1) := 1 ; S ← 1 (látott, de nem átvizsgált)

WHILE S 6= ∅u← SFOR uv ∈ E

IF L(v) = 0 THEN L(v) := 1; S ← v

Ez az algoritmus magában nem ad outputot, csak végigmegy a gráf 1-escsúcsból elérhet® élein.

Lépésszám : Egy csúcsot maximum egyszer rakunk be a sorba, így maximumn-szer tudunk kivenni elemet a sorból. A lépésszám így O(n2), ha szomszédságimátrixban tároljuk a gráfot.

1. Tétel. Nincs olyan algoritmus, amely tetsz®leges, szomszédsági mátrixszaladott gráfról kevesebb, mint

(n2

)id®ben eldönti, hogy összefügg®-e, tehát a szé-

lességi keresés lényegében optimális lépésszámú szomszédsági mátrix esetén.

Éllistás tárolás esetén a FOR ciklus d(u)-szor fut le. A futási id®t ekkor nemérdemes n×max d(u)-val becsülni, hanem

∑u(1+d(u)) = n+2e-vel becsüljük.

Így a futási id® O(n + e) lesz, ami izolált csúcsot nem tartalmazó gráf eseténO(e).

2. Tétel. Ennél lényegesen gyorsabban éllistás tárolásnál sem valósítható mega gráfbejárás feladata.

Bizonyítás: azt állítjuk, hogy kell legalább |E|/2 input olvasás.

Minden élszámra tudunk olyan gráfot konstruálni, hogy ennél kevesebb olva-sással ne legyen eldönthet® a gráf összefügg®sége. Legyen G1 és G2 két egyforma,

11

Page 12: Adatstrukturak

tetsz®leges összefügg® gráf, az inputnak a két komponense. Ha nem olvassuk vé-gig legalább az egyiknek az összes élét, akkor G1 és G2 egy-egy nem végigvizsgáltcsúcsa közé berakhatunk egy új élet (az éllistáik végére), ezt az algoritmus nemveszi észre.

Az alábbiakban megnézünk néhány fontos feladatot, amelyeket a szélességikeresés segítségével könnyen megoldhatunk.

2.1. Összefügg®-e a gráf?

Ha minden 1 ≤ i ≤ n-re L(i) = 1, akkor a gráf összefügg®, különben nem.

2.2. Gráfok komponensekre bontása

A gráf egy adott komponense egy ekvivalencia osztály, ezt úgy tároljuk, hogytetsz®legesen elnevezzük a komponenseket, és egy csúcsra az ®t tartalmazó kom-ponens sorszámát tároljuk (két csúcs akkor van ugyanabban a komponensben,ha ez a szám ugyanaz). Triviális megoldás: 1-es értéket adunk az els® csoport-nak, majd amikor a sor kiürül, akkor keresünk egy olyan w csúcsot, melyreL(w) = 0, és egy innen indított újabb kereséssel megkeressük a 2. komponenscsúcsait, majd így tovább.

1. Állítás. Akár c · n2 id®t is elhasználhatunk csak a 0-k keresésére.

Bizonyítás: A G gráf legyen olyan, hogy az els® n/2 csúcs egy komponensbetartozik, majd minden ezt követ® csúcs izolált. Ekkor az els® komponens utánn/2 + 1 lépés az els® 0 megtalálása, majd n/2 + 2, és így tovább.

Hasznos észrevétel : A csúcsok �látottsága� csak egy irányba változik. Ha azels® bejárásnál az i-edik csúcsnál találtunk 0-t, legközelebb elég az i + 1-dikelemt®l kezdeni a következ® nullás keresését.

Az algoritmus :INIT:

Újsor(S, n) ; Újtömb(L, n)FOR i = 1 . . . n L(i) := 0k := 0

FOR i = 1 . . . nIF L(i) = 0 THEN k + + ; L(i) := k ; S ← iWHILE S 6= ∅

u← SFOR uv ∈ E

IF L(v) = 0 THEN L(v) := k ; S ← v

12

Page 13: Adatstrukturak

Lépésszám(éllistás tárolásnál) : O(n + e).

2.3. Legrövidebb utak

Feljegyezzük, hogy az egyes csúcsokat mely csúcsból láttuk meg, és mindencsúcshoz hozzárendelünk egy SZ szintet.

Az algoritmus :

INIT:Újsor(S, n) ; Újtömb(L, n) ; Újtömb(p, n) ; Újtömb(SZ, n)FOR i = 1 . . . n

L(i) := 0 ; p(i) := i ; SZ(i) := 0k := 0

FOR i = 1 . . . nIF L(i) = 0 THEN k + +, L(i) := k ; S ← iWHILE S 6= ∅

u← SFOR uv ∈ E

IF L(v) = 0 THEN L(v) := k ; S ← v ; p(v) := uSZ(v) := SZ(u) + 1

3. Tétel. {(p(u), u)|p(u) 6= u} ⊆ E(G) egy feszít®erd® lesz. (Ha összefügg® agráf, akkor feszít®fa, különben minden komponensben egy feszít®fa.) Ha a gráfirányított, akkor a gyökért®l elfelé irányított fákat (feny®ket) kapunk.

Bizonyítás (összefügg®, irányítatlan esetre): n− 1 darab él, ha nem feszít®falenne, akkor lenne benne kör, ez azonban nem lehet, mert a kör csúcsai közül asorba leghamarabb berakottnak a szül®je nem lehet egy kés®bb berakott.

4. Tétel. Szélességi keresés esetén

1. Bármikor a sorban balról jobbra a szintszám monoton n®

2. Ha x, y ∈ S, akkor |SZ(x)− SZ(y)| ≤ 1

Bizonyítás: Id®re vonatkozó indukcióval.

� Amikor egy elem van a sorban, triviálisan teljesülnek.

� Amikor új elemet rakunk be elromlanak-e a tulajdonságok? Tegyük fel,hogy v berakásakor valamelyik elromlik, legyen v szül®je u, tehát SZ(u) == SZ(v) − 1. Vegyük észre, hogy a sor minden x elemére, ha SZ(x) 6== SZ(v), akkor x már a sorban volt u kivétele el®tt is.

13

Page 14: Adatstrukturak

1. tulajdonság:

u

SZ:

x v

3 5 4

Ekkor x a v betétele el®tt is benne volt a sorban, ami ellentmond annak,hogy u kivétele el®tt teljesült a 2. tulajdonság.

2. tulajdonság:

u

SZ:

x v

4 3 5

Ekkor is x a v betétele el®tt is benne volt a sorban, ami ellentmond annak,hogy u kivétele el®tt teljesült az 1. tulajdonság.

5. Tétel. Szélességi keresés esetén (összefügg® irányítatlan gráf esetén)

1. A gráf élei nem ugorhatnak át szintet, vagyis, ha uv ∈ E, akkor |SZ(u)−− SZ(v)| ≤ 1

2. Minden x csúcsra SZ(x) az 1 csúcsból az x-be vezet® legrövidebb út hossza.

3. Az egyik legrövidebb út: (1, . . . , p(p(x)), p(x), x)

4. Ha a gráf összefügg®, akkor minden csúcsot bejárunk az algoritmus során,vagyis jó az algoritmus.

Bizonyítás: (El®z® tétel alapján)

1

v

u

*

14

Page 15: Adatstrukturak

1. Nem lehet uv típusú (lásd az ábrán) él a gráfban, mivel amikor u-t kivettüka sorból v még nem lehetett benne a sorban, így u átvizsgálása során bekellett kerülnie eggyel nagyobb szintszámmal.

2. A 3. állításban felírt (jobbról balra generált) csúcssorozat valóban egy útlesz, és az 1. állítás miatt egy legrövidebb út is, mivel a gráf élei nemtudnak szintet ugrani. A hossza nyilván SZ(x).

3. Jelölje d(1, x) egy x csúcs távolságát az 1-t®l. Indirekten tegyük fel, hogylétezik olyan csúcs, ami 1-b®l elérhet®, és ahol nem jártunk. Legyen x∗ azilyenek közül egy olyan, amelyre d(1, x∗) minimális.

1

y

x*

d(1,x )*

Jelölje az 1-b®l x∗-ba vezet® d(1, x∗) hosszú út utolsó el®tti csúcsát y,ekkor y közelebb van 1-hez, így x∗ választása szerint y-ban jártunk, ezértvalamikor y szerepelt a sorban. Amikor megvizsgáltuk a szomszédait x∗-otis megtaláltuk volna.

Megjegyzés: ezúttal azt is újra beláttuk, hogy ez a bejárás egy feszít®erd®thatároz meg.

2.4. Adott gráf kétszínezhet®-e?

Tudjuk (de most újra be is bizonyítjuk), hogy egy gráf akkor és csak akkor nemkétszínezhet®, ha van benne páratlan kör. Színezzük a gráf csúcsait az alábbimódon: Legyen piros, ha SZ értéke páros és kék, ha SZ páratlan.

Mikor nem jó ez a színezés? Felhasználjuk, hogy a gráf élei nem ugorhatnakát szintet. Probléma csak az egy szinten belül men® élekkel lehet. Legyen egyilyen szinten belüli él u és v között.

15

Page 16: Adatstrukturak

u v

Az algoritmust egészítsük ki az ELSE IF SZ(u) = SZ(v) THENBAJ sorral.

BAJ : megkeressük u és v legközelebbi közös ®sét. Az így meghatározott körvalóban páratlan, így a gráf nem kétszínezhet®.

A kör kiíratása : Felváltva a szül®re lépkedve keressük meg az x legközelebbiközös ®st, és közben rakjuk v, p(v), . . . , p(. . . (p(v)) . . .), . . . x-et egy verembeu, p(u), . . . , p(. . . (p(u)) . . .), . . . x-et pedig egy sorba. Ha kiürítjük a vermet, majda sort, akkor az adott kör csúcsait soroljuk fel, a sor utolsó elemét már nem írat-juk ki.

2.5. Irányított gráfok

Minden csúcsot elérünk, amibe van 1-b®l x-be men® irányított út. Ekkor isa legrövidebb ilyet találjuk meg. Ebben az esetben a gráf élei visszafelé márátugorhatnak szintet, lefelé ugyanúgy nem.

Irányított gráfok esetén kétféle összefügg®séget is de�niálhatunk:

� Gyenge összefügg®ség : Ha eltekintünk az irányítástól, akkor összefügg®-e agráf (azaz, ha például a gráfok élei közlekedési utakat jelölnek, bejárható-eez egy biciklin?)

Ekkor lényegében az a kérdés, hogy−→←−G összefügg®-e.

� Er®s összefügg®ség : Bármely x, y ∈ V esetén létezik-e x-b®l y-ba men®irányított út?Triviális megoldás: n darab szélességi keresés (minden csúcsból indítunkegyet).Jobb megoldás: Csinálunk egy szélességi keresést az eredeti gráfban ((−→G,1)-en), majd még egy szélességi keresést a (←−G,1) gráfban. Így összességében2 szélességi keresés elegend® az er®s összefügg®ség eldöntéséhez.

3. Kupac

Egy fa kupacrendezett, ha igazak rá a következ® tulajdonságok:

16

Page 17: Adatstrukturak

� Gyökeres fa, melynek csúcsaiban rekordok helyezkednek el.

� Minden rekordnak van egy kitüntetett mez®je, a K KULCS.

� Bármely v-re, ha létezik a p(v) szül®, akkor K(rek(p(v))) ≤ K(rek(v))(ezt ezentúl K(v)-vel jelöljük), azaz v leszármazottaira igaz, hogy az otttalálható kulcsok minimuma van v-ben. (Egy csúcsot mindig saját magaleszármazottjának tekintünk!)

Kupac: (egyszer¶ kupac, bináris kupac)

� Kupac-rendezett bináris fa (egy csúcs gyermekeinek száma 0, 1 vagy 2)

� A levelek vagy egy, vagy két szomszédos szinten vannak, ez utóbbi esetbenigaz, hogy a fels® tele van, az alsón pedig balra vannak rendezve a levelek.(Tehát a bináris fában a szinteket mindig balról jobbra haladva töltjükfel.)

Tárolás : a kulcsokat az A tömbben tároljuk, ahol :

� A(1) a gyökér kulcsa

� Az i. csúcs bal �ának kulcsa A(2i)-ben lesz, jobb �áé pedig A(2i+1)-ben.

� Az i. csúcs szül®jének kulcsa A(bi/2c).

� Ezenkívül még tárolunk egy VÉGE pointer (számot), mely megadja, hogypillanatnyilag hány elem van a kupacban.

Megjegyzés: Igazából 3 tömbre van szükségünk. Az A-ban tároljuk a csúcsokkulcsait, a B tömbben vagy az i-edik csúcsban tárolt objektum nevét, vagy arekordra mutató pointert, és C(j) pedig a j nev¶ csúcs (ill. rekord) indexe azA-ban és B-ben. Általában csak az A tömbbel való operációt adjuk meg, a többikitalálható. De példaként a FELBILLEGTET eljárásban megadjuk ezeket is.

Példa:

2

2

4

4

6

6

5

5

8 97

1012 15

7 8 9 12 10 15A:

17

Page 18: Adatstrukturak

M¶veletek :

Újkupac(A,n) : egy új, üres kupacot hoz létre (n az egy id®ben a kupacbanszerepl® elemek maximális száma).

Beszúr(A, új) : egy új elemet szúr be a kupacba.

Mintörlés(A) : a minimális kulcsú elemet kiveszi a kupacból és visszaadja.

Kulcs-csökk(A, elem, ∆) : a kupacban lév® elem kulcsát csökkenti ∆-val.(Csak ∆ ≥ 0 esetén kell m¶ködnie). Az elem-et úgy határozzuk meg, hogy rá-mutatunk egy pointerrel (nem tudjuk megkeresni, mivel a kupacban nem tudunkhatékonyan keresni), azaz a C(elem)-edik kupacelem kulcsát csökkentjük.

M¶veletek megvalósítása:

Újkupac(A,n) :

Újtömb(A,n) ; VÉGE:= 0

Beszúr(A, új) :

Ötlet: az adott, hogy hová kell felvenni egy új levelet, oda berakjuk. A kupactulajdonság csak egy él mentén romolhatott el. Ezen él mentén javítjuk a kupac-tulajdonságot, ekkor felette egy másik él mentén romolhat el, így ismételjük,amíg mindenhol helyre nem áll (lehet, hogy egészen a gyökérig el kell mennünk).

Beszúr(A, új) :VÉGE++A(VÉGE) :=K(új)FELBILLEGTET(VÉGE)

FELBILLEGTET(i):AA := A(i) ; BB := B(i)WHILE i > 1 && A(bi/2c) > AA

A(i) := A(bi/2c)B(i) := B(bi/2c)C(B(i)) := ii := bi/2c

A(i) := AAB(i) := BBC(BB) := i

Lépésszám : A fa mélysége blog nc, amib®l következik, hogy a FELBILLEG-TET lépésszáma O(log n).

6. Tétel. Beszúrás után a kupactulajdonság helyreáll.

18

Page 19: Adatstrukturak

Bizonyítás: Úgy tekintjük, hogy mindig i és szül®je tartalmát felcseréljükegy-egy lépésben. Állítás: mindig csak i és a szül®je közti él mentén lehet baja kupac-tulajdonsággal. Ez kezdetben igaz. Ha i gyökér, vagy szül®jének kulcsakisebb-egyenl®, akkor itt sincs baj, tehát kész vagyunk. Különben csere utánezen él mentén a kupac-tulajdonság helyreáll, és mivel a szül®ben lév® kulcscsökken, a másik gyereke felé men® él sem romlik el, tehát csak az új i és szül®jeközötti élen lehet baj.

Mintörlés(A) : Kicseréljük a gyökeret és az utolsó elemet, majd töröljük azutolsó elemet. Itt két élen is elromolhatott a kupac-tulajdonság. Ha cserélni kell,akkor a két gyerek közül mindig a kisebb kulcsúval cserélünk.

Mintörlés(A) :CSERE(A(1), A(VÉGE)) ; VÉGE−−LEBILLEGTET(1)Return(A(VÉGE+1))

LEBILLEGTET(i):AA := A(i) ; j := 2i + 1WHILE j ≤ VÉGE

IF A(j − 1) < A(j) THEN j −−IF A(j) < AA THEN A(i) := A(j); i := j; j := 2i + 1

ELSE j :=VÉGE+2j −−IF j ≤VÉGE && A(j) < AA THEN A(i) := A(j); i := jA(i) := AA

7. Tétel. Mintörlés után a kupactulajdonság helyreáll.

Bizonyítás: Úgy tekintjük, hogy mindig i és kisebbik kulcsú gyereke tartal-mát felcseréljük egy-egy lépésben. Állítás: mindig csak az aktuális i és a gyerekeiközti élek mentén lehet baj a kupac-tulajdonsággal. Ez kezdetben igaz. Ha i-nek nincs gyereke, vagy mindkét gyerekének kulcsa nagyobb-egyenl®, akkor ittsincs baj, tehát kész vagyunk. Különben csere után ezen élek mentén a kupac-tulajdonság helyreáll, és csak az új i és gyerekei között romolhat el.

Lépésszám : O(log n)

Kulcs-csökk(K, elem, ∆) :i := C(elem)A(i) := A(i)−∆FELBILLEGTET(i)

Lépésszám : O(log n)

19

Page 20: Adatstrukturak

Alkalmazások:

Rendezés: üres kupacba sorban Beszúrjuk az elemeket, majd sorban Min-törlünk, ez O(n · log n) lépés. Az alábbi, lineáris idej¶ Kupacépítés segítségévelkicsit jobb lesz. Ezt f®leg olyan estekben érdemes használni, amikor a feladatpéldául az els® k legkisebb elem kiíratása (nagyság szerinti sorrendben), ekkora futási id® O(n + k · log n) lesz.

KUPACÉPÍTÉS (nem alapm¶velet) n darab elem kupacba szervezése.

Tetsz®legesen feltöltjük a tömböt, majd alulról felfelé rakjuk rendbe a kupa-cot.

Az algoritmus:az adatok betöltése tetsz®legesen az A tömbbe.FOR i = n/2 . . . 1(−1)

LEBILLEGTET(i)

Lépésszám : (összes lebillentések száma)=n2 · 0 + n

4 · 1 + n8 · 2 + . . . + 1 · dlog ne ≤ n · ( 1

4 + 28 + 3

16 + . . .)

a := ( 14 + 2

8 + 316 + . . .), könnyen láthatóan ez a sor abszolút konvergens,

ezért az a szám létezik. Ekkor a− a2 = (1

4 + 28 + 3

16 + . . .)− ( 18 + 2

16 + 332 + . . .) =

= (14 + 1

8 + 116 + . . .) = 1

2 =⇒ a = 1

Azaz legfeljebb n darab lebillentés kell, így O(n) elemi lépés lesz a lépésszám.

Kitér® : Algoritmusok lépésszámát akarjuk megbecsülni. 1 Lépés-nek (ejtsd�nagy lépés�) konstans sok elemi lépést fogunk nevezni a továbbiakban. S®t, ha

20

Page 21: Adatstrukturak

szükség lesz rá ezt a konstanst növelni is fogjuk az elemzés során (ez nem foggondot okozni, mert a nagyobb konstansba �beleférnek� a növelés el®tti kisebbkonstansok is).

Következmény: Ha n elemb®l a k darab legkisebbet keressük rendezve, akkorennek a lépésszáma O(n + k · log n) lesz.

További alkalmazások találhatók a következ® fejezetekben.

4. Minimális költség¶ feszít®fa és legrövidebb út

keresése

Adott : G = (V,E) összefügg®, irányítatlan gráf c : E → R élköltségekkel.Feladat : Olyan feszít®fát keresünk, melyre c(T ) =

∑e∈T c(e) minimális.

4.1. Kruskal algoritmusa

I. FÁZIS : rendezzük az éleket költség szerint: c(e1) ≤ c(e2) ≤ c(e3) ≤ . . . ≤≤ c(ee). Ez O(e · log n2) = O(e · log n) id®ben megy, ahol e = |E| és n = |V |.

II. FÁZIS : nyilvántartjuk a komponenseket: K = {{v1}, {v2}, . . . , {vn}}T := ∅FOR i = 1 . . . e

IF NOT ei két vége egy komponensbenTHEN T := T + ei ; két komponens uniója.

Megjegyzés : persze ha azt is �gyeljük, hogy T -ben mikor lesz n− 1 él, akkormár meg is állhatunk.

8. Tétel. Ez az algoritmus valóban minimális költség¶ feszít®fát ad.

Bizonyítás:

e

T:

e e

+ - +

1 2 3

+/- jeleket teszünk aszerint, hogy az adott él benne van-e T -ben (T az algorit-mus által adott fa).

Legyen T ∗ olyan optimális fa, melyre a +/− sorozat a lehet® leghosszabbanmegegyezik T -ével. Legyen az els® különbség az i. oszlopban.

21

Page 22: Adatstrukturak

1. eset (−/+) :

T:

ei

T :*

-

+

Ez nem lehetséges, mivel ha a T -be az algoritmus során nem vettük be az ei

élet, akkor ei két végpontja össze van kötve kisebb sorszámú élekkel, azonban:j < i-re ej ∈ T ⇒ ej ∈ T ∗. Ekkor ei T ∗ eddigi éleivel is kört alkot, ez pedigellentmondás.

2. eset (+/−) :

T:

ei

T :*

+

-

Mi lesz T ∗ + ei ? Mivel T ∗ feszít®fa, ebben lesz pontosan egy C kör. Legyen ej

a maximális index¶ éle a C-nek.

2. Állítás. j > i.

Bizonyítás: különben T -ben is ott lenne a C kör, hiszen T az i-nél kisebbindex¶ éleken megegyezik T ∗-gal.

Következmény : c(ej) ≥ c(ei)

T ∗ + ei − ej feszít®fa lesz (hiszen az egyetlen körb®l hagyunk el egy élt).c(T ∗+ei−ej) ≤ c(T ∗) = OPTIMUM. Tehát T ∗+ei−ej is optimális megoldás,de ez ellentmondás, mert ez már az i. oszlopban is megegyezik T -vel.

Következmények :

1. Ha G-ben bármely két él költsége különbözik, akkor egyértelm¶ az opti-mális feszít®fa.

2. Ha az összes lehetséges jó (költség szerint monoton növ®) élsorozatot vesszük,majd ezekre lefuttatjuk az algoritmust, akkor megkapjuk az összes opti-mális (minimális költség¶) feszít®fát.

22

Page 23: Adatstrukturak

Bizonyítás: T ∗-hoz a sorrend megválasztása:

Az azonos költség¶eket úgy rakjuk sorba, hogy a T ∗-ban szerepl® élek le-gyenek el®l. Az el®z® bizonyítást végiggondolva könny¶ látni, hogy ekkor azalgoritmus éppen T ∗-ot adja.

A II. FÁZISmegvalósítása: DISZJUNKT-UNIÓ és HOLVAN m¶veletekkel.

HOLVAN(x) := az x-et tartalmazó halmaz neve (ez egyértelm¶, mivel a hal-mazok diszjunktak).

DISZJUNKT-UNIÓ (H1,H2) : H := H1∪H2, azaz lecseréljük H1-et és H2-tegy új, H nev¶ halmazra.

A II. FÁZIS során legfeljebb 2e darab HOLVAN és pontosan n − 1 darabDISZJUNKT-UNIÓ m¶veletet hajtunk végre (mivel egy fát építünk).

4.2. DISZJUNKT-UNIÓ�HOLVAN adatstruktúrák

3 megvalósítást fogunk megvizsgálni :

A) megoldás : A tömbbel.

HA1 n

2 H2 H2 H2

INIT: FOR i := 1 . . . nA(i) := i

HOLVAN(i) : Return(A(i))

Lépésszám : O(1).

DISZJUNKT-UNIÓ(H1,H2) :

FOR i := 1 . . . nIF A(i) = H2 THEN A(i) := H1

Lépésszám : O(n)

A II. FÁZIS összlépésszáma: O(e + n2) = O(n2).

Megjegyzés: S¶r¶ gráfokra jó megoldás.

B) megoldás : tömbökkel és láncolással okosabban:

4 tömböt használunk:A : ebben tároljuk a halmazok neveit

23

Page 24: Adatstrukturak

L : a halmaz következ® elemére mutató pointereket tároljukK : K(i) az i. halmaz els® elemeM : M(i) az i. halmaz mérete

1 1 1A 13 6 8 20

6 8 20L 0

nincs több elem a halmazbankövetkezõ elem a halmazban

INIT:FOR i := 1 . . . n

A(i) := i; L(i) := 0; K(i) := i; M(i) := 1

HOLVAN(i) : Return(A(i))

DISZJUNKT-UNIÓ(H1,H2) :IF M(H1) < M(H2) THEN H1 ⇐⇒ H2

(felcseréljük a halmazok neveit =⇒ H1 lesz a nagyobb méret¶)M(H1) := M(H1)+M(H2)

(a H2 végére f¶zöm a H1-et, hogy ne kelljen végigmenni H1-en.)i := K(H2)WHILE L(i) 6= 0

A(i) := H1; i := L(i)A(i) := H1

L(i) := K(H1)K(H1) := K(H2)

Ez min(|H1|, |H2|) Lépés lesz. Tehát ennek a lépésszáma, ha egy konkrétDISZJUNKT-UNIÓ m¶veletet végzünk, picit rosszabb is lehet (a konstans na-gyobb), mint az el®z® megvalósításé.

Elemzés : most nem 1 darab DISZJUNKT-UNIÓ m¶velet lépésszámát vizs-gáljuk, hanem azt, hogy az algoritmus az n− 1 darab DISZJUNKT-UNIÓ m¶-velet során összesen hány lépést tesz.

Az elemzés módszere a strigulázás lesz: táblázatokat készítünk el®re és azalgoritmus minden egyes Lépésénél húzunk egy strigulát a megfelel® táblázatba.A végén összeszámoljuk, hogy összesen hány strigulát húztunk és ez lesz azalgoritmus Lépésszáma.

A Lépés konstansát úgy állítjuk be, hogy egy unió annyi Lépés legyen, minta kisebbik halmaz mérete.

24

Page 25: Adatstrukturak

Strigulázás:

1 ni

1. sor (lépés)

2. sor (lépés)

3. sor (lépés)

A j. m¶veletnél a j. sorban i alá húzunk egy strigulát, ha A(i) tartalma meg-változott. Így pont min(|H1|, |H2|) strigulát húzunk.

9. Tétel. Minden i-re i alá legfeljebb log n strigulát húzunk.

Bizonyítás: Minden csúcs el®ször egy egy elem¶ halmazban volt, ezután min-den strigula behúzásakor egy legalább kétszer akkora méret¶be kerül (hiszen akisebbik halmaz elemeinél húzunk strigulát). Így log n strigula után egy n ele-m¶be kerül, tehát készen vagyunk.

Így n− 1 darab DISZJUNKT-UNIÓ lépésszáma O(n · log n) lesz.

Ezért a II. FÁZIS lépésszáma O(e + n · log n).

Okok amiért II. FÁZIS gyorsításán érdemes dolgozni az I. FÁZIS-sal szem-ben:

� Nem biztos, hogy végig kell menni az összes elemen, ha szerencsénk van,a legkisebb n− 1 élet elég ismerni, tehát a kupac segíthet.

� A rendezési algoritmus minden könyvtárban meg van írva gyorsan.

� El®fodul, hogy eleve rendezve kapjuk az éleket, így nincs is szükség az I.FÁZIS-ra.

� Általában az élek költségei kis egész számok, így O(e) id®ben rendezhet®ek(leszámláló rendezéssel).

� Sok más alkalmazásban is használják a HOLVAN és DISZJUNKT-UNIÓm¶veleteket.

C) megoldás : a DISZJUNKT-UNIÓ m¶veletet akarjuk 1 Lépésben meg-valósítani, a HOLVAN m¶velet lesz lassabb.

Az ötlet : A halmazokat gyökeres fákként (mindenkinek csak szül®pointerelesz) fogjuk ábrázolni, a gyökérben a halmaz neve lesz.

25

Page 26: Adatstrukturak

H1

HOLVAN(x) : x-b®l indulva mindig a szül®re lépünk, míg a gyökérbe nemérünk, ott kiolvassuk a halmaz nevét.

DISZJUNKT-UNIÓ: r rang segítségével. A rang lényegében a fa magasságalesz, pontosabban egy fels® becslés lesz a fa magasságára. Igazából a rangokatnem csak a fákhoz (gyökerekhez), hanem minden egyes csúcshoz hozzárendel-jük, de a fenti jelentésük csak gyökerek esetén lesz meg, a többi esetben azalgoritmushoz nem, csak az elemzéshez használjuk. A rangokat kezdetben csupanullára inicializáljuk. Mindig a kisebb rangú halmazt kötjük át a nagyobba:

H1

H2

Ha r(H1) < r(H2)

H1

H2

26

Page 27: Adatstrukturak

Ha r(H1) > r(H2)

H1H2

Ebben a két esetben nem n® a rang.

Ha r(H1) = r(H2)

H1 H2

r(H1) + + (A H1 rangja n®tt!)

Kitér® :Egy csúcs (v) mélysége : a gyökérb®l a v-be vezet® út hossza.

Egy csúcs (v) magassága : ha l a v alatt a legtávolabbi levél, akkor a v-b®ll-be vezet® út hossza.

A fa magassága:=gyökér magassága= maxv v mélysége=:a fa mélysége.

v

l

HOLVAN javítása: Ötlet: ha már sokat kell dolgoznunk, akkor dolgozha-tunk egy kicsivel többet, ha ezzel a továbbiakban id®t spórolunk. (A többlet-munka során kicsit �helyrepofozzuk� az adatstruktúrát.)

27

Page 28: Adatstrukturak

Módszerek:

Útrövidítés:

x

Még egyszer végigmegyünk a fában azx-t®l a gyökérig vezet® úton, és mindenszül® pointert a gyökérre állítunk (kivéve a gyökérét).

Útfelezés:

x

Az x-t®l a gyökérig vezet® úton minden csúcs szül® pointerét átállítjuk anagyapjára (kivéve a gyökérét és a közvetlenül alatta lév®ét). Ehhez nem kellmég egyszer végigmenni a fán, egyszer¶en egy lépéssel tovább megjegyezzük aszül® pointereket. Ez a módszer akár jobb is lehet mint az útrövidítés, mivel ittelég egyszer végigmenni a fában a keres®úton. Útrövidítés esetén pedig újabbciklust kell használnunk, amely megkezdése (el®készítése) id®t igényel.

Természetesen az útrövidítés és az útfelezés során semelyik csúcs rangja nemváltozik.

28

Page 29: Adatstrukturak

Az útrövidítés és az útfelezés elemzése

A Kruskal algoritmus n − 1 darab DISZJUNKT-UNIÓ és m = 2e darabHOLVAN m¶veletet végez. Azt fogjuk elemezni, hogy összesen hány lépésbenvalósíthatjuk ezt meg.

3. Állítás. r(v) az elején 0 és monoton n®. Ha v nem gyökér egy adott pilla-natban, akkor sose lesz az, és az r(v) már soha többé nem változik.

4. Állítás. r(v) < r(p(v)) (ha v nem gyökér).

Bizonyítás:DISZJUNKT-UNIÓ m¶velet: Ha a kisebb rangút kötöttük be a nagyobb alá,akkor teljesül az állítás. Egyenl® rangúaknál szintén teljesül az állítás, mivelekkor az új gyökér rangját növeljük.

HOLVAN: Ha átkötöm, akkor nagyobb rangúba kötöm, és mivel átkötés el®ttteljesült ez a tulajdonság, tehát nem romolhat el.

5. Állítás. x gyöker¶ fában van legalább 2r(x) darab elem, következésképpen∀v : r(v) ≤ blog nc.

Bizonyítás:1 pontú fára teljesül az állítás.DISZJUNKT-UNIÓ: különböz® rangúak esetén nyilván teljesül. Egyenl® ran-gúnál: mindkét fában legalább 2r(x)−1 darab elem van, a kötés után legalább2 · 2r(x)−1 = 2r(x) lesz.

HOLVAN: nem változtatja meg ezt.

6. Állítás. Állítás:∣∣{v | r(v) = k}

∣∣ ≤ n2k .

Av := {w | w a v leszármazottja volt, amikor r(v) = k lett}

Belátjuk, hogy ha r(x) ≥ k és r(y) ≥ k és x 6= y ⇒ Ax ∩ Ay = ∅. (El®z®állítás ⇒ |Ax| ≥ 2k, tehát ebb®l tényleg következik.)

Tfh. y lett kés®bb k rangú. Ekkor x /∈ y gyöker¶ fának a 4. állítás miatt.Ugyanakkor Ax minden eleme x-szel azonos fában van. ⇒ valóban diszjunktak.

De�níció: Torony függvény: T (0) = 1 és T (n + 1) = 2T (n).Az inverze: G(n) = log∗(n) = min{k | T (k) ≥ n}

Megjegyzés: Ha n ≤ 265536 ⇒ G(n) ≤ 5 (Az univerzumban kevesebb, mint265536 atom van.)

29

Page 30: Adatstrukturak

Rangcsoportok:

0 2 3 51 174 16 65536

R0 R1 R2 R3 R4

Ri := {T (i− 1) + 1 . . . T (i)}. v az Ri rangcsoportban van, ha r(v) ∈ Ri

Elemzés:

DISZJUNKT-UNIÓ: 1 Lépés

HOLVAN: annyi Lépés, ahány csúcsot érintünk az útfelezés/útrövidítés so-rán.

Például:

5 Lépés

A HOLVAN m¶veleteket ügyesen fogjuk elemezni, minden egyes m¶veletsorán annyi strigulát fogunk behúzni, ahány csúcsot érintettünk. Azonban astrigulákat különböz® helyekre fogjuk behúzni. A végén összeszámoljuk (felülr®lbecsüljük) majd az összes helyen lév® strigulákat.

2 féle helyre fogunk strigulát húzni: vagy az adott m¶velethez:1. HOLVAN2. HOLVAN...m. HOLVAN

Vagy a csúcsokhoz (az alaphalmaz elemeihez):v1

v2...vn

30

Page 31: Adatstrukturak

Az i. HOLVAN m¶veletnél a strigulázási szabály:

A m¶velet során bejárt út bármely v csúcsára:

Az i. HOLVAN m¶velethez húzunk egy strigulát, ha:

� v vagy p(v) gyökér,

� vagy ha v szül®je nem ugyanabban a rangcsoportban (hanem nagyobban)van, mint v.

Minden más esetben a v csúcshoz húzunk egy strigulát.

Az összes (m darab) HOLVAN m¶velet után megszámoljuk, hogy hány stri-gula van a m¶veleteknél és mennyi a csúcsoknál.

Maximális rang≤ log n⇒ a legnagyobb rangcsoport (Rα), ahol α ≤ G(log n) == G(n)− 1. Tehát legfeljebb G(n) darab rangcsoportunk van. (A 0-s csoporttalegyütt.)

Az i. HOLVAN sorában a strigulák száma legfeljebb 2+(G(n)−1) = G(n)+1,mert az út mentén a rangcsoport legfeljebb G(n)− 1 -szer n®het.

Hány strigulát húzhattunk egy csúcs mellé:

� Csak akkor kezdünk el strigulákat húzni egy csúcs mellé, ha már nemgyökér.

� Útfelezés/útrövidítés esetén a rang szigorú monotonitása miatt r(p′(v)) >> r(p(v)), azaz v új � p′(v)-vel jelölt � szül®jének rangja szigorúan na-gyobb, mint az átkötés el®tti szül®jéé.

Ha r(v) = r, akkor v a g := G(r)-edik rangcsoportban van.

10. Tétel. Ekkor a v csúcs mellé maximálisan T (g)−T (g−1) strigula kerülhet(g ≥ 1 esetén).

Bizonyítás: T (g) − T (g − 1) szám van a g. rangcsoportban. Ha már kerültstrigula v mellé, akkor r(v) nem változik, míg r(p(v)) id®ben n®. Azonban ha a grangcsoporton túln®tt, akkor az adott csúcs mellé már soha többé nem húzunktöbb strigulát.

Strigulák összeszámolása:N(g) : jelentse azt, hogy maximálisan hány csúcs lehet a g-edik rangcsoportban.

N(g) ≤T (g)∑

r=T (g−1)+1

n

2r≤ n

2T (g−1)+1(1 +

12

+14

+ . . .) =n

2T (g−1)=

n

T (g).

31

Page 32: Adatstrukturak

Összefoglalva: g rangcsoportbeli csúcsok mellé összesen legfeljebb nT (g) ·(T (g)−

− T (g − 1)) ≤ n strigula kerülhet.Ez igaz g = 0-ra is, mivel legfeljebb n darab csúcs lehet a 0. rangcsoportban ésa 0-s rangcsoportú csúcsok mellé csak 1 strigula kerülhet.Így összesen a csúcsok mellé legfeljebb G(n) · n strigula került.

Lépésszám: O(n− 1 + m · (G(n) + 1) + n ·G(n)) = O((n + m) ·G(n)), aholm a HOLVAN m¶veletek száma.

Ha a Kruskal algoritmus II. FÁZISÁT így valósítjuk meg összefügg® gráfra(ekkor: m = 2e > n), akkor a lépésszám O(e ·G(n)) lesz, ami gyakorlati szem-pontból lényegében lineárisnak tekinthet®, de valójában a legrosszabb esetbentényleg nem lineáris, nem csak mi voltunk nagyvonalúak az elemzésnél.

4.3. Prim algoritmusa

Az algoritmus ötlete: Kezdetben induljunk ki az 1-es számú csúcsból, majdminden egyes lépésben b®vítsük ezt a fát (és az S csúcshalmazát), úgy, hogy abel®le kiinduló (S és V − S közötti) legkisebb költség¶ élet vesszük hozzá.

S P M

min

T : aktuális faS : T-nek a csúcshalmazaP := {v ∈ V − S | ∃uv ∈ E, u ∈ S}M := V − S − P

Egy adott lépésnél az M -beli csúcsokkal nem foglalkozunk.A P -beli csúcsokra két dolgot tartunk nyilván:

� K(v) := min{c(uv) | u ∈ S} - ha a v csúcsot kötöm be következ®nek,akkor ez milyen költséggel fog járni.

32

Page 33: Adatstrukturak

� p(v) := argmin{c(uv) | u ∈ S} - ha ®t kötöm be, melyik csúcshoz kellkötni (ha több ilyen csúcs is van, akkor közülük az egyik)

Az algoritmus:

INIT: P := {1}; S := ∅; M := V − {1}; T := ∅K(1) := 0; p(1) := 1

WHILE P 6= ∅v legyen a P -ben minimális K(v) érték¶ csúcsS ← v ← PIF p(v) 6= v THEN T := T + {p(v), v}FOR vu ∈ E

IF u ∈ P && c(vu) < K(u) THEN K(u) := c(vu); p(u) := vIF u ∈M THEN K(u) := c(vu); p(u) := v; P ← u←M

Lépésszám:

Szomszédsági mátrix esetén : O(n2) (láttuk a szélességi keresésnél, hogy ennélgyorsabban nem is lehet).

Éllistával, kupacokkal :

M¶velet Végrehajtások számaMintörlés nKulcs-csökkentés eBeszúrás n

Mindegyik m¶velet O(log n) idej¶, ha kupaccal csináljuk, így az algoritmusO(e · log n) idej¶ lesz.

Megjegyzés : ritka gráfok esetén ez sokkal jobb, mint az O(n2), de még javítanifogunk rajta.

4.4. Dijkstra algoritmusa

Adott: G = (V,E); és c : E → R+0 (hosszúság függvény, néha költségnek hívjuk)

Feladat: keressük az s-b®l t-be vezet® legrövidebb utat.

Az algoritmus ötlete: Irányítatlan gráfokra jól szemléltethet®, ha elkészítjüka gráfot: a csúcsok gyöngyök, az élek megfelel® hosszúságú cérnák. Lefektetjükaz asztalra, és s-nél fogva lassan felemeljük.

A megvalósítás nagyon hasonlít a Prim algoritmuséhoz. Minden egyes lépés-ben azt fogjuk tárolni az egyes csúcsokra, hogy hol vannak, és hogy mi az eddigide talált legrövidebb út K(v) hossza (azaz ha v emelkedne fel legközelebb, ak-kor milyen messze lenne s-t®l). Minden egyes lépésben a P -beli legkisebb kulcsúcsúcsot �emeljük fel�, majd szomszédain módosítjuk a kulcsot.

33

Page 34: Adatstrukturak

S : a leveg®ben lév® gyöngyszemek.

P : olyan gyöngyszemek, amelyek az asztalon vannak, de van olyan szom-szédjuk, ami a leveg®ben van.

M : a többi csúcs.

Megjegyzés: Negatív élhosszakkal nem fog m¶ködni az algoritmus.

Példa:

2

3

-2

Az algoritmus:

INIT: P := {1}; S := ∅; M := V − {1}K(1) := 0; p(1) := 1

WHILE P 6= ∅v legyen a P -ben minimális K(v) érték¶.S ← v ← PFOR vu ∈ E

IF u ∈ P && K(v) + c(vu) < K(u) THENK(u) := K(v) + c(vu); p(u) := v

IF u ∈M THEN K(u) := K(v) + c(vu); p(u) := v; P ← u←M

1. De�níció. Egy s −→ x út S-út, ha minden csúcsa S-ben van kivéve esetlegx-et.

11. Tétel. Az algoritmus során minden WHILE végén:

(a) Bármely x ∈ S-re K(x) a legrövidebb s −→ x út hossza, és az ilyenhosszúságú utak között van S-út is.

(b) Minden x ∈ P -re K(x) a legrövidebb S-út hossza.

Bizonyítás: (a) Elég az éppen S-be átrakott csúcsra belátni, legyen ez r. Azr-be nem létezik K(r)-nél rövidebb út, mivel :

34

Page 35: Adatstrukturak

S P M

h

r

w

>=0

Indirekt tegyük fel, hogy létezik ennél rövidebb Q út, ekkor az indukciós fel-tevés szerint ez nem S-út, legyen az els® P -beli csúcsa w 6= r. Ekkor r de�níciójamiatt K(r) ≤ K(w), és így az indukciós feltevés miatt a Q út s-t®l w-ig terjed®része nem rövidebb, mint K(r) = r-be vezet® legrövidebb S-út hossza. Mivelaz élhosszak nemnegatívak, a Q út w-t®l r-ig terjed® része is nemnegatív, tehátösszesen Q hossza legalább K(r), ami ellentmond Q választásának.

Az állítások többi része hasonlóan bizonyítható.

12. Tétel. (a) Ha az S-be kerülés sorrendjében veszem a csúcsokat(vi : i.-nek került S-be), akkor K(v1) ≤ K(v2) ≤ . . . ≤ K(vn).

(b) Ha utoljára v került S-be, akkor minden u ∈ P -re K(v) ≤ K(u) ≤ K(v)++ maxxy∈E c(xy).

Bizonyítás szintén indukcióval, el®sz®r (b)-t érdemes. Ha utoljára v kerültS-be, akkor minden u ∈ P -re K(v) ≤ K(u), mert a v-t úgy választottuk. Akulcsmódosítások el®tt az indukciós feltevés (a) része miatt a második egyen-l®tlenség is fennállt, és kulcsmódosítás közben nyilván nem romolhat el egyikegyenl®tlenség sem. Ebb®l az (a) rész rögtön következik.

13. Tétel. Az x csúcsba vezet® egyik legrövidebb út (hátulról el®re állítjuk el®):s, . . . , p(p(x)), p(x), x.

Megjegyzések :

� Az algoritmus módosítható úgy, hogy pl. legszélesebb ill. legbiztonságo-sabb utat keressen.

� Ha megengedjük a negatív élhosszakat, akkor a feladat NP -nehéz lesz.

35

Page 36: Adatstrukturak

� Irányított gráfok esetén, ha bármely irányított kör nemnegatív, akkor vanmásik algoritmus (Bellman-Ford), amely helyes és polinomiális, de las-sabb: O(e · n).

� Viszont aciklikus irányított gráfok esetén negatív élsúlyra is van kicsitegyszer¶bb, O(e) idej¶ algoritmus, ezt használják pl. a PERT módszerben.

� Irányítatlan esetben, ha nincs negatív kör, akkor szintén létezik polinomi-ális algoritmus, de az bonyolult.

Elemzés

Ugyanúgy, mint a Prim algoritmusnál, tehát szomszédsági mátrix eseténO(n2) a lépésszám, éllista esetén, ha valamilyen kupacot használunk, akkor pe-dig legfeljebb n darab Beszúrás, n darab Mintörlés, és e darab Kulcs-csök kell.

4.5. d-edfokú kupacok

2. De�níció. Egy fa d-edfokú kupac, ha

� minden csúcsnak legfeljebb d gyereke van

� kupacrendezett

� kiegyensúlyozott

Tömbös megvalósítás esetén 0 az els® index, és az i index¶ csúcs gyerekeinekindexei d · i+1, d · i+2, . . . , d · i+ d. Tehát a j szül®je b j−1

d c. A kiegyensúlyozásitt (is) azt jelenti, hogy a tömbben nincs lyuk.

A m¶veleti id®k változása:

Beszúrás, Kulcs-csökkentés (felbillegtetés): O(logd n)

Min-törlés (lebillegtetés): d gyerekb®l minimum kiválasztása: d−1+ az aktuáliskulccsal való hasonlítás = d. Mivel a fa mélysége logd n, így O(d · logd n) adódik.

Érdekes eset: d = 4. Itt :

Felbill. : log n helyett log4 n = log n2

Lebill. : 2 · log n helyett 4 · log4 n = 2 · log n

Tehát egyértelm¶en jobb.

A Dijkstra és Prim algoritmus lépésszáma d-edfokú kupaccal

36

Page 37: Adatstrukturak

Mi vajon a legjobb d? Erre általában nincs egyértelm¶ válasz, az egyes m¶-veletek gyakoriságától függ.

Tekintsük a Dijkstra (vagy a Prim) algoritmust. Itt az egyes m¶veletek száma:

n db Beszúrás, Min-törlés

e db Kulcs-csökkentés

Az elv: gyorsítsuk amib®l sok van. A teljes lépésszám: O(n·d·logd n+e·logd n) == O(max(n·d·logd n, e·logd n)). Az els® tag d ≥ 3-ra szigorúan növ®, a másodikszigorúan csökken®, tehát a maximum a lehet® legkisebb értéket ott veszi fel,ahol a kett® egyenl®.

d

n · d · logdn = e · logdn

d =e

n

d∗ := max(2,⌈ e

n

⌉)

-et érdemes használni, mert d-nek egésznek kell lennie és nem akarunk 1-etalapnak.

Így a lépésszám O(e · logd∗ n). Ez ritka gráf esetén (ha e ≈ c ·n) nem nagyonsegít, de s¶r¶nél igen:

Ha e ≥ n1+ε ⇒ d∗ ≥ nε ⇒ logd∗ n ≤ 1/ε ⇒ a lépésszám: O( 1ε · e) = O(e),

ha ε konstans.

5. Amortizációs elemzés

5.1. Konvex burok keresése

Adott : pi = (xi, yi) ∈ R2 (1 ≤ i ≤ n és xi 6= xj , ha i 6= j) pontok a síkban.Feladat : A pontok konvex burkának megtalálása (a rajta lév® csúcsok felsorolása

37

Page 38: Adatstrukturak

pozitív irányú bejárás sorrendjében).

F tömb

A tömb

(x ,y )1 1

(x ,y )2 2

(x ,y )k k

(x ,y )k+1 k+1

Megoldás :

I. rendezzük a pontokat xi-k szerint (x1 < x2 < . . . < xn)Id® : O(n · log n)

II. Egy adott ciklusban tudjuk az p1, . . . , pi−1 pontok konvex burkát, különtároljuk balról jobbra rendezetten az F fels® és az A alsó ívet.

FOR i = 2 to nFelez® kereséssel az alsó és a fels® íven végigmenve megkeressük az ug-

rópontot (az utolsó olyat, ami még az p1, . . . , pi halmaz konvex burkán is rajtavan)A és F további részét elfelejtjük, majd végükre rakjuk pi-t.

Megjegyzés: F (j) az ugrópont, ha az F (j − 1) és F (j) pontokat összeköt®egyenes pi felett megy, de az F (j) és F (j + 1) pontokat összeköt® egyenes máralatta.

Id®: 1 pont hozzáadása legfeljebb O(log n), így az összid®: O(n · log n).

Összefoglalva : síkban a konvex burok keresés O(n·log n) id®ben megoldható.

Itt is érdemes a második fázist gyorsítani (pl. lehet, hogy x szerint rendezvekaptuk a pontokat).

14. Tétel. Ha a felez® keresés helyett jobbról indulunk és sorban megvizsgáljuk,hogy az adott pont-e az ugrópont, akkor a második fázis ideje csak O(n).

5.2. Az amortizációs elemzés

Bevezetjük az alábbi jelöléseket:TIi : az i. m¶velet tényleges ideje.Potenciál : bármely állapothoz hozzárendelünk egy nemnegatív valós számot.P0 = 0 és ∀Pi ≥ 0.AIi : az i. m¶velet amortizációs ideje.AIi := TIi + ∆P = TIi + (Pi − Pi−1).

38

Page 39: Adatstrukturak

Így∑

i AIi =∑

i TIi + PT − P0 ≥∑

i TIi.

Tehát az amortizációs id® egy fels® becslést fog adni a m¶veletek összidejére.

Megjegyzés : Tipikusan olyan állításokat bizonyítunk, hogy pl. egy-egy m¶-velet amortizációs ideje legfeljebb O(log n), ebb®l következik hogy m m¶veletelvégzésének tényleges összideje legfeljebb O(m · log n). De persze 1 adott m¶ve-let elvégzésének tényleges ideje lehet akár c · n is, ezért az amortizációs elemzésnem hasznos valós idej¶ folyamatok elemzésekor (pld. : egy repül®gép navigációsrendszerét®l nem azt várjuk, hogy átlagosan gyorsan döntsön, hanem azt, hogyminden egyes vészhelyzetre azonnal reagáljon).

5.3. Példa: a konvex burok keresés amortizációs elemzése

A 14 tétel bizonyítása:

A potenciál de�niálása : P := |F |+ |A|.

1 Lépés de�niálása : F-ben i∗ megkeresése l + 1 Lépés legyen, ha F végér®ll csúcsot töröltünk ki.(Ugyanígy de�niáljuk a Lépéseket A esetén is, ekkor l′ a törölt csúcsok száma).

Amortizációs elemzés : AIk+1 = TIk+1 + ∆P = ((l + 1) + (l′ + 1) + 1 + 1)−− ((l − 1) + (l′ − 1)) = 6

Azaz egy csúcs beszúrásának amortizációs ideje 6. Ez azt jelenti, hogy 6nLépésben, azaz O(n) id®ben megoldható a feladat. Az elemzés persze attól m¶-ködik, hogy ha egy csúcsot F -b®l vagy A-ból kidobunk, akkor azzal kés®bb mársose kell foglalkoznunk, hiszen már az aktuális ponthalmaz konvex burkának isbels® pontjai. Összesen persze a két tömbb®l kevesebb mint 2n esetben dobha-tunk ki pontot.

6. Fejlettebb kupacok

6.1. Fibonacci kupac

Tulajdonságai:

� Több kupacrendezett fából áll, amelyekben egy csúcs gyerekeinek számanincs korlátozva, és nem is kiegyensúlyozottak.

� a gyökerek ciklikusan két irányban körbe vannak láncolva,

� a kupacot egy H pointerrel azonosítjuk, amely a minimális kulcsú gyökérremutat.

Tárolás:

39

Page 40: Adatstrukturak

� Minden elemhez 4 pointert tárolunk: szül®je, bal testvér, jobb testvér, egygyereke (mindegy, hogy melyik gyerek: ®k is ciklikusan két irányban körbevannak láncolva, így gyorsan megtalálhatjuk ®ket).

� r(v) ∈ N : a v elem rangja (a gyerekeinek a száma).

� m(v) ∈ {0,1} : jelöl® bit.

H

M¶veletek :

Beszúrás(új) :

� a gyökerek közé új gyökérként (1 pontú fa) felvesszük új-at.

� Ha KULCS(új) < K(H), akkor a H-t az új-ra állítom.

új elem

Id®: O(1).

Mintörlés :

� MIN := H, a végén Return(MIN)

� I. fázis : H gyermekeit gyökeresítjük és a szül® pointereiket nil-re állítjuk.

� II. fázis : Amíg létezik 2 azonos rangú gyökér, addig LINK m¶velettelösszekapcsoljuk ezeket.

40

Page 41: Adatstrukturak

� III. fázis : végigmegyünk a gyökereken és a minimális kulcsú gyökérre ál-lítjuk H-t.

Megjegyzés: a végén tudni fogjuk, hogy minden elem rangja legfeljebb R == O(log n).

I. fázis ideje:a gyerekek bef¶zése a gyökerek listájába konstans id®ben megy, a szül® pointereknil-re állítása R = O(log n) lépésben (H-nak legfeljebb R gyereke lehet).

LINK(u, v) m¶velet:Ha K(u) ≤ K(v), akkor v-t kötöm u alá és u rangját növelem eggyel, különbenu-t v alá (ebben az esetben v rangja n® eggyel). Visszaadja annak a csúcsnak anevét (pontosabban egy pointert arra a csúcsra), amely gyökér maradt.

1 LINK Ideje: O(1). Ezt fogjuk el®ször 1 Lépés-nek tekinteni.

II. fázis megvalósítása:

T segédtömb segítségével : T (0 . . . R).T indexe: rangokT (i) értéke: mutató egy i rangú gyökérre, ha van az eddig vizsgáltak között, nilkülönben.

Az algoritmus:

FOR i = 0 . . . RT (i) := nil

FOR v ∈ gyökerekw := vWHILE T (r(w)) 6= nil

w := LINK(w, T (r(w)))T (r(w)− 1) := nil

T (r(w)) := w

Id® : Ha a Lépésben a konstanst 2-szeresére vesszük, akkorTI = O(log n) + #LINK.

A Fázis végén legfeljebb R + 1 darab gyökér marad. (Minden lehetségesranghoz legfeljebb 1.)

A LINK-elések után az alábbi alakú ún. kanonikus fák (vagy binomiáliskupacok) keletkeznek (mindaddig, míg csak Beszúrás és Mintörlés m¶veleteketvégeztünk)

41

Page 42: Adatstrukturak

1. rangú 2. rangú 3. rangú

III. fázis ideje:Legfeljebb R = O(log n) összehasonlítással megy.

Összefoglalva: TI = O(log n) + #LINK

1. potenciál : gyökerek száma

Beszúrás : AI = O(1) + 1 = O(1).

Mintörlés : AI ≤ (O(log n) + #LINK) + (−1 + R−#LINK) = O(log n).

Kulcs-csökk :(H, v, ∆) :

Levágjuk v-t a szül®jér®l és gyökeresítjük (bef¶zzük a gyökerek listájába),majd:

� K(v) :=K(v) - ∆

� IF K(v) < K(H) THEN H := v

Ennek a lépésnek a tényleges ideje 1 Lépés, az amortizációs ideje 2 Lépés.

Látszólag készen vagyunk, de van egy nagy baj: Így nem marad igaz, hogya rang legfeljebb R = O(log n).

Szeretnénk: ha r(v) = r, akkor v-nek van legalább cr (c > 1) leszármazottja(ami persze max. n lehet). Ez Kulcs-csökk nélkül még teljesülne, de így nemteljesül : ha minden unokára csinálnak egy-egy Kulcs-csökk m¶veletet, akkorv-nek saját magán kívül csak a gyerekei maradnak meg leszármazottnak, mígrangja nem változik:

42

Page 43: Adatstrukturak

Megoldás: m(v) jelz®bit használata:

� Ha gyökér: 0 (gyökeresítéskor visszaállítjuk 0-ra, ha nem az volt)

� Ha v nem gyökér és levágjuk egy gyerekét, akkor m(v) := 1.

Kaszkád-vágás : addig vágunk, amíg a szül®jének jelz®bitje nem 0. (Utánaezt a 0-t 1-re állítjuk, ha nem gyökéren van.)

0

1

1

v

0

1

1

v

1

v

Tehát a Kulcs-csökkentés végleges megvalósítása:

Kulcs-csökk :(H, v, ∆) :

Levágjuk v-t a szül®jér®l és gyökeresítjük (bef¶zzük a gyökerek listájába),majd:

� A Kaszkád-vágást folytatjuk, addig, amíg az utoljára gyökeresített csúcsszül®je jelöletlen nem lesz, és a végén ezt a szül®t megjelöljük, ha nemgyökér

� K(v) :=K(v) - ∆

� IF K(v) < K(H) THEN H := v

Az elemzéshez egy új potenciált kell de�niálni :

2. (Végs®) Potenciál : #gyökerek +2 ·#jelölt csúcsok.

A Beszúrásnál és Mintörlésnél nem kell kaszkádvágás⇒ itt a potenciálválto-zás csak kevesebb lehet, mint az 1. Potenciállal ( H gyerekeinek gyökeresítésekornéhány jelz®bit 0-ra változhat) ⇒ ezek AI-je jó marad!

Kulcs-csökk : k db vágás van a kaszkádvágás során, ekkor legalább k − 1helyen 0-ra változott meg a jelöl®bit, míg 1-re csak legfeljebb 1 helyen.

TI : k Lépés∆P ≤ −2(k − 1) + k + 2 = 4− k.

� −2(k − 1) : jelöl®bitek száma legalább ennyivel csökken

43

Page 44: Adatstrukturak

� k : új gyökerek

� 2 : ha nem gyökérben hagytuk abba a vagdosást, lesz egy új jelölt

AI = TI + ∆P ≤ 4.

Most belátjuk, hogy a rang nem lehet túl nagy:

y1 y2 yr(x)

Egy tetsz®leges id®pontban indexeljük az x csúcs y1, . . . , yr(x) gyerekeit a gye-rekké válás sorrendjében (azaz, hogy mikor lett utoljára x gyereke).

15. Tétel. r(yi) ≥ i− 2

Bizonyítás:

y1 yi-1

yi

Amikor yi az x gyereke lett (utoljára):

LINK → rangjuk egyenl® volt → ekkor a rangjuk legalább i − 1 volt →azóta yi rangja csak egyet csökkenhetett, különben levágtuk volna x-r®l.

3. De�níció. Sk jelölje azt, hogy egy legalább k-adrangú csúcsnak minimumhány leszármazottja lehet (bármikor).

Megjegyzés: minden elem leszármazottja saját magának.

S0 = 1

S1 = 2

16. Tétel. Sk ≥k−2∑i=0

Si + 2

Bizonyítás:

44

Page 45: Adatstrukturak

y1 y2 yi yk

x

S0 Si-2 Sk-2

Fibonacci számok: F0 = 0 ; F1 = 1 ; Fn+2 = Fn+1 + Fn

17. Tétel. Sk ≥ Fk+2.

Bizonyítás: Indukcióval triviális.

Fk+2 ≥

(√5 + 12

)k

, azaz: Sk ≥

(√5 + 12

)k

Emlékeztet® n jelöli a kupacban szerepl® elemek maximális számát. Tehátbármely v elemnek legfeljebb n leszármazottja lehet ⇒ r(v) ≤ log“√

5+12

” n ≈

≈ 1,44 · log n. Ez lesz R értéke.

Azaz beláttuk, hogy a Fibonacci-kupaccal :

n db beszúrásn db mintörlése db kulcs-csökkentés

összes ideje: O(n log n + e).

Ebb®l következik:

18. Tétel. A Dijkstra és a Prim algoritmus futási ideje Fibonacci-kupaccalO(n log n + e).

Megjegyzések:

� A Dijkstra-ban ez alá nem lehet lemenni (mivel tud rendezni és összefüg-g®séget is el tud dönteni).

� A Prim-nek is ez a legjobb futási ideje, de minimális költség¶ feszít®fátm < n log n esetén lehet gyorsabban is keresni.

6.1.1. Amortizációs id® és a strigulázás kapcsolata

Amikor egy m¶veletet végzünk, akkor kapunk a m¶velet megengedett amorti-zációs idejének megfelel® $-t. Ha az algoritmust kevesebb Lépésb®l tudjuk vég-rehajtani, akkor a maradékot berakjuk a bankba. Ha viszont több Lépésre vanszükségünk, akkor a különbözetet ki kell vennünk a bankból.

45

Page 46: Adatstrukturak

TI<AI

TI'>AI'

IIIIIIIII IIIII

FIZETÉS BANK

AI-TI

IIIIIIII IIIIAI' TI'-AI'

-(TI'-AI')

Kell : A bank pénze ne mehessen le negatívba. Ezt pont azzal biztosítjuk, hogymegköveteljük, hogy P ≥ 0 legyen, ugyanis egy adott pillanatban a bankbanlev® pénz éppen az aktuális potenciál.

6.2. Párosítós kupacok

Ami nem annyira jó a Fibonacci-kupacban:

� nagy helyigény (sok pointer)

� nagy szorzók vannak (1,44) és az 1 Lépés is sok kis elemi m¶veletb®l áll.

Párosítós kupac a gyakorlatban: mindig jobb, mint a Fibonacci, de még nemtaláltak hozzá olyan potenciált, amivel be tudnák látni ugyanazokat az amorti-zációs id®ket.

Ötlet : A Fibonacci-kupacot akarjuk utánozni, de bináris fával és kevesebbpointerrel. El®ször emeljük fel a H gyökeret és helyére f¶zzük be a gyerekeit.Majd forgassuk el 45◦-kal az egészet, ez lesz a párosítós kupac. Tehát itt a balgyerek felel meg az �els®� gyereknek, a jobb gyerek a következ® testvérnek.

a b c

va

b

c

v

A párosítós kupac de�níciója:

� Bináris fa.

� Az egyetlen gyökérnek (ami H-nak felel meg) nem lehet jobb gyereke.

� Félig kupacrendezett: K(v) ≤ K(x) a v bal �ának minden x leszárma-zottjára.

Így csúcsonként akár 2 pointert is nyerhetünk, ha használjuk még a binárisfák memóriatakarékos megvalósítását: csúcsonként 2 pointer és 1 bit.

46

Page 47: Adatstrukturak

1 bit: bal vagy jobb gyerek.

47

Page 48: Adatstrukturak

1. pointer:

� bal gyerek, ha létezik

� jobb gyerek, ha csak az létezik.

� nil : ha egyáltalán nincs gyereke.

2. pointer:

� ha ® maga bal gyerek, akkor a testvérre mutat, ha létezik, különben aszül®re.

� Ha jobb gyerek: a szül®re mutat.

� Gyökérben nil.

Könny¶ Hf: egy eredeti pointer szerinti lépéshez így két lépés és egy harma-dik kiolvasás-vizsgálat kell.

Vissza a párosítós kupachoz: de�niálnunk kell még a m¶veleteket.

LINK m¶velet :

a

x 4

b

y 3

A B

LINK a

xb

A B

y

Id®: O(1).

Kupacm¶veletek :

Beszúrás :1 elem¶ új kupac + LINK

Kulcs-csökk :

� kivágjuk az elemet

� csökkentjük a kulcsot

� majd LINK.

48

Page 49: Adatstrukturak

v

v

TI = O(1).

Mintörlés :

v

vágás

1

2

3

4

5

6

7

8

A gyökeret levágjuk, majd az új gyökért®l jobbra lefelé haladva minden életelvágunk. Így sok kisebb párosítós kupacunk keletkezik. Össze kell LINK-elni aszétvágott kupacokat.

A legjobb megoldás : Elindulunk lefelé és párosával összeLINKeljük a ku-pacokat, majd ezután alulról felfelé haladva végzünk LINK-eléseket (mindig akövetkez®t az el®z® eredményéhez).

Miért ez a legjobb : Az a rossz, ha a két linkelend® kupacnak nagyon eltér amérete. Az a jó, ha kb. egyenl® nagyságúakat linkelünk, ezt próbáljuk elérni.

Ami bizonyítható: a P =∑

v log(#v leszármazottai) potenciállal O(log n)az amortizációs ideje minden m¶veletnek.

Azonban a gyakorlati futtatások azt mutatják, hogy igazából a Kulcs-csökkentésekátlagos ideje konstans.

49

Page 50: Adatstrukturak

6.2.1. A párosítós kupacok legjobb változata

Ötlet : Még lustábban. Nem jó kicsiket nagyobbakkal LINK-elni. Ezt tipikusana Beszúrás és Kulcs-csökk m¶veleteknél tesszük. Ezért ennél a két m¶veletnélLINK-elés helyett egy külön segédterületre rakjuk ®ket.

segédterület

Beszúrás Beszúrás . . .

A segédterületet tárolhatjuk a gyökér jobb leszármazottaiként. Ebben az esetbencsak a Mintörlésnél kell többet dolgoznunk.

Mintörlés :

� El®ször a segédterületen végzünk LINK m¶veleteket. Párosával keletke-zési sorrendben LINK-elünk, majd újra elölr®l párosával, míg az egészsegédterület 1 kupac nem lesz.

� Összelinkeljük az eredeti és a segédkupacot.

� Majd hagyományos Mintörlés.

6.3. r-kupacok

Dijkstra algoritmushoz : Feltesszük, hogy az élek hossza a [0, C] tartománybeliegészek ⇒ a kulcsok a [0, (n− 1)C] tartományban lesznek.

Monoton kupac tulajdonságai :

� Mintörlések kulcsai az id® el®rehaladtával monoton n®nek

� Ha az utolsó Mintörléskor a kulcs dmin, akkor az összes aktuális kulcseleme a [dmin, dmin + C] tartománynak.

Megjegyzés : a Dijkstránál használt kupac ezeket teljesíti.

Monoton kupacokat, ha C nem túl nagy, az úgynevezett r-kupacokkal(r = radix ill. redistributable) érdemes megvalósítani.

Legyen: B = dlog(C + 1)e+ 2

50

Page 51: Adatstrukturak

B 2 B 3 B 4 B5B 1

u2 u3 u4 u5u1

Vödrök:

B1, B2, . . . , BB vödröket készítünk. A Bi vödörhöz az ui fels® korlátot ésa range(Bi) számintervallumot rendeljük. Egy Bi vödörbe azokat az elemeketrakjuk, amelyek kulcsa eleme a range(Bi)-nek.

range(Bi) = [ui−1 + 1, ui].

� minden id®ben: |range(Bi)| ≤ 2i−2 , ha i = 2, . . . , B− 1 és |range(B1)| == 1, |range(BB)| = nC + 1.

Kezdetben :

u0 = -1ui = 2i−1 − 1uB = nC (ebbe a vödörbe biztosan belefér minden elem)

range(B1) = [0]range(B2) = [1]range(B3) = [2, 3]range(B4) = [4, 5, 6, 7]

...

Cél : A kupac elemeit úgy tárolni, hogy v a Bi-ben legyen, ha K(v) ∈range(Bi). Egy vödör tartalma egy oda-vissza láncolt lista lesz.

M¶veletek :

Beszúrás :

FOR j := B . . . 1(−1)IF uj−1 < K(v) THEN v → Bj és kilépünk a ciklusból.

Megjegyzés: 1 elem beszúrására legfeljebb TI = B.

Kulcs-csökk :

� K(v) := K(v)−∆

� IF másik vödörbe THEN kivesszük, elindulunk balra és megkeressük a jóvödröt.

Mintörlés :

� Ha B1 6= ∅ → tetsz®leges elemét töröljük és visszaadjuk.

51

Page 52: Adatstrukturak

� Különben legyen Bj az els® nem üres vödör. Végignézzük a Bj vödörminden elemét. Legyen v a minimális kulcsú, dmin := K(v).

� Átcímkézzük ui-ket:u0 := dmin − 1u1 := dmin

ui := min(ui−1 + 2i−2, uj), ha i = 2, . . . , j − 1.

� Ezután Bj minden elemét egyesével balra mozgatva berakjuk a neki meg-felel® vödörbe, kivéve v-t, amelyet törlünk.

19. Tétel. Ezután Bj minden elemének a helye valamilyen i < j-re Bi lesz.

Bizonyítás: Mivel dmin ∈range(Bj), ezért dmin ≥ uj − 2j−2 + 1. Emiatt azátcímkézések után uj−1 = min(uj , dmin + 1 + 2 + . . . + 2j−3) = min(uj , dmin ++ 2j−2 − 1) ≥ uj , tehát nem lesz kisebb, mint uj átcímkézés el®tti értéke, ígyminden elemet tényleg balra kell mozgatni. Mivel a Bj el®tti vödrök üresekvoltak, és Bj-ben semelyik elem kulcsa nem kisebb, mint dmin, mindenkit jól eltudunk helyezni.

Amortizációs elemzés

A potenciál : P =∑

v∈kupac

b(v), ahol b(v) a v-t tartalmazó vödör sorszáma.

Egy Lépés legyen (el®ször) 1 elem eggyel balra átrakásának ideje (kivesszük,ellen®rizzük, hogy oda való-e, berakjuk).

M¶veletek:

Beszúrás(v) : TI = (B + 1− b(v)) + 1(B + 1− b(v)) : megkeressük, hogy hová kell beszúrni az elemet.1 : beszúrjuk.

∆P = b(v)Így AI = B + 2.

Kulcs-csökk : TI = 1 + (b(v)− buj(v))

∆P = buj(v)− b(v).Tehát AI = 1.

Min-törlés :

Ha B1 nem volt üres, akkor nyilván AI = 1. Egyébként:

TI = j + |Bj |+ j +(1 +

∑u∈Bj ,u 6=v

(j − buj(u)

)), ahol

j : Bj , az els® nem üres vödör megkeresése|Bj | = a j. vödörben lev® elemek száma: végignézzük vj tartalmát és

kiválasztjuk v-t,

52

Page 53: Adatstrukturak

j : ui-k átcímkézése,utolsó tag: balra pakolások ideje (1+ a v kihagyása).

Megjegyzés :∑u∈Bj ,u 6=v

(j − buj(u)) ≥ |Bj | − 1, mivel (j − buj(u)) ≥ 1 a 19. tétel miatt.

Egy Új Lépés:= 2 · Lépés (tehát kétszer annyi elemi lépés), így

TI ≤ j+|Bj |/2+1/2+(1/2)·∑

u∈Bj ,u 6=v

(j−buj(u)

)≤ j+1+

∑u∈Bj ,u 6=v

(j−buj(u)

)

Mivel ∆P = −j −∑

u∈Bj ,u 6=v

(j − buj(u)

), ezért AI ≤ 1.

Tehát ha például n Beszúrást, m Kulcs-csökkentést, és n′ ≤ n Mintörléstvégzünk, akkor:

∑TI ≤

∑AI ≤ n · (B + 2) + m + n′ ≤ n · (log C + 5) + m

darab Lépés, így O(m + n · log C) összes futásid®t kapunk (ha C ≥ 2). Tehát aDijkstra futási ideje [0, C]-beli egész hosszak esetén r-kupaccal : O(e+n · log C).

Ennél a kupacnál is jobbat készített Thorup, legalábbis elméletileg (gyakor-lati megvalósításról és tesztekr®l nem tudunk):

Feltételek: w = szóhossz és w ≥ log n, w ≥ log C, ahol C a hosszak maxi-muma (a hosszak itt is nemnegatív egészek). Tehát azt tesszük fel, hogy mindenélhossz és egy csúcs címe belefér 1 szóba. Valamint feltesszük, hogy 1 Lépésben2 szó összege és szorzata kiszámolható.

Ezen feltevések mellett Thorup kupaca a legrosszabb id®ben számolva a Be-szúrást és Kulcs-csökkentést O(1) id®ben, a Mintörlést pedig O(log log min(n, C))id®ben elvégzi.

Ezzel a kupaccal a Dijkstra O(e + n · log log min(n, C)) idej¶ lesz.

7. Szótárak

Legyen adott egy U univerzum és egy ezen a halmazon értelmezett < rendezés.

Feladat : adatstruktúra készítése S ⊂ U elemek tárolására. S (a pillanatnyiszótár) minden elemét csak egyszer tároljuk.

M¶veletek :

Keresés(x) :

� Könnyített: x ∈?S

53

Page 54: Adatstrukturak

� Nehezebb: keressük meg x-et ha x ∈ S, különben pedig NINCS.

Ha egy szótár csak ezt az egy m¶veletet tudja megvalósítani, akkor statikusszótárnak nevezzük.

Ha a szótár nem statikus, akkor:

Beszúrás(x) :

� Könnyített: garantált, hogy x /∈ S, és beszúrjuk. (S := S + x)

� Nehezebb: ha x /∈ S, akkor S := S + x.

Ha egy adatstruktúrában mindkét m¶velet megoldott, akkor szótárról be-szélünk.

Törlés(x) : ha x ∈ S, akkor S := S − x.

Ha mindhárom m¶velet megoldott, akkor az adatstruktúra szótár törléssel.

Ezen m¶veleteken kívül az alábbi m¶veletek is hasznos kiegészít®k lehetnek:

� min(S)

� max(S)

� Tólig(S,a,b) : = {x ∈ S | a ≤ x ≤ b}

� Fésül(S1,S2)

� Olvaszt(S1,a,S2) : Tudjuk, hogy S1 < a < S2 és S := S1 + a + S2.

� Szétvág(S,a) : Szétvágja S-et olyan S1 és S2-re, hogy S1 < a < S2.

Szótárak megvalósítása: Ha |U | kicsi : tárolhatjuk karakterisztikus vektorbanpointerekkel az elemeket. Az indexek U elemei lesznek.

Innent®l feltesszük, hogy |U | nagy.

Statikus szótárak esetén: S elemeit rendezett tömbben tároljuk és felez®keresést használunk.

x<?T[n/2]

x<?T[n/4]

i

i

h

h. . .

. . . . . .

54

Page 55: Adatstrukturak

7.1. Bináris keres®fa

Ez az el®z®vel lényegében ekvivalens.

1. Küls® tárolású : a fa leveleiben vannak az adatok, a többi csúcsban pedigU elemei szerepelnek �Útjelz®kként�.

u

i

i

h

h

. . .

1

u2

s

u3

Keresés(x) :Legyen r a gyökér.REPEAT

IF x ≤ u(r) és ∃ bal(r) THEN r := bal(r)IF x > u(r) és ∃ jobb(r) THEN r := jobb(r)

IF r levél THENIF x = u(r) THEN RETURN(r)

ELSE RETURN(x /∈ S)ELSE RETURN(x /∈ S).

Megjegyzés : A levelekben balról jobbra haladva S elemei rendezve vannak.

2. Bels® tárolású : a fa csúcsai megfeleltethet®k S elemeinek. A keresés so-rán 3-felé elágazó IF van, amit direktben elég kevés nyelv támogat (pl.FORTRAN). Viszont kevesebb tárhelyet foglal. Az áttekinthet®ség miatta fa minden egy-gyerekes csúcsa alá odaképzelünk egy, minden levele alattkett® �ktív levelet. Tehát minden valódi csúcsnak pontosan két gyerekevan.

s

s'

Keresés(x) : Legyen r a gyökér.REPEAT

IF r �ktív levél THEN RETURN(x /∈ S)IF x = u(r) THEN RETURN(r)IF x < u(r) THEN r := bal(r)IF x > u(r) THEN r := jobb(r)

55

Page 56: Adatstrukturak

A bels®-és küls® tárolású fák összehasonlítása :

Küls® Bels®Memória ∼ 2n kulcs n kulcsMélység dlog ne dlog(n + 1)e − 1Keresés dlog ne összehasonlítás dlog ne − 1 összehasonlítás, de 3 irányú!

Megjegyzés :

� A három irányú összehasonlítás a legtöbb környezetben 2 lépés lesz!

� Az esetek túlnyomó részében bels® tárolású keres®fát fogunk használni.

� Bels® tárolású fánál sikertelen keresés esetén visszaadjuk a megtalált �ktívlevelet is (azaz a szül®jére egy pointert és egy biten, hogy bal vagy jobbgyereke-e). Ez a beszúrásnál fog segíteni.

7.1.1. Optimális bináris keres®fa

Statikus szótárat akarunk tárolni úgy, hogy feltételezzük, hogy rengetegszer kellmajd benne keresni. Ezen keresések összidejét akarjuk minimalizálni.

Adottak :

� S = {a1 < a2 < . . . < an} a szótár elemei.

� ai-t pi valószín¶séggel keressük.

� ha ai < b < ai+1, az ilyen b-ket qi valószín¶séggel keressük.

• ha b < a1, akkor b-t q0, ha pedig an < b, akkor b-t qn valószín¶séggelkeressük.

Egy adott T keres®fa esetén egy keresés várható lépésszáma, melyet a faköltségének is hívunk:

E(keresés)=c(T )=n∑

i=1

pi(d(ai) + 1) +n∑

i=0

qid(i)

� d(ai) : az ai-t tartalmazó csúcs mélysége; a +1 azért kell, mert a gyökérkeresése sem 0 lépés.

� d(i) : az i. (balról jobbra számozva) �ktív levél mélysége.

56

Page 57: Adatstrukturak

Feladat : Minimális költség¶ bináris keres®fa konstrukciója, azaz olyan T , amely-re c(T ) minimális.

Megoldás : Ha ak lenne az optimális T fa gyökerében:

ak

T

a ... ak-1

2

1

T1

a ... ank+1

Ha ez az optimum, akkor szükségképpen T1 és T2 is optimális fa (a bennükszerepl® ai-k által meghatározott részfeladatra). Ez a szuboptimalitás elve.

Megjegyzés : Azok a feladatok, amelyekre a szuboptimalitás elve teljesül,többnyire megoldhatóak hatékonyan.

Ti,j := optimális fa az ai+1 . . . aj szavakon. Ennek gyökere ri,j , költsége ci,j ,súlya pedig wi,j = qi + pi+1 + qi+1 + . . . + pj + qj (wi,j az a valószín¶ség, hogybelépünk egy Ti,j fába).

Inicializálás :

Ti,i = ∅ ; ci,i = 0 ; wi,i = qi.

Nekünk a T0,n fát kell megkeresni. Vegyük észre, hogy ha tudnánk, hogyri,j = k, akkor a szuboptimalitás elve miatt a Ti,j fa gyökerének bal részfájaTi,k−1, jobb részfája pedig Tk,j lesz. Ezért ekkor a költsége ci,j = (ci,k−1 + qi ++pi+1 + . . .+ qk−1)+pk +(ck,j + qk +pk+1 + . . .+ qj) = ci,k−1 + ck,j +wi,j lesz,mivel a Ti,j fában minden csúcs mélysége eggyel nagyobb, mint a Ti,k−1 ill. aTk,j fákban. Vegyük észre, hogy a költségben wi,j állandó, nem függ a k-tól.

Ezek alapján könnyen készíthetünk egy rekurzív algoritmust:

R(i, j) : c′i,j :=∞FOR k := i . . . j

C1 := R(i, k − 1)C2 := R(k, j)IF C1 + C2 < c′i,j THEN c′i,j := C1 + C2; ri,j := k

RETURN(ci,j := c′i,j + wi,j)

Ez az algoritmus azért exponenciális, mert ugyanazt a dolgot többszörszámoljuk ki. A hívások száma az ún. Catalan-szám lesz. Hogy ezt elkerüljük,dinamikus programozással fogjuk megoldani a feladatot.

A dinamikus programozás jellemz®i:

57

Page 58: Adatstrukturak

� Amit már egyszer kiszámoltunk, azt feljegyezzük, hogy ne kelljen mégegyszer kiszámolni, valamint

� jó sorrendben oldjuk meg az egyes részfeladatokat.

a5

a a

q q q q5

4

4

6

63

Az algoritmus (a fenti Inicializálás után):

FOR l = 1 . . . n− 1FOR i = 1 . . . n− l

j := i + lci,j := wi,j + mini<k≤j(ci,k−1 + ck,j)ri,j := argmini<k≤j(ci,k−1 + ck,j)

Id® : O(n3).

7.1.2. M¶veletek általános bináris keres®fában

Keresés(x) : lásd fentebb.

Beszúrás(x) : Keresés(x), ha x /∈ S, megkapjuk az r �ktív levelet és berakjukoda x-et. Küls®nél a keresés vagy egy levélben áll le, akkor ahelyett egy bels®csúcs kell, az eredeti levél és a beszúrandó lesznek a gyerekei. Vagy pedig egyolyan x csúcsban, melynek pl. nincs jobb gyereke, de a keresés jobbra lépne;ekkor x új jobb gyerekébe rakjuk az új elemet.

Törlés(x) :

� Küls®: triviális (megkeressük és kitöröljük), de a testvérét felrakjuk a szü-l®be (ne legyen egy felesleges útjelz® tábla).

� Bels®:

Két eset lesz:

1. eset : Ha x-nek legfeljebb egy gyereke van, akkor a gyereke jön a helyére.Ekkor az új fa is jó keres®fa lesz.

58

Page 59: Adatstrukturak

x

yy

2. eset : Ha x-nek 2 gyereke van:

� Megkeressük az x-et közvetlenül megel®z® y elemet. Ezt úgy tesszük, hogy1-et balra lépünk és utána amíg lehet mindig jobbra.

� x-et és y-t felcseréljük, majd az új x-et töröljük az els® módszer szerint(ennek már nincs jobb gyereke).

x

y

y

Jó az algoritmus: ha töröljük x-et, akkor y már jó helyen lesz. Nem romlikel a keres®fa tulajdonság.

Ami rossz :

� A lépésszámok legrosszabb esetben a fa mélységével egyenl®ek.

� Nem tudunk semmit a fa mélységér®l !

� Ha például n elemet szúrunk be növekv® sorrendben, akkor a fa mélységen lesz.

Cél : Olyan fa kialakítása, amelynek mélysége O(log n).

59

Page 60: Adatstrukturak

7.2. 2-3 fák

Tulajdonságok :

� Minden csúcsnak 2,3 vagy 0 gyereke lesz (kivéve ha a fa 2 pontú).

� Küls® tárolású lesz a fa

� Minden levél ugyanazon a szinten lesz. Így n ≥ 2 esetén legfeljebb dlog nemélység¶ lesz a fa.

� Minden nem-levél csúcsban két útjelz® táblát tárolunk.

De�níció : max(v)= a v alatti levelek kulcsainak maximuma.

u u u1 2 3

x

max(u ) max(u )1 2

Tehát egy v csúcsban az els® útjelz® max(u1), a második max(u2), ha v-neku1 az els® és u2 a második gyereke.

Keresés(s) :

� IF u levélben vagyunk THEN

� IF s = max(u) THEN Return(u) ELSE Return(nincs)

� ELSE IF s ≤ max(u1) THEN → u1

� ELSE IF s ≤ max(u2) THEN → u2

� ELSE → u3

Ez mindig legfeljebb log n lépés lesz.

Beszúrás(s) :

s

x

� Megkeressük, hogy hová kell beszúrni s-et, jelölje x az utolsó nem-levélcsúcsot.

60

Page 61: Adatstrukturak

� Ha x-nek 2 gyereke volt, akkor beszúrjuk és így 3 gyereke lesz (x-benátállítjuk az útjelz®ket).

� Ha x-nek 3 gyereke volt, akkor szétszedem x-et 2 darab 2 gyerekes csúccsá.

x x1 2

Ha x szül®jének 2 gyereke volt, akkor nincs gond, ha 3, akkor ezt a csúcsotis szétvágjuk és így folytatjuk a gyökér felé. Ha eljutunk a gyökérig és agyökérnek 3 gyereke volt, akkor a gyökeret is kettészedjük, beszúrunk egyúj gyökeret, és így n® a fa magassága.

Id® : O(log n)

Az útjelz®ket mindkét esetben állítgatni kell.

20. Tétel. Ha az új elem (s) beszúrásától max(v) n®tt, akkor v gyökér, vagyannak csupa-jobb leszármazottja, azaz minden eddiginél nagyobb elemet szúrtunkbe.

Bizonyítás: Ha egy lépésben nem jobbra mentem, akkor az úgy lehetett, hogy otts ≤ m1 vagy s ≤ m2 volt. Érdemes a maximális elem értékét külön is eltárolni.

Következmény : Általában felfelé nem kell átírogatni az útjelz® táblákat.

Példa, amikor át kell írni :

u u u1 2 3

x

max(u ) max(u )1 2

x1 x2

Ennek a maximuma nincsfeljegyezve!

Ekkor nem tudjuk mind a 4 gyereknek a maximumát (most fel kell írnunk). Ahiányzó érték max(x) lesz, de ez is fel van írva a nagyszül®ben, vagy valamelyiktávolabbi ®sben.

61

Page 62: Adatstrukturak

m2=max(y)

y

Ha így eljutunk a gyökérig, akkor a max(x) a külön tárolt maximum lesz. Ezlegfeljebb log n darab fellépést és legfeljebb log n darab lefelé lépést jelenthet,de ekkor az y minden ®sének maximuma is megvan. Könny¶ látni, hogy ha xgyereke lett az új levél, akkor elég x-t®l a gyökérig vezet® úton lev® csúcsokmaximumát tudni.

max(y)

y

gyökér

Törlés(s) :

� Megkeressük az s-et tartalmazó levelet és kitöröljük.

� Ha p(s) = x-nek 3 gyereke volt, akkor készen vagyunk (de az útjelz®ketfelfelé javítani kell, max(x) változhatott!).

� Ha nem, akkor 2 esetet különböztetünk meg:

1. Létezik x-nek szomszédos testvére 3 gyerekkel : elkérjük az egyiket (afelénk es®t).

y

z

x

s

y x

z

max(z) fel van írva vagy y-ban, vagy p(x)-ben. Felfelé javítanunk kella jelz®táblákat!

62

Page 63: Adatstrukturak

2. Ha nem létezik, akkor x-et összevonjuk valamelyik testvérével.

x

y y

x

Lehet, hogy ekkor az új x szül®jének lesz csak 1 gyereke, tehát felfeléfolytatni kell. Hogyan ér véget az algoritmus:� A szül® 3 gyerekes volt, és most kett® maradt neki.� Feljutunk egészen a gyökérig, töröljük az 1 gyerekes gyökeret (ha

n ≥ 2) és így csökken a fa magassága.

7.3. B-fák

Tulajdonságai :

� Minden nem-levél csúcsra igaz, hogy:⌈

B2

⌉≤ # gyerekek ≤ B (kivéve,

ha gyökér és ha n <⌈

B2

⌉).

� Egy csúcsban B − 1 útjelz® lesz.

� Minden m¶velet a 2-3 fák mintájára fog menni.

Küls® táraknál használják: Ezek a tárolók 1 olvasás során egy egész lapotolvasnak be. Az tart sok ideig, míg a fejet a megfelel® lapra pozícionálja a vezér-lés. Az a cél, hogy minél kevesebb lapot kelljen olvasni ahhoz, hogy megtudjuk,hogy hol van az az adat, amit a tárolón keresünk. Úgy érdemes B-t úgy meg-választani, hogy a B − 1 útjelz® elférjen egy lapon.

Példa : Ha n = 224 ∼ 16.7 millió és B = 32, akkor a fa mélysége legfeljebb6 lesz. Ha a fels® 3 szintet a memóriában tároljuk (ez 322 ∼ 1000 lap), akkorminden m¶velet legfeljebb 4 lapolvasás lesz (azaz legfeljebb 4-szer kell olvasni awinchestert).

7.4. Piros-fekete fák

Eredetük : Bináris faként tárolt 2-4 fák:

63

Page 64: Adatstrukturak

p

f

p

p

f

Tulajdonságai :

0. Bels® tárolású bináris keres®fa,

1. minden csúcsa piros(p) vagy fekete(f) ; a �ktív levelek feketék,

2. piros csúcs apja fekete,

3. hogy kiegyensúlyozott legyen a fa: akárhogyan megyek le egy csúcsból (x)egy alatta lev® �ktív levélig, az úton mindig ugyanannyi fekete csúcs van.Ezt x fekete magasságának hívjuk és mf (x)-szel jelöljük.

21. Tétel. Egy piros-fekete fa mélysége legfeljebb 2 · log n.

Bizonyítás: indukcióval, vagy a piros csúcsok fekete szül®be való behúzásával(ekkor minden �ktív levél mélysége ugyanaz lesz), triviális. Érdemes megjegyez-ni, hogy a fenti feltételek implicite tartalmazzák, hogy ha egy v csúcsnak csakegy valódi gyereke van, akkor az egy piros levél (v másik gyereke egy fekete �ktívlevél, így ha v piros lenne, akkor fekete magassága 1 lenne, de ez csak úgy lehet,ha másik gyereke is egy �ktív levél ; ha pedig v fekete, akkor fekete magassága2, tehát csak piros valódi leszármazottja lehet).

M¶veletek :

Keresés(x) : Ugyanúgy kell megvalósítani, mint egy tetsz®leges bináris fában.

Egy kiegészít® alapm¶velet :

Billentés(x) :

x

A B

C

y=P(x) x

B C

A

y

Billentés(x)

Piros-fekete fáknál ez nem mindig lesz jó. Ha y fekete és x piros, és ekkor mégát is kell színezni x-et és y-t, hogy teljesüljön a 3. tulajdonság. Pl. ha a fa alakjaa következ®:

64

Page 65: Adatstrukturak

x

A B

C

y x

B C

A

y

Billentés(x)

p pf

f f

f

Beszúrás(s) : A beszúrás egy fekete szín¶ x �ktív levél helyére történik, alattalétrejön két új fekete �ktív levél. Ezt a csúcsot (x-et) pirosra kell színeznünk a3. tulajdonság fenntartása miatt.

f

ff

p

Akkor van probléma, ha a beszúrt x elem y apja piros szín¶ (ha fekete, akkorkészen vagyunk). Ezen belül három esetet különböztetünk meg:

ff

p

px

1. eset : Ha y testvére piros:

f

p

p p f

p

p

f

x

y

x

y

Ezután x := p(y) és folytatjuk felfelé az eljárást (ez legfeljebb log n lépést jelent).

2. eset : Ha p(p(x)) = z-nek x bal-bal vagy jobb-jobb unokája.

65

Page 66: Adatstrukturak

x

A B

C

y

Billentés(y)D

z

A B

CD

x

yf

p

pf

zp

f

p

f

7. Állítás. Egy ilyen billentés után rendben van a fa.

3. eset : Ha nem az 1. vagy 2. eset áll fenn. Ekkor is elég 2 Billentés:

B C

Billentés(x)

A

A B C D

Z

x

y

D

z

y

x

A B

C D

y

zx

Billentés(x)

f

pp

p

f

fp

p

f

f p

f

8. Állítás. Egy ilyen dupla billentés után rendben van a fa.

Összefoglalva : Egy Beszúrás(x) legfeljebb log n átszínezés és legfeljebb 2 Bil-lentés m¶velettel megvalósítható.

Törlés(x) : Itt 5 különböz® eset lesz és belátható, hogy legfeljebb log n átszíne-zéssel és legfeljebb 3 billentéssel megoldható a m¶velet.

7.5. AVL-fák (Adelszon-Velszkij és Landisz)

Tulajdonságai :

� Bináris keres®fa,

� m(f) = 0, ha f �ktív, ahol m a magasság,

� ∀x : |m(bal(x))−m(jobb(x))| ≤ 1.

Ezen tulajdonság ellen®rzése és fenntartása csúcsonként 2 bittel biztosítható:1. a bal gyerek magasabb-e mint a jobb gyerek, illetve 2. a jobb gyerek magasabb-e mint a bal gyerek.

Könnyen bizonyítható, hogy ha ezek a tulajdonságok teljesülnek egy d mély-ség¶ fára, akkor ennek legalább Fd+3 − 1 csúcsa van. Ebb®l következik, hogy afa mélysége legfeljebb 1,44 · dlog ne lehet.

66

Page 67: Adatstrukturak

M¶veletek :

Beszúrás(s) : Beszúrjuk s-et, majd megkeressük a legközelebbi x ®sét, ahol a3. tulajdonság elromlott; közben persze a fenti jelz®biteket megfelel®en átállít-juk. Majd itt egy szimpla vagy egy dupla billentéssel a tulajdonság helyreállít-ható az alábbi módon:

1. eset : s az x bal-bal, vagy jobb-jobb unokájának a leszármazottja

x

y

y

Bill(y)

s

A B

C

s

A

B C

x

2a. eset : s az x bal-jobb, vagy jobb-bal unokája

Bill(s)

x

y

s

s

xyBill(s)

2b. eset : s az x bal-jobb, vagy jobb-bal z unokájának valódi leszármazottja

Bill(z)

x

B

s

CA

B

s

xy

z

D

CD

A

y

z

Bill(z)

Belátható, hogy egy beszúrásnál az x elem helyének megkeresése legfel-jebb d1,44 · log ne id®t vesz igénybe és az egész m¶velet végrehajtása legfeljebbd1,44 · log ne bit átállítással, valamint legfeljebb 2 Billentéssel jár. Érdemes meg-jegyezni, hogy x megkeresését már a Beszúrás el®tt, miközben s helyét keressük,könnyen elvégezhetjük. Azonban ekkor is az s és x közötti csúcsoknál kell állíta-ni a biteket. Azonban x felett már nem, mert a billentések után azok magasságaugyanaz lesz, mint beszúrás el®tt.

Törlés(s) : Legfeljebb d1,44 · log ne billentéssel megoldható (lehet, hogy azegész fát végig kell billegtetni).

67

Page 68: Adatstrukturak

7.6. Önkiegyensúlyozó fák (Splay-tree; Sleator és Tarjan)

Itt is bels® tárolású bináris fákat használunk, azonban a kiegyensúlyozottságranem teszünk explicit feltételt, amit fent kellene tartani. Helyette id®nként bil-legtetünk, és majd belátjuk, hogy átlagosan, azaz amortizációs id®ben mindenm¶velet elég gyors lesz � azaz O(log n) idej¶.

M¶veletek :

Dbill(x) : Kétfajta Duplabillentést különböztetünk meg.

(a) Ha x a nagyszül®nek bal-bal, vagy jobb-jobb unokája: Billentés(y), majdBillentés(x)

x

A B

C

y

1. Billentés(y)D

z

AB

C D

x

y

2. Billentés(x)

z

(b) Ha x a nagyszül®nek bal-jobb, vagy jobb-bal unokája: Billentés(x), majdújra Billentés(x)

x

B C

A

y

1. Billentés(x)D

z

A B C D

x

y

2. Billentés(x)

z

Felbillegtet(x) :WHILE p(p(x)) 6= nil

Dbill(x)IF p(x) 6= nil THEN Bill(x)

A felbillegtetés ideológiája hasonlít az útfelezésre, ha x mélysége h volt, akkorFelbillegtet(x) után x minden leszármazottjának mélysége bh/2c-lel csökken.

Az alábbiakban a vessz®s m¶veletek az új m¶veletek, a vessz®tlenek a ha-gyományos bináris fában végrehajtott m¶veletek.

Keresés'(x):Keresés(x)Felbillegtet(x)

68

Page 69: Adatstrukturak

Beszúrás'(x):Beszúrás(x)Felbillegtet(x)

Törlés'(x):z := p(y), ahol y az x megel®z®je

(y = x, ha x-nek legfeljebb 1 gyereke van)Törlés(x)Felbillegtet(z)

Id®: Mindhárom m¶velet tényleges ideje nagyjából kétszerese a Felbillegtettényleges idejének. A Lépést úgy választjuk meg, hogy kétszer annyi elemi lé-pést tartalmazzon, mint egy dupla billentés. Ekkor egy m¶velet tényleges idejelegfeljebb 2+ a Felbillegtetésnél végrehajtott (dupla vagy szimpla) billegtetésekszáma.

Potenciál :

x súlya: w(x) := x leszármazottainak száma (saját magát is beleértve)x rangja: r(x) := blog w(x)cA potenciál : P :=

∑r(x)

22. Tétel. AI((Felbillegtet(x)) ≤ 1 + 3 · (r(gyökér) − r(x)) ≤ 1 + 3 · blog nc == O(log n).

Bizonyítás: Belátjuk minden egyes billent® lépésre, hogy teljesül a fenti állí-tás megfelel®je. Összeadva ezeket egy teleszkópikus összeget kapunk, amelyb®lminden tag kiesik, kivéve 1 + 3 · (r(gyökér) − r(x)). A továbbiakban r jelöli abillentés el®tti, míg r′ a billentés utáni rangot.

1. Szimpla billentés: (y = p(x) gyökér):AI ≤ 1 + 3 · (r(y)− r(x)).

1. Billentés(x)A

B C

x

y

r'

CA B

x

y

r

∆P = r′(x)+ r′(y)− r(x)− r(y) = r′(y)− r(x) ≤ r(y)− r(x) ≤ 3 · (r(y)−− r(x)), mivel r′(x) = r(y) és r′(y) ≤ r(y) és r(y) ≥ r(x). Tehát AI = 1++ ∆P ≤ 1 + 3 · (r(y)− r(x)).

2. (a) típusú Duplabillentés:

Be kell látnunk, hogy AI ≤ 3(̇r(z)− r(x)).

69

Page 70: Adatstrukturak

∆P = r′(z) + r′(y) + r′(x)− r(z)− r(y)− r(x) ≤ 2 · (r(z)− r(x)), mivelr′(z) és r′(y) ≤ r′(x) = r(z), és r(y) ≥ r(x).Ha r(z) > r(x)⇒, ekkor 3 ·(r(z)−r(x)) ≥ 2 ·(r(z)−r(x))+1 ≥ ∆P +TI.Ha r(z) = r(x) = r (ez az alsó-egészrész miatt lehetséges) ⇒ r(y) = r ésr′(x) = r.Elég belátni, hogy r′(z) < r, mert akkor ∆P ≤ 2r + r′(z)− 3r ≤ −1, ígyAI ≤ 3 · 0, mert ∆P ≤ −1 és TI = 1.

x

A B

C

y

1. Billentés(y)D

z

AB

C D

x

y

2. Billentés(x)

β

β

α

α és β jelentse az adott részfa csúcsainak a számát.Ekkor: w(z) = α + β.Indirekt tegyük fel, hogy r′(z) = r ⇒ β ≥ 2r. Mivel r(y) = r ⇒ α ≥ 2r,innen: α + β ≥ 2r+1 ⇒ r′(x) ≥ r + 1, ami ellentmondás.

3. (b) típusú Duplabillentés:Minden a 2. ponthoz hasonlóan megy.

x

B C

A

y

1. Billentés(x)D

z

A B C D

x

y

2. Billentés(x)

zαα

β β

Most r′(y) < r vagy r′(z) < r -et kell megmutatnunk.Indirekt tegyük fel, hogy r′(y) = r′(z) = r ⇒ α ≥ 2r, β ≥ 2r ⇒ r′(x) ≥≥ r + 1, ami ellentmondás.

70

Page 71: Adatstrukturak

Végs® elemzés :

AI(Keresés') ≤ ∆P (Keresés)+∆P (Felbillegtet)+2+TI(Felbillegtet) (mivelTI(Keresés) belefér a Felbillegtet tényleges idejébe). Így, mivel ∆P (Keresés) == 0, ezért AI(Keresés') = O(log n).

AI(Törlés') ≤ ∆P (Törlés) + ∆P (Felbillegtet) + 2 + TI(Felbillegtet) (mivelTI(Törlés) belefér a Felbillegtet tényleges idejébe). Így, mivel ∆P (Törlés) < 0,ezért AI(Törlés') = O(log n).

AI(Beszúrás') ≤ ∆P (Beszúrás) + ∆P (Felbillegtet) + 2 + TI(Felbillegtet)(mivel TI(Beszúrás) belefér a Felbillegtet tényleges idejébe). Így, ha belátjuk,hogy ∆P (Beszúrás) = O(log n), akkor AI(Keresés') = O(log n).

x beszúrásakor w(y) csak akkor n®, ha x az y leszármazottja. r(y) csakakkor n®, ha y a gyökérb®l x-be vezet® úton van és w(y) = 2k − 1 alakú volt.Mivel az úton felfelé w(y) szigorúan n® ⇒ csak ≤ blog nc ilyen lehet (k == 1 . . . blog nc)⇒ ∆P (Beszúrás) ≤ log n.

Összegezve : Minden m¶velet amortizációs ideje O(log n).

Ez az adatstruktúra nagyon jól alkalmazható például a Szétvág(S, a) m¶ve-letre is : a-t felbillegtetjük és a két részfa lesz a megoldás.

8. Hashelés

Cél : A szótárm¶veleteket akarjuk megvalósítani úgy, hogy átlagosan jó meg-oldást kapjunk. Ehhez el®ször is egy olyan h : U → [0,1 . . .M − 1] függvénytkeresünk, amely az x ∈ U elemekre ad egy címet. A célunk az, hogy ezen acímen tároljuk x-et.

M jelentse a táblaméretet, N az aktuálisan benne tárolt adatok számát ésα := N

M .

Születésnap paradoxon : Ha N ≥√

ln 4 ·M , akkor legalább 12 valószín¶séggel

lesz olyan x 6= y, hogy h(x) = h(y). Ezt ütközésnek fogjuk nevezni.

Ennek ellenére az a cél, hogy a h függvény egyenletesen terítse szét az inpu-tokat, vagyis Pr(h(x) = i) = 1

M legyen minden i < M számra. Itt a valószín¶ségaz input kulcsokon értend®, amelyeken egy (általában el®ttünk csak körül-belülismert) eloszlás van, amely szerint érkezni fognak. Az elemzésekben fel fogjuktenni, hogy sikerült olyan hash függvényt találni, amelyre a Pr(h(x) = i) = 1

Mfeltétel teljesül.

Két dolgot fogunk vizsgálni : hogyan keressünk jó hash függvényt és hogyankezeljük az ütközéseket.

71

Page 72: Adatstrukturak

Persze mindenekel®tt az U univerzum elemeit valahogyan természetes szá-mokra kell leképeznünk. Ez általában könyen megoldható úgy, hogy különböz®kulcsoknak különböz® számok feleljenek meg. Ezt a továbbiakban feltételezzük,tehát innent®l úgy tekintjük, mintha U elemei természetes számok volnának.

8.1. Hash függvények

1. Osztó-módszer:h(K) = Kmod M , ahol K a kulcs (egy szám) és M egy prím.

2. Szorzó-módszer:

h(K) =⌊{ A

W·K}·M

⌋, ahol {} a törtrész, M = 2m és W = 2w alakú.

Ezért a W -vel való osztás, a törtrész, az M -el való szorzás és az egész-rész bitléptetésekkel/levágásokkal gyorsan megvalósítható; igazából csakaz A ·K szorzás kiszámítása igényel lényeges id®t.

A megválasztása: az lenne a legjobb választás, ha AW = α irracionális lenne

(α < 1).Megjegyzés : {α ·K} ∈ [0; 1).Szemléltetés : egy egységnyi kerület¶ körön K-szor mérem fel egymás utánα-t.

α8α2α

23. Tétel. (T. Sós Vera): Ha α irracionális, akkor a szomszédos pontokközötti távolságok összesen 3 félék lesznek és a következ® ((K + 1) · α) alegnagyobb ívet osztja ketté.

Ezen belül a legegyenletesebb akkor lesz a felosztás, ha α =√

5−12 , ekkor

a legnagyobb intervallumot a következ® elem az aranymetszés arányábanfogja felosztani.

Ezek alapján A megválasztása: úgy válasszuk A-t, hogy AW ∼

√5−12 legyen.

72

Page 73: Adatstrukturak

8.2. Ütközések feloldása

8.2.1. Láncolt hash-elés

nil

LISTAFEJEK

L0

M-1

f(K)=inil

A láncolt lista elemei:

� egy-egy teljes rekord, vagy

� mutató a rekordra és a rekord kulcsa

Keresés(K) : az h(K)-dik vödröt végigjárjuk.

Beszúrás(K) :

� Ha tudjuk, hogy nincs a táblában, akkor a lista elejére szúrhatjuk (1 lépés).

� Ha nem tudjuk, akkor végigjárjuk a listát és ha nem találtuk akkor avégére beszúrjuk.

Törlés(K) : egyszer¶.

Id® :

c′N : a sikertelen keresés várható lépésszáma, ahol f(K) = i 1M valószín¶ség-

gel.

cN : a sikeres keresés várható lépésszáma, ha minden elemet 1N valószín¶ség-

gel keresünk.

Emlékeztet®: α = NM .

Legyenek k0, k1, . . . kM−1 a láncok hosszai, nyilván ezek átlaga α.

73

Page 74: Adatstrukturak

Ekkor: c′N =M−1∑i=0

1M

(ki + 1) =∑

ki

M+∑ 1

M=

N

M+ 1 = α + 1.

A ξi valószín¶ségi változó jelentse azt, hogy az i. elem beszúrásához hánylépést tettünk meg (a keresése is ennyi lépés lesz).

Ekkor: E(ξi) = c′i−1 és cN = E(∑

1N ξi) = 1

N

∑E(ξi) = 1

N

∑c′i−1 a várható

érték linearitása miatt.

Innen: cN =N∑

i=1

1N

(1 +i− 1M

) = 1 +1N

N∑i=1

(i− 1M

) = 1 +N ·(N−1)

2

NM= 1 +

+N − 12M

≈ 1 +α

2.

A láncolt hash-elés el®nyei :

� egyszer¶,

� mindig tudunk új elemet berakni, azaz nem telik be (amíg tudunk helyetfoglalni a memóriában),

� a nagyon sok elemet tartalmazó vödörbe nem megy nagyobb valószín¶ség-gel elem, mint egy üres vödörbe,

� könny¶ törölni,

� ha például α ∼ 1, akkor cN ≈ 1,5 és c′N ≈ 2,

� küls® táras megoldásként kifejezetten jó. Pl. ha egy lapra 10 rekord fér és

α-t 8-nak választjuk, akkor a lapelérések várható száma sikeres keresésnél

1.4, beszúrásnál 1.8 alatt marad.

Hátrányai :

� nagy memóriaigény (M + N darab pointer kell),

� közben kell memóriát allokálni.

8.3. Nyílt címzés

A nyílt címzéses módszerekben közös, hogy minden módszer esetén egy �x tábláthasználunk (tömböt) és feltesszük, hogy N ≤M − 1 (mindig hagyunk egy üreshelyet).

74

Page 75: Adatstrukturak

0

M-1

A hash függvény: h : U → [0,M − 1] mellett több másik hash függvényt ishasználunk: hi : U → [1,M − 1], ahol i = 1, . . . M − 1 és h0 = 0.

A következ® keresési sorozatot vizsgáljuk:h(K)−h0(K), h(K)−h1(K), . . . h(K)−hM−1(K) mod M , ahol a h1(K), h2(K), . . . hM−1(K)sorozat az 1,2, . . . M − 1 egy permutációja.

A hash-elés menete: kiszámítjuk a tagokat addig, amíg nem lesz üres azadott �x tábla adott index¶ eleme.

Beszúrás : a sorozat els® üres helyére

Keresés : a sorozat szerint sorban keresünk (csak az els® üres helyig kellkeresni)

Megjegyzés :

� A nyílt címzés név onnan származik, hogy nincs el®re eldöntve, hogy hovárakom az egyes elemeket.

� Annál jobb lesz az eredmény minél "véletlenebb" a permutáció.

8.4. Lineáris hash-elés

A második hash függvény: hi := i. Ha a tömbben elérünk az els® elemig, akkorhátulról indulunk tovább. Ez magyarázza azt, hogy a hash függvényben kivonásszerepel összeadás helyett (a 0-val gyorsabban tudunk összehasonlítani).

h(K)

K

75

Page 76: Adatstrukturak

El®ny :

� Gyors és egyszer¶.

Hátrányok :

� Ha kialakul egy hosszú telített rész (lánc), akkor nagy annak a valószín¶-sége, hogy a következ® elem is ebbe a láncba érkezik,

� A láncok össze tudnak n®ni.

Lépések : cN = 12 (1 + 1

1−α ) és c′N = 12 ((1 + 1

1−α )2).

cN és c′N néhány értéke:

α 12

23 0,8 0,9

cN 1,5 2 3 5,5c′N 2,5 5 13 50,5

Ennél a módszernél még lehet törölni.

Törlés : Az okoz gondot, ha a kés®bbiekben nem találjuk meg K ′-t, azaz K ′

a törölt elem felett (ciklikusan értend®!), h(K ′) pedig alatta van.

h(K')

K'

K1törölt

Megoldás: Elindulunk a törölt elemt®l felfelé. Ha gondot okozó K ′ elemet ta-lálunk, azt nyugodtan átrakhatjuk a törölt elem helyére, és K ′ eredeti helyéttekintve törölt helynek, rekurzívan folytatjuk az eljárást. Ha elérünk egy üreshelyet, akkor nyugodtan megállhatunk, mindent rendbe raktunk.

8.5. Dupla hash-elés

Csak egy újabb hash függvényt keresünk, melyre h′(K) ∈ [1,M − 1] és mindigrelatív prím M -hez. Legyen hi(K) = i · h′(K).

Ez a módszer akkor lesz igazán jó (amit a további elemzésekben fel is te-szünk), ha Pr

(h(K1) = h(K2) és h′(K1) = h′(K2)

)≈ 1

M2 teljesül mindenK1 6= K2-re.

76

Page 77: Adatstrukturak

Osztó-módszer : M ′ és M legyenek ikerprímek és h′(K) := 1+(bKM cmodM ′).

A +1 azért kell, hogy i · h′ ne legyen 0.

Szorzó-módszer : Jelölje a az AK szorzat következ® m bitjét. h′(K) := a OR1 (az utolsó bitjét 1-re állítjuk, így nem lesz 0 és biztosan relatív prím lesz akett®-hatvány M -hez).

h(K) a 1

mm

A*K

Lépések : cN = 1α (ln 1

1−α ) és c′N = 11−α .

cN és c′N néhány értéke:

α 12

23 0,8 0,9

cN 1,39 1,65 2,01 2,56c′N 2 3 5 10

Megjegyzés : Ez egy elég jó módszer (ha h és h′ teljesítik a feltételeket), ennélsokkal jobbat nem is igen várhatunk.

Törlés dupla hash-elésnél : Az el®z® trükköt itt nem alkalmazhatjuk. Amikortörlünk egy elemet, akkor egy speciális szimbólumot helyezünk el a helyére,ami azt jelöli, hogy az adott elem törölt. A beszúrásnál ide beszúrhatunk, dea keresésnél tovább kell lépnünk. Az a probléma, hogy sok törlésnél gyorsanmegtelik a tábla ilyen szimbólumokkal.

8.6. A dupla hash-elés Brent-féle változata

Ennél a módszernél cN → 2,49, ha α → 1. A beszúrásnál némi plusz munkátvégzünk, hogy a majdani kereséseket gyorsítsuk. Jó pl. program fordítása soránszimbólumtábla építésére.

Ötlet : Ha a beszúrandó K kulcsot be tudom rakni az els® vagy a másodikhelyre, akkor berakom. Különben sima berakásnál az ® keresése már legalábbhárom lépés lenne. Legyen a h(K) helyet elfoglaló kulcs K1. Ha K1-et eggyelhátrébb tudom rakni a keresési sorában, akkor K1 keresésén 1-et rontok, delegalább 2-t javítok K keresésén.

Az algoritmus ez után is mohó módon folytatódik. Ha K1-et nem sikerült ah(K)−h′(K1) helyre rakni, akkor utána K-t próbáljuk a h(K)− 2h′(K) helyrerakni, ha ez se megy, akkor K1-et a h(K)−2h′(K1) helyre és K-t a h(K) helyre,ha ez se megy, akkor K2-t (aki a h(K)−h′(K) helyet foglalja) próbáljuk eggyelhátrébb rakni a h(K)− h′(K)− h′(K2) helyre és K-t berakjuk a h(K)− h′(K)helyre, és így tovább.

77

Page 78: Adatstrukturak

8.7. Univerzális hash-elés

Ötlet : Vegyünk sok hash függvényt és ezekb®l válasszuk egyet.

H → [0,M −1] : hash függvények halmaza. H univerzális, ha ∀K1 6= K2 ∈ U-ra: Prh∈H

(h(K1) = h(K2)

)= 1

M .

Konstrukció : Feltesszük, hogy M prím, és K-t felírjuk M alapú számrend-szerben:

K =∑r

i=0 xi ·M i, ahol r-et úgy választjuk, hogy K < Mr+1 minden kulcsra.

Legyenek a0, a1, . . . ar ∈ [0,M − 1] véletlenek és függetlenek.

ha0,...ar(K) :=

∑ri=0 ai · xi mod M .

24. Tétel. Ez univerzális, vagyis Pr(∑

ai · xi mod M =∑

ai · yi mod M)

== 1

M , ha legalább egy j-re xj 6= yj.

Bizonyítás : ha K1 6= K2 (és xi reprezentálja K1-et, yi pedig K2-t), akkorvalóban ∃j, hogy xj 6= yj .

Elég belátnunk, hogy ezek feltételes valószín¶sége 1/M minden rögzítetta0, a1, . . . aj−1, aj+1, . . . ar - re.

Ha egyenl®ség van, akkor: aj(xj − yj) ≡ −∑r

i=0,i 6=j ai(xi − yi) mod M .Mivel xj−yj 6≡ 0 és a jobb oldal a feltételes valószín¶ségben egy rögzített szám,így egyetlen aj létezik, ami kielégítené a kongruenciát.

9. Geometriai adatstruktúrák

Egy GPS-hez szükséges program alapvet® feladatait fogjuk megvalósítani ebbena részben.

A feladat : Adott egy �x térkép és arra vagyunk kíváncsiak, hogy hogyan néz kia térkép egy adott környezetünkben. A kérdés, hogy hogyan érdemes tárolni atérképet, hogy ezt a feladatot gyorsan meg tudjuk valósítani.

78

Page 79: Adatstrukturak

Feltételezések (egyszer¶sítések) :

1. a térkép objektumai pontokból és szakaszokból állnak (körökkel nem ér-demes foglalkozni, mert vagy csak akkor akarjuk kirajzolni, ha a közép-pontjuk is a téglalapba esik, vagy pedig egy térképen csak 2-3 féle méret¶kör van, amelyek középpontjait a megfelel®en megnövelt téglalapban ke-reshetjük),

2. a nevek az objektumokhoz tartoznak, amikor megjelenítünk egy objektu-mot kiírjuk a hozzá tartozó neveket is,

3. egy pont maximum 6 szakasznak a végpontja,

4. a szakaszok nem metszik egymást.

Megjegyzés : Rengeteg további alkalmazás van, pl. VLSI áramkörök tervezése,CAD rendszerek, ill. több dimenzióban VR alkalmazások (repül®gép-szimulátor,játékok), vagy akár adatbázisok bizonyos tulajdonságú elemeinek kilistázása.

9.1. Egy dimenziós feladatok

I. TÁROLNI : x1, x2, . . . xn pontokat.

KÉRDÉS : PONTOK(xb, xj) - felsorolni azokat a pontokat, amelyek ebbeaz intervallumba esnek, vagyis a válasz: {xi : xb ≤ xi ≤ xj}.

Az output hosszát nem tudjuk el®re. Legyen ezentúl k az output hossza. Afutási id®ket ezentúl k és n függvényében fogjuk vizsgálni.

ID� : O(log n + k)

TÁR : O(n)

FELÉPÍTÉS : O(n · log n)

Megoldás : rendezett tömbben tároljuk a pontokat; xb-t megkeressük felez®kereséssel, majd innent®l listázunk, míg xj felé nem érünk.

II. TÁROLNI : I1, I2, . . . In ⊆ R intervallumok, ahol Ii = [xib, x

ij ].

KÉRDÉS : INTERV (x) → felsorolni Ii-ket, amelyekre x ∈ Ii.

ID� : O(log n + k)

TÁR : O(n)

FELÉPÍTÉS : O(n · log n)

Megoldás : intervallum fa. A 2n darab xij , x

ib közül legyen x0 a középs® (az

n-dik).

Rekurzívan fát építünk:

79

Page 80: Adatstrukturak

v0

x -tól balralévõ elemek

0

x ,L ,L0 b j

x -tól jobbralévõ elemek

0

� a gyökérben raktározzuk el összes x0-t tartalmazó intervallumot. EzekI(v0) = {Ii | xi

b ≤ x0 ≤ xij}.

� a bal részfába azokat az elemeket, amelyek szigorúan balra vannak az x0-tól, vagyis: {Ii | xi

j < x0}. Itt legfeljebb n2 intervallum lesz.

� a jobb részfában a szigorúan jobbra lév® intervallumok lesznek.

� a két részfát rekurzívan ugyanígy építjük fel.

0x x

Tegyük fel, hogy az INTERV (x) kérdésnél pl. x ≤ x0. Az x-et tartalmazóintervallumok kétfajták lehetnek:

� azok, amelyek nem érik el x0-t � ezek a bal részfában lesznek,

� azok, amelyek elmennek x0-ig � ezeket a gyökérben tároltuk.

Megoldás : A v0 csúcsban x0 értéke mellett I(v0)-t is tároljuk, mégpedigkétszer, egy Lb(v0) és egy Lj(v0) listában.

Lb(v0) : x0-t tartalmazó intervallumok bal végpont szerinti növekv® sorrend-ben.

Lj(v0) : x0-t tartalmazó intervallumok jobb végpont szerinti csökken® sor-rendben.

Ha x < x0 : Lb felsorolása az els® elemét®l, amíg a bal végpont ≤ x.

Lépésszám v0-ban: 1 + k0, ha k0 darab intervallum található itt, amibenbenne van x is. Ha x < x0 : rekurzívan folytatom a bal fában. A fa mélysége �a felezés miatt � legfeljebb log n lesz.

A felépítéshez hint: az elején rendezzük az intervallumokat három tömbbe:összes végpont szerint, bal végpont szerint és jobb végpont szerint. Egy adottcsúcsnál el®ször ezeket lineáris id®ben szétszedjük három részre, utána Lb és Lj

már könnyen kinyerhet®.

80

Page 81: Adatstrukturak

9.2. Két dimenziós feladatok

III. TÁROLNI : p1, p2, . . . pn ∈ R2 pontok, pi = (xi, yi).

KÉRDÉS : Egy adott [xb, xj ]×[ya, yf ] téglalapba es® pontok felsorolása, azaz{pi | xb ≤ xi ≤ xj és ya ≤ yi ≤ yf}.

Megoldás : Tartomány-fa (range tree). Els® lépés:

� xi koordináták szerint kiegyensúlyozott küls® tárolású bináris keres®fátépítünk,

� a levelekre pi-ket írjuk fel.

Ha v a fa egy csúcsa, akkor ASSOC(v) := {pi | v alatti levélben van}.

Ezeket egy-egy L(v) tömbben tároljuk, mely az ASSOC(v) elemeit tartal-mazza y koordináták szerint rendezve.

TÁR : O(n · log n) (egy pont minden szinten pontosan egyszer szerepel).

Válaszoló algoritmus : El®ször xb és xj keresése.

x keresése x kereséseb j

? ?

Legyen vsplit az a csúcs, ahol a két keresés elágazik. Egy csúcs fontos, haa vsplit-t®l az xb keresésekor elért levélbe vezet® úton lév® olyan csúcs jobbgyereke, ahol balra léptünk, illetve, ha a vsplit-t®l az xj keresésekor elért levélbevezet® úton lév® olyan csúcs bal gyereke, ahol jobbra léptünk. Könny¶ látni,hogy a kilistázandó pontok mind vagy ASSOC(v)-ben vannak egy fontos vcsúcsra, vagy a két elért levél valamelyikében. Tehát minden fontos v csúcsbanki kell válogatni ASSOC(v) elemeib®l a kérdésnek megfelel®eket, majd a kételért levélben lev® pontot leellen®rizni, hogy jók-e.

81

Page 82: Adatstrukturak

A fa mélysége log n, így legfeljebb 2 · log n fontos csúcs van.

Minden fontos v-re ya-t megkeressük felez® kereséssel L(v)-ben és kilistázzuka pontokat yf -ig.

Egy darab v-nél legfeljebb log n+1+kv lépés kell, ahol kv a v-nél kilistázottelemek száma.

ID� : O(log2 n + k)

FELÉPÍTÉS : O(n · log n) Hint: rendezzük a pontokat x és y koordináta

szerint is, megfelel® kereszt-linkelésekkel, ekkor egy csúcsnál a listák lineáris

id®ben kettészedhet®k.

Megjegyzés :

� ez az algoritmus m¶ködik több dimenzióban is, úgy, hogy d dimenzióban azid® O(logd n+k) lesz és L(v) rekurzívan egy d−1 dimenziós tartományfa.

Kérdés : az O(log2 n + k) id®t lehet-e csökkenteni?

A cél : O(log n + k) keresési id®, ehhez az kell, hogy a v-nél csak O(1 + kv)id®t töltsünk.

9.2.1. Kaszkád tárolás

A és B rendezett tömböket szeretnénk tárolni, ahol A ⊇ B.

A

H

1008070625937302319103

B 807062301910

nil

H(i) := min{l | B(l) ≥ A(i)}, illetve nil, ha nem létezik ilyen l.

Ha például ya = 20, akkor megkeressük az A-ban az els® ennél nagyobb-egyenl® elemet (ez A(4) = 23), és H(4) megmutatja, hogy a 30 lesz a B-ben azels® megfelel® elem.

ASSOC(v) = ASSOC(b(v)) ∪ASSOC(j(v)).

Kaszkád tárolásnál minden csúcsban az L(v) mellett egy Hb(v) és Hj(v)pointertömböt is tárolunk.

82

Page 83: Adatstrukturak

ya-t csak a gyökérnél keressük, utána Hb vagy Hj mutatja meg a "helyét"(az els® ya-nál nem kisebb elemet).

ID� : O(log n + k)

TÁR : O(n · log n)

FELÉPÍTÉS : O(n · log n) Hint: el®ször rendezzük a pontokat egy tömbbe

x szerint, egy másikba y szerint. Ezután felülr®l lefelé konstruálunk, id®nként

kettészedünk egy listát és Hb ill. Hj tömböket töltünk fel közben. Minden megy

a tárhelyben lineáris id®ben.

9.3. Egy téglalapot metsz® szakaszok lekérdezése

Visszatérve az alapfeladatunkra: a kérdezett téglalapba (ablak) es® pontokat letudjuk kérdezni, ha tartomány-fában tároltuk ®ket. Hasonló a helyzet az összesolyan szakasszal, amelynek legalább egyik végpontja az ablakba esik, itt csakkét dologra kell vigyázni:

� a szakaszok végpontjaival együtt tároljuk el a szakasz sorszámát is,

� ha egy szakasz mindkét végpontja az ablakban van, akkor csak egyszerírjuk ki.

De persze lehetnek olyan, a téglalapot metsz® szakaszok is, melyeknek mind-két végpontjuk kívül van. El®ször azt a speciális esetet oldjuk meg, amikor min-den tárolt szakaszunk vízszintes vagy függ®leges, és csak a következ® fejezetbenkezeljük a ferde szakaszok esetét (pl. VLSI tervezésnél ilyenek nincsenek is).Tehát most azokat a vízszintes és függ®leges szakaszokat szeretnénk kiíratni,melyek teljesen átmetszik az ablakot. Az ilyenek vagy vízszintesek és metszik ajobb oldalt, vagy függ®legesek és metszik a fels® oldalt. Ez a két feladat nyilván�ugyanaz�, tehát elég az els® esetet kezelni. Azonban újra �gyelni kell arra, hogymost ki fogjuk válogatni az összes vízszintes szakaszt, mely metszi a jobb oldalt,tehát azokat is, amelyek bal végpontja benne van az ablakban � ezeket azonbanmár egyszer kiírtuk, nem szabad újra.

83

Page 84: Adatstrukturak

Hint a kétszeri kiírás megakadályozására : egyszer¶, de kicsit kényelmetlenmegoldás lehet, ha egyrészt felveszünk egy n hosszú tömböt (n a szakaszokszáma) és egy sort. Ha bármely fázisban megtaláljuk az i. szakaszt, akkor meg-nézzük, hogy a tömb i. eleme 1-e, ha igen megyünk tovább, ha nem, akkor egyreállítjuk és i-t berakjuk a sorba. A végén a sorból ki tudjuk íratni az összesmegtalált szakaszt, és közben a tömböt újra le tudjuk nullázni.

IV. TÁROLNI : Vízszintes szakaszok a síkon.

KÉRDÉS : METSZ�([x]× [ya, yf ]).

VÁLASZ : felsoroljuk az összes olyan vízszintes szakaszt, mely metszi a kér-dezett függ®leges szakaszt.

Intervallum-fát készítünk az x tengelyre es® vetületek szerint. DE az eredetimegoldással ellentétben az I(v) halmazokat nem két listában tároljuk, hanemhelyette két kupacos keres®fában (lásd alább). Az els®ben az intervallumokata bal, a másodikban a jobb végpontjuk szerint. A keresés majdnem ugyanúgymegy, mint a hagyományos intervallum-fában, csak amikor az adott v csúcs I(v)halmazából ki akarjuk válogatni a minket érdekl®ket, akkor pl. x < x0 eseténaz els® kupacos keres®fában keressük meg azokat, akiknek a bal végpontja a(−∞, x]× [ya, yf ] végtelen téglalapba esik.

y

ya

f

x

Tehát a következ® feladatot kell még megoldanunk, melyre a tartomány-fa is megoldás lenne, de most egy még hatékonyabb megoldást adunk (kisebbtárhellyel).

9.3.1. Kupacos keres®fák

V. TÁROLNI : p1, p2, . . . pn ∈ R2

KÉRDÉS : PONTOK((−∞, x]× [ya, yf ]).

84

Page 85: Adatstrukturak

y

ya

f

x j

Megoldás : Kupacos keres®fa � a legszebb öszvér adatstruktúra.

El®ször egy kis el®készületre van szükségünk, egy új m¶veletet vizsgálunkmeg kupacokban. Tehát adott egy bináris kupac, és egy K kulcs, a feladat pedigaz, hogy soroljuk fel az összes olyan v csúcsát a kupacnak, amelyre K(v) ≤ K.

megoldás : REPORT (v0,K) hívása, ahol v0 a kupac gyökere.

REPORT (v,K)IF K(v) ≤ K THEN PRINT v ; REPORT (b(v),K) ; REPORT (j(v),K)

25. Tétel. Ez O(1 + k) id®ben fut.

Bizonyítás : Ha meghívtuk REPORT (u, K)-t, akkor vagy u gyökér volt, vagyu része az outputnak, vagy p(u) része az outputnak, tehát k hosszú output eseténlegfeljebb 3k + 1 hívás lesz.

Megjegyzés : Ez persze csak akkor igaz, ha nem rendezve kellenek az elemek,különben mindenhol Mintörlés kellene.

A Kupacos keres®fa egy kiegyensúlyozott bináris fa, amelynek minden v csú-csában egy q(v) pont és egy y(v) �útjelz®tábla� van.

Ez az öszvér adatstruktúra egyszerre lesz x koordináta szerint kupac, és ykoordináta szerint bináris keres®fa; pontosabban csak annak hasonmása, azt afontos keres®fa tulajdonságot fogja teljesíteni, hogy egy adott v csúcsnál a balrészfában csupa olyan pontot tárolunk, melyek y koordinátája ≤ y(v), a jobbrészfában pedig csupa olyan pontot tárolunk, melyek y koordinátája > y(v) ,(demagában a v csúcsban tárolt q(v) pontnak semmi köze nem lesz y(v)-hez).

Felveszünk egy v0 gyökeret, q(v0) := a legbaloldalibb pont.

y(v0) := y′, amelyre S = {p1, p2, . . . pn} \ {q(v0)} halmaznak a fele van azy = y′ egyenes felett. Sb = {pi ∈ S | yi ≤ y′} és Sj = {pi ∈ S | yi > y′}. Ezeketrekurzívan ugyanígy tároljuk a gyökér bal ill. jobb részfájában.

85

Page 86: Adatstrukturak

rekurzívan y'alatti nem q(v)pontok

rekurzívan y'feletti nemq(v) pontok

A Keresés így megy: el®ször ya-t és yf -et keressük a fában.

y

belsõ lelógóelemek: ezek yszerint csupa jópontok

a y f

A keresési utak során bejárt csúcsokban tárolt q(v) pontokat egyesével leel-len®rizzük, hogy benne vannak-e a kérdezett téglalapban. Ezeken kívül mindenmás jó pont valamely fontos csúcs alatt lesz. Ráadásul egy v fontos csúcs alattiminden pont y koordinátája az [ya, yf ] intervallumba esik, így a fontos csúcsokrészfáit már kupacként kezelhetjük, és az el®bb látott módon ki tudjuk írni a jópontokat O(1 + kv) id®ben, ahol most kv az output összes, a v részfájába es®pontjainak számát jelöli.

ID� : O(log n + k)

Ez ugyanolyan gyors, mint a tartomány-fa kaszkádolással, de egyszer¶bb amegvalósítás és kisebb a tárigény:

TÁR : O(n)

FELÉPÍTÉS : O(n · log n)

9.4. Ferde szakaszok lekérdezése

Ami hátravan, az az ablakot teljesen átmetsz® ferde szakaszok lekérdezése. Eztnégy részben valósítjuk meg, külön-külön lekérdezzük a téglalap négy oldalát

86

Page 87: Adatstrukturak

metsz® ferde szakaszokat. Szimmetria okokból nyilván itt is elég lekérdezni egyadott függ®leges szakaszt metsz® ferde szakaszokat.

y

ya

f

x

Megjegyzés : Most el®ször fogjuk kihasználni, hogy a szakaszok nem metsz-hetik egymást.

Megoldás : A vetületeket most is mint intervallumokat tároljuk. Azonban errea célra az intervallum-fa jelenleg nem felel meg nekünk, ezért egy újabb, els®ránézésre sokkal rosszabb megoldást kell adnunk erre az egy dimenziós feladatra.

9.4.1. Szakasz-fa

Felbontjuk a számegyenest a végpontok által meghatározott egypontú és nyíltszakaszokra. Egy-egy ilyen szakaszba azok az x-ek esnek, amelyekre biztosanugyanaz a válasz (az ®t tartalmazó intervallumok halmaza).

Összesen legfeljebb 4n + 1 darab ilyen szakasz lesz: legfeljebb 2n darab 1pontú és legfeljebb 2n+1 darab nyílt szakasz (két tárolt intervallum végpontjaiegybe is eshetnek).

Egy kiegyensúlyozott bináris keres®fát építünk, melynek leveleire ráírjuk aszakaszokat úgy, hogy balról jobbra rendezve legyenek. A fa egy v csúcsára de�-niáljuk egyrészt az Int(v) intervallumot, mely a v alatti levelekre írott szakaszokuniója; másrészt az ASSOC(v) := {Ij | Ij ⊇ Int(v), de Ij 6⊇ Int(p(v))} hal-mazt. A v csúcsnál tároljuk ASSOC(v)-t mégpedig egy tömbben (itt még vannémi szabadságfokunk, hogy milyen sorrendben, ezt a következ® alfejezetben kiis fogjuk használni).

87

Page 88: Adatstrukturak

-) . () .() .() .

v

26. Tétel. Egy adott Ij intervallumot a fa egy szintjén maximum kétszer tárol-juk, így az összes tárigény O(n · log n).

Bizonyítás : Ha Ij egy szinten háromszor lenne tárolva, akkor legyenek balróljobbra a, b, c a csúcsok, amiben tároltuk. Mivel Int(a) ⊆ Ij és Int(c) ⊆ Ij , ezérta keres®fa tulajdonságai miatt nyilván b szül®jére Int(p(b)) ⊆ Ij , tehát Ij nemlehet benne ASSOC(b)-ben.

Keresés : a fában itt is x-et keressük, és a keresési út során érintett minden vcsúcsra a teljes ASSOC(v)-t kilistázzuk. Tehát O(log n + k) id®ben itt is megy.

A szakasz-fa el®nye az intervallum-fához képest, hogy a csúcsokban tároltASSOC(v) halmazok uniója pontosan az, amit ki kell adnunk, ebb®l itt nemkell válogatni. Pont ezért, ha az ASSOC(v) tömböket jól rendezzük, akkor mégegy másik szempont szerint tudunk majd bel®lük szelektálni.

9.4.2. Egy függ®leges szakaszt metsz® ferde szakaszok

A szakaszokat az x tengelyre es® vetületük szerint szakasz-fában tároljuk, ésebben keressük x-et. A keresés során a fa egy adott v csúcsánál ASSOC(v)-ben azok a ferde szakaszok vannak, amelyek vetülete tartalmazza Int(v)-t, denem tartalmazza Int(p(v))-t. Ezek tehát mind átmennek az Int(v)× (−∞,∞)függ®leges végtelen csíkon. Mivel nem metszik egymást, így alulról felfelé egyér-telm¶en rendezhet®k, tehát eszerint tároljuk ®ket az ASSOC(v)-t tartalmazótömbben. Kereséskor felez® kereséssel könnyen megtalálhatjuk a legalsó olyat,mely metszi a kérdezett [x]× [ya, yf ] szakaszt, majd ett®l kezdve addig íratjuk kiASSOC(v) elemeit, míg metszik ezt a kérdezett szakaszt. A v-nél eltöltött id®így O(log n + kv), tehát az összes keresési id® O(log2 n + k). Az egész struktúrafelépíthet® O(n log n) id®ben.

88

Page 89: Adatstrukturak

xInt(v)

89