Előadást letölteni
Az előadás letöltése folymat van. Kérjük, várjon
KiadtaAndrea Piroska Szalainé Megváltozta több, mint 5 éve
1
Rekurzió 4. Szlávi Péter ELTE Informatika Szakmódszertani Csoport
Rekurzió 4. Szlávi Péter ELTE Informatika Szakmódszertani Csoport 2000 Rekurzió 1
2
Tartalom 0 Bevezetés 1 Rekurzív specifikáció
Tartalom 0 Bevezetés 0.1 A rekurzió lényege; „klasszikus” példák 0.2 A rekurzió helye a programkészítés folyamatában 1 Rekurzív specifikáció 1.1 Formalizmus 1.2 Példák 2 Rekurzív specifikáció és rekurzív algoritmus 3 Rekurzió megvalósítása nem rekurzív környezetben 3.1 Problémák 3.2 Példák 3.3 A valódi megoldás ötlete, avagy mit tesz egy fordító program? Rekurzió 4 Rekurzió 1
3
Tartalom 4 Rekurzió és iteráció 5 Rekurzív típusok 4.1 Oda 4.2 Vissza
Tartalom 4 Rekurzió és iteráció 4.1 Oda 4.2 Vissza 5 Rekurzív típusok 5.1 Nevezetes rekurzív adatszerkezetek 5.2 Rekurzív adatszerkezetek megadása 5.3 A struktúrabejárás mint a feldolgozás „kerete” Rekurzió 4 Rekurzió 1
4
Tartalom 6 Rekurzív adattípusok: fák 6.1 Bináris fák
Tartalom 6 Rekurzív adattípusok: fák 6.1 Bináris fák 6.1.0 Példák, alapfogalmak 6.1.1 Algebrai specifikáció 6.1.2 Exportmodul 6.1.3 Megvalósítási modul Egy másik elképzelés 6.1.5 Összetett műveletek 6.1.6 Keresőfák 6.1.7 Rendező fák 6.2 Nem bináris fák 6.2.1 Algebrai specifikáció 6.2.2 Exportmodul 6.2.3 Megvalósítási modul 6.3 B-fák Rekurzió 4 Rekurzió 1
5
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák 6.1 Bináris fák 6.1.0 Példák, alapfogalmak Kifejezések Családfák Keresőfák (amik a gyors megtalálást célozzák) Rendezőfák („virtuális fa” -- időleges állapot) Rekurzió 4 Rekurzió 1
6
6 Rekurzív adattípusok: fák (folytatás)
6 Rekurzív adattípusok: fák (folytatás) 6.1.1 Algebrai specifikáció Típus BinFa(Elem): Asszociált műveletek: Üres:BinFa Üres?(BinFa):Logikai EgyEleműFa(Elem):BinFa [Létrehoz] BalraIlleszt(BinFa,BinFa):BinFa {NemDef} [Illeszt] JobbraIlleszt(BinFa,BinFa):BinFa {NemDef} GyökérElem(BinFa):Elem {NemDef} [Elem] BalGyerek(BinFa):BinFa {NemDef} [Rész] JobbGyerek(BinFa):BinFa {NemDef} GyökérMódosít(BinFa,Elem):BinFa {NemDef} [Módosít] *Illeszt(mire,mit) A rekord-szerű filozófia tükröződik a BinFa típuskonstrukció nyelvezetén. A „sokaságszerű” rekurzióból kimaradó műveletek: Leválaszt(Rek,Szel,Rek):RekRek {NemDef} Elsőre(Rek):Rek {NemDef} Következőre(Rek,Szel):Rek {NemDef} Elején?(Rek):Logikai {NemDef} Végén?(Rek):Logikai {NemDef} Rekurzió 4 Rekurzió 1
7
6 Rekurzív adattípusok: fák (folytatás)
6 Rekurzív adattípusok: fák (folytatás) Jelölések: b,b’,b”,bb,b’:BinFa(Elem) – általában az aposztróf időbeliségre utal e:Elem „=”:BinFaBinFaLogikai, strukturális és elemérték-szintű azonosság Axiómák: 1º Üres – axióma Üres?(Üres) 1’º Üres – hiba-axióma b=Üres GyökérElem(b)=NemDef BalGyerek(b)=NemDef JobbGyerek(b)=NemDef 2º EgyElemű – axióma b=EgyElemű(e) Üres?(b) GyökérElem(b)=e Üres?(BalGyerek(b)) Üres?(JobbGyerek(b)) A szigorúbb feltételrendszerrel fogalmazódott meg az axiómarendszer. (Nem élünk az intelligensebb memóriakezelés adta nagyvonalúbb lehetőséggel.) Rekurzió 4 Rekurzió 1
8
6 Rekurzív adattípusok: fák (folytatás)
6 Rekurzív adattípusok: fák (folytatás) 3º *Illeszt – axióma [*=Bal/Jobb] Üres?(b) Üres?(*Gyerek(b)) *raIlleszt(b,bb)=b’ *Gyerek(b’)=bb GyökérElem(b)=GyökérElem(b’) … 3’º *Illeszt – hiba-axióma Üres?(b) Üres?(*Gyerek(b)) *raIlleszt(b,bb)=NemDef 4º GyökérMódosít – axióma Üres?(b) GyökérMódosít(b,e)=b’ GyökérElem(b’)=e 4’º GyökérMódosít – hiba-axióma Üres?(b) GyökérMódosít(b,e)=NemDef Rekurzió 4 Rekurzió 1
9
6 Rekurzív adattípusok: fák (folytatás)
6 Rekurzív adattípusok: fák (folytatás) 6.1.2 Exportmodul ExportModul BinFa(Típus TElem): Függvény Üres?(Konstans f:BinFa):Logikai Konstans Üres:BinFa Függvény EgyEleműFa(Konstans e:TElem):BinFa Eljárás BalraIlleszt(Változó f:BinFa,Konstans g:BinFa) [Ef: az f nem üres, a balrésze üres] Eljárás JobbraIlleszt(Változó f:BinFa,Konstans g:BinFa) [Ef: az f nem üres, a jobbrésze üres] Függvény GyökérElem(Konstans f:BinFa):TElem [Ef: az f nem üres] Függvény BalGyerek(Konstans f:BinFa ):BinFa Függvény JobbGyerek(Konstans f:BinFa ):BinFa Eljárás GyökérMódosít(Változó f:BinFa,Konstans e:TElem) [Ef: az f nem üres] … Rekurzió 4 Rekurzió 1
10
6 Rekurzív adattípusok: fák (folytatás)
6 Rekurzív adattípusok: fák (folytatás) … Eljárás FaTörlés(Változó f:BinFa) [értékmegosztás esetén] Modul vége. Megjegyzés: A hiba-kezelése –szokásos módon– egy hiba-komponens- sel lehetséges. Ez esetben a fenti eljárások/függvények BinFa-paramé- terének hozzáférését változóra kell ókor-ókor módosítani. És szükség van egy Hibás? függvényre is. Rekurzió 4 Rekurzió 1
11
6 Rekurzív adattípusok: fák (folytatás)
6 Rekurzív adattípusok: fák (folytatás) 6.1.3 Megvalósítási modul Megjegyzések: Visszavezetés az „általános” rekurzióra annak is a rekord-szemléletű definíciójára Modul BinFa(Típus TElem): Reprezentáció Típus RBinFa=Rekurzió(elem:TElem, bal,jobb:RBinFa) Változó f:RBinFa Implementáció Konstans Üres:RBinFa() Függvény Üres?(Konstans f:RBinFa):Logikai Üres?:=f=Üres Függvény vége. … átnevezés Átnevezés -- visszavezetés Visszavezetés a rekurzióra Rekurzió 4 Rekurzió 1
12
6 Rekurzív adattípusok: fák (folytatás)
6 Rekurzív adattípusok: fák (folytatás) … Függvény EgyEleműFa(Konstans e:TElem):RBinFa EgyEleműFa:=RBinFa(e,Üres,Üres) Függvény vége. Eljárás BalraIlleszt(Változó f:RBinFa, Konstans g:RBinFa) [Ef: RBinFa’Üres?(f) RBinFa’Üres?(f.bal)] f.bal:=g Eljárás vége. Eljárás JobbraIlleszt(Változó f:RBinFa, Konstans g:RBinFa) [Ef: RBinFa’Üres?(f) RBinFa’Üres?(f.jobb)] f.jobb:=g Eljárás vége. Függvény GyökérElem(Konstans f:RBinFa):RBinFa [Ef: RBinFa’Üres?(f)] GyökérElem:=f.elem Függvény vége. RBinFa-műveletekkel kifejezve Az operátorok explicit minősítése valójában fölösleges, hiszen paramétereinek típusa egyértelműen közli: RBinFa, azaz a reprezentációnál felhasznált típusról van szó. Csak a nyomaték kedvéért vezettem be az eddig nem használt jelölést. Rekurzió 4 Rekurzió 1
13
6 Rekurzív adattípusok: fák (folytatás)
6 Rekurzív adattípusok: fák (folytatás) … Függvény BalGyerek(Konstans f:RBinFa):RBinFa BalGyerek:=f.bal Eljárás vége. Függvény JobbGyerek(Konstans f:RBinFa):RBinFa JobbGyerek:=f.jobb Eljárás vége. Eljárás GyökérMódosít(Változó f:RBinFa,Konstans e:TElem) [Ef: RBinFa’Üres?(f)] f.elem:=e Eljárás vége. Inicializálás [deklarációknál automatikusan végrehajtódik] f:=Üres Modul vége. Rekurzió 4 Rekurzió 1
14
6 Rekurzív adattípusok: fák (folytatás)
6 Rekurzív adattípusok: fák (folytatás) 6.1.4 Egy másik elképzelés Alapja a rekurzió típus „tulajdonos-számlálásos” ábrázolási módszere. (Lásd előző előadásban.) Típus TBinFa=Rekord(gyökér:TBinFaElemMut, hiba:Logikai) TBinFaElemMut=TBinFaElem’Mutató TBinFaElem=Rekord(érték:TElem tulSzám:Egész [tulajdonosok száma] bal,jobb:TBinFa) Rekurzió 4 Rekurzió 1
15
6 Rekurzív adattípusok: fák (folytatás)
6 Rekurzív adattípusok: fák (folytatás) A műveletek értelmezésének módosítása: „intelligens”, azaz tulajdonos-számot kezelők: Eljárás ÜresséTesz(Változó bf:TBinFa) [Ef: bf] Függvény Üres?(Konstans bf:TBinFa):Logikai Függvény GyökérElem(Változó bf:TBinFa):TElem [Ef: bf] Eljárás GyökérElemMódosít(Változó bf:TBinFa, Konstans e:TElem) Függvény BalFa(Változó bf:TBinFa):TBinFa Függvény JobbFa(Változó bf:TBinFa):TBinFa Algoritmikus nyelvünk modulfogalma szerint az inicializáláskor üres értket kap. Így a bf ef. kezdetben is tud teljesülni. Általában a bf létezése nehezen ellenőrizhető feltétel. Érdemes belegondolni!!! Az algoritmikus nyelvünk modul fogalma szerint viszont az inicializálás (a deklarációhoz rendelt kód futása) során üres kezdőértéket kap. Kékkel jelöltük a tulajdonos-számtól független (tehát azt „triviálisan” kezelő) operációkat. Rekurzió 4 Rekurzió 1
16
6 Rekurzív adattípusok: fák (folytatás)
6 Rekurzív adattípusok: fák (folytatás) „intelligensek” folytatása: Eljárás BalraIlleszt(Változó bf:TBinFa, Konstans mit:TBinFa) [Ef: bf mit] Eljárás JobbraIlleszt(Változó bf:TBinFa, Konstans mit:TBinFa) [Ef: bf mit] Eljárás ÉrtéketKap(Változó bf:TBinFa, Konstans mit:TBinFa) [Ef: bf,mit] Függvény Hibás?(Változó bf:TBinFa):Logikai [Ef: bf] Rekurzió 4 Rekurzió 1
17
6 Rekurzív adattípusok: fák (folytatás)
6 Rekurzív adattípusok: fák (folytatás) „erőszakos”, más szóval „bamba”, azaz tulajdono- sokra nem figyelők (az := operátoron túl): Eljárás Üres(Változó bf:TBinFa) [Ef: -] Eljárás EgyEleműFa(Változó bf:TBinFa, Konstans e:TELem) Eljárás _BalraIlleszt_(Változó bf:TBinFa, Konstans mit:TBinFa) [Ef: bf] Eljárás _JobbraIlleszt_(Változó bf:TBinFa, Konstans mit:TBinFa) Fontos különbséget tenni: konstruktor és konstrukciós műveletek között. Az utóbbi a bővebb művelethalmaz: ebbe tartozik minden művelet, amely az adott típusú szerkezetet módosítja. Az első kettő konstruktor művelet, tehát akkor működik helyesen, ha a bf nem létezik (de legalábbis üres). Az illesz- tők is csak akkor helyesek, ha a megfelelő ág üres. Hibajel- zés azonban semmiképpen nem képződik. Rekurzió 4 Rekurzió 1
18
6 Rekurzív adattípusok: fák (folytatás)
6 Rekurzív adattípusok: fák (folytatás) … és az „alaphoz” tartozó, nem exportált tulajdo- nos-szám műveletek: Eljárás TulajNövelés( Változó bf:TBinFa): Változó sbf:TBinFa Ha nem Üres?(bf) akkor TBinFaElem(bf.gyoker).tulSzám:+1 sbf:=bf.BalFa TulajNövelés(sbf) bf._BalraIlleszt_(sbf) sbf:=bf.JobbFa TulajNövelés(sbf) bf._JobbraIlleszt_(sbf) Elágazás vége [nincs szükség az ÜresséTesz(sbf)-re, mert sbf nem vált tulajdonossá] Eljárás vége. Eljárás TulajCsökkentés( Változó bf:TBinFa): Változó sbf:TBinFa Ha nem Üres?(bf) akkor TBinFaElem(bf.gyoker).tulSzám:-1 sbf:=bf.BalFa TulajCsökkentés(sbf) bf._BalraIlleszt_(sbf) sbf:=bf.JobbFa TulajCsökkentés(sbf) bf._JobbraIlleszt_(sbf) Ha TBinFaElem(bf.gyökér).tulSzám= akkor Felszabadít(bf.gyökér) Elágazás vége [nincs szükség az ÜresséTesz(sbf)-re, mert sbf nem vált tulajdonossá] Eljárás vége. Az sbf konstrukciós műveletére explicite nincs szükség. Legalábbis az algoritmikus nyelvünkben. Nem így pl. a Delphi-Lazarus-ban, ahol nincs a deklaráció életbelépésekor automatikus inicializálás. Rekurzió 4 Rekurzió 1
19
6 Rekurzív adattípusok: fák (folytatás)
6 Rekurzív adattípusok: fák (folytatás) Még egyszer a TBinFa-műveletkészlet használat- „módszertana”: mikor, melyik művelet használandó, módszertani elvek? Szabályok: Minden deklarált TBinFa adatobjektumot inicia- lizálni kell (Üres, EgyeleműFa konstruktorokkal). Az adat megsemmisülése előtt (pl. ez történik egy lokális adat eljárásból való kilépéskor) üressé kell tenni (ha adminisztratívan is tulajdonossá vált). Kerülendő a „sima” értékadás, helyette az Érté- ketKap-ot kell használni. Ha ez automatikusan nem történt meg. Rekurzió 4 Rekurzió 1
20
6 Rekurzív adattípusok: fák (folytatás)
6 Rekurzív adattípusok: fák (folytatás) Illusztrálásképpen kövessük és értelmezzük a követ- kező programot: ! Rekurzió 4 Rekurzió 1
21
6 Rekurzív adattípusok: fák (folytatás)
6 Rekurzív adattípusok: fák (folytatás) 6.1.5 Összetett műveletek Elemszám: Mélység: … hf … Specifikáció – az uf. definíciós része Def: Elemszám:BinFaEgész , ha Üres?(f) Elemszám(f):= 1+Elemszám(BalGyerek(f)) Elemszám(JobbGyerek(f)) , ha egyébként Eljárás Elemszám(Konstans f:BinFa):Egész Ha Üres?(f) akkor Elemszám:= különben Elemszám:=1+Elemszám(BalGyerek(f)) Elemszám(JobbGyerek(f)) Elágazás vége Eljárás vége. Algoritmus Rekurzió 4 Rekurzió 1
22
6 Rekurzív adattípusok: fák (folytatás)
6 Rekurzív adattípusok: fák (folytatás) Bejárások Eljárás BKJ(Konstans bf:BinFa): Ha nem Üres?(bf) akkor BKJ(BalGyerek(bf)) Ki: GyökérElem(bf) BKJ(JobbGyerek(bf)) Elágazás vége Eljárás vége. Eljárás KBJ(Konstans bf:BinFa): Ha nem Üres?(bf) akkor Ki: GyökérElem(bf) KBJ(BalGyerek(bf)) KBJ(JobbGyerek(bf)) Elágazás vége Eljárás vége. Eljárás BJK(Konstans bf:BinFa): Ha nem Üres?(bf) akkor BJK(BalGyerek(bf)) BJK(JobbGyerek(bf)) Ki: GyökérElem(bf) Elágazás vége Eljárás vége. Rekurzió 4 Rekurzió 1
23
6 Rekurzív adattípusok: fák (folytatás)
6 Rekurzív adattípusok: fák (folytatás) A bejárások iteratív változatai Bal-közép-jobb Az algoritmus, először „kézzel”: * b + a 2 := x Rekurzió 4 Rekurzió 1
24
6 Rekurzív adattípusok: fák (folytatás)
6 Rekurzív adattípusok: fák (folytatás) A bejárások iteratív változatai Az algoritmus, vázlatosan: Még nem másodszor értünk vissza a gyökérhez … gyökérre állás Ciklus amíg nem le a gyökérről Ciklus amíg nem le a fáról Verembe(ahol tartunk) Balralépés Ciklus vége Veremből(ahova vissza kell lépni) Ha nem le a gyökérről akkor Ki: Elem(ahol tartunk) Jobbralépés Elágazás vége Ciklus vége … Nem léptünk le egy levélről, azaz van út előre * b + a 2 := x Rekurzió 4 Rekurzió 1
25
6 Rekurzív adattípusok: fák (folytatás)
6 Rekurzív adattípusok: fák (folytatás) Kövessük az algoritmust üres és egyelemű binfára! … és pontosítva: Eljárás BKJ(Konstans bf:BinFa): Változó rf:BinFa; v:Verem(BinFa) Üres(v); Verembe(v,Üres) rf:=bf Ciklus amíg nem Üres?(v) Ciklus amíg nem Üres?(rf) Verembe(v,rf) rf:=BalGyerek(rf) Ciklus vége Veremből(v,rf) Ha nem Üres?(v) akkor Ki:Gyökér(rf) rf:=JobbGyerek(rf) Elágazás vége Ciklus vége Eljárás vége. … gyökérre állás Ciklus amíg nem le a gyökérről Ciklus amíg nem le a fáról Verembe(ahol tartunk) Balralépés Ciklus vége Veremből(ahova vissza kell lépni) Ha nem le a gyökérről akkor Ki: Elem(ahol tartunk) Jobbralépés Elágazás vége Ciklus vége … Rekurzió 4 Rekurzió 1
26
6 Rekurzív adattípusok: fák (folytatás)
6 Rekurzív adattípusok: fák (folytatás) Közép-bal-jobb … hf … Bal-jobb-közép … hf … Rekurzió 4 Rekurzió 1
27
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák 6.1.6 Kereső fák Cél: gyors keresés + kényelmes módosíthatóság Lényeg: Típus TElem=Rekord(kulcs:TKulcs, egyéb:TEgyéb) Műveletek (a szokásos BinFa műveleteken túl): keresés elem-beillesztés, -törlés kiegyensúlyozás Rövid leírhatóság kedvéért, átnevezzük: TKFa Logaritmikus sebességgel Láncolt szerkezetek rugalmasságával Típus TKeresőFa=BinFa(TElem) [Ef: Rendezett(TKulcs) Típusinvariáns: f:TKeresőFa: GyökérElem(r).kulcs>GyökérElem(BalGyerek(r)).kulcs GyökérElem(r).kulcsGyökérElem(JobbGyerek(r)).kulcs] A „keresőfa” tulajdonság Rekurzió 4 Rekurzió 1
28
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Kulcsegyértelműség Rekord-szerűen: Függvény Keresés(Konstans k:TKulcs, kf:TKFa):TKFa [Uf: ekf: k=e.kulcs f=Keresés(k,kf): GyökérElem(f).kulcs=k ¬ekf: k=e.kulcs Keresés(k,kf)=Üres] Függvény Beillesztés(Konstans e:TElem, kf:TKFa):TKFa [Ef: ║{xkf: x.kulcs=e.kulcs}║≤1 Uf: f=Beillesztés(e,kf) akf: a.kulcs=e.kulcs xkf: x.kulcse.kulcs xf xkf: x.kulcs=e.kulcs x’=ef ¬akf: a.kulcs=e.kulcs xkf xf ef ] Definíciós ok miatt: a rendezés szerinti helyére kerül az e elem! Rekurzió 4 Rekurzió 1
29
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Kulcsegyértelműség Függvény Törlés(Konstans k:TKulcs, kf:TKFa):TKFa [Ef: x,ykf: xy x.kulcsy.kulcs Uf: ekf: e.kulcs=k f=Törlés(k,kf): ef akf: a.kulcsk af ¬ekf: e.kulcs=k Törlés(k,kf)=kf] Függvény Kiegyensúlyozás(Konstans kf:TKFa):TKFa [Uf: Kiegyensúlyozott(kf) Kiegyensúlyozás(kf)=kf ¬Kiegyensúlyozott(kf) f=Kiegyensúlyozás(kf): Kiegyensúlyozott(f)] L. később! Rekurzió 4 Rekurzió 1
30
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Kimenő értéke a kf-nek Sokaság-szerűen: Előzetes megjegyzés: az utófeltételben a BinFa sokaság-szerű műveleteit függvé- nyes jelölésekkel (értelemszerű értéktípussal) fogjuk használni. Szavakkal: ha benne van a keresett, akkor az lesz az aktuális; ha nincs benne, akkor van olyan keresőfa, amely a kf-ből úgy kapható, hogy az aktuálisra illesztjük a megfelelő szelektoron át. (Azaz oda lesz állítva az akt mutató.) Eljárás Keresés(Konstans k:TKulcs, Változó kf:TKFa, van:Logikai, melyik:Szelektor) [Uf: ekf:k=e.kulcs Elem(kf’).kulcs=k van ¬ekf:k=e.kulcs ¬van fTKFa: f=Illeszt(EgyEleműFa((k,eb)),kf’,melyik)] Rekurzió 4 Rekurzió 1
31
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Eljárás Beillesztés(Konstans e:TElem, Változó kf:TKFa) [Ef: ║{xkf: x.kulcs=e.kulcs}║≤1 Uf: ekf’ Elem(kf’)=e] Eljárás Törlés(Konstans k:TKulcs, Változó kf:TKFa) [Ef: x,ykf: xy x.kulcsy.kulcs Uf: ekf: e.kulcs=k akf: af ef ¬ekf: e.kulcs=k kf’=kf] Függvény Kiegyensúlyozás(Változó kf:TKFa) [… ugyanaz …] Kimenő értéke a kf-nek Rekurzió 4 Rekurzió 1
32
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Megvalósítások: Keresés Rekord-szerűen: Függvény Keresés(Konstans k:TKulcs, kf:TKFa):TKFa [Uf: ekf: k=e.kulcs f=Keresés(k,kf) GyökérElem(f).kulcs=k ¬ekf: k=e.kulcs Keresés(k,kf)=Üres] Elágazás Üres?(kf) esetén Keresés:=kf k<GyökérElem(kf).kulcs esetén Keresés:= Keresés(k,BalGyerek(kf)) k>GyökérElem(kf).kulcs esetén Keresés:= Keresés(k,JobbGyerek(kf)) k=GyökérElem(kf).kulcs esetén Keresés:=kf Elágazás vége Függvény vége. Rekurzió 4 Rekurzió 1
33
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Sokaság-szerűen (visszatérünk a rekurzió nyelvére): Eljárás Keresés(Konstans k:TKulcs, Változó kf:TKFa,van:Logikai,melyik:Szelektor): [Uf: ekf: k=e.kulcs Elem(kf’).kulcs=k van ¬ekf: k=e.kulcs ¬van Üres?(kf) fTKFa: f=Illeszt(EgyEleműFa((k,eb)),kf’,melyik)] Ha nem Üres?(kf) akkor Elsőre(kf); van:=Igaz [értsd: lehet, hogy van] Ciklus amíg van és kElem(kf).kulcs Ha k<Elem(kf).kulcs akkor Ha Üres?(Rész(kf,bal)) akkor van:=Hamis; melyik:=bal különben Következőre(kf,bal) Elágazás vége különben … A sokaság-szerűség szinte „diktálja” az iteratív megoldást. Rekurzió 4 Rekurzió 1
34
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák … különben Ha Üres?(Rész(kf,jobb)) akkor van:=Hamis; melyik:=jobb különben Következőre(kf,jobb) Elágazás vége Elágazás vége Ciklus vége különben [Üres esetben] van:=Hamis Elágazás vége Eljárás vége. Ugyanezt Rekord-szerűen is: Függvény Keresés2(Konstans k:TKulcs, kf:TKFa, Változó melyik:Szelektor’):TKFa … hf.; vigyázat: a kf üres esetén melyik-nek különleges érték (pl gyökér) kell; Szelektor-bővítés: Szelektor’… Rekurzió 4 Rekurzió 1
35
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Törlés Az extra gond: a törlés során az elem kiesés miatt a fát sokszor át kell strukturálni, hogy a binfaság és a típusinvariancia is megmaradjon. Az ‘egyértelműség’ ef-ével nem foglalkozunk! Rekord-szerűen: A megoldandó estek: a törlendő levélelem nincs jobboldali részfája nincs baloldali részfája egyik részfája sem üres Függvény Törlés(Konstans k:TKulcs, kf:TKFa):TKFa [Uf: ekf: e.kulcs=k f=Törlés(k,kf): … ¬ekf: e.kulcs=k Törlés(k,kf)=kf] elemzés lásd a „nincs jobboldali …” esetet Rekurzió 4 Rekurzió 1
36
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Függvény Törlés(Konstans k:TKulcs,kf:TKFa):TKFa [Uf: ekf: e.kulcs=k f=Törlés(k,kf): … ¬ekf: e.kulcs=k Törlés(k,kf)=kf] Elágazás Üres?(kf) esetén Törlés:=kf k<GyökérElem(kf).kulcs esetén Törlés:= TKFa(GyökérElem(kf), Törlés(k,BalGyerek(kf)), JobbGyerek(kf)) k>GyökérElem(kf).kulcs esetén Törlés:= TKFa(GyökérElem(kf), JobbGyerek(kf), Törlés(k,BalGyerek(kf)) k=GyökérElem(kf).kulcs esetén Törlés:= GyökérTörlés(k,kf) Elágazás vége Függvény vége. Rekurzió 4 Rekurzió 1
37
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Függvény GyökérTörlés(Konstans k:TKulcs, kf:TKFa):TKFa Változó fa:TKFa; jlb:TElem Elágazás Üres?(BalGyerek(kf)) esetén GyökérTörlés:=JobbGyerek(kf) Üres?(JobbGyerek(kf)) esetén GyökérTörlés:=BalGyerek(kf) egyéb esetben JobbLegbalLe(kf,jlb,fa) GyökérTörlés:=TKFa(jlb, BalGyerek(kf), fa) Elágazás vége Függvény vége. Eljárás JobbLegbalLe(Konstans kf:TKFa, Változó e:TElem, ág:TKFa): … hf. … JobbGyerek(kf)-jlb=fa Rekurzió 4 Rekurzió 1
38
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Sokaság-szerűen: Az ábrázolás további gondja: nem elegendő a törlendőre pozícionálni, hanem annak őse is kell, hiszen őrá kell akasztani a törölt leszárma- zottait. Lásd az alábbi magyarázó ábrát: 9 ős 9 9 4 törlendő 6 1 6 1 1 7 1 7 7 6 8 8 6 8 Rekurzió 4 Rekurzió 1
39
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Algoritmusa: Eljárás Törlés(Konstans k:TKulcs, Változó kf:TKFa): Változó melyik:Szelektor talált:Logikai MódosítottKeresés(k,kf,melyik,talált) Ha talált akkor TénylegesTörlés(melyik,kf) Eljárás vége. Eljárás MódosítottKeresés(Konstans k:TKulcs, Változó kf:TKFa,melyik:Szelektor,talált:Logikai): [Uf: Elem(Rész(kf’,melyik)).kulcs=k] … hf. … Eljárás vége. Eljárás TénylegesTörlés(Konstans melyik:Szelektor, Változó kf:TKFa): … hf. … Eljárás vége. A MódosítottKeresés precizírozandó: Uf: Elején?(kf) Elem(kf).kulcs=k Elem(kf’).kulcs=k melyik=gyökér (Szelektor!) … Azaz az akt melyik szelektorán lóg a törlendő k kulcsú Rekurzió 4 Rekurzió 1
40
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák 1 2 2 1 3 Kiegyensúlyozás A probléma forrása… Definíciók: 1. Kiegyensúlyozott az a bináris fa, amelynek tetszőleges pont- jában „gyökerező” részfáinak ághosszai legfeljebb eggyel térnek el egymástól (AVL-fa). 2. Teljesen kiegyensúlyozott az a bináris fa, amelynek tetszőleges pontjában „gyökerező” részfáinak pontszámai legfeljebb eggyel térnek el egymástól. 3. Teljes az a bináris fa, amelynek tetszőleges pontjában „gyöke- rező” részfáinak pontszámai pontosan megegyeznek. Állítás: {kf: Teljes(kf)} {kf: TeljesenKiegyensúlyozott(kf)} {kf: Kiegyensúlyozott(kf)} Praktikus megállapodás: csak AVL-fákkal foglalkozunk. 3 ((1)2(3)) és (1(2(3))) „lényegében” ugyanazt a keresőfát jelöli, de mégis mennyire más Kérdés: bármely fát át lehet-e alakítani (akár rendezettségtől függetlenül) teljessé, vagy teljesen kiegyensúlyozottá, vagy kiegyensúlyozottá? Állítás: nem lehet tetszőleges fát teljessé tenni, de teljesen kiegyensúlyozottá vagy kiegyensúlyozottá igen. Ui.: * teljes bináris fa elemeinek a száma: 1 v. 3 v. … 2n-1; az ettől eltérő elemszámú fát nem lehet teljessé tenni… * teljesen kiegyensúlyozott (elemi) fák: 1..5 eleműek; érzés: bármely n>5 elemű fát átalakíthatunk úgy, hogy a két részfa elemszáma legfeljebb 1-gyel térjen el a másiktól: n=1+(n div 2)+(n-(n div 2)-1), ahol 0<=(n div 2)-(n-(n div 2)-1)<=1 indukcióval belátható… * kiegyensúlyozottra hasonlóan… Rekurzió 4 Rekurzió 1
41
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák A cél: a beszúrás és a törlés műveletek módosítása úgy, hogy ha előtte az AVL-tulajdonság teljesült, akkor utána is teljesüljön. A beszúrás lényege: a) egyszeres elforgatás x y y x f1 f3 f1 f2 ? új elem f2 f3 ? új elem Rekurzió 4 Rekurzió 1
42
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák b) kétszeres elforgatás Technikai megjegyzés: a folyamatos kiegyensúlyozás megkönnyíthető a szintszám tárolásával: Típus TElem=Rekord(kulcs:TKulcs,egyéb:TEgyéb, szint:Egész) x z y y x z f4 f1 f2 f3 f2 f3 f1 f4 ? új elem ? új elem Rekurzió 4 Rekurzió 1
43
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák 6.1.7 Rendező fák Cél: a rendezés hatékony támogatása. Kiindulópont: keresőfa, amelyet Bal-közép-jobb bejárva kapjuk a rendezett sorozatot. (Felépítéskor kiegyensúlyo- zottságra kell törekedni.) Ábrázolási szokások: Kitaposott úttal dinamikus fa (módosítható) Kupaccal (heap-pel) statikus A keresőfa-tulajdonságot helyettesítve a kupac-tulajdonsággal Rekurzió 4 Rekurzió 1
44
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Kitaposott út: Sokaság-szemléletű, ui.: Minden elemnek van egy „visszamutató” mezője, a bejárás (most a BKJ) szerint kitöltve: Típus TBinFaElem=Rekord( elem:TElem, bal,jobb,vissza:TBinFaElem’Mutató) nem rekurzív struktúra (így nincs Rekord-szerű változata!) lehetővé teszi a Veremnélküli használatot Rekurzió 4 Rekurzió 1
45
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Az exportmodul és Függvény VisszaŐs(Konstans rf:BinFa):BinFa [Uf: az akt az eddigi akt őse lesz, ha lehet, különben nemDef] Eljárás VisszaMódosít(Változó rf:BinFa, Konstans mire:BinFa) [Uf: az rf akt elemének vissza mutatója a mire akt elemére mutasson] a megvalósítás is módosul… Függvény VisszaŐs(Konstans rf:BinFa):BinFa … hf. … Eljárás VisszaMódosít(Változó rf:BinFa, Konstans mire:BinFa) … hf. … … a többi rutin is módosítandó … Rekurzió 4 Rekurzió 1
46
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák egy új alap elv a műveletekhez: minden művelet az aktuális elemhez képest értendő Pl. egy ága akkor Üres, ha az aktuális elem adott ága üres; vagy BalGyerek függvény hívása a paraméterfát eredményezi, de a fa aktuális eleme bal „irányba” lép egyet… Rekurzió 4 Rekurzió 1
47
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Egy elem beillesztése: Eljárás Beilleszt(Változó rf:BinFa, Konstans e:TElem): [Uf: … hf. … ] Változó sf,új,előző:BinFa, irány:Szelektor új:=EgyeleműFa(e) sf:=rf Ciklus amíg nem Üres?(sf) előző:=sf Ha e<GyökérElem(előző) akkor sf:=BalGyerek(sf); irány:=bal különben sf:=JobbGyerek(sf); irány:=jobb Elágazás vége Ciklus vége … előző gyökér|akt … Elem bal|jobb|vissza Elem bal|jobb|vissza új gyökér|akt Rekurzió 4 Rekurzió 1
48
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák előző gyökér|akt … Ha irány=bal akkor BalraIlleszt(előző,új) VisszaMódosít(új,előző) különben JobbraIlleszt(előző,új) VisszaMódosít(új,VisszaŐs(előző)) VisszaMódosít(előző,Üres) Elágazás vége Eljárás vége. … Elem bal|jobb|vissza Elem bal|jobb|vissza Elem bal|jobb|vissza Elem bal|jobb|vissza új gyökér|akt Egy elem törlése: … hf. … Elem bal|jobb|vissza új gyökér|akt Rekurzió 4 Rekurzió 1
49
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Maga a rendezett sorozat: (=BKJ-bejárással) Eljárás BKJ(Konstans f: BinFa): Változó sf:BinFa sf:=f Ciklus amíg nem Üres?(sf) Ciklus amíg nem Üres?(BalGyerek(sf)) sf:=BalGyerek(sf) Ciklus vége Ki: GyökérElem(sf) Ciklus amíg Üres?(JobbGyerek(sf)) és nem Üres?(VisszaŐs(sf)) sf:=VisszaŐs(sf) sf:=JobbGyerek(sf) Eljárás vége. 5 3 7 2 4 6 8 1 Rekurzió 4 Rekurzió 1
50
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Kupaccal (heap/halom/piramis): Folytonos ábrázolású Speciális kupac-tulajdonság: a kupac gyökéreleme kisebb (vagy egyenlő), mint a közvetlen leszármazottak a kupac balról folytonos, azaz ha nem teljes a fa, akkor csak a legutolsó szintből hiányozhatnak elemek, de azok is csak a szint jobb széléről. 5 5 3 7 2 4 6 8 1 3 7 2 4 6 8 1 BalGyerek(i)=2*i JobbGyerek(i)=2*i+1 A rendezés „irányától” függően Rekurzió 4 Rekurzió 1
51
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák A rendezendő sorozat A kupac-rendezés „működése” (példa): 5 3 7 2 4 6 8 1 A kupacosítás: 5 3 7 2 4 6 8 1 5 3 7 1 4 6 8 2 5 3 6 1 4 7 8 2 5 1 6 3 4 7 8 2 5 1 6 2 4 7 8 3 1 5 6 2 4 7 8 3 Rekurzió 4 Rekurzió 1
52
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Ime a kupac! 1 2 6 5 4 7 8 3 1 2 6 3 4 7 8 5 A rendezés: „Helyre-csere”! 8 1 2 6 3 4 7 5 Kupac helyrehozás 5 2 6 3 4 7 8 1 2 5 6 3 4 7 8 1 2 3 6 5 4 7 8 1 Rekurzió 4 Rekurzió 1
53
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák „Helyre-csere”! 2 3 6 5 4 7 8 1 „Helyre-csere”! Kupac helyrehozás 8 3 6 5 4 7 2 1 3 8 6 5 4 7 2 1 3 4 6 5 8 7 2 1 Kupac helyrehozás 7 4 6 5 8 3 2 1 4 7 6 5 8 3 2 1 4 5 6 7 8 3 2 1 Rekurzió 4 Rekurzió 1
54
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák „Helyre-csere”! 4 5 6 7 8 3 2 1 „Helyre-csere”! Kupac helyrehozás 8 5 6 7 4 3 2 1 5 8 6 7 4 3 2 1 5 7 6 8 4 3 2 1 Kupac helyrehozás „Helyre-csere”! 8 7 6 5 4 3 2 1 6 7 8 5 4 3 2 1 Rekurzió 4 Rekurzió 1
55
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Kupac helyrehozás 8 7 6 5 4 3 2 1 „Helyre-csere”! 7 8 6 5 4 3 2 1 8 7 6 5 4 3 2 1 A rendezett sorozat Rekurzió 4 Rekurzió 1
56
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák A kupac fogalomkörének megközelítése: Kupac= BinFa=Tömb(1..ElemSzám: TElem) típusú vektor, KupacHossz = a kupac (azaz a még rendezetlen elemek) elemszáma, BalGyerek(elemindex) = 2*elemindex, JobbGyerek(elemindex) = 2*elemindex+1, UtolsóSzülő(kupac) = kupachossz DIV 2 MinGyerek(elemindex) = a kisebbik gyereke az elemnek, VanGyerek(elemindex) = igaz, ha BalGyerek(elemindex)£KupacHossz, Érték(elemindex) = az elem fabeli értéke. Rekurzió 4 Rekurzió 1
57
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Algoritmusvázlatok: Eljárás HeapSort(Változó kupac:BinFa): HSFaLétrehozása(kupac) Ciklus i=KupacHossz-tól 2-ig -1-esével Csere(i,1) [KupacHosszi] KupacHossz:-1 GyökérHelyre(1) Ciklus vége Eljárás vége. a minimumot a rendezettek közé a csere miatt elromlott „fa" kupacosítása Eljárás HSFalétrehozása(Változó kupac:BinFa): Ciklus j=UtolsóSzülő(kupac)-től 1-ig -1-esével GyökérHelyre(j) Ciklus vége Eljárás vége. a j. elem „lecsúsztatása" a kupac-hosszadik elemig bezárólag Rekurzió 4 Rekurzió 1
58
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Eljárás GyökérHelyre(Változó gyökér: Egész): szülő:=gyökér; gyerek:=MinGyerek(szülő) Ciklus amíg VanGyerek(szülő) és Érték(szülő)>Érték(gyerek) Csere(szülő,gyerek); szülő:=gyerek gyerek:=MinGyerek(gyerek) Ciklus vége Eljárás vége. Függvény MinGyerek(Konstans elem:Egész):Egész Elágazás JobbGyerek(elem)>KupacHossz esetén Mingyerek:=BalGyerek(elem) Érték(BalGyerek(elem))<Érték(JobbGyerek(elem)) esetén Mingyerek:=BalGyerek(elem) egyéb esetben Mingyerek:=JobbGyerek(elem) Elágazás vége Függvény vége. Rekurzió 4 Rekurzió 1
59
6 Rekurzív adattípusok: fák
Függvény MinGyerek(Konstans elem:Egész):Egész Elágazás JobbGyerek(elem)>KupacHossz esetén Mingyerek:=BalGyerek(elem) Érték(BalGyerek(elem))<Érték(JobbGyerek(elem)) esetén Mingyerek:=BalGyerek(elem) egyéb esetben Mingyerek:=JobbGyerek(elem) Elágazás vége Függvény vége. 6 Rekurzív adattípusok: fák A heapsort hatékonyságáról (T; N=elemszám) HeapSort (HS) T(HS)=T(HSFL)+T(N*(…+GyH))= =O(N)+O(NlogN)=O(NlogN) HSFaLétrehozása (HSFL) T(HSFL)=T((N Div 2)*GyH)= =O(N*logN) (sőt bizonyítható: O(N)) GyökérHelyre (GyH) T(GyH)=T(logN*(…+MGy))= =O(logN) MinGyerek (MGy) T(MGy)=O(1) A heapsort hatékonyságáról (T; N=elemszám) HeapSort (HS) T(HS)=T(HSFL)+T(N*(…+GyH))= = HSFaLétrehozása (HSFL) T(HSFL)=T((N Div 2)*GyH)= =O(N*logN) (sőt bizonyítható: O(N)) GyökérHelyre (GyH) T(GyH)=T(logN*(…+MGy))= =O(logN) MinGyerek (MGy) T(MGy)=O(1) Eljárás GyökérHelyre(Változó gyökér:Egész): szülő:=gyökér; gyerek:=MinGyerek(szülő) Ciklus amíg VanGyerek(szülő) és Érték(szülő)>Érték(gyerek) Csere(szülő,gyerek); szülő:=gyerek gyerek:=MinGyerek(gyerek) Ciklus vége Eljárás vége. Eljárás HeapSort(Változó kupac:BinFa): HSFaLétrehozása(kupac) Ciklus i=KupacHossz-tól 2-ig -1-esével Csere(i,1); KupacHossz: GyökérHelyre(1) Ciklus vége Eljárás vége. Eljárás HSFalétrehozása(Változó kupac:BinFa): Ciklus j=UtolsóSzülő(kupac)-től 1-ig -1-esével GyökérHelyre(j) Ciklus vége Eljárás vége. Rekurzió 4 Rekurzió 1
60
6 Rekurzív adattípusok: fák
Egy lehetséges Pascal megvalósítás kezdeményei: Type TKupac=Record kH:Integer; elem:Array [1..MaxN] of TElem End; {Exportálandó műveletek:} Procedure KupacLetrehozas(Var kupac:TKupac); Function KupacHossz(Const kupac:TKupac):Integer; Function Balgyerek(Const kupac:TKupac; Const kinek:Integer):Integer; Function Jobbgyerek(Const kupac:TKupac; Const kinek:Integer):Integer; Function Mingyerek(Const kupac:TKupac; Const kinek:Integer):Integer; Function Vangyerek(Const kupac:TKupac; Const kinek:Integer):Boolean; Function UtolsoSzulo(Const kupac:TKupac):Integer; Function Ertek(Const kupac:TKupac; Const kinek:Integer):TElem; Procedure KupacRovidites(Var kupac:TKupac); Procedure GyokerHelyre(Var kupac:TKupac; Const gyoker:Integer); Procedure Csere(Var kupac:TKupac; Const mit,mivel:Integer); Rekurzió 4
61
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák A kupac speciális alkalmazása: prioritási sor Prioritási sor = kupac + kupachossz Eljárás PrSorba(Változó PS:BinFa, Konstans elem:TElem): PS.kupac(PS.hossz+1):=elem PS.hossz:=PS.hossz+1 gyerek:=PS.hossz; szülő:=gyerek DIV 2 Ciklus amíg szülő1 és PS.kupac(gyerek)>PS.kupac(szülő) Csere(PS.kupac(gyerek),PS.kupac(szülő)) gyerek:=szülő; szülő:=gyerek DIV 2 Ciklus vége Eljárás vége. Eljárás PrSorból(Változó PS:BinFa, elem:TElem): … hf. … Eljárás vége. Rekurzió 4 Rekurzió 1
62
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák A Kupac mint típus Algebrai leírása Típus Kupac(Elem): Asszociált műveletek: Létrehoz(Elem*): Kupac [egy elemsorozatból készít kupacot] Kupac?(Kupac,Egész): Logikai [rendelkezik-e a kupac- tulajdonsággal a struktúra egy adott indexű elemétől kezdődően] KupacHossz(Kupac): Egész [az elemsorozat kupac-tulajdonsággal rendelkező „elejének” hossza] Méret(KupacTömb): Egész [a teljes elemsorozat hossza] KupacRedukció(Kupac): Kupac [a Kupac első és utolsó elemének cseréje, majd a kupac-tulajdonság helyreállítása] Elem(KupacTömb,Egész): Elem{NemDef} [az elemsorozat adottadik eleme] BalGyerek(Egész): Egész JobbGyerek(Egész): Egész Rekurzió 4 Rekurzió 1
63
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Axiómák: Jelölések: s,s’:Kupac(Elem) = Kupac-típusú objektum t:Tömb(Elem) = tömb típusú objektum 1o Létrehoz – axióma s=Létrehoz(t) Kupac?( s,1) KupacHossz(s)=Méret(s)=Méret(t) 2o Kupac? – axióma Kupac?(s,i) i>KupacHossz(s) BalGyerek(i)KupacHossz(s) Elem(s,i)Elem(s,BalGyerek(i)) Kupac?(s,BalGyerek(i)) JobbGyerek(i)KupacHossz(s) Elem(s,i)Elem(s,JobbGyerek(i)) Kupac?(s,JobblGyerek(i)) Rekurzió 4 Rekurzió 1
64
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák 3o KupacRedukció – axióma s’=KupacRedukció(s) Elem(s,1)=Elem(s’,KupacHossz(s)) KupacHossz(s’)=KupacHossz(s)-1 Kupac?(s’,1) 4o Elem – hiba-axióma i[1..Méret(s)] Elem(s,i)=NemDef Rekurzió 4 Rekurzió 1
65
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák 6.2 Nem bináris fák 6.2.1 Algebrai specifikáció Típus Fa(Elem): Asszociált műveletek: Üres:Fa Üres?(Fa):Logikai EgyEleműFa(Elem):Fa [Létrehoz] GyerekSzám(Fa):Egész Beilleszt(Fa,Fa):Fa {NemDef} [Illeszt utolsó gyerekként] GyökérElem(Fa):Elem {NemDef} [Elem] Gyerek(Fa,Egész):Fa {NemDef} [Rész; i. gyermek] GyökérMódosít(Fa,Elem):Fa {NemDef} [Módosít] Beilleszt(mire,mit) Rekurzió 4 Rekurzió 1
66
6 Rekurzív adattípusok: fák (folytatás)
6 Rekurzív adattípusok: fák (folytatás) Jelölések: f,f’,ff,f’:Fa(Elem) – általában az aposztróf időbeliségre utal e:Elem i:Egész „=”:FaFaLogikai, strukturális és elemérték-szintű azonosság Axiómák: 1º Üres – axióma Üres?(Üres) 1’º Üres – hiba-axióma GyökérElem(Üres)=NemDef GyerekSzám(Üres)=0 Gyerek(Üres,i)=NemDef 2º EgyEleműFa – axióma f=EgyEleműFa(e) Üres?(f) GyökérElem(f)=e GyerekSzám(f)=0 Üres?(Gyerek(f,i)) Rekurzió 4 Rekurzió 1
67
6 Rekurzív adattípusok: fák (folytatás)
6 Rekurzív adattípusok: fák (folytatás) 3º Beilleszt – axióma Üres?(f) GyerekSzám(f)=i Beilleszt(f,ff)=f’ Gyerek(f’,i+1)=ff GyerekSzám(f’)=i+1 j>i Üres?(Gyerek(f,j)) 3’º Beilleszt – hiba-axióma Üres?(f) Beilleszt(f,ff)=NemDef 4º GyökérMódosít – axióma Üres?(f) GyökérMódosít(f,e)=f’ GyökérElem(f’)=e 5’º GyökérMódosít – hiba-axióma Üres?(f) GyökérMódosít(f,e)=NemDef Rekurzió 4 Rekurzió 1
68
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák 6.2.2 Exportmodul ExportModul Fa(Típus TElem): Függvény Üres?(Konstans f:Fa):Logikai Konstans Üres:Fa Függvény EgyEleműFa(Konstans e:TElem):Fa Függvény GyerekSzám(Konstans f:Fa):Egész Eljárás Beilleszt(Változó mire:Fa, Konstans mit:Fa) [Ef: mire nem üres Uf: … utolsó gyerekként …] Függvény GyökérElem(Konstans f:Fa):TElem [Ef: f nem üres] Függvény Gyerek(Konstans f:Fa,i:Egész):Fa [Ef: f nem üres és az „i-edikség” értelmesen megfogalmazható] … Rekurzió 4 Rekurzió 1
69
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák … Eljárás GyökérMódosít(Változó f:Fa, Konstans e:TElem) [Ef: f nem Üres] Modul vége. Megjegyzés: A hiba-kezelése –szokásos módon– egy hiba-komponens- sel lehetséges. Ez esetben a fenti eljárások/függvények Fa-paraméteré- nek hozzáférését változóra kell ókor-ókor módosítani. És szükség van egy Hibás? Függvényre is. Rekurzió 4 Rekurzió 1
70
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák 6.2.3 Megvalósítási modul Rekord-szerű, visszavezetés a rekurzióra Modul Fa(Típus TElem): Reprezentáció Változó f:Rekurzió(Elem:TElem, ág:Sorozat(Fa)) Implementáció Függvény Üres?(Konstans f:Fa):Logikai … hf. … Konstans Üres:Fa … hf. … Függvény EgyEleműFa(Konstans e:TElem):Fa EgyEleműFa:=Fa(e,ÜresSorozat) Függvény vége. Függvény GyerekSzám(Konstans f:Fa):Egész GyerekSzám:=ElemSzám(f.ág) Függvény vége. … Sorozat-műveletek: ÜresSorozat, ElemSzám, Végére, (i) Rekurzió 4 Rekurzió 1
71
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák … Eljárás Beilleszt(Változó mire:Fa, Konstans mit:Fa): mire.ág:=Végére(mire.ág,mit) Eljárás vége. Függvény GyökérElem(Konstans f:Fa):TElem … hf. … Eljárás Gyerek(Konstans f:Fa,i:Egész):Fa Ha iElemSzám(f) akkor Gyerek:=f.ág(i) különben Gyerek:=Üres Függvény vége. Eljárás GyökérMódosít(Változó f:Fa, Konstans e:TElem) … hf. … Modul vége. Rekurzió 4 Rekurzió 1
72
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Egy alternatív megvalósítás: bináris faként Modul Fa(Típus TElem): Reprezentáció Változó f:BinFa(TElem) Implementáció Függvény Üres?(Konstans f:Fa):Logikai … hf. … Konstans Üres:Fa … hf. … Függvény EgyEleműFa(Konstans e:TElem):Fa … hf. … Függvény GyerekSzám(Konstans f:Fa):Egész Ha Üres?(BalGyerek(f)) akkor GyerekSzám:=0 különben GyerekSzám:=1+TestvérSzám(BalGyerek(f)) Elágazás vége Függvény vége. Függvény TestvérSzám(Konstans f:Fa):Egész … hf. … Megállapodás: Balra a leszármazottak, jobbra a testvérek. Lásd az ötletet. Rekurzió 4 Rekurzió 1
73
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Eljárás Beilleszt(Változó mire:Fa, Konstans mit:Fa): Ha Üres?(BalGyerek(mire)) akkor BalraIlleszt(mire,mit) különben BeillesztTestvérnek(BalGyerek(mire),mit) Elágazás vége Eljárás vége. Eljárás BeillesztTestvérnek(Változó mire:Fa, Konstans mit:Fa): Ha Üres?(JobbGyerek(mire)) akkor JobbraIlleszt(mire,mit) különben BeillesztTestvérnek(JobbGyerek(mire),mit) Elágazás vége Eljárás vége. Függvény GyökérElem(Konstans f:Fa):TElem … hf. … Rekurzió 4 Rekurzió 1
74
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák 6.3 B-fák Létrejöttének okairól: háttértár blokk-írás, -olvasás műveletek optimalizálása… A lényeg (-: béta-változata :-): Rögzített paraméter Típus B_Fa=Rekurzió(db:Egész,elem:Tömb(1..2*N-1:TElem), ág:Tömb(0..2*N-1:B_Fa)) [Típusinvariáns: bf:B_Fa: N>0 bf.db[N-1,2*N-1] i[1..bf.db): bf.elemibf.elemi+1 bf.ág0.elem[Min’TElem..bf.elem1) i[1..db): bf.ági.elem[bf.elemi..bf.elemi+1) bf.ágbf.db.elem[bf.elembf.db..Max’TElem]] A „csak egy nem rekurzív ág” feltételtől eltekintünk! Egy „csöppnyi” baj: nem tartalmazhat N-1-nél kevesebb elemet?!? Rekurzió 4 Rekurzió 1
75
6 Rekurzív adattípusok: fák
Paraméteres típus. N – fizikai méret, k – logikai méret 6 Rekurzív adattípusok: fák Módosítás: A gyökér eltérő definiálása, kezelése. Előzetes definíciók: A B-fa elemben lévő értékek sorozata Típus TElemek(N,k)=Tömb(1..2*N-1:TElem) [Típusinvariáns: ek:TElemek: k[1..2*N-1] Rendezettek(ek,k)] Def: Rendezettek(TElemek,Egész):L Rendezettek(x,k):=i[1..k): xi<xi+1 TB_FElemek(N,k,x)=Tömb(0..2*N-1:TB_FElem) [Típusinvariáns: bf:TB_FElemek: k[1..2*N-1] x:TElemek(N,k) RendezettFa(bf0, Min’TElem,x1) i[1..k): RendezettFa(bfi, xi,xi+1) RendezettFa(bfk, xk,Max’TElem)] Def: RendezettFa(TB_FElemek,TElem,TElem):L RendezettFa(f, a,b):=(f= f.elem[a..b)) A B-fa elemben lévő B-fák sorozata Rekurzió 4 Rekurzió 1
76
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák A B-fa definiálása: A gyökérelem A többi B-fa elemek B_Fa(N)=TB_Gyökér(N) TB_Gyökér(N)=Rekord(db:Egész,elem:TElemek(N,db), ág:TB_FElemek(N,db)) [Típusinvariáns: gy:TB_Gyökér: N>0 gy.db[1..2*N-1]] TB_FElem(N)=Rekurzió(db:Egész,elem:TElemek(N,db)), ág:TB_FElemek(N,db)) [Típusinvariáns:bf: B_Fa: N>0 bf.db[N-1..2*N-1]] A különbség: a db-mező értéktartománya!!! Rekurzió 4 Rekurzió 1
77
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Pl.: N=3, akkor értékek száma: 2..5 1, 2 22, 25, 26 31, 32, 33, 38 11, 19 10, 20, 30 A definíció értelmes. Ui. N0 és elemszámra: B- fa. Lássunk néhány növekvő elemszámú példát: A frissen érkező elemet dőlt, árnyékos betűkkel jelöltük. 10 10;40 10;20;40 10;20;30;40 10;15;20;30;40 20 10;15;17 30;40 20 1;10;15;17 30;40 Rekurzió 4 Rekurzió 1
78
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Elvárások: ExportModul B_Fa(Típus TElem,TKulcs [TElem]): Konstans Üres:B_Fa Függvény Üres?(Konstans f:B_Fa):Logikai Függvény EgyeleműFa(Konstans e:TElem):B_Fa Eljárás Beilleszt(Változó f:B_Fa, Konstans e:TElem) [Ef: ef] Eljárás Keres(Konstans f:B_Fa, k:TKulcs, Változó van:Logikai, e:TElem) Eljárás Töröl(Változó f:B_Fa, Konstans k:TKulcs) [Ef: (k,?)f] Modul vége. Rekurzió 4 Rekurzió 1
79
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák A megvalósítás: Az egyszerűség kedvéért eltérünk korábbi szigorú, „csak 1 nem rekurzív ág” feltételtől. Modul B_Fa(Típus TElem,TKulcs [TElem]): Reprezentáció Típus RBFa=Rekurzió(db:Egész,elem:Tömb(1..2*N:TElem), ág:Tömb(0..2*N-1:RBFa)) Változó bf:RBFa Implementáció Konstans Üres:B_Fa … hf. … Függvény Üres?(Konstans f:B_Fa):Logikai … hf. … Függvény EgyeleműFa(Konstans e:TElem):B_Fa … hf. … Eljárás Beilleszt(Változó f:B_Fa, Konstans e:TElem) [Ef: ef] … hf. … Rekurzió 4 Rekurzió 1
80
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Eljárás Keres(Konstans f:B_Fa, k:TKulcs, Változó van:Logikai, e:TElem) … hf. … Eljárás Töröl(Változó f:B_Fa, Konstans k:TKulcs) [Ef: (k,?)f] … hf. … Inicializálás bf:=Üres Modul vége. A továbbiakban csak néhány példával illusztráljuk a beillesztés műveletét… Rekurzió 4 Rekurzió 1
81
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák 15;5 3 Új elem beillesztése – példával: 10; 20; 30 5; 10; 15; 20; 30 Telítődött: bontás 13 55;40;7;2 15 3; 5; 10 20; 30 15 2; 3; 5; 7; 10 20; 30; 40; 55 Telítődött: bontás 5; 15 2; 3 20; 30; 40; 55 7; 10; 13 Rekurzió 4 Rekurzió 1
82
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák 22;95 Új elem beillesztése – példával (folytatás): 5; 15 2; 3 20; 30; 40; 55 7; 10; 13 Telítődött: bontás 5; 15; 30 2; 3 20; 22 7; 10; 13 40; 55; 95 Rekurzió 4 Rekurzió 1
83
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák 1;6;0;-1 Új elem beillesztése – példával (folytatás): 5; 15; 30 2; 3 20; 22 7; 10; 13 40; 55; 95 4;29;50;71 5; 15; 30 -1; 0; 1; 2; 3 20; 22 6; 7; 10; 13 40; 55; 95 Telítődött: bontás 1; 5; 15; 30 -1; 0 20; 22; 29 6; 7; 10; 13 40; 50; 55; 71; 95 2; 3; 4 Rekurzió 4 Rekurzió 1
84
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák 45 Új elem beillesztése – példával (folytatás): 1; 5; 15; 30 -1; 0 20; 22; 29 6; 7; 10; 13 40; 50; 55; 71; 95 2; 3; 4 Telítődött: bontás 1; 5; 15; 30; 55 -1; 0 20; 22; 29 6; 7; 10; 13 40; 45; 50 2; 3; 4 71; 95 Rekurzió 4 Rekurzió 1
85
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Gyökér tele: „ok nélküli” bontás 8 Új elem beillesztése – példával (folytatás): 1; 5; 15; 30; 55 -1; 0 20; 22; 29 6; 7; 10; 13 40; 45; 50 2; 3; 4 71; 95 1; 5 -1; 0 20; 22; 29 6; 7; 8; 10; 13 40; 45; 50 2; 3; 4 71; 95 30; 55 15 Rekurzió 4 Rekurzió 1
86
6 Rekurzív adattípusok: fák
6 Rekurzív adattípusok: fák Összefoglalva: Ha a B-fa elembe belefér, beszúrjuk. Ha tele van, arányosan kettévágjuk, a középsőt eggyel feljebb beszúrjuk; s így már helyre tehető az elem. Szintterebélyesedés. Ha a gyökér tele van, biztos-ami-biztos, előre ketté-vágjuk; s egy új gyökérelem képződik a kettévágandó középső elemével feltöltve. Szintszám-növekedés. A beszúrás O(N*logNK) blokkolvasással jár, ahol N a minimum fokszám (azaz egy B-fa elembe minimálisan tart-ható értékek száma-1), K a fában lévő értékek (TElem) száma. Rekurzió 4 Rekurzió 1
Hasonló előadás
© 2024 SlidePlayer.hu Inc.
All rights reserved.