9.3 Algoritmin valinta

Samankaltaiset tiedostot
1.1 Tavallinen binäärihakupuu

1 Erilaisia tapoja järjestää

Hakupuut. tässä luvussa tarkastelemme puita tiedon tallennusrakenteina

Algoritmit 2. Luento 4 To Timo Männikkö

Algoritmit 2. Luento 3 Ti Timo Männikkö

Algoritmit 2. Luento 4 Ke Timo Männikkö

Algoritmit 2. Luento 3 Ti Timo Männikkö

4 Tehokkuus ja algoritmien suunnittelu

Algoritmit 2. Luento 2 To Timo Männikkö

Algoritmit 1. Luento 7 Ti Timo Männikkö

Algoritmit 2. Luento 2 Ke Timo Männikkö

14 Tasapainotetut puurakenteet

A TIETORAKENTEET JA ALGORITMIT

Pinot, jonot, yleisemmin sekvenssit: kokoelma peräkkäisiä alkioita (lineaarinen järjestys) Yleisempi tilanne: alkioiden hierarkia

Algoritmit 2. Luento 6 To Timo Männikkö

AVL-puut. eräs tapa tasapainottaa binäärihakupuu siten, että korkeus on O(log n) kun puussa on n avainta

Algoritmit 2. Luento 7 Ti Timo Männikkö

(a) L on listan tunnussolmu, joten se ei voi olla null. Algoritmi lisäämiselle loppuun:

1 Puu, Keko ja Prioriteettijono

811312A Tietorakenteet ja algoritmit V Hash-taulukot ja binääriset etsintäpuut

TKT20001 Tietorakenteet ja algoritmit Erilliskoe , malliratkaisut (Jyrki Kivinen)

Tehtävän V.1 ratkaisuehdotus Tietorakenteet, syksy 2003

Algoritmit 2. Luento 5 Ti Timo Männikkö

Algoritmit 1. Luento 6 Ke Timo Männikkö

3. Hakupuut. B-puu on hakupuun laji, joka sopii mm. tietokantasovelluksiin, joissa rakenne on talletettu kiintolevylle eikä keskusmuistiin.

9 Erilaisia tapoja järjestää

Algoritmit 2. Luento 6 Ke Timo Männikkö

811312A Tietorakenteet ja algoritmit II Perustietorakenteet

Algoritmit 2. Luento 5 Ti Timo Männikkö

811312A Tietorakenteet ja algoritmit, , Harjoitus 5, Ratkaisu

Miten käydä läpi puun alkiot (traversal)?

v 1 v 2 v 3 v 4 d lapsisolmua d 1 avainta lapsen v i alipuun avaimet k i 1 ja k i k 0 =, k d = Sisäsolmuissa vähint. yksi avain vähint.

Algoritmit 2. Luento 14 Ke Timo Männikkö

Binäärihaun vertailujärjestys

Algoritmit 1. Luento 8 Ke Timo Männikkö

58131 Tietorakenteet ja algoritmit (kevät 2016) Ensimmäinen välikoe, malliratkaisut

58131 Tietorakenteet ja algoritmit (kevät 2013) Kurssikoe 1, , vastauksia

1.1 Pino (stack) Koodiluonnos. Graafinen esitys ...

Tietorakenteet, laskuharjoitus 7, ratkaisuja

Hajautus. operaatiot insert ja search pyritään tekemään erittäin nopeiksi

4. Joukkojen käsittely

58131 Tietorakenteet (kevät 2008) 1. kurssikoe, ratkaisuja

Algoritmi on periaatteellisella tasolla seuraava:

Algoritmit 1. Luento 12 Ke Timo Männikkö

Tietorakenteet ja algoritmit Johdanto Lauri Malmi / Ari Korhonen

5 Kertaluokkamerkinnät

811312A Tietorakenteet ja algoritmit, , Harjoitus 5, Ratkaisu

Tietorakenteet ja algoritmit - syksy

Algoritmit 1. Luento 12 Ti Timo Männikkö

Algoritmit 1. Luento 4 Ke Timo Männikkö

Tietorakenteet, laskuharjoitus 6,

58131 Tietorakenteet ja algoritmit Uusinta- ja erilliskoe ratkaisuja (Jyrki Kivinen)

811312A Tietorakenteet ja algoritmit, , Harjoitus 7, ratkaisu

Algoritmit 1. Luento 1 Ti Timo Männikkö

58131 Tietorakenteet Erilliskoe , ratkaisuja (Jyrki Kivinen)

Algoritmit 2. Demot Timo Männikkö

Algoritmit 1. Luento 5 Ti Timo Männikkö

Tämä on helpompi ymmärtää, kun tulkitaan keko täydellisesti tasapainotetuksi binääripuuksi, jonka juuri on talletettu taulukon paikkaan

