Lisää segmenttipuusta



Samankaltaiset tiedostot
Luku 8. Aluekyselyt. 8.1 Summataulukko

Luku 6. Dynaaminen ohjelmointi. 6.1 Funktion muisti

Hakupuut. tässä luvussa tarkastelemme puita tiedon tallennusrakenteina

Algoritmit 2. Luento 2 To Timo Männikkö

Algoritmit 2. Luento 2 Ke Timo Männikkö

Diskreetit rakenteet

811312A Tietorakenteet ja algoritmit, , Harjoitus 7, ratkaisu

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

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

Luonnollisten lukujen laskutoimitusten määrittely Peanon aksioomien pohjalta

A TIETORAKENTEET JA ALGORITMIT

Matematiikan tukikurssi 3.4.

String-vertailusta ja Scannerin käytöstä (1/2) String-vertailusta ja Scannerin käytöstä (2/2) Luentoesimerkki 4.1

Algoritmit 1. Luento 13 Ti Timo Männikkö

Tietorakenteet, laskuharjoitus 7, ratkaisuja

Asteri Kirjanpito Dos ALV% nousu 1 %-yksiköllä Vuosipäivitys

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

TKT20001 Tietorakenteet ja algoritmit Erilliskoe , malliratkaisut (Jyrki Kivinen)

Algoritmit 1. Luento 8 Ke Timo Männikkö

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

Luku 7. Verkkoalgoritmit. 7.1 Määritelmiä

Johdatus diskreettiin matematiikkaan Harjoitus 7,

Algoritmit 2. Luento 5 Ti Timo Männikkö

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

Marjan makuisia koruja rautalangasta ja helmistä -Portfolio

Algoritmit 1. Luento 7 Ti Timo Männikkö

Algoritmit 2. Luento 8 Ke Timo Männikkö

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.

monissa laskimissa luvun x käänteisluku saadaan näyttöön painamalla x - näppäintä.

Algoritmit 2. Luento 6 To Timo Männikkö

Algoritmit 2. Luento 7 Ti Timo Männikkö

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

ALGORITMIT 1 DEMOVASTAUKSET KEVÄT 2012

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.

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

Kesäkuu Synkka Tuote Pakkaushierarkia yksittäin ja monipakkauksissa myytäville tuotteille

811312A Tietorakenteet ja algoritmit, , Harjoitus 5, Ratkaisu

Algoritmit 2. Luento 5 Ti Timo Männikkö

Taulukkolaskenta II. Taulukkolaskennan edistyneempiä piirteitä

Dynaamisen järjestelmän siirtofunktio

Matkahuolto lisäosa WooCommerce alustalle (c) Webbisivut.org

Ehto- ja toistolauseet

Racket ohjelmointia II. Tiina Partanen 2015

Algoritmit 1. Luento 13 Ma Timo Männikkö

Luku 3. Listankäsittelyä. 3.1 Listat

Matematiikan tukikurssi

811312A Tietorakenteet ja algoritmit V Verkkojen algoritmeja Osa 2 : Kruskalin ja Dijkstran algoritmit

Tietorakenteet, laskuharjoitus 6,

Algoritmit 2. Luento 9 Ti Timo Männikkö

Binäärihaun vertailujärjestys

Asteri Kirjanpito Dos rakentamispalvelun alv Vuosipäivitys

MOBILITY TOOL -TÄYTTÖOHJE

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

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

Algoritmit 2. Luento 6 Ke Timo Männikkö

Algoritmit ja tietorakenteet Copyright Hannu Laine. 1, kun n= 0. n*(n-1)!, kun n>0;

Epäyhtälön molemmille puolille voidaan lisätä sama luku: kaikilla reaaliluvuilla a, b ja c on voimassa a < b a + c < b + c ja a b a + c b + c.

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

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

58131 Tietorakenteet ja algoritmit (syksy 2015) Toinen välikoe, malliratkaisut

58131 Tietorakenteet ja algoritmit (kevät 2014) Uusinta- ja erilliskoe, , vastauksia

Muita linkattuja rakenteita

MS-A Matriisilaskenta Laskuharjoitus 3

Sisältö Yleistä. Esittely ja luominen. Alkioiden käsittely. Kaksiulotteinen taulukko. Taulukko metodin parametrina. Taulukko ja HelloWorld-ohjelma. Ta

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

Luento 6. June 1, Luento 6

Ohje hakulomakkeen täyttämiseen yliopistohaku.fi -palvelussa

