CS-A1140 Tietorakenteet ja algoritmit Kierros 4: Binäärihakupuut Tommi Junttila Aalto-yliopisto Perustieteiden korkeakoulu Tietotekniikan laitos Syksy 2016
Sisältö Binäärihakupuut Avainten lisääminen, etsiminen ja poistaminen Pahimman tapauksen käytös Tasapainoiset hakupuut AVL-puut Punamustat puut 2/53
Materiaali: Hakupuut: kappaleet 12.1 12.3 kirjassa Introduction to Algorithms, 3rd ed. (online via Aalto lib) AVL-puut: nämä kalvot wikipedia Punamustat puut: Kappaleet 13.1 13.4 kirjassa Introduction to Algorithms, 3rd ed. (online via Aalto lib) 3/53
Samantapaista materiaalia muualla: Hakupuut: Kappale 3.2 kirjassa Algorithms, 4th ed. Punamustat puut: Linkkejä: Kappale 3.3 kirjassa Algorithms, 4th ed. (avainten poistoa ei käsitelty) MIT 6.006 OCW video on binary search trees MIT 6.006 OCW video on AVL trees 4/53
Binäärihakupuut 5/53
Tällä ja seuraavalla kierroksella tarkastellaan tietorakenteita ja algoritmeja, joilla voidaan toteuttaa dynaamisia joukkoja ja assosiatiivisia kuvauksia (engl. maps, dictionaries) Dynaaminen tarkoittaa tässä, että joukkoihin/kuvauksiin lisätään ja poistetaan alkioita, joilla on jokin avain, jatkuvasti (engl. online), ei vain kerran alussa tms Samaistetaan alkio avaimensa kanssa (esim. henkilö hetu) esityksen yksinkertaisuuden vuoksi Dynaamisen joukon abstraktin tietotyypin rajapinta voisi olla: INSERT(k) lisää avaimen k joukkoon SEARCH(k) etsii, onko avain k joukossa, ja DELETE(k) poistaa avaimen k joukosta Scalassa rajapintaa vastaa scala.collection.mutable.set-piirre, joka on toteutettu mm. TreeSet- ja HashSet-luokissa Javassa vastine on Set-rajapinta Kuvauksissa avaimeen liitetään myös jokin arvo Kalvoissa keskitytään esityksen yksinkertaistamisen takia joukkoihin (kuvaukset ovat melko suoraviivainen laajennus) 6/53
Tällä kierroksella tarkastellaan järjestettyjä joukkoja, joissa oletetaan jokin järjestys avainten välille ja pienimmän, seuraavaksi pienimmän jne avaimen etsiminen on tehokasta Järjestettyjen joukkojen rajapinta laajentaa perusrajapintaa esim. seuraavilla metodeilla: 1. MIN() palauttaa joukon pienimmän avaimen, 2. MAX() palauttaa joukon suurimman avaimen, 3. PREDECESSOR(k) etsii joukon suurimman avaimen, joka on pienempi kuin k 4. SUCCESSOR(k) etsii joukon pienimmän avaimen, joka on suurempi kuin k Scalan kirjastossa TreeSet-luokka toteuttaa rajapinnan version, joka sallii joukon avainten läpikäynnin järjestyksessä Javan standardikirjastossa TreeSet-luokan rajapinta on hyvin lähellä yllä kuvattua (MIN() vastaa metodi first jne) 7/53
Huomioi ero edellisen kierroksen prioriteettijonojen rajapintaan: mielivaltaisten avainten poistaminen sekä pienimmän, suurimman, seuraavaksi suuremman jne avaimen tehokas löytäminen on nyt tuettua Jälleen tavoitteena on saada aikaan logaritmisessa ajassa toimivia algoritmeja yllä mainittujen metodien toteuttamiseen 8/53
Tällä kierroksella tarkastellaan järjestettyjen joukkojen toteuttamista binääripuilla, joilla on tiettyjä lisäominaisuuksia Jokaiseen puun solmuun liitetään alkio, jolla on jokin avain; solmuun x liitetyn alkion avain on x.key Määritelmä Binääripuu on binäärihakupuu (engl. binary search tree, BST) jos seuraava hakupuuominaisuus pätee: jokaiselle puun solmulle x pätee, että 1. jos solmu y sijaitsee solmun x vasemman lapsen alipuussa, niin y.key x.key 2. jos solmu y sijaitsee solmun x oikean lapsen alipuussa, niin y.key x.key Oletetaan jatkossa, että avaimet ovat erillisiä 1 1 Yhtäsuurten avainten osalta katso Problem 12.1 kirjassa Introduction to Algorithms, 3rd ed. (online via Aalto lib) 9/53
Esimerkki: Kolme binäärihakupuuta ja binääripuu, joka ei ole hakupuu: 5 8 8 2 8 3 9 8 5 9 6 11 2 6 11 3 9 2 6 11 9 4 7 2 6 4 Oikealla olevassa puussa hakupuuominaisuus ei päde koska solmu, jonka avain on 4, on avaimen 8 omaavan solmun oikeassa alipuussa 10/53
Avainten etsiminen Hakupuuominaisuuden takia avainten etsintä binäärihakupuussa on helppoa Aloittaen juurisolmusta, käydään puuta läpi rekursiivisesti Jos tarkasteltavan solmun x avain on k, lopetetaan avaimen löydyttyä Jos solmun x avain on suurempi kuin k, mennään solmun vasempaan lapseen jos sellainen on, tai muutoin lopetetaan koska avainta ei ole puussa Jos solmun x avain on pienempi kuin k, mennään solmun oikeaan lapseen jos sellainen on, tai muutoin lopetetaan koska avainta ei ole puussa 11/53
Esimerkki: Tarkastellaan alla olevaa binäärihakupuuta. 8 3 9 2 6 11 4 7 Jos etsitään avainta 4, 1. aloitetaan juuresta ja huomataan, että 8 > 4, 2. mennään vasempaan lapseen ja huomataan, että 3 < 4, 3. mennään oikeaan lapseen ja huomataan, että 6 > 4, 4. mennään vasempaan lapseen ja huomataan, että 4 = 4, ja 5. lopetetaan raportoimalla, että vain 4 löytyi 12/53
Esimerkki: Tarkastellaan jälleen seuraavaa binäärihakupuuta. 8 3 9 2 6 11 4 7 Jos etsitään avainta 5, 1. aloitetaan juuresta ja huomataan, että 8 > 5, 2. mennään vasempaan lapseen ja huomataan, että 3 < 5, 3. mennään oikeaan lapseen ja huomataan, että 6 > 5, 4. mennään vasempaan lapseen ja huomataan, että 4 < 5, ja 5. huomataan, että solmulla ei ole oikeaa lasta ja lopetetaan toteamukseen, että avain 5 ei esiinny puussa 13/53
Avainten lisääminen Toimitaan ensin kuten avainta etsittäessä Jos avain löytyy puusta, lopetetaan Muutoin etsimisprosessin viimeinen askel olisi tahtonut mennä jonkin solmun n vasempaan (tai oikeaan) lapseen, jota ei kuitenkaan ollut lisätään uusi solmu n avaimella k puuhun niin, että siitä tulee solmun n vasen (tai oikea) lapsi 14/53
Esimerkki: Tarkastellaan vasemmanpuoleista binäärihakupuuta. 8 8 3 9 3 9 2 6 11 2 6 11 4 7 4 7 10 Lisättäessä avain 10 puuhun 1. aloitetaan juuresta ja huomataan, että 8 < 10 2. mennään oikeaan lapseen ja huomataan, että 9 < 10 3. mennään oikeaa lapseen ja huomataan, että 11 > 10 4. huomataan, että solmulla ei ole vasenta lasta 5. lisätään uusi avaimen 10 omaava solmu vasemmaksi lapseksi Muokattu hakupuu on kuvattu yllä oikealla puolella 15/53
Avainten poistaminen Avaimen k poistaminen on hieman monimutkaisempaa Ensin etsitään solmu z, joka omaa avaimen k. Tämän jälkeen 1. jos solmu on lehti, se poistetaan 2. jos solmulla on yksi lapsi, poistetaan solmu ja laitetaan sen ainoa lapsi sen paikalle puussa 3. muutoin solmulla on kaksi lasta ja 3.1 etsitään solmu y, joka omaa suurimman avaimen solmun z vasemman lapsen alipuussa 3.2 vaihdetaan solmun z avaimeksi solmun y avain ja 3.3 poistetaan solmu y ja laitetaan sen vasen lapsi x (jos sellainen on) sen paikalle puuhun. Huomaa, ettei solmulla y ole oikeaa lasta Tehtävä: tarkastele seuraavia esimerkkejä ja perustele itsellesi, miksi hakupuuominaisuus säilyy voimassa yllä kuvatulla poistoprosessilla 16/53
Esimerkki: Poistetaan avain 33 vasemmanpuoleisesta hakupuusta 11 11 5 31 remove 33 5 31 2 7 19 45 2 7 19 45 12 27 z 33 47 12 27 47 24 24 21 25 21 25 Täsä tapauksessa riittää vain poistaa avaimen 33 omaava solmu z 17/53
Esimerkki: Poistetaan avain 27 vasemmanpuoleisesta hakupuusta 11 11 5 31 remove 27 5 31 2 7 19 45 2 7 19 45 12 z 27 33 47 12 24 33 47 x 24 21 25 21 25 Nyt poistetaan avaimen 27 omaava solmu z ja laitetaan sen ainoa lapsi x sen paikalle hakupuuhun 18/53
Esimerkki: Poistetaan avain 31 vasemmanpuoleisesta hakupuusta 11 11 5 z 31 remove 31 5 27 2 7 19 45 2 7 19 45 12 y 27 33 47 12 24 33 47 z 24 21 25 21 25 Koska avaimen 31 omaavalla solmulla z on kaksi lasta, etsitään sen vasemman lapsen alipuun suurimman avaimen 27 omaava solmu y Siirretään solmun avain y solmun z avaimeksi (punainen nuoli kuvassa) Lopuksi poistetaan solmu y ja siirretään sen ainoa lapsi x sen paikalle puussa (sininen nuoli kuvassa) 19/53
Avainten listaaminen nousevassa järjestyksessä Hakupuuominaisuuden ansiosta puun avainten läpikäynti nousevassa järjestyksessä on helppoa: käydään vain puun solmut läpi sisäjärjestyksessä (edellinen kierros) ja tulostetaan avain kun solmussa vieraillaan Täten voitaisiin järjestää n avainta 1. lisäämällä ne yksi kerrallaan alun perin tyhjään hakupuuhun ja 2. listaamalla lopuksi puun avaimet läpi järjestyksessä Esimerkki: Tarkastellaan oikeanpuoleista hakupuuta Käydään solmut läpi sisäjärjestyksessä ja saadaan avaimet järjestyksessä 2,3,4,6,7,8,9,10,11 2 3 6 8 9 11 4 7 10 20/53
Pienimmän ja suurimman avaimen etsiminen Puun pienin avain voidaan löytää yksinkertaisesti käymällä puuta läpi juuresta alkaen ja menemällä aina vasemmanpuoleiseen lapseen kunnes vasenta lasta ei enää löydy Samoin suurin avain löytyy oikeanpuoleisimmasta solmusta Esimerkki: Tarkastellaan vasemmalla olevaa hakupuuta Pienin avain on 2 Suurin avain on 11 2 3 6 8 9 11 4 7 10 21/53
Edeltäjä- ja seuraaja-avainten etsiminen Mielivaltaisen avaimen k edeltäjä hakupuussa on sen suurin avain, joka on pienempi kuin k, tai None jos kaikki avaimet puussa ovat vähintään yhtä suuria kuin k Se voidaan löytää alustamalla muuttuja best arvoon None ja sitten käymällä puuta läpi juuresta alkaen niin pitkälle kuin mahdollista: Jos nykyisen solmun avain k on vähintään k, mennään vasempaan lapseen Muutoin asetetaan best arvoon k ja mennään oikeaan lapseen Lopussa, kun lapsi puuttuu, raportoidaan arvo best Avaimen k seuraaja puussa voidaan etsiä vastaavalla tavalla 22/53
Esimerkki: Tarkastellaan oikeanpuoleista hakupuuta Avaimen 5 edeltäjä puussa on 4 8 Avaimen 20 edeltäjä puussa on 11 3 9 Avaimella 2 ei ole edeltäjää puussa Avaimen 4 seuraaja puussa on 6 2 6 11 4 7 10 23/53
Ajoaika-analyysiä Esitetyt algoritmit avainten lisäämiselle ja etsimiselle käyvät läpi vain yhtä polkua puussa ja suorittavat vakioaikaisia operaatioita jokaisessa solmussa (oletetaan vertailu vakioaikaiseksi) Niinpä niiden aikavaatimus on O(h), missä h on puun korkeus Avanten poistoalgoritmi käy myös läpi yhden polun kunnes se löytää poistettavan avaimen ja tämän jälkeen jatkaa polkua löytääkseen tilalle vaihdettavan avaimen Siten sen ajoaikavaatimus on myös O(h). 24/53
Keskimääräisen ja pahimman tapauksen ajoaika Voidaan osoittaa, että jos tehdään hakupuu lisäämällä tyhjään puuhun n satunnaista erillistä avainta, niin puun odotettu korkeus on O(log 2 n), katso kappale 12.4 kirjassa Introduction to Algorithms, 3rd ed. (online via Aalto lib) Mutta on helppoa lisätä avaimia myös niin, että puusta tulee erittäin epätasapainoinen linkitettyä listaa muistuttava rakenne Esimerkki: Lisäämällä avaimet 1, 2, 3, 4 ja 5 tässä järjestyksessä saa aikaan oikeanpuoleisen hakupuun Tämä on käytännöllisesti katsoen sama rakenne kuin linkitetty lista Täten pahimman tapauksen ajoaika aiemmille operaatioille on Θ(n) kun avaimia on puussa n kpl 1 2 3 4 5 25/53
Tasapainoiset binäärihakupuut 26/53
Avainten lisääminen, etsiminen ja poistaminen saadaan toimimaan ajassa O(log 2 n), missä n on avainten lukumäärä puussa, tasapainottamalla hakupuut Tasapainotus takaa, että puiden korkeus on aina O(log 2 n) Tasapainotus voidaan tehdä monella eri tekniikalla, esimerkiksi tälle wikipedia-sivulle on koottu eri tapoja Seuraavassa tarkastelaan AVL-puita, joka on ensimmäiseksi esitelty tasapainoisten puiden luokka, ja punamustia puita (engl. red-black trees), joita käytetään useassa standardikirjastossa 27/53
Kiertäminen Eri tasapainotusmenetelmissä käytetty apurutiini on kiertäminen (engl. rotation) Tarkastellaan solmua x, jolla on oikea lapsi y. Kun solmua kierretään vasemmalle, niin solmun alipuu muutetaan muotoon, missä solmusta y tulee alipuun juuri, solmusta x tulee solmun y vasen lapsi ja solmun y vasemmasta lapsesta tulee solmun x oikea lapsi Oikealle kiertäminen määritellään vastaavasti solmulle, jolla on vasen lapsi x y y rotate x left x subtree 1 rotate y right subtree 3 subtree 2 subtree 3 subtree 1 subtree 2 28/53
x y y rotate x left x subtree 1 rotate y right subtree 3 subtree 2 subtree 3 subtree 1 subtree 2 Vasemmalle ja oikealle kiertäminen säilyttävät hakupuuominaisuuden eli jos hakupuuominaisuus pätee binääripuulle ennen kiertämistä, niin se pätee kiertämisen jälkeenkin Tämä nähdään yllä olevasta kuvasta seuraavasti: Alkuperäisen alipuun solmujen läpikäynti sisäjärjestyksessä tuottaa järjestyksessä avaimet alipuussa 1, solmun x avaimen, alipuun 2 avaimet, solmun y avaimen ja alipuun 3 avaimet Vasemmalle kiertämisen jälkeen syntyneen alipuun läpikäynti sisäjärjestyksessä tuottaa alipuun 1 avaimet, solmun x avaimen, alipuun 2 avaimet, solmun y avaimen ja alipuun 3 avaimet Vastaavasti oikealle kiertämisen kohdalla 29/53
AVL-puut 30/53
AVL-puut ovat eräs tasapainoisten hakupuiden luokka AVL tulee tietorakenteen keksijöiden nimistä Georgy Adelson-Velsky ja Evgenii Landis Materiaali ja linkkejä: nämä kalvot wikipedia MIT 6.006 OCW video on AVL trees Eräs visualisointityökalu AVL-puille 31/53
Määritelmä Binäärihakupuu on AVL-puu jos sen jokaiselle solmulle x pätee, että solmun vasemman ja oikean lapsen alipuiden korkeudet eroavat korkeintaan yhdellä Esimerkki: Tarkastellaan alla olevaa neljää hakupuuta 9 9 9 9 5 15 5 12 5 15 5 15 7 12 17 17 12 17 12 17 14 15 16 Kaksi vasemmanpuoleista ovat AVL-puita Kolmas ei ole AVL-puu koska avaimen 12 omaavan solmun vasen alipuu on tyhjä, eli korkeus on -1, kun taas oikean alipuun korkeus on 1 Oikeanpuoleisin ei ole AVL-puu koska juuren vasemman alipuun korkeus on 0 ja oikean 2 32/53
Annettuna AVL-puu, jonka korkeus on h. Kuinka monta solmua se sisältää vähintään? Tämä alaraja voidaan ilmaista rekursioyhtälönä T(h): T( 1) = 0 ja T(0) = 1 T(h) = 1 + T(h 1) + T(h 2) kaikille h 2 Muistetaan, että Fibonaccin luvut F n on määritelty kaavoilla F 0 = 0, F 1 = 1 ja F n = F n 1 + F n 2 kun n 2 Täten T(h) > F h+1 Koska F n on lukua ϕn 5 lähinnä oleva kokonaisluku, missä ϕ = 1, 618..., niin korkeuden h omaava AVL-puu sisältää eksponentiaalisen määrän solmuja suhteessa korkeuteen Kääntäen, n-solmuisen AVL-puun korkeus on logaritminen suhteessa arvoon n 33/53
Avainten lisääminen Lisätään avain k AVL-puuhun Alussa toimitaan kuten yleisillä hakupuillakin: etsitään avaimen oikea paikka puussa ja lisätään uusi avaimen omaava lehti z Nyt kuitenkin solmun z vanhemman p, kuten sen edeltäjienkin, korkeus on saattanut kasvaa yhdellä. Sen takia ALV-ominaisuus ei välttämättä enää päde vaan puussa voi olla solmuja, joiden toisen lapsen alipuu on kaksi tasoa korkeampi kuin toisen Puuta täytyy siis tasapainottaa, jotta AVL-ominaisuus pätee jälleen Tehdään tämä alhaalta ylöspäin alkaen solmun p vanhemmasta p (AVL-ominaisuus pätee jo solmun p alipuussa; miksi?) 34/53
Näytetään yleisesti, kuinka voidaan AVL-tasapainottaa solmun x alipuu, missä toisen lapsen y alipuun korkeus on h + 2 kun taas toisen lapsen alipuun korkeus on h Oletetaan nämä lapset jo tasapainoisiksi eli AVL-ominaisuus pätee niiden alipuissa Tasapainotuksen jälkeen AVL-ominaisuus pätee uudessa alipuussa Koska uuden alipuun korkeus on voinut kasvaa yhdellä avaimen lisäyksen jälkeen, pitää tasapainotuksen jälkeen tarkastaa (rekursiivisesti) tarvitseeko solmun x vanhemman alipuuta tasapainottaa myös Esitetään seuraavassa tasapainotus vain tapauksille, missä korkeamman alipuun solmu y on solmun x oikea lapsi. Vasemman lapsen tapaus on symmetrinen tämän kanssa. 35/53
Tapaus I: y on kallellaan oikealle Solmun y alipuun korkeus on h + 2 mutta solmun x vasemman alipuun korkeus on h Solmun y oikean alipuun korkeus on h + 1 ja vasemman h Jos kierretään solmua x vasemmalle, saatavan uuden alipuun juuri on nyt y ja AVL-ominaisuus pätee siinä x y h + 2 h y h + 2 rotate x left x h + 1 h + 1 subtree 1 h h + 1 h h subtree 3 subtree 2 subtree 3 subtree 1 subtree 2 36/53
Esimerkki: Tarkastellaan vasemmanpuoleista AVL-puuta. 9 2 9 2 9 2 9 2 9 2 9 2 8 0 12 1 8 0 12 1 8 0 12 1 8 0 x 12 2 8 0 17 1 8 0 17 1 17 0 17 0 17 1 y 17 1 12 0 19 0 12 0 19 0 19 0 19 0 19 0 Kun siihen lisätään avain 19, 1. lisätään ensin uusi avaimen omaava lehtisolmu korkeudelle 0 2. sen vanhempi on tasapainoinen, päivitetään korkeudeksi 1 3. seuraava vanhempi x ei ole tasapainoinen (vasemman lapsen alipuun korkeus on -1 ja oikean on 1) ja sen oikea, solmun y alipuu on kallellaan oikealle kierretään solmua x vasemalle ja saadaan alipuu tasapainoon 4. seuraava vanhempi eli juuri on tasapainoinen 37/53
Tapaus II: y ei ole kallellaan Solmun y alipuun korkeus on h + 2 mutta solmun x vasemman alipuun korkeus on h Solmun y vasemman ja oikean alipuun korkeus on h + 1 Kiertämällä jälleen solmua x vasemmalle saadaan uusi alipuu, jonka juuri on solmu y ja jossa AVL-ominaisuus pätee x y h + 3 h y h + 2 rotate x left x h + 2 h + 1 subtree 1 h + 1 h + 1 h h + 1 subtree 3 subtree 2 subtree 3 subtree 1 subtree 2 38/53
Tapaus III: y on kallellaan vasemmalle Solmun y alipuun korkeus on h + 2 mutta solmun x vasemman alipuun korkeus on h Solmun y vasemman alipuun korkeus on h + 1 ja oikean h Kierretään ensin solmua y oikealle ja saadaan solmun x oikeasta alipuusta oikealle kallellaan oleva. Tämän jälkeen toimitaan kuten tapauksessa I eli kierretään solmua x vasemmalle. h x rotate y right y h + 2 x h z h + 2 subtree 1 z h + 1 h subtree 1 h y h + 1 h h subtree 3 subtree 2a h h subtree 2a subtree 2b subtree 2b subtree 3 rotate x left z h + 2 x h + 1 y h + 1 h h h h subtree 1 subtree 2a subtree 2b subtree 3 39/53
Esimerkki: Tarkastellaan alla vasemmalla olevaa AVL-puuta 9 2 9 2 9 2 9 2 9 2 9 2 8 0 12 1 8 0 12 1 8 0 12 1 8 0 x 12 2 8 0 x 12 2 8 0 15 1 17 0 17 0 17 1 y 17 1 15 1 12 0 17 0 Lisätään avain 15: 15 0 15 0 z 15 0 1. lisätään ensin lehtisolmu avaimella ja korkeudella 0, 2. lehden vanhempi on tasapainoinen, päivitetään korkeudeksi 1 3. seuraava vanhempi x ei ole tasapainoinen (sen vasen alipuu on tyhjä eli korkeus on -1 ja oikean alipuun korkeus on 1) ja tämän oikea solmun y alipuu on kallellaan vasemmalle; kierretään ensin solmua y vasemmalle, jotta x: oikeasta alipuu on kallellaan oikealle ja 4. sitten kierretään solmua x vasemmalle ja saadaan uusi alipuu tasapainoon 5. seuraava vanhempi eli juuri on jo tasapainoinen 17 0 40/53
Esimerkki: Tarkastellaan vasemmanpuoleista AVL-puuta. 9 2 9 2 x 9 3 x 9 3 12 2 8 0 15 1 8 0 15 1 8 0 y 15 2 8 0 12 2 9 1 15 1 12 0 17 0 12 0 17 0 z 12 1 17 0 15 1 8 0 14 0 17 0 14 0 Lisätään siihen avain 14. 14 0 1. Ensin lisätään uusi lehtisolmu avaimella. 14 0 17 0 2. Uuden solmun vanhempi z ja tämän vanhempi y ovat kumpikin tasapainoisia. Mutta seuraava vanhempi eli juuri x ei ole tasapainoinen (vasemman alipuun korkeus on 0 ja oikean 2) ja oikea alipuu on kallellaan vasemmalle. 3. Kierretään solmua y oikealle, jotta solmun x oikea alipuu on oikealle kallellaan. 4. Kierretään solmua x vasemmalle ja saadaan koko puu tasapainoiseksi. 41/53
Avainten poistaminen Alussa toimitaan kuten tasapainottomien puiden tapauksessa Kun on poistettu solmu, niin sen vanhemman ja muiden edeltäjien korkeus voi pienentyä yhdellä Tällöin voi jälleen syntyä korkeintaan kahden suuruista epätasapainoa solmujen alupuiden välille ja voidaan käyttää edellä kuvattuja tasapainotusmenetelmiä AVL-ominaisuuden palauttamiseksi 42/53
Esimerkki: Tarkastellaan vasemman puoleista AVL-puuta. 15 3 x 15 3 10 2 10 2 z 20 1 y 10 2 17 0 8 1 15 1 8 1 12 0 w 17 0 8 1 12 0 4 0 12 0 17 0 4 0 Poistettaessa avain 20, 4 0 poistetaan solmu z ja laitetaan solmu w sen paikalle huomataan, että vanhempi eli solmu x on nyt epätasapainoinen ja että sen vasen alipuu on kallellaan vasemmalle kierretään solmua x oikealle ja saadaan puu jälleen tasapainoiseksi 43/53
Punamustat puut 44/53
Eräs toinen tasapainoisten hakupuiden luokka Vain yksi väribitti lisätietoa per solmu Toteutettu useassa standardikirjastossa, esim Scalassa a TreeMap on muuttumaton järjestettyjen kuvausten luokka, joka käyttää punamustia puita lähdekoodi luokille TreeMap ja RedBlackTree Javassa java.util.treemap toteuttaa muuttuvatilaiset järjestetyt kuvaukset punamustien puiden avulla. Vastaavasti java.util.treeset käyttää TreeMap-luokkaa järjestettyjen joukkojen toteuttamiseen. erään toteutuksen lähdekoodi Eräs visualisointityökalu punamustille puille 45/53
Määritelmä Hakupuu on punamusta puu jos 1. Sen jokainen solmu on väritetty joko punaiseksi tai mustaksi 2. Juurisolmu on musta 3. Jos solmu on punainen, niin kummatkin sen lapsista ovat mustia 4. Jokaiselle sen solmuista pätee, että jokainen polku solmusta mihin tahansa jälkeläislehteen sisältää saman määrän mustia solmuja Esimerkki: vasemmalla: punamusta puu keskellä: vaatimus 3 ei päde oikealla: vaatimus 4 ei päde 34 34 34 21 40 21 40 21 40 12 27 37 50 12 27 37 50 12 27 37 50 10 10 24 28 10 24 28 46/53
Punaiset solmut sallivat tietyn määrän epätasapainoa mutta eivät liikaa koska millään polulla ei voi olla kahta punaista solmua peräkkäin Lause 13.1 kirjassa Cormen et al Jos punamustassa puussa on n solmua, niin sen korkeus on korkeintaan 2log 2 (n + 1). Koska punamustat puut ovat hakupuita, avainten etsiminen ja läpikäynti toimii kuten hakupuilla yleensäkin Täten avaimen etsiminen sekä edeltäjä- ja seuraaja-avainten etsiminen ovat logaritmisen ajan operaatioita punamustissa puissa 47/53
Kuten AVL-puidenkin tapauksessa, pitää enää näyttää kuinka punamustia puita voidaan muokata lisäämällä ja poistamalla avaimia Jälleen toimitaan kuten hakupuissa yleensäkin mutta solmun lisäyksen tai poiston jälkeen uudelleentasapainotetaan puu mikäli punamustan puun vaatimukset eivät päde muutoksen jälkeen 48/53
Avainten lisääminen Ensin toimitaan kuten perushakupuilla eli lisätään uusi lehtisolmu Uusi lehti on aluksi punainen 1. Jos sen vanhempi on musta, puu on edelleen punamusta puu ja lisäys on valmis 2. Jos vanhempi on punainen, vaatimus 3 ei päde ja pitää tasapainottaa Yleisemminkin seuraavssa oletetaan, että solmu z on juuri väritetty punaiseksi ja sen vanhempi p on myös punainen ja sitten tasapainotetaan puuta ylöspäin kunnes se on taas punamusta puu Esityksen yksinkertaistamiseksi esitetään vain tapaus, jossa z on vanhempansa vasen lapsi. Oikean lapsen tapaus on symmetrinen. 49/53
Tapaus I Myös solmun p sisarus u (u on solmun z setä eli uncle ) on punainen Alipuut solmuissa c 1, c 2, b, u 1 ja u 2 ovat punamustia puita, joissa jokainen polku lehteen sisältää k mustaa solmua g g p u p u z b u 1 u 2 z b u 1 u 2 c 1 c 2 c 1 c 2 Väritetään g punaiseksi ja p sekä u mustiksi Solmun g alipuu on nyt muutoin punamusta puu paitsi sen juuri on punainen kaikki polut lehtiin sisältävät k + 1 mustaa solmua kuten ennen uudelleenväritystäkin Jos g on koko puun juuri, väritetään se mustaksi ja lopetetaan Muutoin jatketaan tasapainottamista ylöspäin jos solmun g vanhempi on punainen 50/53
Tapaus II Solmun p sisarus u on musta ja Solmu z on solmun p vasen lapsi Solmujen c 1, c 2, b ja u alipuut ovat punamustia puita, joissa kaikki polut lehtiin sisältävät k mustaa solmua g p p u z g z b c 1 c 2 b u c 1 c 2 Kierretään solmua g oikealle ja väritetään p mustaksi ja g punaiseksi Uusi solmun p alipuu on punamusta puu ja kaikki sen polut sisältävät saman määrän k + 1 mustia solmuja kuin solmusta g ennen kiertämistä ja uudelleenvärittämistä Tasapainotus on nyt tehty 51/53
Tapaus III Solmun p sisarus u on musta ja solmu z on solmun p oikea lapsi Solmujen c 1, c 2, b ja u alipuut ovat punamustia puita, joissa kaikki polut lehtiin sisältävät k mustaa solmua g g z rotate p left rotate g right p u z u p g b z p c2 b c1 c2 u c1 c2 b c1 Kierretään solmua p vasemmalle Kierretään solmua g oikealle ja väritetään z mustaksi ja g punaiseksi Uusi solmun z alipuu on punamusta puu ja kaikki sen polut sisältävät saman määrän k + 1 mustia solmuja kuin solmusta g ennen kiertämistä ja uudelleenvärittämistä Tasapainotus on nyt tehty 52/53
Avainten poistaminen Avainten poistaminen on hieman monimutkaisempaa Perusprosessi on samanlainen kuin perushakupuilla Jos poistettava solmu on punainen, punamustan puun ominaisuudet säilyvät eikä tarvetta tasapainottamiselle ole Mustaa solmua poistettaessa alipuun polkujen mustien solmujen määrä laskee yhdellä ja voidaan joutua tasapainottamaan puuta Yksityiskohdat esitetty kappaleessa 13.4 kirjassa Introduction to Algorithms, 3rd ed. (online via Aalto lib), eivät kuulu kurssin sisältöön 53/53