Koe ma 1.3 klo salissa A111, koeaika kuten tavallista 2h 30min

811312A Tietorakenteet ja algoritmit Kertausta kurssin alkuosasta

Tietorakenteet ja algoritmit

2. Seuraavassa kuvassa on verkon solmujen topologinen järjestys: x t v q z u s y w r. Kuva 1: Tehtävän 2 solmut järjestettynä topologisesti.

Algoritmit 1. Luento 3 Ti Timo Männikkö

lähtokohta: kahden O(h) korkuisen keon yhdistäminen uudella juurella vie O(h) operaatiota vrt. RemoveMinElem() keossa

Tiraka, yhteenveto tenttiinlukua varten

Ohjelmoinnin perusteet Y Python

A TIETORAKENTEET JA ALGORITMIT KORVAAVAT HARJOITUSTEHTÄVÄT 3, DEADLINE KLO 12:00

TKHJ:ssä on yleensä komento create index, jolla taululle voidaan luoda hakemisto

Algoritmit 2. Luento 9 Ti Timo Männikkö

Algoritmit 1. Luento 14 Ke Timo Männikkö

811312A Tietorakenteet ja algoritmit III Lajittelualgoritmeista

Kierros 4: Binäärihakupuut

f(n) = Ω(g(n)) jos ja vain jos g(n) = O(f(n))

CS-A1140 Tietorakenteet ja algoritmit

Algoritmit 2. Luento 8 To Timo Männikkö

Algoritmit 1. Luento 11 Ti Timo Männikkö

A ja B pelaavat sarjan pelejä. Sarjan voittaja on se, joka ensin voittaa n peliä.

58131 Tietorakenteet (kevät 2009) Harjoitus 6, ratkaisuja (Antti Laaksonen)

ALGORITMIT 1 DEMOVASTAUKSET KEVÄT 2012

7. Tasapainoitetut hakupuut

13 Lyhimmät painotetut polut

B + -puut. Kerttu Pollari-Malmi

1.4 Funktioiden kertaluokat

811312A Tietorakenteet ja algoritmit , Harjoitus 2 ratkaisu

TIE Tietorakenteet ja algoritmit 261

811312A Tietorakenteet ja algoritmit, , Harjoitus 3, Ratkaisu

1. (a) Seuraava algoritmi tutkii, onko jokin luku taulukossa monta kertaa:

58131 Tietorakenteet (kevät 2009) Harjoitus 11, ratkaisuja (Topi Musto)

private TreeMap<String, Opiskelija> nimella; private TreeMap<String, Opiskelija> numerolla;

Algoritmit 1. Demot Timo Männikkö

Algebralliset tietotyypit ym. TIEA341 Funktio ohjelmointi 1 Syksy 2005

Algoritmit 1. Luento 9 Ti Timo Männikkö

Algoritmit 1. Luento 10 Ke Timo Männikkö

58131 Tietorakenteet ja algoritmit Uusinta- ja erilliskoe malliratkaisut ja arvosteluperusteet

Hajautusrakenteet. R&G Chapter Tietokannan hallinta, kevät 2006, Jan 1

5. Hajautus. Tarkastellaan edelleen sivulla 161 esitellyn joukkotietotyypin toteuttamista

A TIETORAKENTEET JA ALGORITMIT

Hajautusrakenteet. Hajautukseen perustuvat tiedostorakenteet. Hajautukseen perustuvat tiedostorakenteet. Hajautukseen perustuvat tiedostorakenteet

Datatähti 2019 loppu

5. Keko. Tietorakenne keko eli kasa (heap) on tehokas toteutus abstraktille tietotyypille prioriteettijono, jonka operaatiot ovat seuraavat:

Transkriptio:

TIE-20100 Tietorakenteet ja algoritmit 218 9.3 Algoritmin valinta Merkittävin algoritmin valintaan vaikuttava tekijä on yleensä sen suorituskyky käyttötilanteessa. Muitakin perusteita kuitenkin on: toteutuksen helppous onko valmiina saatavilla sopivaa algoritmia? onko tehokkuuden parannuksesta saatava lisähyöty monimutkaisemman algoritmin toteuttamisen tuottavan lisätyön arvoinen? yksinkertaisen algoritmin toteutukseen ei ehkä jää yhtä helposti virheitä yksinkertaista ratkaisua on helpompi ylläpitää tulosten tarkkuus liukuluvuilla laskettaessa pyöristysvirheiden kertyminen saattaa olla merkittävä ongelma suoritusajan vaihtelu voi olla tärkeämpää tietää, kuinka kauan algoritmilla menee

