58131 Tietorakenteet (kevät 2009) Harjoitus 6, ratkaisuja (Antti Laaksonen) 1. Avaimet 1, 2, 3 ja 4 mahtuvat samaan lehtisolmuun. Tässä tapauksessa puussa on vain yksi solmu, joka on samaan aikaan juurisolmu ja lehtisolmu. Kun avain 5 lisätään puuhun, aiempi lehtisolmu täytyy jakaa kahteen osaan. Lisäksi tarvitaan sisäsolmu, joka viittaa kumpaankin lehtisolmuun ja joka on puun uusi juurisolmu. Avain 6 mahtuu vielä toiseen lehtisolmuun. Avaimet 7, 8, 9 ja 10 lisätään puuhun vastaavasti.
Kun avain 11 lisätään puuhun, sisäsolmuun tulisi avain 8, mutta sisäsolmu on jo täynnä. Tämän vuoksi sisäsolmu täytyy halkaista, jolloin sen keskimmäinen avain 4 siirtyy ylemmälle tasolle ja muut avaimet jakautuvat kahteen sisäsolmuun. Halkaistava sisäsolmu on puun juurisolmu, joten lisäksi ylemmälle tasolle tarvitaan uusi sisäsolmu, josta tulee puun uusi juurisolmu. Sisäsolmun halkaisun jälkeen avain 8 sijoitetaan oikeaan alempaan sisäsolmuun. Avaimen 12 lisäys ei aiheuta muutoksia puun rakenteeseen. Kun avain 1 poistetaan puusta, kaksi lehtisolmua täytyy yhdistää, jolloin vasen alempi sisäsolmu jää tyhjäksi. Oikealla alemmalla sisäsolmulla on tarkalleen t + 1 lasta, joten luentomateriaalin mukaan on kaksi eri tapaa toimia. Valittu tapa vaikuttaa myös myöhempiin poistoihin: (a) Tilanne korjataan yhdistämällä alemmat sisäsolmut. Nyt ylemmällä sisäsolmulla on vain yksi lapsi, joten se poistetaan tarpeettomana. Avaimen 2 poisto säilyttää puun rakenteen ennallaan. Kun avain 3 poistetaan puusta, kaksi lehtisolmua täytyy jälleen yhdistää, jolloin sisäsolmusta poistetaan yksi avain. Avaimen 4 poisto säilyttää puun rakenteen ennallaan. 2
(b) Tilanne korjataan siirtämällä avaimia sisäsolmuissa yksi askel vasemmalle, jolloin puussa on edelleen kolme sisäsolmua. Avaimen 2 poisto säilyttää puun rakenteen ennallaan. Kun avain 3 poistetaan puusta, kaksi lehtisolmua täytyy jälleen yhdistää ja vasen alempi sisäsolmu jää tyhjäksi. Nyt alemmat sisäsolmut yhdistetään ja ylempi sisäsolmu poistetaan tarpeettomana. Avaimen 4 poisto säilyttää puun rakenteen ennallaan. Yllä olevan kaltaisissa tapauksissa, joissa luentomateriaalin antama toimintaohje ei ole yksikäsitteinen, molemmat vaihtoehdot tietysti hyväksytään. 3
2. Tutkitaan, kuinka monta alkiota lehtisolmussa voi olla ja kuinka monta lapsiosoitinta sisäsolmussa voi olla. Solmun täytyy mahtua yhteen lohkoon, eli sen koko saa olla korkeintaan 4 kilotavua eli 4096 tavua. Yksi lehtisolmussa oleva alkio tarvitsee 8 tavua tilaa avaimelle ja 64 tavua tilaa datakentälle, joten alkio tarvitsee yhteensä 72 tavua tilaa. Lehtisolmuun mahtuu siis korkeintaan 4096/72 = 56 alkiota. Tästä saadaan t:n arvoksi 28, mikä tarkoittaa, että yhdessä lehtisolmussa täytyy olla ainakin 28 alkiota. Jokainen sisäsolmun lapsiosoitin tarvitsee 4 tavua tilaa. Lisäksi solmuun täytyy tallentaa avaimia yksi vähemmän kuin lapsiosoittimia, ja jokainen niistä tarvitsee 8 tavua tilaa. Sisäsolmuun mahtuu siis korkeintaan (4096 4)/(4 + 8) + 1 = 342 lapsiosoitinta. Tästä saadaan t:n arvoksi 171, mikä tarkoittaa, että yhdessä sisäsolmussa täytyy olla ainakin 171 lapsiosoitinta. Yritetään nyt muodostaa mahdollisimman korkea B + -puu. Joka vaiheessa solmujen kannattaa antaa olla mahdollisimman tyhjiä, jotta puusta tulee mahdollisimman korkea. Puun juurisolmussa voi olla poikkeuksellisesti vain yksi alkio tai kaksi lapsiosoitinta. Muuten pienimmät sallitut määrät ovat lehtisolmussa 28 alkiota ja sisäsolmussa 171 lapsiosoitinta. Alkioiden vaaditusta määrästä eri korkeuksilla saadaan seuraava taulukko: korkeus alkioita vähintään 0 1 1 2 28 = 56 2 2 171 28 = 9576 3 2 171 2 28 = 1637496 4 2 171 3 28 = 280011816 Kun puun korkeus on 4 tai suurempi, alkioita on oltava yli 100 miljoonaa, joten suurin mahdollinen puun korkeus on 3. Tällaisesta puusta alkion hakeminen vie aikaa keskimäärin 30 ms, koska yhden solmun hakeminen vie aikaa keskimäärin 10 ms ja solmuja täytyy hakea 3. Luennoilla on osoitettu, että jos AVL-puun korkeus on h, siinä on ainakin F h+3 1 alkiota, missä F 0 = 0, F 1 = 1 ja F n = F n 2 +F n 1, kun n > 1 (Fibonaccin lukusarja). F 39 = 63245986 ja F 40 = 102334155, joten suurin korkeus, jossa alkioiden määrä voi olla 100 miljoonaa, on 36. Jos tällaisesta puusta haetaan alkiota, joka sijaitsee mahdollisimman syvällä puussa, ja jokainen siirtyminen puussa vaatii erillisen levyhaun, aikaa kuluu keskimäärin 360 ms. Puun alkiot ovat keskittyneet sen alaosaan, joten tämä laskelma antaa suuntaa myös tapaukseen, jossa puusta haetaan satunnaista alkiota. 3. Kun B + -puussa on n alkiota ja vakiot a ja b ovat tiedossa, alkion hakemiseen puusta kuluu noin log t (n) levyhakua, joista jokainen vie aikaa a+bt. Tehtävänä on siis valita t:n arvo niin, että tulo log t (n) (a+bt) on mahdollisimman pieni. Kun t:n arvo kasvaa, toisaalta log t (n) pienenee ja toisaalta a + bt suurenee, joten täytyy löytää tasapainokohta, jossa molemmat tulon tekijät ovat kohtuullisen pienet. Logaritmin laskusääntöjen mukaan log t (n) = ln(n)/ ln(t). Kun alkioiden määrä n on vakio, riittää saattaa lauseke (a + bt)/ ln(t) mahdollisimman pieneksi. Suoraviivainen menetelmä on tulkita lauseke muuttujan t funktioksi ja etsiä derivaatan nollakohtaa. D a + bt ln(t) = b ln(t) (a/t + b) ln(t) 2 Derivaatan nollakohdassa b ln(t) = a/t + b, ja nollakohtia voi olla vain yksi, koska t:n kasvaessa yhtälön vasen puoli suurenee ja oikea puoli pienenee. Yhtälössä esiintyvät sekä t että ln(t), joten t:lle ei saa suoraa laskukaavaa, mutta sopivan t:n voi etsiä numeerisesti, kuten seuraavaksi nähdään. 4
Etsitään pienimmän hakuajan tuottavaa t:n arvoa, kun a = 5000 ja b = 10. Piirretään ensin funktion f(t) = (5000 + 10t)/ ln(t) kuvaaja, jonka perusteella paras t:n arvo osuu välille 100 150. Etsitään funktion minimikohtaa binäärihakua muistuttavalla tavalla. Ensin todetaan, että t:n arvo 100 on liian pieni, koska b ln(100) < a/100 + b. Sitten todetaan, että t:n arvo 150 on liian suuri, koska b ln(150) > a/150 + b. Tämän jälkeen puolitetaan väliä valitsemalla toistuvasti t:n arvoksi välin keskipiste ja tarkistamalla, onko valittu t:n arvo liian pieni vai liian suuri. t b ln(t) a/t + b päätelmä 100 46,0517 60,0000 100 < t 150 50,1064 43,3333 100 < t < 150 125 48,2831 50,0000 125 < t < 150 137 49,1998 46,4964 125 < t < 137 131 48,7520 48,1679 125 < t < 131 128 48,5203 49,0625 128 < t < 131 129 48,5981 48,7597 129 < t < 131 130 48,6753 48,4615 129 < t < 130 Tämän perusteella paras valinta t:n arvoksi on 129 tai 130. Laskemalla funktion arvo näissä pisteissä saadaan f(129) 1294, 2886 ja f(130) 1294, 2898. Siis f(129) < f(130) eli t:n arvo 129 on paras, mutta ero on hyvin pieni, niin kuin kuvaajastakin voi huomata. 5