Datatähti 2019 loppu

Nopea kertolasku, Karatsuban algoritmi

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

MAA10 HARJOITUSTEHTÄVIÄ

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

Ilmoittautuminen kansalliseen, SM-, AM- tai avoimeen kilpailuun

10. Painotetut graafit

Algoritmit 1. Luento 1 Ti Timo Männikkö

Työtapaturman ilmoittaminen 2016-> Uusi sähköinen lomake, täyttäminen esimies ja palkkahallinto

811312A Tietorakenteet ja algoritmit, , Harjoitus 2, Ratkaisu

Taustaa KY:n nykyisestä toiminnasta KY:n strategia

Algoritmi on periaatteellisella tasolla seuraava:

SKYPE-RYHMÄN LUOMINEN

Tiraka, yhteenveto tenttiinlukua varten

Vaihtoehtoinen tapa määritellä funktioita f : N R on

AJOK/KEAJ/IAJOK. Koetallennus

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

Rekursio. Funktio f : N R määritellään yleensä antamalla lauseke funktion arvolle f (n). Vaihtoehtoinen tapa määritellä funktioita f : N R on

A TIETORAKENTEET JA ALGORITMIT

Väli- ja loppuraportointi

Raportointi hankkeen tulosten kuvaajana ja toteutuksen tukena

Tietorakenteet ja algoritmit - syksy

C-ohjelma. C-ohjelma. C-ohjelma. C-ohjelma. C-ohjelma. C-ohjelma. Operaatioiden suoritusjärjestys

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

Excel pivot. Mihin ja milloin pivot:ia voi käyttää

2.2 Täydellinen yhtälö. Ratkaisukaava

Suunnistaminen peukalokompassilla Peukalokompasseissa on eroa

Hae Opiskelija käyttöohje

Ohjelmoinnin perusteet Y Python

58131 Tietorakenteet ja algoritmit (syksy 2015)

4A 4h. KIMMOKERROIN E

4. Joukkojen käsittely

Laakerin kestoikälaskenta ISO-281, ISO-281Add1 ja ISO16281 mukaan

Transkriptio:

Luku 24 Lisää segmenttipuusta Segmenttipuu on monipuolinen tietorakenne, joka mahdollistaa monenlaisten kyselyiden toteuttamisen tehokkaasti. Tähän mennessä olemme käyttäneet kuitenkin segmenttipuuta melko rajoittuneesti. Nyt on aika tutustua pintaa syvemmältä segmenttipuun mahdollisuuksiin. 24.1 Kulku puussa Tähän mennessä olemme kulkeneet segmenttipuuta alhaalta ylöspäin lehdistä juureen. Vaihtoehtoinen tapa toteuttaa puun käsittely on kulkea ylhäältä alaspäin juuresta lehtiin. Tämä kulkusuunta on usein kätevä silloin, kun kyseessä on perustilannetta monimutkaisempi segmenttipuu. Esimerkiksi välin [a, b] summan laskeminen segmenttipuussa tapahtuu alhaalta ylöspäin tuttuun tapaan näin (luku 8.4): int summa(int a, int b) { a += N; b += N; int s = 0; while (a <= b) { if (a%2 == 1) s += p[a++]; if (b%2 == 0) s += p[b--]; a /= 2; b /= 2; } return s; } Ylhäältä alaspäin toteutettuna funktiosta tulee: int summa(int a, int b, int k, int c, int d) { if (a > d b < c) return 0; if (a == c && b == d) return p[k]; int w = d-c+1; return summa(a, min(b,c+w/2-1), 2*k, c, c+w/2-1) + summa(max(a,c+w/2), b, 2*k+1, c+w/2, d); } 140