TIE-20100 Tietorakenteet ja algoritmit 219 esim. usein signaalinkäsittelyssä suoritusaika ei saa vaihdella yhtään Myös ohjelmointiympäristö saattaa asettaa rajoituksia: monet kielet vaativat, että taulukoille määritellään maksimikoko taulukoihin perustuville algoritmeille tulee käännösaikainen, keinotekoinen yläraja listarakenteilla saadaan algoritmi toimimaan niin kauan, kuin koneessa riittää muistia listarakenteilla muisti voi loppua yllättäen, kiinteillä taulukoilla ei listarakenteet eivät aina sopivia esim. sulautettuihin sovelluksiin joissain ympäristöissä rekursiolle varattu muistitila on paljon pienempi kuin muu datatila jos muistia kulutetaan paljon, on valittava ei-rekursiivinen algoritmi (tai toteutus)

TIE-20100 Tietorakenteet ja algoritmit 220 Mikäli suorituskykyä päätetään pitää primaarisena valintaperusteena, kannattaa pohtia ainakin seuraavia asioita: Onko syöteaineisto niin iso, että asymptoottinen tehokkuus antaa oikean kuvan suorituskyvystä? Saako hitain tapaus olla hidas, jos keskimääräinen suorituskyky on hyvä? Onko muistin käyttö olennainen tekijä? Onko syöteaineistossa säännöllisyyttä, jota voidaan käyttää hyväksi yhdellä ajokerralla? usealla ajokerralla? Onko syöteaineistossa säännöllisyyttä, joka aiheuttaa huonoimman tapauksen realisoitumisen usein jollakin algoritmilla?

TIE-20100 Tietorakenteet ja algoritmit 221 Esimerkki: yhteystiedot operaatiot numeron kysely nimen perusteella uuden kontaktin liittäminen luetteloon vanhan kontaktin poisto oletuksia lisäyksiä ja poistoja tehdään harvoin kyselyjä tehdään usein lisäykset ja poistot tulevat ryhminä Rajoitus: käytössämme on vain taulukkorakenne

TIE-20100 Tietorakenteet ja algoritmit 222 1. yritelmä: järjestämätön taulukko Virtanen Järvinen Lahtinen 123 555 123 111 123 444 1 2 n Lisätään uudet tilaajat loppuun: O(1). Etsitään selaamalla alusta (tai lopusta): O(n). Poistetaan siirtämällä viimeinen alkio poistettavan päälle: O(1) + etsintäkulut = O(n). Ratkaisu ei ole hyvä, koska usein tarvittavat operaatiot ovat hitaita.

TIE-20100 Tietorakenteet ja algoritmit 223 2. yritelmä: järjestetty taulukko, 1. versio Lisätään uudet tilaajat suoraan järjestyksen mukaiseen paikkaan, ja siirretään loppuja alkioita taaksepäin: O(n). Poistetaan siirtämällä loppuja alkioita eteenpäin O(n). Käytetään etsinnässä puolitushakua: O(lgn). Nyt usein käytetty etsintä on tehokas, mutta poisto on edelleen hidas, samoin lisäys. Ratkaisu vaikuttaa kuitenkin paremmalta kuin ensimmäinen yritelmä, mikäli alkuperäinen oletuksemme siitä, että hakuja tapahtuu selvästi useammin kuin lisäyksiä ja poistoja, pitää paikkansa.

TIE-20100 Tietorakenteet ja algoritmit 224 3. yritelmä: melkein järjestetty taulukko Pidetään suurin osa taulukosta järjestettynä, lopussa pieni järjestämätön alue (koko l). vertaa puhelinluettelo + lisälehdet Lisäykset tehdään loppualueelle: O(1). Etsintä tapahtuu ensin puolitushaulla järjestyksessä olevasta alkuosasta ja tarvittaessa selaamalla loppuosasta: O(lg n) + O(l). Poisto suoritetaan jättämällä nimi paikalleen ja asettamalla numeroksi 0: O(1) + etsintäkulut = O(lg n) + O(l). Kun loppualue on kasvanut liian suureksi, järjestetään koko taulukko: Θ(n lg n). Kohtalainen ratkaisu, mutta Θ(l) voi olla iso ajoittainen järjestäminen maksaa

TIE-20100 Tietorakenteet ja algoritmit 225 4. yritelmä: järjestetty taulukko, 2. versio Hyödynnetään tietoa siitä, että poistot ja lisäykset tulevat ryhminä. Järjestetään lisättävien ja poistettavien ryhmät. Lomitetaan (samaan tapaan kuin MERGE) taulukko ja lisättävien ryhmä siten, että samalla poistetaan poistettavien ryhmään kuuluvat. Nyt haku on edelleen logaritmista. Lisäys- ja poistotoimenpide kuluttaa aikaa O(l lg l) + O(p lg p) + O(n), kun l on lisättävien määrä ja p poistettavien määrä. Melko hyvä ratkaisu! Seuraavaksi käydään tällaisten ongelmien kanssa hyödyllisten tietorakenteiden kimppuun. Ongelman ratkaisemiseksi voitaisiin siis käyttää ns. dynaamisten säiliöitä/joukkoja

