REKURSIO. Rekursiivinen ohjelma Kutsuu itseään. Rekursiivinen rakenne. Rakenne sisältyy itseensä. Rekursiivinen funktio. On määritelty itsensä avulla

Samankaltaiset tiedostot
Tietorakenteet ja algoritmit. Kertaus. Ari Korhonen

Algoritmianalyysin perusteet

Tietorakenteet ja algoritmit

Algoritmit 2. Luento 8 To Timo Männikkö

Tietorakenteet ja algoritmit - syksy

Tietorakenteet ja algoritmit Johdanto Lauri Malmi / Ari Korhonen

Algoritmit 1. Luento 3 Ti Timo Männikkö

Algoritmien suunnittelumenetelmiä

811120P Diskreetit rakenteet

Algoritmit 1. Luento 11 Ti Timo Männikkö

Algoritmit 2. Luento 14 Ke Timo Männikkö

ALGORITMIT 1 DEMOVASTAUKSET KEVÄT 2012

Algoritmit 1. Luento 12 Ti Timo Männikkö

Algoritmit 2. Luento 2 To Timo Männikkö

Algoritmit 2. Luento 2 Ke Timo Männikkö

4 Tehokkuus ja algoritmien suunnittelu

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

Johdatus diskreettiin matematiikkaan Harjoitus 5, Ratkaise rekursioyhtälö

Algoritmit 1. Luento 13 Ti Timo Männikkö

Algoritmit 2. Luento 13 Ti Timo Männikkö

Tietorakenteet, laskuharjoitus 3, ratkaisuja

Algoritmit 1. Luento 12 Ke Timo Männikkö

A TIETORAKENTEET JA ALGORITMIT

Algoritmit 1. Demot Timo Männikkö

Algoritmit 2. Luento 7 Ti Timo Männikkö

811312A Tietorakenteet ja algoritmit, , Harjoitus 7, ratkaisu

811312A Tietorakenteet ja algoritmit Kertausta kurssin alkuosasta

Nopea kertolasku, Karatsuban algoritmi

811312A Tietorakenteet ja algoritmit Kertausta kurssin alkuosasta

58131 Tietorakenteet ja algoritmit (syksy 2015)

Ohjelmoinnin peruskurssien laaja oppimäärä

Algoritmit 1. Luento 5 Ti Timo Männikkö

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

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

A TIETORAKENTEET JA ALGORITMIT

Luku 6. Dynaaminen ohjelmointi. 6.1 Funktion muisti

811312A Tietorakenteet ja algoritmit, VI Algoritmien suunnitteluparadigmoja

Algoritmit 1. Luento 10 Ke Timo Männikkö

2.2.1 Ratkaiseminen arvausta sovittamalla

4. Algoritmien tehokkuus

Tietorakenteet ja algoritmit syksy Laskuharjoitus 1

Algoritmit 1. Luento 2 Ke Timo Männikkö

Tietorakenteet, laskuharjoitus 1,

Algoritmit 1. Luento 1 Ti Timo Männikkö

815338A Ohjelmointikielten periaatteet Harjoitus 6 Vastaukset

Lineaariset perustietorakenteet

Tutkimusmenetelmät-kurssi, s-2004

Algoritmit 1. Luento 8 Ke Timo Männikkö

Rekursioyhtälön ratkaisutapa #1: iteratiivinen korvaus

Algoritmit 1. Luento 13 Ma Timo Männikkö

811312A Tietorakenteet ja algoritmit II Perustietorakenteet

Muuttujien roolit Kiintoarvo cin >> r;

TIE Tietorakenteet ja algoritmit 25

815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset

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.

TAMPEREEN TEKNILLINEN YLIOPISTO

Kysymyksiä koko kurssista?

815338A Ohjelmointikielten periaatteet Harjoitus 7 Vastaukset

Tietorakenteet, laskuharjoitus 7, ratkaisuja

1.4 Funktioiden kertaluokat

811312A Tietorakenteet ja algoritmit III Lajittelualgoritmeista

811312A Tietorakenteet ja algoritmit, , Harjoitus 3, Ratkaisu

Algoritmit 2. Luento 4 To Timo Männikkö

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

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

Ohjelmoinnin peruskurssien laaja oppimäärä

811312A Tietorakenteet ja algoritmit, , Harjoitus 4, Ratkaisu

Hakupuut. tässä luvussa tarkastelemme puita tiedon tallennusrakenteina