Nyt välin [a, b] summan saa laskettua kutsumalla funktiota näin: int s = summa(a, b, 1, 0, N-1); Parametri k ilmaisee kohdan taulukossa p. Aluksi k:n arvona on 1, koska summan laskeminen alkaa segmenttipuun juuresta. Väli [c, d] on parametria k vastaava väli, aluksi koko kyselyalue eli [0, N 1]. Jos väli [a, b] on välin [c, d] ulkopuolella, välin summa on 0. Jos taas välit [a, b] ja [c, d] ovat samat, summan saa taulukosta p. Jos väli [a, b] on välin [c, d] sisällä, haku jatkuu rekursiivisesti välin [c, d] vasemmasta ja oikeasta puoliskosta. Kun w on välin [c, d] pituus, vasen puolisko kattaa välin [c, c + w/2 1] ja oikea puolisko kattaa välin [c + w/2, d]. Seuraava kuva näyttää, kuinka haku etenee puussa, kun tehtävänä on laskea puun alle merkityn välin summa. Harmaat solmut ovat kohtia, joissa rekursio päättyy ja välin summan saa taulukosta p. 72 39 33 22 17 20 13 13 9 9 8 8 12 8 5 5 8 6 3 2 7 2 6 7 1 7 5 6 2 3 2 Myös tässä toteutuksessa kyselyn aikavaativuus on O(log n). 24.2 Laiska päivitys Laiska päivitys mahdollistaa segmenttipuun, jossa sekä päivitykset että kyselyt kohdistuvat väleihin. Ideana on tallentaa jokaiseen solmun varsinaisen arvon lisäksi tietoa, miten solmun alipuuta tulee päivittää. Päivitys on kuitenkin laiska eikä se tapahdu, jos alipuuta ei tarvitse käsitellä. Tarkastellaan esimerkkinä segmenttipuuta, jonka operaatiot ovat: kasvata jokaista välin [a, b] arvoa x:llä laske välin [a, b] arvojen summa Molemmat puun operaatiot toteutetaan ylhäältä alaspäin. Jokaisessa solmussa on kaksi arvoa: solmua vastaavan alipuun summa, kuten tavallisessa segment- 141

tipuussa, sekä laiskaan päivitykseen liittyvä arvo z. Arvo z solmussa tarkoittaa, että kaikkiin solmun alipuun solmuihin tulee lisätä arvo z. Perustilanteessa jokaisessa solmussa z = 0, mikä tarkoittaa, että mitään päivityksiä ei ole kesken. Näin on seuraavassa kuvassa: 72/0 39/0 33/0 22/0 17/0 20/0 13/0 13/0 9/0 9/0 8/0 8/0 12/0 8/0 5/0 5 8 6 3 2 7 2 6 7 1 7 5 6 2 3 2 Nyt jokaisen solmun sisältönä on lukupari s/z, missä s on alipuun summa ja z on alipuuhun lisättävä arvo. Kasvatetaan sitten välin arvoja 2:llä: 74/0 41/0 35/0 22/0 19/0 20/2 13/0 13/0 9/0 9/0 8/2 8/0 12/0 8/2 5/0 5 8 6 3 2 9 2 6 7 1 7 5 6 2 3 2 Puussa tapahtui nyt kahdenlaisia muutoksia. Kussakin rekursion välisolmussa alipuun summa kasvoi 2:lla. Rekursion päätesolmuihin taas tuli laiska päivitys: arvo z kasvoi 2:lla mutta alipuun summat eivät muuttuneet vielä. Laiska päivitys jatkuu puussa alaspäin vasta sitten, kun on todellinen syy mennä alemmas alipuuta toisen päivityksen tai summakyselyn takia. Useita laiskoja päivityksiä voi olla päällekkäin niin, että z kertoo niiden summan. Laiskan päivityksen ansiosta päivitysoperaation aikavaativuus on vain O(log n), koska operaatio käsittelee puusta samaa osaa kuin välikysely. 142

Katsotaan lopuksi, miten laiska päivitys etenee kyselyoperaatiossa: 74/0 41/0 35/0 22/0 19/0 22/0 13/0 13/0 9/0 9/0 8/2 8/2 12/2 10/0 5/0 5 8 6 3 2 9 2 6 7 1 7 5 8 4 3 2 Laiskan päivityksen z-arvo siirtyi kerrosta alemmas kaikista solmuista, joiden alipuun summaa tarvittiin kyselyissä. Laiska päivitys eteni siis juuri sen verran eteenpäin, että haluttu summa saatiin laskettua. 24.3 Harva lukuväli Tavallisen segmenttipuun rajoituksena on, että lukuvälinä on yhtenäinen alue 0,1,2,..., N 1. Tämä ratkaisu ei toimi, jos N on niin iso, että muisti ei riitä segmenttipuun tallentamiseen. Segmenttipuun yleistämiseen harvalle lukuvälille on kuitenkin monia mahdollisuuksia. 24.3.1 Koordinaattien pakkaus Yksinkertaisin tapa toteuttaa harvan lukuvälin segmenttipuu on käyttää koordinaattien pakkausta (luku 9.3). Tällöin lukuväliksi tulee 0, 1, 2,... ja tavallinen segmenttipuu riittää. Koordinaattien pakkausta voi kuitenkin käyttää vain, jos kaikki lukuvälin arvot tunnetaan algoritmin alussa. 24.3.2 map-rakenne Tavallinen tapa toteuttaa taulukko, joka on vapaasti indeksoitavissa, on käyttää map-rakennetta. Yllättävää kyllä, idea on mahdollista yleistää myös harvan lukuvälin segmenttipuuhun. Tällaisen harvan segmenttipuun voi toteuttaa kuten tavallisen segmenttipuun, mutta taulukko p on korvattu map-rakenteella. Tällöin muistissa ovat vain ne segmenttipuun solmut, joita on tarvittu segmenttipuun käsittelyn aikana, ja muiden solmujen tulkitaan olevan oletusarvoisia. Harvan lukuvälin segmenttipuu on mukavaa toteuttaa map-rakenteena, mutta huonona puolena on, että ratkaisu on usein käytännössä melko hidas. 143