TIE-20100 Tietorakenteet ja algoritmit 226 10 Kannattaako data pitää järjestyksessä? Kun ongelmassa tarvitaan järjestystietoa, yksi mieleenjuolahtava idea yleensä on pitää tieto järjestyksessä sitä mukaan, kun sitä lisätään tietorakenteeseen. Onko tämä siis tehokas tapa lähestyä järjestystietoa tarvitsevia ongelmia? 7 2 5 9 15 42

TIE-20100 Tietorakenteet ja algoritmit 227 järjestetyn tietojoukon selaaminen voidaan lopettaa, kun on kohdattu etsittyä suurempi riittää selata keskimäärin puolet alkioista selaaminen nopeutuu vakiokertoimen verran lisäyksessä on ensin etsittävä oikea paikka eli tietoalkioita on selattava läpi lisäys keskelle tietojoukkoa on Θ(n) koko tietojoukon lisäyksestä tulee Θ(n 2 )

TIE-20100 Tietorakenteet ja algoritmit 228 järjestyksessä pitäminen ei yleensä kannata, ellei rakenteen käyttötarkoitus hyödy siitä ja voidaan käyttää rakennetta, johon lisäys keskelle voidaan tehdä vakioajassa. jos sama avain ei saa esiintyä kuin kerran niin lisäys edellyttää selausta joka tapauksessa järjestyksessä pitäminen muuttuu kannattavaksi kunhan vakioaikainen keskelle lisääminen on rakenteessa mahdollista

TIE-20100 Tietorakenteet ja algoritmit 229 10.1 Hajautustaulu Hajautustaulun ideana on tiivistää dynaamisen joukon avainten arvoalue pienemmäksi hajautusfunktion (hash function) h avulla, siten että ne voidaan tallettaa taulukkoon. taulukon etuna on sen tarjoama tehokas vakioaikainen indeksointi N=30000 111222 13579 111222 567135 123456 201304 h(k) 567135 13579 123456 201304 121212 121212

TIE-20100 Tietorakenteet ja algoritmit 230 Avainten arvoalueen tiivistämisestä seuraa kuitenkin ongelma: törmäykset. useampi kuin yksi alkio voi hajautua samaan hajautustaulun lokeroon Tavallisin tapa ratkaista ongelma on ketjuttaminen (chaining). samaan lokeroon hajautuvat alkiot talletetaan listoihin muitakin ratkaisutapoja on avoimen osoituksen käsittelytavalla alkio laitetaan sekundääriseen lokeroon, mikäli primäärinen ei ole vapaana joissakin tapauksissa avainten arvoalue on niin pieni, että arvoalueen tiivistämistä ei tarvita, eikä siis synny törmäyksiäkään tällainen suoraosoitustaulu (direct-access table) on hyvin yksinkertainen ja tehokas tällä kurssilla kuitenkin käsitellään ainoastaan ketjutettuja hajautustauluja

TIE-20100 Tietorakenteet ja algoritmit 231 Alla oleva kuva esittää ketjutettua hajautustaulua, jonka avaimet on hajautettu etukirjaimen mukaan viereisen taulukon avulla. Onko tämä hyvä hajautus? Ei. Katsotaan seuraavaksi, miksei. h(k) alkukirjain 0 H P X 1 A I Q Y 2 B J R Z 3 C K S Ä 4 D L T Ö 5 E M U Å 6 F N V 7 G O W

TIE-20100 Tietorakenteet ja algoritmit 232 Ketjutettu hajautustaulu tarjoaa ainoastaan sanakirjan operaatiot, mutta ne ovat hyvin yksinkertaisia: CHAINED-HASH-SEARCH(T, k) etsi listasta T [h(k)] alkio, jonka avain on k CHAINED-HASH-INSERT(T, x) lisää x listan T [h(x key)] alkuun CHAINED-HASH-DELETE(T, x) poista x listasta T [h(x key)]

TIE-20100 Tietorakenteet ja algoritmit 233 Suoritusajat: lisäys: Θ(1) etsintä: hitaimmassa tapauksessa Θ(n) poisto: jos lista kaksisuuntainen, niin Θ(1); yksisuuntaisella hitaimmillaan Θ(n), koska poistettavan edeltäjä on ensin etsittävä listasta käytännössä ero ei kuitenkaan ole kovin merkittävä, koska yleensä poistettava alkio joudutaan joka tapauksessa etsimään listasta Ketjutetun hajautustaulun operaatioiden keskimääräiset suoritusajat riippuvat listojen pituuksista.