TIEA341 Funktio-ohjelmointi 1, kevät 2008

Algoritmit 1. Luento 14 Ke Timo Männikkö

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

. Kun p = 1, jono suppenee raja-arvoon 1. Jos p = 2, jono hajaantuu. Jono suppenee siis lineaarisesti. Vastaavasti jonolle r k+1 = r k, suhde on r k+1

Algoritmit 1. Luento 10 Ke Timo Männikkö

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

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

Algoritmit 1. Demot Timo Männikkö

1 Erilaisia tapoja järjestää

Algoritmit 2. Luento 13 Ti Timo Männikkö

Matematiikan tukikurssi, kurssikerta 5

Johdatus matematiikkaan

Numeeriset menetelmät

Tieto ja sen osoite (3) Jakso 3 Konekielinen ohjelmointi (TTK-91, KOKSI) Osoitinmuuttujat. Tieto ja sen osoite (5)

Tietorakenteet (syksy 2013)

12. Algoritminsuunnittelun perusmenetelmiä

12. Algoritminsuunnittelun perusmenetelmiä

802328A LUKUTEORIAN PERUSTEET OSA III BASICS OF NUMBER THEORY PART III

Tiraka, yhteenveto tenttiinlukua varten

a k+1 = 2a k + 1 = 2(2 k 1) + 1 = 2 k+1 1. xxxxxx xxxxxx xxxxxx xxxxxx

Ohjelmoinnin peruskurssien laaja oppimäärä

4. Joukkojen käsittely

Luku 8. Aluekyselyt. 8.1 Summataulukko

Jakso 3 Konekielinen ohjelmointi (TTK-91, KOKSI)

Jakso 3 Konekielinen ohjelmointi (TTK-91, KOKSI)

A TIETORAKENTEET JA ALGORITMIT

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

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.

3. Laskennan vaativuusteoriaa

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

Lyhyt kertaus osoittimista

ja λ 2 = 2x 1r 0 x 2 + 2x 1r 0 x 2

Transkriptio:

REKURSIO Rekursiivinen ohjelma Kutsuu itseään Rekursiivinen rakenne Rakenne sisältyy itseensä Rekursiivinen funktio On määritelty itsensä avulla Esim. Fibonacci-luvut: X(i) = X(i-1) + X(i-2), X(0) = X(1) = 1 24.9.2015 Tietorakenteet ja algoritmit 1

Rekursio ei voi jatkua loputtomiin Täytyy löytyä päätösehto jonka toteutuminen lopettaa rekursion Esim. Kertoma: Rekursio: N! = N(N-1)! Päätösehto: 0! = 1 24.9.2015 Tietorakenteet ja algoritmit 2

Rekursion neljä kultaista sääntöä: 1. Perustapaukset (ratkaistavissa ilman rekursiota) 2. Edistyminen (liikutaan perustapausta kohti) 3. Oletus (kaikki rekursiiviset kutsut toimivat) 4. Vältä turhaa työtä (jokainen tapaus ratkaistaan vain kerran) 24.9.2015 Tietorakenteet ja algoritmit 3

