This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA
=P^.Kulcs[i+1] Then Q:=R;{kerút R-en át megy} {3}End Else Begin {kettévágás} PVag(i,P,Q,R); If K>=P^.Kulcs[i+1] Then Q:=R;{kerut az úuj ponton át megy} End; End{Q televolt}; i:=PKeres(Q,K); {K keresése a Q pontban} If Q^.Level Then Break; P:=Q; {továbblépés a keresési úton} Q:=Q^.Fiu[i]; End{while}; {Q a Kerut(F,K) vege, level es Q^.Rang<2T-1} JobbraLep(Q,i+1); {b˝ ovítés a Q levél pontban} Q^.Kulcs[i+1]:=K; Q^.Adat[i+1]:=X; {kulcs es adat beillesztése} End{Bovit}; Procedure Torol(Var F: BFA; K: KulcsTip; Var Volt:Boolean); Var P,Q,R,Pt:BFa; i,it: Word; Begin Volt:=False; If F=Nil Then Exit; P:=F; While True Do Begin {P^.Rang>=T, ha P<>F} i:=PKeres(P,K); {a K kulcs keresése a P pontban} 9
If (i>0) And (P^.Kulcs[i]=K) Then Begin{K megvan} Pt:=P; it:=i; Volt:=True; {feljegyezzük} End; If P^.Level Then Break; Q:=P^.Fiu[i]; If Q^.Rang=T-1 Then Begin If i>0 Then Begin R:=P^.Fiu[i-1]; If R^.Rang>=T Then BalrolAt(i,P,Q,R) Else Begin Osszevon(i,P,R,Q); Q:=R End End Else Begin R:=P^.Fiu[i+1]; If R^.Rang>=T Then JobbrolAt(i,P,Q,R) Else Osszevon(i+1,P,Q,R); End; End; P:=Q; End{while}; If Not Volt Then Exit; If i=0 Then i:=1; Pt^.Adat[it]:=P^.Adat[i]; Pt^.Kulcs[it]:=P^.Kulcs[i]; BalraLep(P,i+1); If F^.Rang=0 Then Begin P:=F; If F^.Level Then F:=Nil Else F:=F^.Fiu[0]; Dispose(P); End; End; {Torol} End {B_Fa}.
8.3.
{Q pótlásra szorul} {Q-nak van bal testvére}
{pótlás a bal testvérb˝ ol} {R is és Q is minimális}
{Q-nak csak jobb testvére van}
{pótlás a jobb testvérb˝ ol} {R is és Q is minimális}
{tovaább lefelé a keresési úton}
{átmasolás K helyére} {effektív törlés a levél pontban} {a fa magassága csökkent} {a fa üressé vált}
{a gyökerpontot töröljük}
B-fák külso˝ megvalósítása.
Adatszerkezet külso˝ megvalósítása azt jelenti, hogy minden cellát (pontot) adott file egy rekordja tárol. Tehát egy cellát a filebeli rekordsorszáma azonosít. B-fa külso˝ adatszerkezetként történo˝ megvalósítása esetén exogén ábrázolást célszeru˝ alkalmazni. Tehát külön fileban tároljuk a fa adatszerkezetet és külön fileban az adatokat. A fa (k, r) párokat tartalmaz, ahol r annak az adatelemnek a adatfilebeli rekordsorszáma, amelynek kulcsa k. A törlések miatt a fát tároló file egyes rekordjai használaton kívüliek lehetnek. A töredezettség csökkentése érdekében célszeru˝ ezeket egy láncba szervezni, így új pont létesítésekor ezek újra felhasználhatók lesznek. 8.3.1.
Muveletek ˝ a külso˝ megvalósításhoz
ION YIT(Var F:KBFa; BFaFNev:String ) A muvelet ˝ hozzárendeli az F fához a BFaFNev nevu˝ filet, amely a fa külso˝ megvalósítását ˝ ez nem létezett, akkor új filet hoz létre. Továbbá elokészíti ˝ tárolja. Ha a muvelet ˝ elott (inicializálja) a további muveletek ˝ által használt belso˝ adatszerkezetet.
10
0
1
2
3
m
4
10. ábra. Fa külso˝ tárolása során a szabad rekordokat láncba szervezzük. A file 0. rekordja tartalmazza a fa gyökerének rekordsorszámát és a szabad lánc fejét.
IOZ AR(Var F:KBFa); Lezárja az F fához tartozó filet és felszabadítja a lefoglalt belso˝ adatszerkezetet. IOU J P ONT(Var F:KBFa; Var P:BFa) A muvelet ˝ az F fához egy új pontot hoz létre. Az új pont memória helye a P ↑ .Belso, filebeli rekordsorszáma pedig P ↑ .Kulso lesz. IOPTOROL(Var F:KBFa; Var P:BFa); A muvelet ˝ törli az F fa P ↑ .Kulso pontját és felszabadítja a pont által lefoglalt P ↑ .Belso memóriát. IOB E(Var F:KBFa; r:KPointer; Var P:BFa); Beolvassa a memóriába az F fa r rekordsorszámú pontját. A P változó értéke annak a belso˝ pontnak a címe lesz, ahova az r pontot beolvasta. IOK I(Var F:KBFa; Var P:BFa); A muvelet ˝ kiírja az F fát tároló fileba a memóriában P helyen lévo˝ fa pontot. (A muvelet ˝ végrehajtása nem feltétlenül eredményez tényleges kiírást. Ha a pont nem változott a beolvasás óta, nem kell visszaírni.) IOM OD(Var P:BFa); A muvelet ˝ megjelöli, hogy a P pont módosult. A belso˝ algoritmus átírása külso˝ algoritmussá.
Bels˝ o m˝ uvelet: --------------------------New(P); -------------------------P^.Kulcs[i]:=K; -------------------------Q:=P^.Fiu[i]; -------------------------P:=Q; -------------------------Dispose(P);
A megfelel˝ o küls˝ o m˝ uvelet: --------------------------IOUjPont(F, P); -------------------------P^.Belso.Kulcs[i]:=K; IOMod(P); -------------------------IOKi(F, P); {ha P már nem aktív} IOBe(F, P^.Belso.Fiu[i], Q); -------------------------IOKi(F, P); {ha P már nem aktív} P:=Q; -------------------------IOPTorol(P);
A teljes megvalósítás megtalálható a kb_fa.pas állományban. Az I/O muveletek ˝ egyszeru˝ megvalósítás.
Procedure IOBe(Var F:KBFa; r:KPointer; Var P:BFa); Begin New(P); Seek(F.FaF, r); Read(F.FaF, P^.Belso); P^.Kulso:=r; P^.Modos:=False; End; Procedure IOKi(Var F:KBFa; Var P:BFa); Begin If P^.Modos Then Begin Seek(F.FaF, P^.Kulso); Write(F.FaF, P^.Belso); P^.Kulso:=r; 11
P^.Modos:=False;End; End; Dispose(P); End; Ekkor egyszerre legfeljebb 5 pont van a memóriában (törlés esetén), feltéve, hogy a gyökér mindig benn van. Azonban alkalmazás ˝ gyorsítás során ugyanarra a pontra többször történhet hivatkozás. Ezért, ha van elég memória több pont számára, akkor jelentos érheto˝ el, ha csak akkor írunk ki pontot, ha már egy új pont beolvasásához nincs szabad hely. Ekkor, ha van bent olyan pont, amely nem változott, akkor annak a helyébe olvasunk be, így nem kell kiírni. Továbbá, minden beolvasott ponthoz tartozzon egy Aktiv ˝ amely azt jelezze, hogy a pontot nem lehet felülírni a memóriában, mert még szükség van rá a muveletek mezo, ˝ során.
Puf
Kulso
Belso
Modos Aktiv
1 2 3 4 5 11. ábra. A fa memóriába beolvasott pontjait tároló adatszerkezet.
Unit KB_FaIO; Interface Const T=100; TT=2*T-1; {a B-fa rendje T} IOPufM=400; {az I/O pufferek száma} Type Kulcstip=Single; Adattip=Word; KPointer=Longint; AdatHiv =Longint; BFa = ^BFaPont; KBFAPont=Record Level :Boolean; Fok :0..TT; Fiu : Array[0..TT] of KPointer; Adat : Array[1..TT] of Adathiv; Kulcs : Array[1..TT] of KulcsTip; End; BFAPont=Record Belso :KBFaPont; Kulso :KPointer; Modos, Aktiv :Boolean; End; KBFa=Record FaF:File of KBFaPont; {a B-fa file} AF :File of Adattip; {az adatfile} G:BFa; {a B_fa gyökere (a memóriában)} IOPuf:Array[1..IOPufM] of BFa; FMeret, {a FaF file mérete } FSzabad:Longint {a szabad (törölt rekordok) láncának feje}; End; { Az IO interface m˝ uveletei:} Procedure IONyit(Var F:KBFa; BFaFNev:String ); 12
Procedure Procedure Procedure Procedure Procedure Procedure
IOZar(Var F:KBFa); IOBe(Var F:KBFa; r:KPointer; Var P:BFa); IOKi(Var F:KBFa; Var P:BFa); IOUjPont(Var F:KBFa; Var P:BFa); IOPTorol(Var F:KBFa; Var P:BFa); IOMod(Var P:BFa);
Procedure IONyit(Var F:KBFa; BFaFNev:String); Var r:Longint; i:Integer; Begin With F Do Begin For i:=1 To IOPufM Do Begin {pufferek letesitese, } New(IOPuf[i]); {inincializalasa} IOPuf[i]^.Modos:=False; IOPuf[i]^.Aktiv:=False; {Nem aktiv a puffer} IOPuf[i]^.kulso:=0; {ures a puffer} End; G:=IOPuf[1]; {helyfoglalas a gyokernek} Assign(FaF, BFaFNev); {a B-fat tarolo file megnyitasa} {$I-} Reset(FaF); {$I+} If IOResult<>0 Then Begin {a kulso B-fa meg nem letezett, ujat csinalunk} Rewrite(FaF); G^.Belso.Fok:=0; {ures fa, ures gyokerpont} G^.Kulso:=1; {a gyoker az 1. rekordba megy} G^.Modos:=True; FSzabad:=0; {nincs torolt rekord a fileban} FMeret:=2; {0.,1. rekord mar foglalt} End Else Begin {a kulso B-fa mar letezett} Read(FaF, G^.Belso); {a 0. admin rekord beolvasasa} r:=G^.Belso.Fiu[0]; {a fa gyokerenek rek.sorszama} FSzabad:=G^.Belso.Fiu[1];{a szabad rek. lancanak feje} Seek(FaF, r); {a gyoker beolvasasa} Read(FaF, G^.Belso); G^.Kulso:=r; FMeret:=FileSize(FaF); End; End{with}; F.G^.Aktiv:=True; End{IONyit}; Procedure IOZar(Var F:KBFa); Var i:Integer; Begin With F Do Begin For i:=1 To IOPufM Do If IOPuf[i]^.Modos Then Begin{a modosult rekordok kiirasa} Seek(FaF,IOPuf[i]^.Kulso); Write(FaF,IOPuf[i]^.Belso); End; G^.Belso.Fiu[0]:=G^.Kulso; {a gyoker rek beirasa az admin rekordba} G^.Belso.Fiu[1]:=FSzabad; {a szabad lanc fejenek beirasa } Seek(FaF,0); {a 0. admin rekord kiirasa} Write(FaF,G^.Belso); Close(FaF); 13
End{with}; End{IOZar}; Procedure IOBe(Var F:KBFa; r:KPointer; Var P:BFa); Var i,ri,ui,mi,fi:Integer; Begin ri:=0; ui:=0; mi:=0; fi:=0; With F Do Begin For i:=1 To IOPufM Do If IOPuf[i]<>G Then Begin If IOPuf[i]^.Kulso=r Then ri:=i Else If Not IOPuf[i]^.Aktiv Then Begin fi:=i; If IOPuf[i]^.Kulso=0 Then ui:=i; If Not IOPuf[i]^.Modos Then mi:=i; End; End; If ri>0 Then P:=IOPuf[ri] Else If ui>0 Then P:=IOPuf[ui] Else If mi>0 Then P:=IOPuf[mi] Else If fi>0 Then P:=IOPuf[fi] Else Begin WriteLn(’IOBe: Nincs eleg puffer’); Halt; End; If (P^.Kulso<>r) Then Begin If P^.Modos Then Begin{P modosult, ezert elobb ki kell irni} Seek(FaF, P^.Kulso); Write(FaF, P^.Belso); End; Seek(FaF, r); Read(FaF, P^.Belso); P^.Kulso:=r; P^.Modos:=False; End; End{with}; P^.Aktiv:=Ture; End{IOBe}; Procedure IOUjPont(Var F:KBFa; Var P:BFa); Var r:Longint; i,ui,mi,fi:Integer; Begin With F Do Begin ui:=0; mi:=0; fi:=0; For i:=1 To IOPufM Do {puffer keresese} If (IOPuf[i]<>G) And Not IOPuf[i]^.Aktiv Then Begin fi:=i; {nem aktiv puffer} If IOPuf[i]^.Kulso=0 Then {ures puffer} ui:=i; If Not IOPuf[i]^.Modos Then{nem modosult puffer} mi:=i; 14
End; If ui>0 Then {van-e ures puffer } P:=IOPuf[ui] Else If mi>0 Then {van-e nem modosult puffer} P:=IOPuf[mi] Else If fi>0 Then {csak modosult, de nem Aktiv puffer van} P:=IOPuf[fi] Else Begin WriteLn(’IOUj: Nincs eleg puffer’); Halt; End; If P^.Modos Then Begin Seek(FaF, P^.Kulso); Write(FaF, P^.Belso); End; If FSzabad<>0 Then Begin r:=FSzabad; Seek(FaF, r); Read(FaF, P^.Belso); FSzabad:=P^.Belso.Fiu[0]; End Else Begin r:=FMeret; Inc(FMeret); End; End{with}; P^.Kulso:=r; P^.Modos:=False; P^.Aktiv:=True; End{IOUjPont};
{P modosult, ezert elobb ki kell irni}
{van torolt rekord a faban} {a kovetkezo szabad rekord beolvasasa}
{nincs torolt rekord, a file bovul(a vegen)}
Procedure IOPTorol(Var F:KBFa; Var P:BFa); Begin With F Do Begin P^.Belso.Fiu[0]:=FSzabad; Seek(FaF, P^.Kulso); Write(FaF, P^.Belso); FSzabad:=P^.Kulso; End; P^.Kulso:=0; P^.Modos:=False; P^.Aktiv:=False; End{IOPTorol}; Procedure IOKi(Var F:KBFa; Var P:BFa); Begin If (P<>Nil) And (P<>F.G) Then P^.Aktiv:=False; End{IOKi}; Procedure IOMod(Var P:BFa); Begin P^.Modos:=True; End{IOMod}; End{KB_FaIO}.
15