TIE-20100 Tietorakenteet ja algoritmit 234 huonoimmassa tapauksessa kaikki alkiot joutuvat samaan listaan jolloin suoritusajat ovat Θ(n) keskimääräisen tapauksen selville saamiseksi käytämme seuraavia merkintöjä: m = hajautustaulun koko n = alkioiden määrä taulussa α = n m = täyttöaste (load factor) eli listan keskimääräinen pituus lisäksi keskimääräisen suoritusajan arvioimiseksi on tehtävä oletus siitä, miten hyvin h hajauttaa alkiot jos esim. h(k) = nimen alkukirjaimen 3 ylintä bittiä, niin kaikki osuvat samaan listaan usein oletetaan että, jokaisella alkiolla on yhtä suuri todennäköisyys osua mihin tahansa lokeroon tasainen hajautus (simple uniform hashing) oletetaan myös, että h(k):n laskenta kuluttaa Θ(1) aikaa

TIE-20100 Tietorakenteet ja algoritmit 235 jos etsitään alkiota, jota ei ole taulussa, niin joudutaan selaamaan koko lista läpi joudutaan tutkimaan keskimäärin α alkiota suoritusaika keskimäärin Θ(1 + α) jos oletetaan, että listassa oleva avain on mikä tahansa listan alkio samalla todennäköisyydellä, joudutaan listaa selamaan etsinnän yhteydessä keskimäärin puoleen väliin siinäkin tapauksessa, että avain löytyy listasta suoritusaika keskimäärin Θ(1 + α 2 ) = Θ(1 + α) jos täyttöaste pidetään alle jonkin kiinteän rajan (esim. α < 50 %), niin Θ(1 + α) = Θ(1) ketjutetun hajautustaulun kaikki operaatiot voi toteuttaa keskimäärin ajassa Θ(1) tämä edellyttää, että hajautustaulun koko on samaa luokkaa kuin sinne talletettavien alkioiden määrä

TIE-20100 Tietorakenteet ja algoritmit 236 Laskiessamme keskimääräistä suoritusaikaa oletimme, että hajautusfunktio hajauttaa täydellisesti. Ei kuitenkaan ole mitenkään itsestään selvää, että näin tapahtuu. Hajautusfunktion laatu on kriittisin tekijä hajautustaulun suorituskyvyn muodostumisessa. Hyvän hajautusfunktion ominaisuuksia: hajautusfunktion on oltava deterministinen muutoin kerran tauluun pantua ei välttämättä enää koskaan löydetä! tästä huolimatta olisi hyvä, että hajautusfunktion arvo olisi mahdollisimman satunnainen kuhunkin lokeroon tulisi osua mahdollisimman tarkasti 1 m avaimista

TIE-20100 Tietorakenteet ja algoritmit 237 valitettavasti täysin tasaisesti hajottavan hajautusfunktion teko on useinmiten mahdotonta eri arvojen esiintymistodennäköisyydet aineistossa ovat yleensä tuntemattomia aineisto ei yleensä ole tasaisesti jakautunut lähes mikä tahansa järkevä hajautusfunktio jakaa tasaisesti jakautuneen aineiston täydellisesti yleensä hajautusfunktio pyritään muodostamaan siten, että se sotkee tehokkaasti kaikki syöteaineistossa luultavasti esiintyvät säännönmukaisuudet esimerkiksi nimien tapauksessa ei katsota yksittäisiä kirjaimia, vaan otetaan jotenkin huomioon nimen kaikki bitit

TIE-20100 Tietorakenteet ja algoritmit 238 esittelemme kaksi yleistä usein hyvin toimivaa hajautusfunktion luontimenetelmää oletamme, että avaimet ovat luonnollisia lukuja 0, 1, 2,... jollei näin ole, avain voidaan usein tulkita luonnolliseksi luvuksi esim. nimen saa luvuksi muuttamalla kirjaimet numeroiksi ASCII-koodiarvon mukaan, ja laskemalla ne sopivasti painottaen yhteen

TIE-20100 Tietorakenteet ja algoritmit 239 Hajautusfunktion luonti jakomenetelmällä on yksinkertaista ja nopeaa. h(k) = k mod m sitä kannattaa kuitenkin käyttää vain, jos m:n arvo on sopiva esim. jos m = 2 b jollekin b N = {0, 1, 2,...}, niin h(k) = k:n b alinta bittiä funktio ei edes katso kaikkia k:n bittejä funktio todennäköisesti hajauttaa huonosti, jos avaimet ovat peräisin binäärijärjestelmästä