Esim. Kertoma rekursiivisena: int factorial(int n) /* n: askeltaja */ { if (n==0) return 1; else return factorial(n-1)*n; Esim. Kertoma ei-rekursiivisena: int factorial(int n) /* n: kiintoarvo */ { int i,fact; fact = 1; /* fact: kokooja */ for (i=2; i<=n; i++) /* i: askeltaja */ fact = fact*i; return fact; 24.9.2015 Tietorakenteet ja algoritmit 4

Esim. Fibonacci-luvut: int fibonacci(int n) { if (n<=1) return 1; else return fibonacci(n-1)+fibonacci(n-2); F5 F6 F4 {Rikkoo neljättä sääntöä F4 F3 F3 F2 Parempi toteuttaa eirekursiivisena Mutta: voitaisiin muuntaa lineaarisessa ajassa toimivaksi taulukoinnilla! F2 F3 F2 F2 F1 F2 F1 F1 F0 F1 F0 F1 F1 F0 F1 F0 F1 F0 24.9.2015 Tietorakenteet ja algoritmit 5

Rekursiohistoriapuu Puurakenne, jossa solmu jokaista rekursiokutsua kohti Solmut aktivoituvat ns. esijärjestyksessä (ks. puiden läpikäynti) Ensimmäistä kutsua vastaa puun juuri Pinokehys aktiivinen, kunnes kaikki alipuut on käyty läpi Pinokehys poistuu, kun rekursio palaa solmusta Esim. Fibonaccin luvut: int fibonacci(int n) { if (n<=1) return 1; else return fibonacci(n-1)+fibonacci(n-2); 24.9.2015 Tietorakenteet ja algoritmit 6

Dynaaminen ohjelmointi Dynamic Programming Jaetaan ongelma (rekursiivisesti) osaongelmiin, joita yhdistelemällä alkuperäinen ongelma ratkeaa Mitä jos sama pienempi osaongelma joudutaan ratkaisemaan useaan kertaan? Tämä rikkoo rekursion 4. kultaista sääntöä! Vrt. Hajoita ja hallitse (esim. Quicksort), jossa sama aliongelma esiintyy vain kerran Ratkaisuja Top-down: memoization / taulukointi tai Bottom-up: koostaminen 24.9.2015 Tietorakenteet ja algoritmit 7

Taulukointi Vrt. Fibonaccin luvut: Taulukoimalla: var arr = new Array[Int](MAX_N); def fib_r(n: Int): Int = { if (n <= 1) 1 else { fib_r(n - 1) + fib_r(n - 2) def fib_m(n: Int): Int = { if (n <= 1) 1 else { if (arr(n) == 0) arr(n) = fib_m(n - 1) + fib_m(n - 2) arr(n) Esim. Fibonaccin luvut voidaan laskea pitämällä kirjaa jo lasketuista tapauksista Yleisesti pidetään kirjaa (top-down) jo laskettujen aliongelmien ratkaisuista ja tehdään laskentaa vain, jos ratkaisua ei vielä tunneta 24.9.2015 Tietorakenteet ja algoritmit 8

Koostaminen Esim. Fibonaccin luvut voidaan laskea myös lähtemällä liikkeelle tapauksista old = older = 1 ja laskemalla (bottom-up) silmukassa current = old + older ja päivittämällä old & older def fib_iter(n: Int) = { var old, older, current = 1 for (i <- 1 until n) { older = old old = current current = old + older current Yleisesti: koostetaan tunnetuista aliongelmien ratkaisuista monimutkaisempia ratkaisuja 24.9.2015 Tietorakenteet ja algoritmit 9

Esim. Hanoin tornit (Edouard Lucas, 1883): Siirrä renkaat toiseen tappiin yksi kerrallaan niin, että isompi rengas ei koskaan ole pienemmän päällä: Mistä Minne Vi a N K2.17? 24.9.2015 Tietorakenteet ja algoritmit 10

Esim. Hanoin tornit (Edouard Lucas, 1883): Ratkaisu rekursion avulla: Mistä Minne Vi a N-1 N-1 1 K2.17 24.9.2015 Tietorakenteet ja algoritmit 11

void hanoi(int N, int mista, int minne, int via) { if (N==1) printf( Siirrä rengas tapista %d tappiin %d kiitos\n, mista, minne); else { hanoi(n-1, mista, via, minne); hanoi(1, mista, minne, via); hanoi(n-1, via, minne, mista); Mistä Minne Vi a Kotitehtävä: Ohjelmoi hanoi haluamallasi ohjelmointikielellä ja testaa, että se toimii! K2.17 24.9.2015 Tietorakenteet ja algoritmit 12

Hanoin tornien rekursiohistoriapuu Esim. hanoin(3, 1, 2, 3) void hanoi(int N, int mista, int minne, int via) { if (N==1) printf( Siirrä rengas tapista %d tappiin %d kiitos\n, mista, minne); else { hanoi(n-1, mista, via, minne); hanoi(1, mista, minne, via); // printf hanoi(n-1, via, minne, mista); h(3,1,2,3) Mistä Minne Vi a K2.17 h(2,1,3,2) h(1,1,2,3) 24.9.2015 Tietorakenteet ja algoritmit 13

Rekursiohistoriapuu Esim. hanoi(3, 1, 2, 3) void hanoi(int N, int mista, int minne, int via) { if (N==1) printf( Siirrä rengas tapista %d tappiin %d kiitos\n, mista, minne); else { hanoi(n-1, mista, via, minne); hanoi(1, mista, minne, via); // printf hanoi(n-1, via, minne, mista); h(3,1,2,3) h(2,1,3,2) h(1,1,2,3) h(2,3,2,1) h(1,1,2,3) h(1,1,3,2) h(1,2,3,1) h(1,3,1,2) h(1,3,2,1) h(1,1,2,3) 24.9.2015 Tietorakenteet ja algoritmit 14

Analyysiä Mikä on Hanoin-tornit algoritmin aikakompleksisuus? Askelten lukumäärä s = 2 N -1 Todistus? void hanoi(int N, int mista, int minne, int via) { if (N==1) printf( Siirrä rengas tapista %d tappiin %d kiitos\n, mista, minne); else { hanoi(n-1, mista, via, minne); hanoi(1, mista, minne, via); hanoi(n-1, via, minne, mista); Perustapaukset s 1 = 1, s 2 = 3, s 3 = 7, Induktio-oletus: s N-1 = 2 N-1-1 (1) Induktioaskel: S N = S N-1 + 1 + S N-1 = 2S N-1 + 1 sij. (1) = 2(2 N-1-1) + 1 = 2 N - 1 24.9.2015 15

Rekursioyhtälöt Edellä olisi yhtä hyvin voitu merkitä vrt. s 1 = 1, s N = 2 N - 1 S(1) = 1, S(2) = 3, S(3) = 7 ja S(N) = 2 N 1 tai T(1) = 1, T(N) = 2 N 1 Algoritmianalyysissä useimmiten algoritmin aikakompleksisuuha merkitään T(N):llä Lisäksi haetaan suuruusluokkaa, eli esim. T(N) = O(2 N ) 24.9.2015 Tietorakenteet ja algoritmit 16

5.9 Rekursioyhtälöt Mentaalisen mallin muodostuminen (muna-kana-ongelma) 1. Rekursiohistoriapuut, laskennan etenemisen sisäistäminen 2. Laskennan vaativuuden erottaminen itse laskennen lopputuloksesta 3. Valikoitu arvaus laskennan vaativuudelle 4. Yhteys induktiotodistukseen 5. Rekursioyhtälö mentaalisen mallin ulkoistamisen välineenä Rekursioyhtälöiden ratkaisumenetelmiä (todistus) Aritmeettiset ja geometriset sarjakehitelmät Parametrien muunnokset Lausekkeen manipulointi Näiden yhdistely Master Theorem (Cormen) Induktiotodistus (e-book) 22.09.2015 Tietorakenteet ja algoritmit Y - syksy 2015 17

Esim 1. Linkitetyn listan läpikäynti silmukassa, poista joka kierroksella yksi alkio (ks. aritmeettinen sarja): T(N) = T(N-1) + N, T(1) =1 N T(N) = k = N (N + 1) / 2 k=1 T(N) on noin N 2 / 2 = O(N 2 ) T(N-1) = T((N-1)-1) + (N-1) = T(N-2) + N - 1 T(N-2) = T((N-2)-1) + (N-2) = T(N-3) + N - 2 T(N-k) = T((N-k)-1) + (N-k) = T(N-k-1) + N - k 22.09.2015 Tietorakenteet ja algoritmit Y - syksy 2015 18

Esim 2. Binäärihaku, puolita aineisto vakioajassa: T(N) = T(N/2) + 1, T(1) =1 N = 2 k, k = log 2 N (parametrin muunnos) T(2 k ) = T(2 k-1 ) + 1 = T(2 k-2 ) + 1 + 1 = T(2 0 ) + k = k +1 T(N) = O(k) = O(log N) Esim 3. Quick select, puolita aineisto lineaarisessa ajassa (geometrinen sarja): T(N) = T(N/2) + N, T(1) = 1 T(N) = N + N/2 + N/4 + N/8 +... = 2N = O(N) 22.09.2015 Tietorakenteet ja algoritmit Y - syksy 2015 19

Esim 4. Hajoita ja hallitse : Jaa aineisto kahteen osaan lineaarisessa ajassa, käsittele molemmat puolet rekursiivisesti T(N) = 2T(N/2) + N, T(1) = 1 N = 2 k, k = log 2 N T(2 k ) = 2T(2 k-1 ) + 2 k <=> T(2 k ) / 2 k = T(2 k-1 ) / 2 k-1 + 1 <=> T(2 k-1 ) / 2 k-1 = T(2 k-2 ) / 2 k-2 + 1 <=> T(2 k-2 ) / 2 k-2 = T(2 k-3 ) / 2 k-3 + 1... <=> T(2 2 ) / 2 2 = T(2 1 ) / 2 1 + 1 <=> T(2 1 ) / 2 1 = T(2 0 ) / 2 0 + 1 Lasketaan yhteen (teleskooppi) T(2 k ) / 2 k = k T(N) = T(2 k ) = k 2 k = N log N = O(N log N) 22.09.2015 Tietorakenteet ja algoritmit Y - syksy 2015 20

Esim 5. Potenssiinkorotus: Jos laskettaisiin x n = x*x*x*...*x, n-1 kertolaskua => O(n) Mutta voidaan laskea esim. x 9 = (x 2 ) 4 x = ((x 2 ) 2 ) 2 x (vain 4 kertolaskua 8:n sijaan!) integer pow(int x, int n){ switch (n) { case 0: return 1; break; case 1: return x; break; default: if (n&1) return pow(x*x, n/2)*x; else return pow(x*x, n/2); T(n) = T(n/2) + 1, T(1) = T(0) = 1 T(n) = O(log n) (Ratkaisu: vrt. Esim. kohta 2 edellä) 22.09.2015 Tietorakenteet ja algoritmit Y - syksy 2015 21

5.10 Kuinka analyysi tarkistetaan? Empiirisesti Toteuttamalla ohjelma Tehdään koeajoja mahdollisimman suurilla aineistoilla N, 2N, 4N, 8N,... Kun N tuplaantuu O(N) - algoritmien ajoaika tuplaantuu O(N 2 ) : nelinkertaistuu O(N 3 ) : kahdeksankertaistuu jne. O(log N) : vain vakiotermi lisää riippumatta N:stä O(N log N) : hiukan huonompi kuin O(N) Alemman asteen termit sotkevat empiiristä tarkastelua 22.09.2015 Tietorakenteet ja algoritmit Y - syksy 2015 22

Jos T(N) on mitattu suoritusaika ja oletetaan, että T(N) = O( f(n) ), niin voidaan tilastoida suuretta c = T(N)/f(N) satunnaisilla N:n arvoilla Jos c lähestyy positiivista arvoa f(n) on tiukka raja, ehkä T(N) = θ( f(n) ) Jos c lähestyy nollaa f(n) on liian lepsu raja, voidaan sanoa että T(N) = o( f(n) ) Jos arvot hajaantuvat f(n) kasvaa liian hitaasti, T(N) ei ole O( f(n) ) 22.09.2015 Tietorakenteet ja algoritmit Y - syksy 2015 23

5.11 Analyyttisten tulosten tulkinta Usein ei ole olemassa selvästi parasta algoritmia tai tietorakennetta. Valintaan vaikuttaa monia tekijöitä : kuinka usein ohjelmaa tarvitaan? syötteen koko (aineiston määrä) suoritusaikavaatimukset reaaliaikainen / eräluonteinen työ lisäysten / poistojen / päivitysten määrä ja suhde hakuihin Matemaattinen analyysi kertoo vain osan totuudesta. Muita tekijöitä ovat : kääntäjä käyttöjärjestelmä I/O:n määrä Yleensä kannattaa aloittaa yksinkertaisella menetelmällä (brute force well tuned) 22.09.2015 Tietorakenteet ja algoritmit Y - syksy 2015 24

Ongelman kasvaessa algoritmia voidaan vaihtaa tehokkaampaan uusimatta koko ohjelmaa N 2 N * LOG N Algoritmin viilaaminen katkaistaan sopivasti. Ohjelmakoodin optimointi käsin kannattaa harvoin. Tärkeämpää on se, että ohjelmassa on varauduttu muutoksiin hyvin ehjä kokonaisuus abstraktit tietotyypit Ohjelman ylläpidettävyys on usein tärkeämpää kuin tehokkuus! 22.09.2015 Tietorakenteet ja algoritmit Y - syksy 2015 25

Ensi kerraksi Tee viikon 39 viikkoharjoitukset loppuun Tutustu järjestämismenetelmiin ja kertaa asioita Ks. luentotehtävä (viikko 40) A+:ssa Voit tutustua myös lisää algoritmien suunnittelumenetelmiin (mm. taulukointi, dynaaminen ohjelmointi) Tee itseopiskeluna viikon 41 harjoitukset (prioritettijonot) ml. viikon 41 luentotehtävä 22.09.2015 Tietorakenteet ja algoritmit Y - syksy 2015 26