24.3.3 Dynaaminen puu Tehokas tapa toteuttaa yleinen harvan lukuvälin segmenttipuu on luoda puun solmuja dynaamisesti ja toteuttaa puun käsittely ylhäältä alaspäin. Aluksi puun ainoa solmu on väliä [0, N 1] vastaava puu. Kun puuhun tapahtuu kyselyitä ja päivityksiä, siihen lisätään tarvittavia solmuja. Jokainen kysely ja päivitys lisää enintään O(log n) uutta solmua puuhun. Esimerkiksi jos N = 16 ja lukuvälin arvoja 3 ja 10 on muutettu, puu näyttää muistissa seuraavanlaiselta: [0, 15] [0,7] [8, 15] [0,3] [8, 11] [2,3] [10, 11] [3] [10] Solmut on kätevää tallentaa tietueina tähän tapaan: struct solmu { int x; int a, b; solmu *l, *r; solmu(int x, int a, int b) : x(x), a(a), b(b) {} }; Tässä x on solmussa oleva arvo, [a, b] on solmua vastaava väli ja l ja r osoittavat solmun vasempaan ja oikeaan alipuuhun. Tämän jälkeen solmuja voi käsitellä seuraavasti: // uuden solmun luonti solmu *s = new solmu(0, 0, 15); // kentän muuttaminen s->x = 5; 144

24.4 Kaksiulotteisuus Kaksiulotteinen segmenttipuu mahdollistaa kyselyt kaksiulotteisen taulukon alueella. Kaksiulotteisen segmenttipuun voi toteuttaa rakentamalla segmenttipuun, jonka jokaisessa solmussa on segmenttipuu. Nyt suuri segmenttipuu vastaa taulukon rivejä ja pienet segmenttipuut vastaavat sarakkeita. Esimerkiksi taulukosta 7 6 1 6 8 7 5 2 3 9 7 1 8 5 3 8 syntyy seuraavanlainen segmenttipuu: 86 53 33 26 27 16 17 42 28 14 15 13 6 8 44 25 19 11 14 10 9 20 22 20 24 13 7 15 7 12 8 13 11 7 6 1 6 8 7 5 2 3 9 7 1 8 5 3 8 Tässä segmenttipuussa operaatioiden aikavaativuus on O(log 2 n), koska suuressa segmenttipuussa käsitellään O(log n) solmua, ja jokaisessa solmussa pienen segmenttipuun käsittely vie aikaa O(log n). 145

24.5 Muutoshistoria Segmenttipuuta on myös mahdollista laajentaa niin, että muistissa on kaikki puun vaiheet historian aikana. Tämä perustuu siihen, että jokainen muutos vaikuttaa vain pieneen osaan puun solmuista. Tarkastellaan esimerkiksi seuraavaa muutossarjaa: vaihe 1 vaihe 2 vaihe 3 Punaiset solmut muuttuvat päivityksessä, ja muut solmut säilyvät ennallaan. Muistia säästävä tapa tallentaa muutoshistoria on käyttää mahdollisimman paljon hyväksi puun vanhoja osia joka muutoksen jälkeen. Tässä tapauksessa muutoshistorian voisi tallentaa seuraavasti: vaihe 1 vaihe 2 vaihe 3 Jokainen muutos tuo vain O(log n) uutta solmua puuhun, joten koko muutoshistorian pitäminen muistissa on mahdollista. 146