TIE-20100 Tietorakenteet ja algoritmit 240 samasta syystä tulee välttää m:n arvoja muotoa m = 10 b, jos avaimet ovat peräisin kymmenjärjestelmän luvuista jos avaimet ovat muodostetut tulkitsemalla merkkijono 128-järjestelmän luvuksi, niin m = 127 on huono valinta, koska silloin saman merkkijonon kaikki permutaatiot osuvat samaan lokeroon hyviä m:n arvoja ovat yleensä alkuluvut, jotka eivät ole lähellä 2:n potensseja esim. halutaan 700 listaa 701 kelpaa kannattaa tarkistaa kokeilemalla pienellä oikealla aineistolla, hajauttaako funktio avaimet tehokkaasti

TIE-20100 Tietorakenteet ja algoritmit 241 Hajautusfunktion luonti kertomenetelmällä ei aseta suuria vaatimuksia m:n arvolle. valitaan vakio A siten, että 0 < A < 1 h(k) = m(ka ka ) jos m = 2 b, koneen sanapituus on w, ja k ja 2 w A mahtuvat yhteen sanaan, niin h(k) voidaan laskea helposti seuraavasti: h(k) = (((2w A) k) mod 2 w ) 2 w b mikä arvo A:lle tulisi valita? kaikki A:n arvot toimivat ainakin jollain lailla kuulemma A 5 1 2 toimii usein aika hyvin

TIE-20100 Tietorakenteet ja algoritmit 242 11 Binäärihakupuu http://imgur.com/l77fy5x Tässä luvussa käsitellään erilaisia yleisiä puurakenteita. Ensin opitaan, millainen rakenne on binäärihakupuu, ja tasapainotetaan binäärihakupuu muuttamalla se puna-mustaksi puuksi. Sitten tutustutaan monihaaraisiin puihin: merkkijonopuu Trie ja B-puu. Lopuksi vilkaistaan splay- ja AVL-puita.

TIE-20100 Tietorakenteet ja algoritmit 243 11.1 Tavallinen binäärihakupuu Kertauksena: Binääripuu (binary tree) on äärellinen solmuista (node) koostuva rakenne, joka on joko tyhjä, tai sisältää yhden solmun nimeltä juuri (root), sekä kaksi binääripuuta nimeltä vasen alipuu (left subtree) ja oikea alipuu (right subtree). Kuva 14: Kertaus: Binääripuu

TIE-20100 Tietorakenteet ja algoritmit 244 Lisäksi määritellään: Lapseton solmu: lehti (leaf ). Muut solmut sisäsolmuja. Solmu on lastensa isä (parent) ja solmun esi-isiä (ancestor) ovat solmu itse, solmun isä, tämän isä jne. Jälkeläinen vastaavasti. (descendant) sisäsolmuja 18 13 25 lehtiä juuri 8 15 22 30 5 9 14 23 26 33 3 6 32 35

TIE-20100 Tietorakenteet ja algoritmit 245 Binäärihakupuu (binary search tree) on binääripuu, jonka kaikille solmuille x pätee: Jos l on mikä tahansa solmu x:n vasemmassa alipuussa ja r mikä tahansa solmu x:n oikeassa alipuussa, niin l.key x.key r.key Edellisen sivun binääripuu on binäärihakupuu Luvussa 8.2 esitelty kekorakenne on binääripuu muttei binäärihakupuu Useinmiten binäärihakupuu esitetään linkitettynä rakenteena, jossa jokaisessa alkiossa on kentät avain (key), vasen lapsi (left), oikea lapsi (right) ja vanhempi (p (parent)). Lisäksi alkiolla on oheisdataa.

TIE-20100 Tietorakenteet ja algoritmit 246 Kuva 15: Hakupuita

TIE-20100 Tietorakenteet ja algoritmit 247 Avaimen haku binäärihakupuusta : koko puusta haku R-TREE-SEARCH(T.root, k) palauttaa osoittimen x solmuun, jolle x key = k, tai NIL, jos tällaista solmua ei ole R-TREE-SEARCH(x, k) 1 if x = NIL or k = x key then 2 return x (etsitty avain löytyi) 3 if k < x key then (jos etsitty on pienempi kuin avain...) 4 return R-TREE-SEARCH(x left, k) (...etsitään vasemmasta alipuusta) 5 else (muuten...) 6 return R-TREE-SEARCH(x right, k) (...etsitään oikeasta alipuusta)

