Tietorakenteet ja algoritmit

Slides:



Advertisements
Samankaltaiset esitykset
18. Abstraktit tietotyypit
Advertisements

Copyright  Hannu Laine Bittitason-operaatiot Hannu Laine.
Tietorakenteet ja algoritmit
Olio-ohjelmoinnin perusteet luento 3: Muuttujista ja funktioista Sami Jantunen LTY/Tietotekniikan osasto.
© Hannu Laine 1 Tietorakenteet ja algoritmit Funktio-osoittimet Funktio-osoittimen ja taulukko-osoittimen vertailu Funktio-osoittimen käyttötapoja.
11/9/2012 © Hannu Laine 1 Tietorakenteet ja algoritmit Elegantti toteutus funktiolle insert_to_list_end Alkion lisäys sisällön mukaan järjestettyyn listaan.
2.8.3 Abstraktit tietotyypit
Rakenteinen ohjelmointi
Taulukot: Array Taulukko Javassa pitää aina perustaa (new)
Copyright  Hannu Laine Osoittimet ja taulukot Hannu Laine.
C-kieli ja dynaaminen muistin varaus
22. Taulukot.
Rakenteinen ohjelmointi
Käännösaikaiset virheilmoitukset • Tulee silloin, kun koodissa on jotain sellaista, joka ei ole Javan syntaksin mukaista • Esim. – Syntax error, insert.
ATK70d / Ohjelmointi 1 Kuplalajittelu © Helia / Jukka Harju, 2004.
10/9/2012 © Hannu Laine 1 Tietorakenteet ja algoritmit Listan määritelmä Listan toteutustapoja Yksinkertainen taulukkototeutus Linkattu taulukko Dynaamisesti.
13. Pakkaukset.
Langattomien laitteiden matematiikka 1
Näytölle tulostaminen. 7.2 Sisällys System.out.println - ja System.out.print -operaatiot. Tulostus erikoismerkeillä. Edistyneempää tulosteiden.
Sovellusohjelman suunnittelu & toteutus
C-ohjelmointi, kevät 2006 Taulukot Binääritiedostot Luento
AS Automaation signaalinkäsittelymenetelmät
Java-ohjelmointi Opas ammattimaiseen osaamiseen Luku 4 Toistolauseet
KERTAUSTA PERUSASTEEN MATEMATIIKASTA Piia junes
TMA.003 / L3 ( )1 3. Funktioista 3.1. Kuvaus ja funktio Olkoon A ja B ei-tyhjiä joukkoja. Tulojoukon A  B = {(x,y) | x  A, y  B} osajoukko on.
Vakio-osoitin ja osoitin vakioon tMyn1 Vakio-osoitin ja osoitin vakioon Tavallinen osoitin voi vaihtaa osoitettavaa keskusmuistialuetta. Tämä voidaan tehdä.
Toiston tekeminen Javalla  Mikä toistorakenne on?  while toistorakenne  do-while toistorakenne  for toistorakenne 1.
Ohjelmoinnin tekniikkaa Sisällys for -lause lyhemmin. Vaihtoehtoisia merkintöjä aritmeettisille lauseille. Useiden muuttujien esittely.
TAULUKKO YKSIULOTTEINEN TAULUKKO. TAULUKKO  Taulukon tarkoitus Ohjelmassa tarvitaan paljon samantyyppisiä samaan kohdealueeseen kuuluvia muuttujia Näitä.
Binäärinen hakupuu Jokaisessa solmussa on yksikäsitteinen avain
2. Vuokaaviot.
1 Kertaus koetta varten oleellisista asioista Jukka Juslin.
Map-luokka Mikä Map on? Mapin esittely ja luonti Map-luokan metodeja Mappiin lisääminen Mapin läpikäynti Mapista poistaminen 1.
ict1td002 - Copyright Raine Kauppinen 1 Alkuarvot ja tyyppimuunnokset (1/5)  Aiemmin olemme jo antaneet muuttujille alkuarvoja, esimerkiksi: int.
2.7 Rekursio ja iteraatio Algoritminen ongelmanratkaisu ei ole
Metodit – Arvotyyppi Ellei metodi palauta arvoa, sen arvotyyppi on void Tällöin ”return;”-lauseke ei ole metodissa pakollinen, vaikka sen käyttö on sallittua.
Algoritmi-harjoituksia…
5. Kapselointi Yleistä Kapseloinnilla (encapsulation) tarkoitetaan luokan tietojen ja toimintojen pakkaamista yhdeksi suojatuksi kokonaisuudeksi.
@ Leena Lahtinen OHJELMAN OSITTAMINEN LUOKKA ATTRIBUUTIT METODIT.
3.2 Kompleksisuus Vain pieni osa kaikista tehtävistä on laskettavissa tai edes osittainkaan laskettavissa. Laskettavien osalta saattaa olla tarpeellista.
22. Taulukot.
1 Ohjelmointikielten varhaishistoria Esa-Matti Miettinen
© Jukka Juslin1 Osio2 Olio-ohjelmointi: Merkkijonot eli Stringit Jukka Juslin.
Rinnakkaisuus Järjestelmässä, jossa voi olla useita prosesseja rinnakkain suorituksessa voi tulla tilanteita, joissa prosessien suoritusta täytyy kontrolloida.
Johdetun luokan olion esittely... tMyn1 Johdetun luokan olion esittely ja määrittely Esittelyluokka tarkoittaa olion tunnuksen luokkaa. Määrittelyluokka.
DO NOT PRINT THIS DOCUMENT SQL -valintaehto CREATE TABLE opettaja ( opetunnus varchar(12) NOT NULL, nimi varchar(40) NOT NULL, puhelin varchar(12), tyohuone.
Visual Basic -ohjelmointi
S ysteemianalyysin Laboratorio Teknillinen korkeakoulu Esitelmä 2 - Jirka Poropudas Optimointiopin seminaari - Kevät 2005 / 1 Bayes-verkoista s
Visual Basic -ohjelmointi
Tiedon vieminen funktiolle tMyn1 Tiedon vieminen funktiolle, parametrit Argumentin vieminen funktiolle voidaan toteuttaa kahdella menetelmällä: –Pass-by-Value.
S ysteemianalyysin Laboratorio Aalto-yliopiston teknillinen korkeakoulu Ohjaamaton oppiminen– Heikki Vesterinen Optimointiopin seminaari - Syksy 2010 Ohjaamaton.
Ohjelmointi 1. toinen luento1 Taulukot n Kiinteät taulukot: alkioiden määrä tiedetään Dim intCount(12) As Integer 0 indeksit saavat arvoja 0-12 (Option.
21. Rekursio.
Foreach-toistolausetMyn1 foreach-toistolause foreach-rakenteella on kätevä käydä läpi kaikki taulukon alkiot. Erityisen kätevää se on hajautustaulukon.
Ohjausrakenteet Määräävät ohjelmakoodin suoritusjärjestyksen Ehtolause if – else on muotoa if (lauseke) lause1 else lause2 Jos lauseke on tosi, niin suoritetaan.
Prioriteettijonot ja kekolajittelu (heapsort)
Kuplalajittelu (bubble sort)
Puun määritelmä Puu on yhden tai useamman kytketyn solmun muodostama hierarkinen joukko Lehtisolmuista juurisolmuun on yksikäsitteinen polku Käytetään.
Jakolajittelu (Radix sort) Vertailu tehdään avaimen osien perusteella Avaimia käsitellään R-kantaisina arvoina esim. postin lajittelukone prosessoi lähetykset.
Lajittelun sovelluksia Yksilöllisyyden testaaminen Kopioiden poistaminen Mediaani/n:ksi suurimman valinta frekvenssien laskenta/yleisin alkio, l.moodi.
Hajoita ja hallitse (divide and conquer) Pikalajittele n-alkioinen taulukko 1. Divide: Jaetaan taulukko kahdeksi alitaulukoksi tukialkion (pivot) x suhteen:
Ohjelmassa tänään Ohjelmointimallit Pseudokieli Modulaarisuus.
Hajakoodaus Talletetaan alkiot avain-indeksoituun taulukkoon Hajakoodausfunktio Menetelmä avain-indeksin laskemiseen avaimesta Törmäyksen selvitysstrategia.
Muuttujan osoite int a=1; 0xbfffea64 /* tulostetaan a:n osoite*/ printf(“%p\n”, &a); 0xbfffea68 /* tulostetaan a:n osoite + 1*/ printf(“%p\n”, &a+1); /*
Symbolitaulut Joukko hakuavaimen omaavia tietueita LISÄÄ uusi tietue ETSI tietue hakuavaimen perusteella Sovelluksia: Spell checker etsii sanoja sanakirjasta.
Jatkeet TIES341 Funktio-ohjelmointi 2 Kevät 2006.
5. Kapselointi.
8. Rekursio.
8. Rekursio.
4. Luokan testaus ja käyttö olion kautta
Esityksen transkriptio:

Tietorakenteet ja algoritmit Rekursio Rekursion käyttötapauksia Rekursio määritelmissä Rekursio ongelmanratkaisussa ja ohjelmointitekniikkana Esimerkkejä taulukolla Esimerkkejä linkatulla listalla Hanoin tornit © Hannu Laine 11/9/2012

Rekursio Rekursio tarkoittaa ”palauttamista itseensä”. Rekursiota käytetään Määritelmissä Ongelmanratkaisussa Ohjelmointitekniikkana (toisto) Funktio, joka kutsuu itseään on rekursiivinen © Hannu Laine 11/9/2012

Rekursio määritelmissä Asioita voidaan määritellä rekursiivisesti. Esimerkiksi lista, binääripuu ja kertoma (n!) voidaan määritellä rekursiivisesti. Esimerkkinä kertoman rekursiivinen määrittely. Matemaattinen käsite kertoma määritellään näin 1, kun n= 0 (rekursion kanta) n! = n*(n-1)!, kun n>0 (rekursiivinen osa) Seuraavalla sivulla sovelletaan kertoman määritelmää käytäntöön. © Hannu Laine 11/9/2012

Kertoman määritelmän käyttö Käytetään edellisen sivun kertoman määritelmää ja selvitetään, mitä on 5! 5! = 5*(5-1)! = 5*4! = 5*(4*(4-1)!) = 5*(4*3!) = 5*(4*(3*(3-1)!)) = 5*(4*(3*2!)) = 5*(4*(3*(2*(2-1)!))) = 5*(4*(3*(2*1!))) = 5*(4*(3*(2*(1*(1-1)!)))) = 5*(4*(3*(2*(1*0!)))) = 5*(4*(3*(2*(1*1)))) = 5*(4*(3*(2*1))) = 5*(4*(3*2)) = 5*(4*6) = 5*24 = 120 Pienennetään probleemaa Kanta eli yksinkertainen tapaus löytynyt Palataan ”takaperin” ratkaisuun © Hannu Laine 11/9/2012

Rekursio ohjelmointitekniikkana Rekursiivinen funktio kutsuu itse itseään. Esimerkki. Kertoman laskenta // Rekursiivinen funktio, joka laskee kertoman int factorial(int number) { if (number == 0) return 1; if (number > 0) return number*factorial(number-1); } void main (void) { printf("\nThe factorial of 4 is %d", factorial(4)); Iteratiivinen olisi tässä parempi. Esimerkki annettu periaatteen oppimisen tarkoituksessa. © Hannu Laine 11/9/2012

Rekursio ongelmanratkaisussa Periaate 1. Etsitään yksinkertainen tapaus (ns.rekursion kanta) 2. Palautetaan ongelma itseensä, mutta kooltaan pienennettynä 3. Toistetaan kohtaa 2, kunnes päästään yksinkertaiseen tapauksen (kantaan) 4. Paluu "takaperin" lopulliseen ratkaisuun Esimerkkejä Seuraavaksi käsitellään erilaisia esimerkkejä, kuinka rekursiota käytetään ongelmanratkaisussa ja ohjelmoitaessa ongelman ratkaisevaa funktiota. Esimerkit ovat 1. Taulukon alkioiden tulostus käänteisessä järjestyksessä 2. Taulukon alkioiden järjestyksen kääntö 3. Linkatun listan alkioiden tulostus käänteisessä järjestyksessä 4. Linkatun listan loppuun lisääminen 5. Hanoin tornit © Hannu Laine 11/9/2012

Taulukon alkioiden tulostus käänteisessä järjestyksessä 1 Ajattelutapa Oletetaan, että taulukossa on n alkiota. Yksinkertainen tapaus: Taulukko on tyhjä eli siinä on 0 alkiota. Ratkaisu on yksinkertainen, koska ei tarvitse tulostaa tai tehdä mitään. Probleeman pienentäminen: Jos taulukko ei ole tyhjä eli n > 0. Tulostetaan käänteisessä järjestyksessä yhtä alkiota pienempi taulukko, joka seuraa ensimmäistä alkiota. Tämän jälkeen tulostetaan alkuperäisen taulukon ensimmäinen alkio. Asia ohjelmana seuraavalla sivulla. Sama alkuperäinen ongelma mutta pienempänä © Hannu Laine 11/9/2012

Taulukon alkioiden tulostus käänteisessä järjestyksessä 2 void print_array(const int* arr, int n); void print_in_reverse_order(const int* arr, int n); void main(void) { int array[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; print_array(array, 10); print_in_reverse_order(array, 10); } void print_in_reverse_order(const int* arr, int n) { if ( n == 0) { //printf("\n"); Tulee alkuun return; else { print_in_reverse_order(arr + 1, n - 1); printf("%d ", *arr); Tarkastellaan, miten prosessori suorittaa tämän funktion. void print_array(const int* arr, int n) { const int *p; for (p = arr; p < arr + n; p++) printf("%d ", *p); printf("\n"); } © Hannu Laine 11/9/2012

Taulukon alkioiden järjestyksen kääntö 1 Ajattelutapa Oletetaan, että taulukossa on n alkiota. Yksinkertainen tapaus: Taulukko on tyhjä eli siinä on 0 alkiota. Ratkaisu on yksinkertainen, koska ei tarvitse tehdä mitään. Probleeman pienentäminen: Jos taulukko ei ole tyhjä eli n > 0. Käännetään alkioiden järjestys yhtä alkiota pienemmässä taulukossa, joka seuraa ensimmäistä alkiota. Sitten laitetaan talteen alkuperäisen taulukon ensimmäinen alkio. Seuraavaksi siirretään käännetty pienempi taulukko askel taaksepäin alkuperäisessä taulukossa. Lopuksi viedään talteen laitettu alkuperäisen taulukon ensimmäinen alkio taulukon viimeiseksi. Asia ohjelmana seuraavalla sivulla. Sama alkuperäinen ongelma mutta pienempänä © Hannu Laine 11/9/2012

Taulukon alkioiden järjestyksen kääntö 2 void invert_array(int *array, int n) { int aux; if (n == 0) return; else { aux = *array; invert_array(array+1, n-1); move_one_step_backwards(array, n-1); *(array+n-1) = aux; } void move_one_step_backwards(int *array, int n) { int i; for (i = 0; i < n; i++) array[i] = array[i+1]; Tarkastellaan, miten prosessori suorittaa tämän funktion. © Hannu Laine 11/9/2012

Rekursiivisia funktioita linkatulle listalle Linkatun listan alkioiden tulostus käänteisessä järjestyksessä Tässä rekursio sopii, koska osoittimet on laitettava joka tapauksessa jonnekin talteen. Linkattu merkkilista on määritelty muodossa typedef Tpointer Tlist; Seuraava funktio tulostaa listan käännetyssä järjestyksessä. void print_list_in_reverse (Tlist list) { if (list == NULL) printf("\nList in reverse order :"); else { print_list_in_reverse (list->next); printf("%c ", list->item); } kanta (triviaali tapaus) probleeman ”pienentäminen” © Hannu Laine 11/9/2012

Kuinka rekursiivinen funktio toimii Käydään läpi edellisen sivun funktion toiminta ja oletetaan että linkattu lista on muotoa: c 3000 1000 a 2000 b Luvut 1000, 2000 ja 3000 kuvaavat muistiosoitteita. 1000 3000 2000 NULL Pinon sisältö kun rekursion kanta saavutetaan. © Hannu Laine 11/9/2012

Muita rekursiivisia funktioita linkatulle listalle Linkatun listan loppuun lisääminen insert_to_list_end Rekursiivinen ratkaisu voi olla myös tehottomampi kuin iteratiivinen (pinon ”haaskaus”). Linkattu merkkilista on määritelty muodossa typedef Tpointer Tlist; Rekursiivinen funktio, jolla lisätään alkio listan loppuun. void insert_to_list_end(Tlist *list, Titem data) { if (*list == NULL ) { *list = (Tpointer) malloc(sizeof(Tnode)); (*list) -> item = data; (*list) -> next = NULL;} else insert_to_list_end_1(&((*list)->next), data); } © Hannu Laine 11/9/2012

Rekursion oikea ja ”väärä” käyttö Funktio print_list_in_reverse on esimerkki oikeasta tavasta käyttää rekursiota, koska siinä pinoon tallennettavaa ”historiaa” todella tarvitaan. Rekursion oikeaa käyttöä ei ole toteuttaa sillä vain toisto, koska funktion parametrit ja mahdolliset paikalliset muuttujat viedään joka kutsukerralla uudelleen pinoon ja näin haaskataan pinomuistia. © Hannu Laine 11/9/2012

Hanoin tornit Klassinen esimerkki rekursiosta probleemanratkaisussa: Hanoin tornit. Probleeman kuvaus: Kultalevyt sauvassa a on siirrettävä sauvaan c sauvaa b hyväksikäyttäen siten, että 1. Missään vaiheessa isompi levy ei ole pienemmän päällä missään sauvassa. 2. Vain yksi levy kerrallaan saa olla pois sauvoista. Käydään läpi ongelman rekursiivisen ratkaisun ajatteluperiaate alla olevan kuvan avulla. Ratkaisun periaate: 1. siirretään n-1 levyä sääntöjä noudattaen tangosta a tankoon b käyttäen hyväksi tankoa c 2. siirretään tankoon a jäänyt suurin levy tankoon c 3. siirrettään n-1 levyä sääntöjä noudattaen tangosta b tankoon c käyttäen hyväksi tankoa a © Hannu Laine 11/9/2012

Hanoin tornien ongelman ratkaiseva ohjelma #include <stdio.h> void siirra (int n, char tanko1, char tanko2, char tanko3) { // seuraavilla riveillä voitaisiin testata, montako kertaa funktiossa on käyty // static int kerta = 0; // printf(”Kerta := %d n = %d\n", kerta++, n); if (n==1) printf("\n Siirrä tangosta %c tankoon %c ", tanko1, tanko3); else { siirra(n - 1, tanko1, tanko3, tanko2); siirra(n - 1, tanko2, tanko1, tanko3); } void main (void) { int n; printf("\n Montako levyä :"); scanf("%d", &n); printf("\n Käytä seuraavia siirtoja "); siirra(n, 'a', 'b', 'c'); © Hannu Laine 11/9/2012

Hanoin tornien kutsupuu © Hannu Laine 11/9/2012

Rekursion, pinon ja puiden yhteydet. Rekursio, pino ja puut ovat kiinteästi yhteen “kietoutuneita”. Rekursion toteuttamiseen käytetään pinoa. Rekursiivisen funktion, jossa funktio kutsuu itseään kaksi kertaa, kutsuista muodostuu ns. kutsupuu. Tietorakenne puu määritellään rekursiivisesti. Useimmat puita käsittelevät operaatiofunktiot toteutetaan rekursiivisesti. Puihin tutustutaan paremmin osassa 13 © Hannu Laine 11/9/2012

Lisää rekursiolle sopivia probleemoita Sivulla 6 mainittiin eräitä yksinkertaisia probleemoita, jotka voidaan ratkaista rekursiivisesti, vaikka niiden iteratiivinen ratkaisukin on melko suoraviivainen. Seuraavassa esimerkkejä, joissa rekursio yksinkertaistaa huomattavasti ratkaisua: Infix-lausekkeen muuntaminen postfix-muotoon Ruudukossa olevan mielivaltaisen yhtenäisen tahran koon laskeminen (labratehtävänä) Puumaisen hakemistorakenteen läpikäynti Reitin etsintä verkosta Monet binäärisen etsintäpuun operaatiofunktiot Jne Muista myös mitä sivulla 14 on sanottu © Hannu Laine 11/9/2012