BFák Kiegyensúlyozott keresőfák Hatékonyság: O(lg(n)), de a nagy fokszám miatt igen alacsony szorzótényezővel Alkalmazás: Lemezen tárolt adatbázisoknál Mágneslemezen hatékony tárolásra lett tervezve Ki/Be műveletek minimalizálása Elágazási tényező: néhány ezerig is terjedhet Időszükséglet=Ki/Be idő+memória számolás ideje
BFák M Q T X D H B C F G J K L N P R S V W Y Z Egy csúcs n db kulcsot tartalmaz a kulcstartomány felosztása a csúcsnak n+1 gyereke van. Levélcsúcs: egyetlen gyereke sincs
Lemezműveletek modellezése x: egy adathivatkozás, nem tudni, hogy hol van Ha x a lemezen van, akkor x mezői nem elérhetők LemezrőlOlvas(x) ha lemezen van, akkor beolvassa. Egyébként hatástalan, LemezreÍr(x) kiírja a lemezre, ha történt módosítás. Egyébként hatástalan. Egy csúcs mérete = lemez blokkmérete. Ez az elágazási tényező felső korlátja is.
BFa Definíciója A T BFa olyan gyökeres fa, amelyre: 1. Minden x csúcsnak a következő mezői vannak: n: az x csúcsban tárolt kulcsok száma n db kulcs úgy, hogy kulcs[1]<=…<=kulcs[n] levél=Igaz, ha x levél, Hamis egyébként 2. Ha x belső csúcs, akkor gyerek[i] vektor, ahol i<=n a gyerekekre mutató vektor. Ha x levél, akkor a vektor tartalma meghatározatlan 3. Ha ki egy kulcs, amelyik a gyerek[i] részfában van, akkor: k1<=kulcs[1]<=k2<=kulcs[2]<=…<=kulcs[n]<= kn+1
BFa Definíciója Minden levél magassága egyenlő, ez a fa h magassága Minimális fokszám: t>=2, maximális fokszám: 2t Minden nem gyökér csúcsnak legalább t-1 kulcsa van Minden csúcsnak legfeljebb 2t-1 kulcsa van Egy csúcs telített, ha pontosan 2t-1 kulcsa van Gyökércsúcsnak legalább 1 kulcsa2 gyereke van Legegyszerűbb eset: t=2 minden csúcsnak 2,3 vagy 4 gyereke lehet 2-3-4 fának nevezzük (gyakorlatban t>>>2 !)
BFa magassága Tétel: Ha n>=1 és T egy n kulcsos BFa, magassága h és min.fokszáma t>=2 h<=logt(n+1)/2 Biz: egy h magasságú bfa csúcsszáma akkor minimális, ha minden nem gyökér belső csúcsnak éppen t-1 kulcsa van. Ilyenkor: n=2+2t+2t2+…+2th-1=1+(t-1)*i=1Σh 2th-1 = =1+2(t-1)(th-1)/(t-1)=2th-1 Vagyis más fákra n>=2th-1 logt(n+1)/2>=h
Keresés BFában BFaKeres(k) i=1 while i<=n és k>kulcs[i] i=i+1 if i<=n és k=kulcs[i] then return (Me,i) if levél then return NIL else LemezrőlOlvas(gyerek[i]) return gyerek[i].BFaKeres(k) Többutas elágaztató döntés Ha megtaláltuk csúcs és index visszaadása Jobbrekurzív algoritmus: HF: átírni ciklikussá
Üres BFa készítése ÚjBFa() bfa=CsúcsotElhelyez() bfa.levél=Igaz bfa.n=0 LemezreÍr(bfa) return(bfa) Lemezen helyfoglalás
BFa egy csúcsának kettévágása Me: nem telített csúcs, csúcs=gyerek[i], ami telített BFaVágásGyerek(i,csúcs) új=CsúcsotElhelyez() új.levél=csúcs.levél csúcs.n=t-1 for j=1 to t-1 új.kulcs[j]=csúcs.kulcs[j+1] if not csúcs.levél then for j=1 to t új.gyerek[j]=csúcs.gyerek[j+1] csúcs.n=t-1 for j=n downto i gyerek[n+2]=gyerek[n+1] kulcs[n+1]=kulcs[n] gyerek[i+1]=új kulcs[i]=csúcs.kulcs[i] n=n+1 LemezreÍr(csúcs), LemezreÍr(új), LemezreÍr(Me) Új csúcs kezdőértékezése Csúcs fokszáma csökken Gyerekek, kulcsok átmásolása Új csúcs beszúrása apa csúcsai közé
Csúcs kettévágása N W N S W P Q R S T U V P Q R T U V
Kulcs beszúrása BFába Beszúrás mindig levélelemnél történika fa magassága nem változik(egyfajta kiegyenlítettség megmarad) Ha a beszúrási ponthoz vezető út bármelyik eleme telített, akkor felhasad két fele méretű csúcsra A fa nem a levelénél, hanem a gyökerénél nő
Kulcs beszúrása BFába TelítetlenBFábaBeszúr(kulcs) i=n if levél then while i>=1 és k<kulcs[i] kulcs[i+1]=kulcs[i] i=i-1 kulcs[i+1]=k n=n+1 LemezreÍr(Me) else while i>=1 és k<kulcs[i] i=i-1 i=i+1 LemezrőlOlvas(gyerek[i]) if gyerek[i].n=2t+1 then BFaVágásGyerek(i,gyerek[i]) if k>kulcs[i] then i=i+1 gyerek[i].TelítetlenBFábaBeszúr(kulcs) A fa gyökere telítetlen Beszúrás levélelembe Ha a gyerek telített, akkor felhasítjuk Meghatározzuk, hogy a rekurziót melyik gyerekkel folytassuk
Ezt csak a bfa gyökerére hívjuk meg Kulcs beszúrása BFába BFábaBeszúr(k) if n=2t+1 then új=CsúcsotElhelyez() új.levél=Hamis új.n=0 új.gyerek[1]=Me új.BFaVágásGyerek(1,Me) új.TelítetlenBFábaBeszúr(k) else TelítetlenBFábaBeszúr(k) Ezt csak a bfa gyökerére hívjuk meg
Kulcs törlése BFából Hasonlít a beszúrásra, de kicsit bonyolultabb A minimális fokszámnál szélesebb csúcsokból törlünk. A keskenyebbeket egyesíteni próbáljuk A rekurzió során lefelé menőben minden egyesíthető csúcsot egyesítünk, felfelé pedig törlünk a pontos algoritmust nem adjuk meg, ez HF!!
0. t=3legalább t-1=2 kulcslegfeljebb 2t-1=5 kulcs csomópontonként T X C G L A B D E F J K L N O Q R S U V Y Z P T X C G M A B D E J K L N O Q R S U V Y Z 0. t=3legalább t-1=2 kulcslegfeljebb 2t-1=5 kulcs csomópontonként 1. Ha a k kulcs az x levélelemben vankulcs törlése levélelemből
P C G M T X A B D E Y Z U V Q R S N O J K L P C G L T X A B D E Y Z U V Q R S N O J K 2. Ha a k kulcs az x belső csúcsban van, és a megelőző k’ kulcsot tartalmazó gyerek fokszáma legalább t+1 a. megelőző k’ kulcsot rekurzívan töröljük a gyerekből, majd a k’ kulcsot beemeljük az x csúcsba b. Szimmetrikusan: ha a rákövetkező k” kulcsot tartalmazó gyerek fokszáma legalább t+1…
P C G L T X A B D E Y Z U V Q R S N O J K P T X C L A B D E J K N O Q R S U V Y Z 2.c. 2a-2b után tudjuk, hogy a megelőző és a következő gyerek egyesíthető, ebbe levisszük a törlendő k kulcsotezután töröljük a k csúcsot
Kulcs törlése BFából 3. Ha a k kulcs az x belső csúcsban nincs, akkor meghatározzuk annak a részfájának a csúcsát, amelyikben benne lehet. A rekurzív hívást csak t kulccsal (1 extra kulccsal) rendelkező részfákon hajtjuk végre, hogy legyen mit törölni. Ha mégis csak t-1 kulcsa lenne, akkor a. Ha van olyan testvére, amelynek legalább t gyereke van, akkor az x csúcsból a megelőző vagy rákövetkező elemet vigyük a gyerekbe, a testvéréből pedig 1 kulcsot vigyünk az x csúcsba. b. Ha nincs ilyen testvére, akkor egyesítsük a két testvért. c. Ha a gyökér két utolsó testvérét egyesítjük, akkor a gyökérkulcsot is vigyük ide le, ilyenkor csökken a fa fokszáma
CL és TX egyesítése, P lemozdítása A B D E J K N O Q R S U V Y Z C L P T X A B D E J K N O Q R S U V Y Z A fa magassága csökken C L P T X A B E J K Y Z U V Q R S N O
C L P T X A B E J K N O Q R S U V Y Z E L P T X A C J K N O Q R S U V Y Z A B törlése megsértené a minimális fokszám elvét, viszont a testvérének van egy extra kulcsaa testvérétől 1-et felviszünk, fentről egyet lehozunk, és ekkor már törölhetjük az elemet