TIE-20100 Tietorakenteet ja algoritmit 248 Algoritmi suunnistaa juuresta alaspäin huonoimmassa tapauksessa pisimmän polun päässä olevaan lehteen asti. suoritusaika O(h), missä h on puun korkeus lisämuistin tarve O(h), rekursion vuoksi Saman voi tehdä myös ilman rekursiota, mikä on suositeltavaa. tällöin lisämuistin tarve on vain Θ(1) ajoaika on yhä O(h) TREE-SEARCH(x, k) 1 while x NIL and k x key do (kunnes avain on löytynyt tai ollaan lehdessä) 2 if k < x key then (jos etsitty on pienempi kuin avain...) 3 x := x left (...siirrytään vasemmalle) 4 else (muuten...) 5 x := x right (...siirrytään oikealle) 6 return x (palautetaan tulos)

TIE-20100 Tietorakenteet ja algoritmit 249 Minimi ja maksimi: minimi löydetään menemällä vasemmalle niin kauan kun se on mahdollista TREE-MINIMUM(x) 1 while x left NIL do 2 x := x left 3 return x maksimi löydetään vastaavasti menemällä oikealle niin kauan kun se on mahdollista TREE-MAXIMUM(x) 1 while x right NIL do 2 x := x right 3 return x molempien ajoaika on O(h) ja lisämuistin tarve Θ(1)

TIE-20100 Tietorakenteet ja algoritmit 250 Solmun seuraajaa ja edeltäjää kannattaa etsiä binäärihakupuusta puun rakenteen avulla mieluummin kuin avainten arvojen perusteella. tällöin kaikki alkiot saadaan käytyä niiden avulla läpi, vaikka puussa olisi yhtä suuria avaimia tarvitaan siis algoritmi, joka etsii annettua solmua välijärjestyksessä seuraavan solmun sellainen voidaan rakentaa algoritmin TREE-MINIMUM avulla Kuva 16: Solmun seuraaja?

TIE-20100 Tietorakenteet ja algoritmit 251 Binäärihakupuun solmun seuraaja on joko: oikean alipuun pienin alkio tai solmusta juureen vievällä polulla ensimmäinen kohdattu solmu, jonka vasempaan alipuuhun solmu kuuluu jos edellä mainittuja solmuja ei löydy, on kysymyksessä puun suurin solmu Kuva 17: Seuraajat

TIE-20100 Tietorakenteet ja algoritmit 252 TREE-SUCCESSOR(x) 1 if x right NIL then (jos oikea alipuu löytyy...) 2 return TREE-MINIMUM(x right) (...etsitään sen minimi) 3 y := x p (muuten lähdetään kulkemaan kohti juurta) 4 while y NIL and x = y right do (kunnes ollaan tultu vasemmasta lapsesta) 5 x := y 6 y := y p 7 return y (palautetaan löydetty solmu) huomaa, että avainten arvoja ei edes katsota! vrt. seuraajan löytäminen järjestetystä listasta ajoaika O(h), lisämuistin tarve Θ(1) TREE-PREDECESSOR voidaan toteuttaa vastaavalla tavalla

TIE-20100 Tietorakenteet ja algoritmit 253 TREE-SUCCESSORIN ja TREE-MINIMUMIN avulla voidaan rakentaa toinen tapa selata puu läpi välijärjestyksessä. TREE-SCAN-ALL(T ) 1 if T.root NIL then 2 x := TREE-MINIMUM(T.root) (aloitetaan selaus puun minimistä) 3 else 4 x := NIL 5 while x NIL do (selataan niin kauan kun seuraajia löytyy) 6 käsittele alkio x 7 x := TREE-SUCCESSOR(x) jokainen kaari kuljetaan kerran molempiin suuntiin TREE-SCAN-ALL selviää ajassa Θ(n), vaikka kutsuukin TREE-SUCCESSORia n kertaa

TIE-20100 Tietorakenteet ja algoritmit 254 lisämuistin tarve Θ(1) TREE-SCAN-ALL on asymptoottisesti yhtä nopea, ja muistinkulutukseltaan asymptoottisesti parempi kuin INORDER-TREE-WALK vakiokertoimissa ei suurta eroa kannattaa valita TREE-SCAN-ALL, jos tietueissa on p-kentät TREE-SCAN-ALL sallii useat yhtäaikaiset selaukset, INORDER-TREE-WALK ei

TIE-20100 Tietorakenteet ja algoritmit 255 Lisäys binäärihakupuuhun: TREE-INSERT(T, z) (z osoittaa käyttäjän varaamaa alustettua tietuetta) 1 y := NIL; x := T.root (aloitetaan juuresta) 2 while x NIL do (laskeudutaan kunnes kohdataan tyhjä paikka) 3 y := x (otetaan potentiaalinen isä-solmu talteen) 4 if z key < x key then (siirrytään oikealle tai vasemmalle) 5 x := x left 6 else 7 x := x right 8 z p := y (sijoitetaan löydetty solmu uuden solmun isäksi) 9 if y = NIL then 10 T.root := z (puun ainoa solmu on juuri) 11 else if z key < y key then (sijoitetaan uusi solmu isänsä vasemmaksi... ) 12 y left := z 13 else (... tai oikeaksi lapseksi) 14 y right := z 15 z left := NIL; z right := NIL Algoritmi suunnistaa juuresta lehteen; uusi solmu sijoitetaan aina lehdeksi. ajoaika O(h), lisämuistin tarve Θ(1)

