2. A rekurzió mint típuskonstrukció Szlávi Péter ELTE Média- és Oktatásinformatikai Tanszék
A rekurzió mint típuskonstrukció 22/73 Tartalom 1 Bináris fák 1.0 Példák, alapfogalmak 1.1 Algebrai specifikáció 1.2 Exportmodul 1.3 Megvalósítási modul 1.4 Egy másik elképzelés 1.5 Összetett műveletek 1.6 Kereső fák 1.7 Rendező fák 2 Nem bináris fák 2.1 Algebrai specifikáció 2.2 Exportmodul 2.3 Megvalósítási modul Csak érdekességként
A rekurzió mint típuskonstrukció 23/73 1 Bináris fák 1.0 Példák, alapfogalmak Kifejezések Kifejezések Családfák Családfák Kereső fák (amik a gyors megtalálást célozzák) Rendező fák („virtuális fa” -- időleges állapot)
A rekurzió mint típuskonstrukció 24/73 Megjegyzés: Kifejezések sin(b(i)+a*x) „szabad szintaxisú” operátor (indexelés) prefix operátor (sin) + *Ind bi Sin ax * b + a2 := x x:=(a+2)*b nem kommutatív bináris operátor
A rekurzió mint típuskonstrukció 25/73 Megjegyzés: családfák John Ronald Reuel Tolkien családfája Ejnye. Ez nem is bináris!?!:-) Ejnye. Ez nem is bináris!?! :-)
A rekurzió mint típuskonstrukció 26/73 Megjegyzés: családfák A Tolkien család „leszármazási erdeje” (részlet) Mandy T Royd T Ruth T Hugh Baker Joan T Michael T Jan Turner Joan Griffits Michael T Edith Bratt J.Ronald R. T Hilary A.R. T Mabel Suffield Arthur R. T Jelmagyarázat: Kékek a fiúk; oválisban a há- zastársak.
A rekurzió mint típuskonstrukció 27/73 1 Bináris fák 1.1 Algebrai specifikáció Típus BinFa(Elem): Asszociált műveletek: 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] A „sokaságszerű” rekurzióból kimaradó műveletek: Leválaszt(Rek,Szel,Rek):Rek Rek {NemDef} Elsőre(Rek):Rek {NemDef} Következőre(Rek,Szel):Rek {NemDef} Elején?(Rek):Logikai {NemDef} Végén?(Rek):Logikai {NemDef} *Illeszt(mire,mit)
A rekurzió mint típuskonstrukció 28/73 1 Bináris fák Jelölések Jelölések: b,b’,b”,bb,b’:BinFa(Elem) – általában az aposztróf időbeliségre utal e:Elem „=”:BinFa BinFa Logikai, strukturális és elemérték-szintű azonosságAxió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 rekurzió mint típuskonstrukció 29/73 1 Bináris fák 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
A rekurzió mint típuskonstrukció 210/73 1 Bináris fák 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 [Ef: az f nem üres] Függvény JobbGyerek(Konstans f:BinFa ):BinFa [Ef: az f nem üres] …
A rekurzió mint típuskonstrukció 211/73 1 Bináris fák Eljárás GyökérMódosít(Változó f:BinFa,Konstans e:TElem) [Ef: az f nem üres] … 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.
A rekurzió mint típuskonstrukció 212/73 1 Bináris fák 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árarekord-szemléletű 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(RBinFa’Üres) 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
A rekurzió mint típuskonstrukció 213/73 1 Bináris fák … 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
A rekurzió mint típuskonstrukció 214/73 1 Bináris fák … Függvény BalGyerek(Konstans f:RBinFa):RBinFa [Ef: RBinFa’Üres?(f)] BalGyerek:=f.bal Eljárás vége. Függvény JobbGyerek(Konstans f:RBinFa):RBinFa [Ef: RBinFa’Üres?(f)] 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.
A rekurzió mint típuskonstrukció 215/73 1 Bináris fák 1.4 Egy másik elképzelés a megvalósításra Alapja a rekurzió típus „tulajdonos-számlálásos” ábrázolási módszere. ( Lásd az előző előadásban. )előadásban Modul BinFa(Típus TElem): Reprezentáció 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)
A rekurzió mint típuskonstrukció 216/73 1 Bináris fák 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 [Ef: bf] 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) [Ef: bf ] Függvény BalFa(Változó bf:TBinFa):TBinFa [Ef: bf ] Függvény JobbFa(Változó bf:TBinFa):TBinFa [Ef: bf ] Algoritmikus nyelvünk modulfogalma szerint az inicializáláskor üres értket kap. Így a bf ef. kezdetben is tud teljesülni. bf≠ bf bf.gyökér≠Sehova
A rekurzió mint típuskonstrukció 217/73 1 Bináris fák „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]
A rekurzió mint típuskonstrukció 218/73 1 Bináris fák „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) [Ef: -] Eljárás _BalraIlleszt_(Változó bf:TBinFa, Konstans mit:TBinFa) [Ef: bf ] Eljárás _JobbraIlleszt_(Változó bf:TBinFa, Konstans mit:TBinFa) [Ef: bf ] 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.
A rekurzió mint típuskonstrukció 219/73 1 Bináris fák … é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) _BalraIlleszt_(bf,sbf) sbf:=bf.JobbFa TulajNövelés(sbf) _JobbraIlleszt_(bf.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) _BalraIlleszt_(bf,sbf) sbf:=bf.JobbFa TulajCsökkentés(sbf) _JobbraIlleszt_(bf,sbf) Ha TBinFaElem(bf.gyökér).tulSzám=0 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.
A rekurzió mint típuskonstrukció 220/73 1 Bináris fák Még egyszer a BinFa-műveletkészlet használat- „módszertana”: mikor, melyik művelet használandó, módszertani elvek?Szabályok: 1. Minden deklarált BinFa adatobjektumot inicia- lizálni kell (Üres, EgyeleműFa konstruktorokkal). 2. 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. 3. Kerülendő a „sima” értékadás, helyette az Érté- ketKap-ot kell használni. Ha ez automatikusan nem történt meg.
A rekurzió mint típuskonstrukció 221/73 1 Bináris fák Illusztrálásképpen kövessük és értelmezzük a követ- kező programot: !
A rekurzió mint típuskonstrukció 222/73 1 Bináris fák Töltse le az 1. exe-t és a exe 2. hozzátartozó listafájlt (14.txt)!listafájl … és próbálja ki! Csak a lépés gombot kell nyomogatni, ill. ha kíváncsi a megjegyzéseimre, akkor jelölje be az erre vonatkozó jelölőt! A 14. lépéshez tartozik a programlista, amely a megfelelő pillanatban egy külön ablakban jelenik meg, hogy lássa, és értelmezni tudja az állapotváltozásokat.
A rekurzió mint típuskonstrukció 223/73 1 Bináris fák 1.5 Összetett műveletek Elemszám Elemszám: Mélység Mélység: … hf … Def: Elemszám:BinFa Egész 0, ha Üres?(f) Elemszám(f):= 1+Elemszám(BalGyerek(f))+ Elemszám(JobbGyerek(f)), ha egyébként Függvény Elemszám(Konstans f:BinFa):Egész Ha Üres?(f) akkor Elemszám:=0 különben Elemszám:=1+Elemszám(BalGyerek(f))+ Elemszám(JobbGyerek(f)) Elágazás vége Függvény vége. Specifikáció – az uf. definíciós része Algoritmus
A rekurzió mint típuskonstrukció 224/73 1 Bináris fák Bejárások Eljárás BKJ(Konstans bf:BinFa): Ha nem Üres?(bf) akkorBKJ(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) akkorKi: 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) akkorBJK(BalGyerek(bf)) BJK(JobbGyerek(bf)) Ki: GyökérElem(bf) Elágazás vége Eljárás vége.
A rekurzió mint típuskonstrukció 225/73 1 Bináris fák A bejárások iteratív változatai Bal-közép-jobb Az algoritmus, először „kézzel”: * b + a2 := x
A rekurzió mint típuskonstrukció 226/73 1 Bináris fák A bejárások iteratív változatai Az algoritmus, vázlatosan: … 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 … Még nem másodszor értünk vissza a gyökérhez Nem léptünk le egy levélről, azaz van út előre * b + a2 := x
A rekurzió mint típuskonstrukció 227/73 1 Bináris fák … é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 … Kövessük az algoritmust üres és üres és egyelemű binfára! egyelemű binfára!
A rekurzió mint típuskonstrukció 228/73 1 Bináris fák Közép-bal-jobb … hf … Bal-jobb-közép … hf …
A rekurzió mint típuskonstrukció 229/73 1 Bináris fák 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 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).kulcs GyökérElem(JobbGyerek(r)).kulcs ] Rövid leírhatóság kedvéért, átnevezzük: TKFa A „kereső fa”-tulajdonság
A rekurzió mint típuskonstrukció 230/73 Függvény Keresés(Konstans k:TKulcs, kf:TKFa):TKFa [Uf: e kf: k=e.kulcs f=Keresés(k,kf): GyökérElem(f).kulcs=k ¬ e kf: k=e.kulcs Keresés(k,kf)=Üres] Függvény Beillesztés(Konstans e:TElem, kf:TKFa):TKFa [Ef: ║{x kf: x.kulcs=e.kulcs}║≤1 Uf: f=Beillesztés(e,kf) a kf: a.kulcs=e.kulcs x kf: x.kulcs e.kulcs x f x kf: x.kulcs=e.kulcs x’=e f ¬ a kf: a.kulcs=e.kulcs x kf x f e f ] KulcsegyértelműségKulcsegyértelműség 1 Bináris fák Rekord-szerűen (szigorúbb értelmezés): Definíciós ok miatt: a rendezés szerinti helyére kerül az e elem!
A rekurzió mint típuskonstrukció 231/73 Függvény Törlés(Konstans k:TKulcs, kf:TKFa):TKFa [Ef: x,y kf: x y x.kulcs y.kulcs Uf: e kf: e.kulcs=k f=Törlés(k,kf): e f a kf: a.kulcs k a f ¬ e kf: 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)] KulcsegyértelműségKulcsegyértelműség 1 Bináris fák L. később! később
A rekurzió mint típuskonstrukció 232/73 1 Bináris fák 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: e kf:k=e.kulcs Elem(kf’).kulcs=k van ¬ e kf:k=e.kulcs ¬van f TKFa: f=Illeszt(EgyEleműFa((k,eb)),kf’,melyik)] Kimenő értéke a kf-nek
A rekurzió mint típuskonstrukció 233/73 1 Bináris fák Eljárás Beillesztés(Konstans e:TElem, Változó kf:TKFa) [Ef: ║{x kf: x.kulcs=e.kulcs}║≤1 Uf: e kf’ Elem(kf’)=e] Eljárás Törlés(Konstans k:TKulcs, Változó kf:TKFa) [Ef: x,y kf: x y x.kulcs y.kulcs Uf: e kf: e.kulcs=k a e kf: a f e f ¬ e kf: e.kulcs=k kf’=kf] Függvény Kiegyensúlyozás(Változó kf:TKFa) [… ugyanaz …] Kimenő értéke a kf-nek
A rekurzió mint típuskonstrukció 234/73 1 Bináris fák Megvalósítások: KeresésKeresés Rekord-szerűen: Függvény Keresés(Konstans k:TKulcs, kf:TKFa):TKFa [Uf: e kf: k=e.kulcs f=Keresés(k,kf) GyökérElem(f).kulcs=k ¬ e kf: k=e.kulcs Keresés(k,kf)=Üres] Elágazás Üres?(kf)eseténKeresés:=kf k GyökérElem(kf).kulcseseténKeresés:= Keresés(k,JobbGyerek(kf)) k=GyökérElem(kf).kulcseseténKeresés:=kf Elágazás vége Függvény vége.
A rekurzió mint típuskonstrukció 235/73 1 Bináris fák Sokaság-szerűen: Eljárás Keresés(Konstans k:TKulcs, Változó kf:TKFa,van:Logikai,melyik:Szelektor): [Uf: e kf: k=e.kulcs Elem(kf’).kulcs=k van ¬ e kf: k=e.kulcs ¬van Üres?(kf) f TKFa: 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 k Elem(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 rekurzió mint típuskonstrukció 236/73 1 Bináris fák Ugyanezt Rekord-szerűen is lehet: 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’… … 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.
A rekurzió mint típuskonstrukció 237/73 1 Bináris fák TörlésTö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.típusinvariancia 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: e kf: e.kulcs=k f=Törlés(k,kf): … ¬ e kf: e.kulcs=k Törlés(k,kf)=kf] elemzéselemzés lásd a „nincs jobboldali …” esetet elemzéselemzés
A rekurzió mint típuskonstrukció 238/73 Megjegyzés: Nincs jobb részfa kf= bf kf= bf
A rekurzió mint típuskonstrukció 239/73 Megjegyzés: Mindkét részfa kf= bf jf bf jf
A rekurzió mint típuskonstrukció 240/73 1 Bináris fák Függvény Törlés(Konstans k:TKulcs,kf:TKFa):TKFa [Uf: e kf: e.kulcs=k f=Törlés(k,kf): … ¬ e kf: 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), 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.
A rekurzió mint típuskonstrukció 241/73 1 Bináris 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
A rekurzió mint típuskonstrukció 242/73 1 Bináris 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ármazottait. Lásd az alábbi magyarázó ábrát: 9 ős 4 törlendő
A rekurzió mint típuskonstrukció 243/73 1 Bináris 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. Azaz az akt melyik szelektorán lóg a törlendő k kulcsú
A rekurzió mint típuskonstrukció 244/73 1 Bináris fák KiegyensúlyozásKiegyensúlyozás A probléma forrása… Definíciók: 1.Kiegyensúlyozott az a bináris fa, amelynek tetszőleges pontjá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ökerező” 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. ((1)2(3)) és (1(2(3))) „lényegében” ugyanazt a keresőfát jelöli, de mégis mennyire más
A rekurzió mint típuskonstrukció 245/73 1 Bináris fák 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 f3f3 f2f2 f1f1 ? új elem x y f3f3 f2f2 f1f1 ?
A rekurzió mint típuskonstrukció 246/73 1 Bináris 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 y f4f4 f2f2 f1f1 ? új elem x z f4f4 f2f2 f1f1 ? z f3f3 y f3f3
A rekurzió mint típuskonstrukció 247/73 1 Bináris fák 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úlyozottságra kell töre- kedni.) Á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
A rekurzió mint típuskonstrukció 248/73 1 Bináris 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
A rekurzió mint típuskonstrukció 249/73 1 Bináris fák Az exportmodul ésexportmodul 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ó …
A rekurzió mint típuskonstrukció 250/73 1 Bináris fák alapelv 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 „teljes” paraméterfát eredményezi, de a fa aktuális eleme bal „irányba” lép egyet…
A rekurzió mint típuskonstrukció 251/73 1 Bináris 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 … … Elem bal | jobb | vissza előző gyökér|akt Elem bal | jobb | vissza új gyökérakt gyökér|akt
A rekurzió mint típuskonstrukció 252/73 1 Bináris fák … 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. … előző gyökér|akt új gyökérakt gyökér|akt Elem bal | jobb | vissza új gyökérakt gyökér|akt Elem bal | jobb | vissza Egy elem törlése: … hf. …
A rekurzió mint típuskonstrukció 253/73 1 Bináris fák Maga a rendezett sorozat: (=BKJ-bejárással)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) Ki: GyökérElem(sf) Ciklus vége sf:=JobbGyerek(sf) Ciklus vége Eljárás vége
A rekurzió mint típuskonstrukció 254/73 1 Bináris fák A rendezés „irányától” függően 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 BalGyerek(i)=2*i JobbGyerek(i)=2*i+1 L. A korábbi előadást. előadás
A rekurzió mint típuskonstrukció 255/73 6 Rekurzív adattípusok: fák A kupac-rendezés „működése” ( példa ): A rendezendő sorozat A kupacosítás:
A rekurzió mint típuskonstrukció 256/73 6 Rekurzív adattípusok: fák A rendezés: Ime a kupac! „Helyre-csere”! Kupac helyrehozás
A rekurzió mint típuskonstrukció 257/73 6 Rekurzív adattípusok: fák „Helyre-csere”! Kupac helyrehozás „Helyre-csere”! Kupac helyrehozás
A rekurzió mint típuskonstrukció 258/73 6 Rekurzív adattípusok: fák „Helyre-csere”! Kupac helyrehozás „Helyre-csere”! Kupac helyrehozás „Helyre-csere”!
A rekurzió mint típuskonstrukció 259/73 6 Rekurzív adattípusok: fák Kupac helyrehozás „Helyre-csere”! A rendezett sorozat
A rekurzió mint típuskonstrukció 260/73 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.
A rekurzió mint típuskonstrukció 261/73 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) [KupacHossz i] KupacHossz:-1 GyökérHelyre(1) Ciklus vége Eljárás vége. a minimumot a rendezettek közé 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 csere miatt elromlott „fa" kupacosítása a j. elem „lecsúsztatása" a kupac- hosszadik elemig bezárólag
A rekurzió mint típuskonstrukció 262/73 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énMingyerek:=BalGyerek(elem) Érték(BalGyerek(elem))<Érték(JobbGyerek(elem)) eseténMingyerek:=BalGyerek(elem) egyéb esetbenMingyerek:=JobbGyerek(elem) Elágazás vége Függvény vége.
A rekurzió mint típuskonstrukció 263/73 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))= = 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 HeapSort(Változó kupac:BinFa): HSFaLétrehozása(kupac) Ciklus i=KupacHossz-tól 2-ig -1-esével Csere(i,1); KupacHossz:-1 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. 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énMingyerek:=BalGyerek(elem) Érték(BalGyerek(elem))<Érték(JobbGyerek(elem)) eseténMingyerek:=BalGyerek(elem) egyéb esetbenMingyerek:=JobbGyerek(elem) Elágazás vége Függvény vége.
A rekurzió mint típuskonstrukció 264/73 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 rekurzió mint típuskonstrukció 265/73 2 Nem bináris fák 2.1 Algebrai specifikáció Típus Fa(Elem): Asszociált műveletek: 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)
A rekurzió mint típuskonstrukció 266/73 2 Nem bináris fák Jelölések Jelölések: f,f’,ff,f’:Fa(Elem) – általában az aposztróf időbeliségre utal e:Elem i:Egész „=”:Fa Fa Logikai, strukturális és elemérték-szintű azonosságAxió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))
A rekurzió mint típuskonstrukció 267/73 2 Nem bináris fák 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
A rekurzió mint típuskonstrukció 268/73 2 Nem bináris fák 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ó] …
A rekurzió mint típuskonstrukció 269/73 2 Nem bináris 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.
A rekurzió mint típuskonstrukció 270/73 2 Nem bináris fák 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, ÜresSorozat, ElemSzám, ElemSzám, Végére, Végére, (i) (i)
A rekurzió mint típuskonstrukció 271/73 2 Nem bináris 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 i ElemSzám(f) akkorGyerek:=f.ág(i) különbenGyerek:=Ü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.
A rekurzió mint típuskonstrukció 272/73 2 Nem bináris 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)BinFa 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, Balra a leszármazottak, jobbra a testvérek. jobbra a testvérek. Lásd az ötletet. ötletet
A rekurzió mint típuskonstrukció 273/73 2 Nem bináris fák Egy alternatív megoldás ötlete: Balra az „1.” gyerek Jobbra a „következő” testvér