TIE-20100 Tietorakenteet ja algoritmit 256 Poisto on monimutkaisempaa, koska se voi kohdistua sisäsolmuun: TREE-DELETE(T, z) (z osoittaa poistettavaa solmua) 1 if z left = NIL or z right = NIL then (jos z:lla on vain yksi lapsi... ) 2 y := z (... asetetaan z poistettavaksi tietueeksi) 3 else 4 y := TREE-SUCCESSOR(z) (muuten poistetaan z:n seuraaja) 5 if y left NIL then (otetaan talteen poistettavan ainoa lapsi) 6 x := y left 7 else 8 x := y right 9 if x NIL then (jos lapsi on olemassa... ) 10 x p := y p (... linkitetään se poistettavan tilalle) 11 if y p = NIL then (jos poistettava oli juuri... ) 12 T.root := x (... merkitään x uudeksi juureksi) 13 else if y = y p left then (sijoitetaan x poistettavan tilalle... ) 14 y p left := x (... sen isän vasemmaksi... ) 15 else 16 y p right := x (... tai oikeaksi lapseksi) 17 if y z then (jos poistettiin joku muu kuin z... ) 18 z key := y key (... vaihdetaan poistetun ja z:n datat) 19 z satellitedata := y satellitedata 20 return y (palautetaan osoitin poistettuun solmuun)

TIE-20100 Tietorakenteet ja algoritmit 257 Huom! Rivillä 5 todellakin tiedetään, että y:llä on korkeintaan yksi lapsi. jos z:lla on vain yksi lapsi, y on z jos rivillä 4 kutsutaan TREE-SUCCESSORIA tiedetään, että z:lla on oikea alipuu, jonka minimi on y minimillä ei voi olla vasenta lasta Algoritmi näyttää monimutkaiselta, mutta rivin 4 TREE-SUCCESSORIA lukuunottamatta kaikki operaatiot ovat vakioaikaisia. ajoaika on siis O(h) ja lisämuistin tarve Θ(1) Siis kaikki dynaamisen joukon perusoperaatiot saadaan binäärihakupuulla toimimaan ajassa O(h) ja lisämuistilla Θ(1): SEARCH, INSERT, DELETE, MINIMUM, MAXIMUM, SUCCESSOR ja PREDECESSOR

TIE-20100 Tietorakenteet ja algoritmit 258 Binäärihakupuita - kuten muitakin tietorakenteita - voi sovittaa uusiin tehtäviin lisäämällä uusia tehtävän kannalta olennaista tietoa sisältäviä kenttiä. tällöin perusoperaatiot tulee muokata ylläpitämään myös uusien kenttien sisältöä esimerkiksi lisäämällä solmuihin kenttä, joka kertoo solmun virittämän alipuun koon saadaan toteutettua algoritmi, joka palauttaa puun korkeuteen nähden lineaarisessa ajassa i:nnen alkion saadaan toteutettua algoritmi, joka puun korkeuteen nähden lineaarisessa ajassa kertoo, monesko kysytty alkio on suuruusjärjestyksessä ilman ylimääräistä kenttää algoritmit täytyisi toteuttaa huomattavasti tehottomammin puun alkioiden määrään nähden lineaarisessa ajassa

TIE-20100 Tietorakenteet ja algoritmit 259 11.2 Kuinka korkeita binäärihakupuut yleensä ovat? Kaikki dynaamisen joukon perusoperaatiot saatiin binäärihakupuulla toimimaan ajassa O(h). puun korkeus on tehokkuuden kannalta keskeinen tekijä. Jos oletetaan, että alkiot on syötetty satunnaisessa järjestyksessä, ja jokainen järjestys on yhtä todennäköinen, suoraan INSERTillä rakennetun binäärihakupuun korkeus on keskimäärin Θ(lg n). kaikki operaatiot keskimäärin Θ(lg n)

TIE-20100 Tietorakenteet ja algoritmit 260 Valitettavasti lopputulos on surkeampi, jos avaimet syötetään (lähes) suuruusjärjestyksessä, kuten viereisestä kuvasta voi havaita. korkeus on n -1, surkeaa! Ongelmaa ei pystytä ratkaisemaan järkevästi esimerkiksi satunnaistamalla, jos halutaan säilyttää kaikki dynaamisen joukon operaatiot. Puu pitää siis tasapainottaa. Siihen palataan myöhemmin. 1 2 3 4 5 6 7