T-106.250/253 Tietorakenteet ja algoritmit T/Y



Samankaltaiset tiedostot
Tietorakenteet ja algoritmit Johdanto Lauri Malmi / Ari Korhonen

Tietorakenteet ja algoritmit - syksy

Algoritmianalyysin perusteet

A TIETORAKENTEET JA ALGORITMIT

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

A TIETORAKENTEET JA ALGORITMIT

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

Tietorakenteet ja algoritmit. Kertaus. Ari Korhonen

9/18/02 1. Tietorakenteet ja algoritmit Y. Syksy Dipoli T

Lineaariset perustietorakenteet

Algoritmit 1. Luento 3 Ti Timo Männikkö

Algoritmit 2. Luento 2 To Timo Männikkö

Algoritmien suunnittelumenetelmiä

Algoritmit 2. Luento 2 Ke Timo Männikkö

Hakupuut. tässä luvussa tarkastelemme puita tiedon tallennusrakenteina

Tietorakenteet ja algoritmit Puurakenteet Ari Korhonen

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

TIETORAKENTEET JA ALGORITMIT

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

Sisällys. 18. Abstraktit tietotyypit. Johdanto. Johdanto

3. Binääripuu, Java-toteutus

811312A Tietorakenteet ja algoritmit II Perustietorakenteet

18. Abstraktit tietotyypit 18.1

Pino S on abstrakti tietotyyppi, jolla on ainakin perusmetodit:

ALGORITMIT 1 DEMOVASTAUKSET KEVÄT 2012

Tietorakenteet ja algoritmit

Algoritmit 2. Luento 7 Ti Timo Männikkö

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

Algoritmit 1. Luento 8 Ke Timo Männikkö

Algoritmit 1. Demot Timo Männikkö

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

4 Tehokkuus ja algoritmien suunnittelu

Muuttujien roolit Kiintoarvo cin >> r;

Lyhyt kertaus osoittimista

Kaksiloppuinen jono D on abstrakti tietotyyppi, jolla on ainakin seuraavat 4 perusmetodia... PushFront(x): lisää tietoalkion x jonon eteen

Rakenteiset tietotyypit Moniulotteiset taulukot

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

Algoritmit 1. Luento 4 Ke Timo Männikkö

1 Puu, Keko ja Prioriteettijono

Algoritmit 1. Luento 2 Ke Timo Männikkö

A TIETORAKENTEET JA ALGORITMIT

Tieto- ja tallennusrakenteet

2) Aliohjelma, jonka toiminta perustuu sivuvaikutuksiin: aliohjelma muuttaa parametrejaan tai globaaleja muuttujia, tulostaa jotakin jne.

Algoritmit 1. Luento 7 Ti Timo Männikkö

Tietorakenteet, laskuharjoitus 3, ratkaisuja

Algoritmit 2. Luento 4 To Timo Männikkö

811312A Tietorakenteet ja algoritmit III Lajittelualgoritmeista

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

Tietorakenteet, laskuharjoitus 6,

Algoritmit 2. Luento 4 Ke Timo Männikkö

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

Kysymyksiä koko kurssista?

Algoritmit 1. Luento 6 Ke Timo Männikkö

Java-kielen perusteet

A TIETORAKENTEET JA ALGORITMIT

Tiraka, yhteenveto tenttiinlukua varten

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

Tietorakenteet ja algoritmit

811312A Tietorakenteet ja algoritmit Kertausta kurssin alkuosasta

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

8. Lajittelu, joukot ja valinta

1 Erilaisia tapoja järjestää

Algoritmit 2. Luento 8 To Timo Männikkö

4. Joukkojen käsittely

Muita linkattuja rakenteita

Tietueet. Tietueiden määrittely

Tietorakenteet ja algoritmit

Tietorakenteet, laskuharjoitus 7, ratkaisuja

Algoritmit 1. Demot Timo Männikkö

811312A Tietorakenteet ja algoritmit, VI Algoritmien suunnitteluparadigmoja

Tietorakenteet ja algoritmit

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.

Koottu lause; { ja } -merkkien väliin kirjoitetut lauseet muodostavat lohkon, jonka sisällä lauseet suoritetaan peräkkäin.

1.1 Tavallinen binäärihakupuu

Jakso 3 Konekielinen ohjelmointi (TTK-91, KOKSI)

Tutkimusmenetelmät-kurssi, s-2004

Tietorakenteet ja algoritmit

10. Painotetut graafit

815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset

811312A Tietorakenteet ja algoritmit, , Harjoitus 7, ratkaisu

Luku 8. Aluekyselyt. 8.1 Summataulukko

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

Jakso 3 Konekielinen ohjelmointi (TTK-91, KOKSI)

Kääreluokat (oppikirjan luku 9.4) (Wrapper-classes)

Algoritmit 2. Luento 3 Ti Timo Männikkö

Java-kielen perusteet

Algoritmit 1. Luento 12 Ti Timo Männikkö

Binäärihaun vertailujärjestys

Algoritmi on periaatteellisella tasolla seuraava:

Listarakenne (ArrayList-luokka)

Sisältö. 22. Taulukot. Yleistä. Yleistä

Operaattoreiden ylikuormitus. Operaattoreiden kuormitus. Operaattoreiden kuormitus. Operaattoreista. Kuormituksesta

Imperatiivisen ohjelmoinnin peruskäsitteet. Meidän käyttämän pseudokielen lauseiden syntaksi

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

Algoritmit 1. Luento 1 Ti Timo Männikkö

Algoritmit 2. Luento 14 Ke Timo Männikkö

Algoritmit 2. Demot Timo Männikkö

TKT20001 Tietorakenteet ja algoritmit Erilliskoe , malliratkaisut (Jyrki Kivinen)

tietueet eri tyyppisiä tietoja saman muuttujan arvoiksi

Tietorakenteet ja algoritmit

Transkriptio:

SIS LLYS 1. JOHDANTO 2. OHJELMOINNIN PERUSTEIDEN KERTAUS 3. ALGORITMITEORIAN PERUSAJATUKSIA 4. LINEAARISET PERUSTIETORAKENTEET 5. ALGORITMIANALYYSI 6. PUURAKENTEET 22.1.2002 1 1. JOHDANTO 1.1 MŠŠritelmiŠ 1.2 Tietorakenteen ja algoritmin valinta 1.3 Algoritmit ja tiedon mššrš 1.4 Tietorakenteet ja toiminnot 1.5 Esimerkki: lineaarinen vs. eksponentiaalinen toteutus 22.1.2002 2

1.1 MŠŠritelmiŠ Algoritmi: EpŠformaalisti: tšsmšllinen menettelytapa, joka ratkaisee jonkin hyvin mššritellyn laskennallisen ongelman. MŠŠritelmŠ: Algoritmi on ŠŠrellinen jono yksikšsitteisiš, ŠŠrellisellŠ tyšllš suoritettavissa olevia kšskyjš, jotka laskevat funktion Ä: I O I on syštejoukko O on tulosjoukko kaikilla i I, algoritmi pysšhtyy s.e., o = Ä(i) O Tietorakenne: Funktion Ä tehokas laskenta edellyttšš, ettš syštejoukko I on hyvin organisoitu PŠteekš sama tulosjoukolle O? Voidaan kuvata tietotyyppeinš Alkeistyypit, perustietotyypit, abstraktit tietotyypit MŠŠritelmŠ: Tietorakenne on joukko tietyn tyyppisiš muuttujia, joilla on jokin mššrštty rakenne. Tietotyypin toteutus 22.1.2002 3 1.2 Tietorakenteen ja algoritmin valinta Sama asia tai toiminto voidaan toteuttaa lukemattoman monella eri tavalla tietokoneohjelmana Eri toteutusten paremmuutta voidaan verrata monessa suhteessa, mm. : toimintojen nopeus (algoritmit) vaadittu muistitila (tietorakenteet) ohjelmakoodin laatu ja yllšpidettšvyys toteutuksen avoimuus laajennuksille TŠllŠ kurssilla keskitytššn kahteen ensimmšiseen nškškulmaan L OPTIMOI KOODIA - VALITSE PAREMPI ALGORITMI 22.1.2002 4

Usein valitsemalla sopiva tiedon esitysrakenne voidaan merkittšvšsti vaikuttaa jonkin algoritmin tehokkuuteen Esimerkki 1: Haku linkitetystš listasta tai haku tasapainotetusta binššripuusta EdellisessŠ hakuaika on suoraan suhteessa talletettujen alkioiden lukumššrššn JŠlkimmŠisessŠ hakuaika on suhteessa talletettujen alkioiden lukumššršn logaritmiin N log 2 N 1000 10 1000000 20 Ê 22.1.2002 5 Esimerkki 2: Miten tallentaa maantieverkko? Seuraajalistana, eli luetellaan jokaiselle solmulle ne solmut, joihin kyseisestš solmusta pššsee Vierusmatriisina (2-ulotteisena taulukkona), jolloin jokaiselle solmuparille merkitššn, onko niiden všlillš yhteyttš (1) vai ei (0) Seuraajalista vaatii tilaa sen verran kuin yhteyksiš on olemassa Vierusmatriisi vaatii tilaa suhteessa solmujen lukumššršn neliššn riippumatta yhteyksien mššršstš Vierusmatriisi voi olla tehokkaampi, jos verkko on tiheš 22.1.2002 6

1.3 Algoritmit ja tiedon mššrš Algoritmin nopeus riippuu tiedon mššršstš (syštteen pituus) Esimerkki 3: Taulukon lajittelu Valintalajittelu on hyvin helppo ymmšrtšš ja toteuttaa Quicksort on paljon mutkikkaampi Valintalajittelun tehokkuus on suhteessa alkioiden lukumššršn N neliššn Quicksortin tehokkuus vastaavasti lukuun N log N N N*log 2 (N) N 2 10 30 100 10 3 1*10 4 10 6 10 6 2*10 4 10 12 22.1.2002 7 Esimerkki 4: Alkioiden (N kpl) talletus listaan Jos kukin alkio talletetaan listan alkuun, eikš listaa pidetš jšrjestyksessš, alkioiden talletus kšy lineaarisessa ajassa (yksittšisen alkion talletus vie vakioajan) Jos kukin alkio talletetaan listan loppuun ja paikka haetaan aina listan alusta lšhtien, alkioiden talletus kšy ajassa, joka on suhteessa listan pituuden neliššn Jos kukin alkio talletetaan listan loppuun ja samalla yllšpidetššn osoitinta listan viimeiseen alkioon, alkioiden talletus kšy taas lineaarisessa ajassa 22.1.2002 8

1.4 Tietorakenteet ja toiminnot Tietorakenteen tehokkuus riippuu siihen kohdistuvista toiminnoista (oikea abstraktio, frekvenssit, jne.) Esimerkki 5: Haetaan tiettyš tietuetta suuresta mššršstš tietueita Jos tiedot ovat staattisia, ne voidaan tallentaa taulukkoon suuruusjšrjestyksessš ja hakea sieltš vaikka binššri- eli puolitushaulla Hakuaika on silloin suhteessa taulukon koon logaritmiin Jos lisštššn uusia tietueita tai poistetaan vanhoja, taulukko pitšš jšrjestšš kokonaan uudelleen. TŠssŠ vaiheessa aikaa kuluu lineaarisesti suhteessa taulukon kokoon. Jos tiedot talletetaan tasapainotettuun binššriseen hakupuuhun, tieto voidaan edelleen hakea logaritmisessa ajassa, mutta myšs lisšykset ja poistot voidaan tehdš logaritmisessa ajassa 22.1.2002 9 1.5 Esimerkki: lineaarinen vs. eksponentiaalinen toteutus Esimerkki 6: Fibonacci-luvut F(0) = F(1) = 1 F(i) = F(i-1) + F(i-2) Lineaarinen menetelmš, kšytetššn muuttujia x, y ja z ja pyšritetššn niitš seuraavassa luupissa z = y + x; x = y; y = z suoritusaika verrannollinen N:ŠŠn 22.1.2002 10

Exponentiaalinen menetelmš, sovelletaan suoraan mššritelmšš rekursiivisesti F3 F4 F5 F3 F6 F2 F2 F1 F2 F3 F4 F1 F2 F1 Laskettaessa F6:n arvoa, lasketaan: F0 F5 F4 F3 F2 F1 1 kerran 2 kertaa 3 kertaa 5 kertaa 8 kertaa F2 F1 F1 F0 F1 F0 F1 F0 F1 F0 Koska pštee, ettš F100 Å F 100, missš F Å 1.618, seuraa, ettš F100:n laskemiseen tarvitaan luokkaa 10 18 operaatiota... 22.1.2002 11 2. OHJELMOINNIN PERUSTEIDEN LYHYT KERTAUS 2.1 YleistŠ 2.2 Taulukko 2.3 Linkitetyn listan (linked list) toteutus 2.4 Tapausesimerkki Polynomi 2.5 Rekursio 22.1.2002 12

2.1 YleistŠ Esitiedot: kyky ymmšrtšš yksinkertaista lausekielistš ohjelmakoodia sekš alkeistyypeillš toteutettuja yksinkertaisia rakenteita Erityisesti: lineaaristen tietorakenteiden toteutus Tietorakenne on lineaarinen, jos kaikki sen alkiot on ryhmitetty perškkšin. TŠllaista rakennetta voidaan kšyttšš esim. yksinkertaisena hakurakenteena, tilapšisenš tallennusrakenteena. 22.1.2002 13 2.2 Taulukko Kuuluu yleisimpien ohjelmointikielten perusrakenteisiin Taulukon mššrittely C-kielessŠ: < type > < name >[<number of elements>] esim. int numbers[10]; numbers[5] = 1; indeksointi alkaa nollasta (0 - N-1) Moniulotteiset taulukot Dynaaminen taulukko 22.1.2002 14

2.3 Linkitetyn listan (linked list) toteutus Lista toteutetaan tyypillisesti osoitinmuuttujien ja dynaamisen muistinvarauksen avulla. Voidaan toteuttaa myšs taulukon avulla Tyypillinen mššrittely C-kielessŠ: struct node { int data; struct node * next; ; typedef struct node * List_t; List_t p, q, r; Esimerkkilista: p 20 10 13 11 K2.1 22.1.2002 15 q r ErŠs mššrittelytapa Java-kielessŠ: Ê class ListNode { private Object data; private ListNode next; ListNode(Object element) { data = element; next = null; Listnode p, q, r; 22.1.2002 16

Alkion poistaminen kšy helposti, kun on kšsillš osoitin poistettavaa alkiota edeltšvššn alkioon: (C) (Java) r = q->next; q->next = r->next; free(r); p 20 10 13 11 r = q.next; q.next = r.next; K2.2 q r EnsimmŠisen alkion poistaminen on erikoistapaus: r = p; r = p; p = p->next; p = p.next; free(r); 22.1.2002 17 Kuinka hoitaa myšs ensimmšinen alkio samalla koodinpštkšllš kuin muutkin? => MŠŠritellŠŠn yksi ylimššršinen header- alkio, jonka tarkoitus on aloittaa lista p head 20 10 13 11 K2.4 Samasta syystš (erikoistapausten všlttšminen) toisinaan mššritellššn listan loppuun ylimššršinen alkio z, josta on viittaus itseensš (Sedgewick: Algorithms) p head 20 10 13 z 22.1.2002 18 K2.5

class LinkedList { private ListNode header; private static ListNode z = new ListNode(null); LinkedList () { header = new ListNode(null); header.next = z; public AddFirst(Object element) { private ListNode temp = new Listnode(element); temp.next = header.next; header.next = temp; 22.1.2002 19 Useampi lista voi kšyttšš samaa z-alkiota Listan loppumisen tarkastaminen: if (q == q->next)...; TAI if (q == z)... Alkion lisššminen on helppoa, kun kšsillš on osoitin siihen alkioon, jonka jšlkeen uusi alkio sijoitetaan p 20 10 13 11 K2.3 r = malloc(sizeof(node)); r->data = 99; r->next = q->next; q->next = r; r q 99 22.1.2002 20

EsimerkkejŠ listan kšsittelyfunktioiden toteuttamisesta: TULOSTA : void print_list(list_t head) { List_t temp; Ê temp = head->next; if (temp == z) printf("list is empty\n"); else { while (temp!= z) { printf("%d ",temp->data); temp = temp->next; printf("\n"); /* print_list */ 22.1.2002 21 EsimerkkejŠ listan kšsittelyfunktioiden toteuttamisesta: TULOSTA : Public void print_list(linkedlist head){ ListNode temp; Ê temp = head.next; if (temp == z) System.out.print("List is empty"); else { while (temp!= z) { System.out.print(temp.data+Ó Ò); temp = temp.next; 22.1.2002 22

LIS ALKIO LISTAN ALKUUN : List_t insert(list_t head, int key) { List_t temp; Ê temp = get_node(); temp->data = key; temp->next = head->next; head->next = temp; return (temp); /* insert */ 22.1.2002 23 HAE ALKIO : List_t search(list_t head, int key) { List_t temp; Ê z->data = key; temp = head->next; while (temp->data!= key) temp = temp->next; Ê return (temp); /* search */ 22.1.2002 24

POISTA ALKIO : Boolean delete(list_t head, int key){ Ê List_t temp, previous; z->data = key; previous = head; temp = head->next; Ê while (temp->data!= key) { temp = temp->next; previous = previous->next; Ê if (temp!= z) { previous->next = temp->next; free (temp); return (TRUE); else return (FALSE); /* delete */ 22.1.2002 25 Lista voidaan toteuttaa myšs taulukon avulla Tarvitaan 2 taulukkoa; data[0..n] next[0..n] arvot osoittimet data next 0 head 4 z 1 T 6 I 5 L 3 S 2 6 A 1 p h e a d L I S T A z 22.1.2002 26 K2.7

Useat listat voivat kšyttšš samaa taulukkoa. Kaksisuuntainen linkitetty lista on nopeampi kšsitellš, mutta vaatii enemmšn muistitilaa. p E E S T A A S K2.8 struct node { char data; struct node *next, *previous; ; Ê typedef struct node * Dlist_t; 22.1.2002 27 2.4 Tapausesimerkki POLYNOMI A i X i i=0...n Jos polynomi on ÔtiheŠÕ l. suurin osa kertoimista poikkeaa nollasta => EsitetŠŠn kertoimet taulukossa Ê Ê #define MAX 1000 struct polynomi { int kerroin[max+1]; int asteluku; ; typedef struct polynomi Polynomi; 22.1.2002 28

Jos polynomi on ÔharvaÕ Ê => EsitetŠŠn kertoimet jšrjestettynš listana struct polynomi { int kerroin, eksponentti; struct polynomi * next; ; typedef struct polynomi * Polynomi; Ei rajaa polynomin asteluvulle! 22.1.2002 29 Toteutetaan polynomeille operaatio: void A_kertaa_B_on_C(Polynomi a,b,c) { Ê /* Toteutus riippuu valitusta tietorakenteesta */... => kšsitellššn polynomia abstraktiona!!! Kutsuvan ohjelman ei tarvitse tietšš miten kertoimet on talletettu, toteutustapaa voidaan vaihtaa tarpeen mukaan!! 22.1.2002 30

2.5 REKURSIO Rekursiivinen ohjelma Kutsuu itseššn Rekursiivinen funktio On mššritelty itsensš avulla Esim. Fibonacci-luvut: X(i) = X(i-1) + X(i-2), X(0) = X(1) = 1 22.1.2002 31 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 22.1.2002 32

Rekursion neljš kultaista sššntšš: Perustapaukset (ratkaistavissa ilman rekursiota) Edistyminen (liikutaan perustapausta kohti) Oletus (kaikki rekursiiviset kutsut toimivat) VŠltŠ turhaa tyštš (jokainen tapaus ratkaistaan vain kerran) 22.1.2002 33 Esim. Kertoma rekursiivisena: int factorial(int n) { if (n==0) return 1; else return n*factorial(n-1); Esim. Kertoma ei-rekursiivisena: int factorial(int n) { int i,fact; Ê fact = 1; for (i=2; i<=n; i++) fact= fact*i; return fact; 22.1.2002 34

Esim. Fibonacci-luvut: int fibonacci(int n) { if (n<=1) return 1; else return fibonacci(n-1)+fibonacci(n-2); Ê {Rikkoo neljšttš sššntšš F4 F5 F3 F6 F3 F4 F2 Parempi toteuttaa eirekursiivisena F3 F2 F2 F1 F2 F1 F1 F0 F2 F1 F1 F0 F1 F0 F1 F0 22.1.2002 F1 F0 35 Esim. Hanoin tornit: SiirrŠ renkaat toiseen tappiin yksi kerrallaan niin, ettš isompi rengas ei koskaan ole pienemmšn pššllš: Mis tä Minne Via K2.17 22.1.2002 36

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); printf(ósiirrš rengas tapista %d tappiin %d, kiitos\nó, mista, minne); hanoi(n-1, via, minne, mista); Mistä Minne Via 22.1.2002 37 K2.17 Hajota ja hallitse ÐmenetelmŠ algoritmisuunnittelussa TehdŠŠn kaksi rekursiivista kutsua, toinen datan yhteen puolikkaaseen ja toinen jšljelle jššneeseen osaa. ErŠs hyvin keskeinen periaate algoritmisuunnittelussa. 22.1.2002 38

3. ALGORITMITEORIAN PERUSAJATUKSIA 3.1 Algoritmit suhteessa tietorakenteisiin 3.2 Algoritmien vertailu 3.3 Algoritmien toteutus 3.4 Abstraktit tietotyypit 22.1.2002 39 3.1 Algoritmit suhteessa tietorakenteisiin Useimmat algoritmit kšsittelevšt jotain tietorakennetta, eikš atomista dataa KŠsiteltŠvŠ data on siten joukko data-alkioita, jotka muodostavat jonkin kokonaisuuden. Algoritmi kšsittelee tštš kokonaisuutta eli tietorakennetta. Esimerkiksi: Lajitellaan tieto suuruusjšrjestykseen EtsitŠŠn jotain yksittšistš tietoa suuresta tietojoukosta Tietojoukon yksittšisten alkioiden všlillš voi olla yhteyksiš, jotka yksilšivšt alkion suhteen muihin alkioihin (verkot) Data esittšš jotain kokonaisuutta koordinaattiavaruudessa 22.1.2002 40

3.1.1. Algoritmi Implementaatio: - method, function, procedure, pvm_spawn,...? Syšte I Tulos O Toimenpiteet, joilla annetulla laillisella syštteellš tulos O voidaan laskea Toimenpide? Laskettavissa ŠŠrellisellŠ mššršllš resursseja Šrellinen kestoaika PysŠhtyy, s.e. O = f(i) (laskenta pššttyy, oikeellisuus) 22.1.2002 41 MitkŠ seuraavista ovat algoritmeja? 1) // eršs C-kielen pššohjelma main() { printf( Input two real numbers ); scanf( %f%f,&x, &y); if (x>y) { float temp; temp=x; x=y; y=temp; ; printf( input a number ); scanf( %f,&z); if ( z>x && z<y? 1 : 0) printf( %f is between %f and %f\n,z,x,y); else printf( %f is not between %f and %f\n,z,x,y); 2) // eršs Java metodi; A on luokkamuuttuja public void togglea() { A =!A; 22.1.2002 42

MitkŠ seuraavista ovat algoritmeja? 3) // eršs C++ pššohjelma #include <fstream> int main() { using namespace std; int intvalue; float realvalue; ifstream indata; ofstream outdata; indata.open( input.dat ); outdata.open( output.dat ); indata >> intvalue; indata >> realvalue; outdata << The input values are << intvalue << and << realvalue << endl; return 0; 22.1.2002 43 3.1.2 Tietorakenteiden kšsitteellinen luokittelu Luokitteluun on erilaisia lšhestymistapoja: MitkŠ seuraavista ovat tietorakenteita? Bitti Boolean Integer Taulukko Tuple Double Verkko 22.1.2002 44

Atominen tieto vs. rakenteinen tieto Riippuu abstraktiotasosta Staattinen vs. dynaaminen tietorakenne MikŠ seuraavista on staattinen, mikš dynaaminen tietorakenne? Taulukko Tietue Dynaaminen taulukko Linkitetty lista Verkko BinŠŠripuu Muistinvaraus kiinteš tai dynaaminen 22.1.2002 45 Alkion saavutettavuus: MitŠ eroa? Taulukko Tietue Linkitetty lista BinŠŠripuu Verkko Alkion paikka voidaan laskea vakioajassa tai sitten ei. 22.1.2002 46

Abstraktiotaso MitŠ eroa? BinŠŠripuu JŠsennyspuu BinŠŠrinen hakupuu Taulukko 1 * + 3 2 A B C D G Hajautustaulukko Talletusrakenne vai semanttinen rakenne: Rakenne voi olla puhdas talletusrakenne tai abstrakti tietotyyppi, jolla on jokin semantiikka 22.1.2002 47 3.2 Algoritmien vertailu Jos sama asia voidaan toteuttaa eri tavoin, tšytyy jotenkin pystyš arvioimaan, mikš toteutus on kulloinkin hyvš VertailukriteereitŠ on monia: Algoritmin askelmššrš suhteessa kšsiteltšvšn tiedon mššrššn ü ü ü Pahin mahdollinen askelmššrš KeskimŠŠrŠinen askelmššrš Tasattu askelmššrš Algoritmin kuluttama todellinen cpu-aika (usein ongelmallinen arvioitava) Algoritmin/tietorakenteen vaatima muistitila suhteessa kšsiteltšvšn tiedon mššrššn => ALGORITMIANALYYSI Algoritmin toteutuksen monimutkaisuus (kannattaako optimointi?) 22.1.2002 48

3.3 Algoritmien toteutus Ohjelman yllšpidettšvyyden kannalta on ehdottomasti jšrkevšš toteuttaa tšrkeš algoritmi siten, ettš sen mahdollinen vaihtaminen tehokkaampaan vaikuttaa mahdollisimman všhšn muuhun ohjelmaan ABSTRAKTIT TIETOTYYPIT (ADT, Abstract data type) Usein algoritmit esitetššn pseudokielellš ( la Pascal) ja jštetššn toteutuksen pienimmšt yksityiskohdat avoimiksi Algoritmin perusajatusta on helpompi ymmšrtšš, kun ei tarvitse kiinnittšš huomiota ohjelmointikielen syntaksiin Kuvaus on kieliriippumaton 22.1.2002 49 3.4 Abstraktit tietotyypit MŠŠritellŠŠn tietorakenteeseen kohdistuvat operaatioit Ei oteta kantaa, miten operaatiot toteutetaan Otetaan kantaa, mitš operaatiot tekevšt (riittšvš tarkkuustaso!) Mahdollistaa toteutuksen muuttamisen joustavasti EsimerkkejŠ: A) Joukko abstraktina tietotyyppinš MŠŠritellŠŠn vaikkapa operaatiot: - Leikkaus; Set cut(set A, Set B) - Unioni; Set union(set A, Set B) - Komplementti; Set cmpl(set A, Set superset) - Koko (= alkioiden mššrš); int size(set A) - Kuuluu joukkoon?; boolean in(element E, Set A) 22.1.2002 50

Operaatiot toteutetaan aliohjelmina Muualla ohjelmassa voidaan kutsua y.o. operaatioita tarvitsematta tietšš, miten alkiot on talletettu (taulukko, lista, puu,...) B) Hakurakenne abstraktina tietotyyppinš MŠŠritellŠŠn, ettš hakurakenne on kokoelma tietueita, jotka voidaan yksiselitteisesti tunnistaa niihin talletetun hakuavaimen arvon perusteella MŠŠritellŠŠn esimerkiksi operaatiot Element Search(Key K) - Etsi tietue annetulla hakuavaimella Element Insert(Key K, Data D) - LisŠŠ rakenteeseen tietue Element Delete(Key K) - Poista rakenteesta tietue Element Next(Element E) [Previous] - Etsi annettua tietuetta lšhinnš seuraava [edellinen] tietue Element[] Print(Key From, Key To) - Etsi tietueet, joiden avainarvot ovat avainarvojen [From,To] všlissš 22.1.2002 51 C) Prioriteettijono abstraktina tietotyyppinš MŠŠritellŠŠn, ettš rakenne on kokoelma alkioita, joihin jokaiseen liittyy alkion suhdetta muihin alkioihin kuvaava prioriteetti MŠŠritellŠŠn esimerkiksi operaatiot Insert(Element E, int P) - LisŠŠ alkio ja aseta sen prioriteetiksi P Element DeleteMax() - Poista ja palauta alkio, jonka prioriteettiarvo on suurin (tai deletemin - pienin) DecreaseKey(Element E, int delta) - pienennš (tai IncreaseKey - suurenna) alkion prioriteettiš deltalla D) Ohjelmointikielet ja abstraktit tietotyypit Esim. C-kielen standardityypit on toteutettu ADT:nŠ: int (16-32 bit) float,double (IEEE,..) char ( 8 bit) 22.1.2002 52

Tiedostojen kšsittely, FILE * Standardi-C ei sisšllš mekanismia, jolla voitaisiin mššritellš abstrakteja tyyppejš Ohjelmoija voi tosin noudattaa samaa periaatetta: MŠŠritellŠŠn aliohjelmat, joilla kšsitellššn tietyntyyppisiš objekteja Ei kšytetš tyypin rakennetta nšiden aliohjelmien ulkopuolella KŠsiteltŠvŠ objekti všlitetššn aliohjelmille muuttujaparametrina KŠsittelyaliohjelmat kootaan yhteen paikkaan ja nimetššn loogisesti VASTUU EHEYDEN NOUDATTAMISESTA J OHJELMOIJALLE OliokielissŠ abstraktit tietotyypit mššritellššn yleensš rajapintoina ja toteutetaan luokkina (Java, C++) 22.1.2002 53 4. LINEAARISET PERUSTIETORAKENTEET 4.1 Johdanto 4.2 Taulukko 4.3 Linkitetty lista (linked list) 4.4 Pino (stack) 4.5 Jono (queue) 4.6 Pakka (deque) 22.1.2002 54

4.1 Johdanto Tietorakenne on lineaarinen, jos kaikki sen alkiot on ryhmitetty perškkšin. TŠllaista rakennetta voidaan kšyttšš esim. yksinkertaisena hakurakenteena, tilapšisenš tallennusrakenteena. 22.1.2002 55 4.2 Taulukko Hyvin yksinkertainen lineaarinen rakenne. Perusrakenne valmiina useimmissa korkean tason ohjelmointikielissš. => Helppo ohjelmoida Alkiot indeksoidaan ensimmšisestš viimeiseen. Mihin tahansa alkioon voidaan heti viitata. Taulukon alkioiden všliin ei voi lisštš uutta alkiota eikš sieltš voi poistaa alkiota. => Rakenne on erittšin jšykkš, jos tšllaisia toimintoja (pšivityksiš) tarvitaan. 22.1.2002 56

4.3 Linkitetty lista (linked list) Taulukkoa paljon joustavampi rakenne monessa tilanteessa. Lista koostuu yksittšisistš alkioista, joihin kuhunkin on talletettu dataa ja osoitin (referenssi) seuraavaan alkioon. Listan kokoa ei ole ennalta rajoitettu, vaan listaan voidaan lisštš ja siitš voidaan poistaa alkioita vapaasti. => Listan kokoa rajoittaa vain kšytettšvissš oleva muisti. Alkioita voi lisštš minne tahansa. Alkioita voi poistaa mistš tahansa. Alkioiden jšrjestystš voi vaihtaa. Listan alkiot voivat olla samaa tyyppiš tai lista voi olla geneerinen. 22.1.2002 57 LINKITETYN LISTAN T RKEIN RAJOITUS Alkioita voi kšydš lšpi vain yksitellen, ts. alkioihin ei voi viitata suoraan (vrt. taulukko) TŠrkeimmŠt operaatiot ovat: TULOSTUS HAKU LIS YS POISTO P IVITYS TYHJ N LISTAN LUOMINEN N:NNEN ALKION PALAUTTAMINEN ONKO LISTA TYHJ? É 22.1.2002 58

Eri operaatioitten vaatima aika: TULOSTUS N HAKU N/2 (epšonnistunut: N) LIS YS 1 POISTO N/2 Lista voidaan pitšš jšrjestyksessš, jolloin (epšonnistunut) haku on nopeampi TiedetŠŠn, ettei enšš kannata etsiš, kun oikea kohta on jo ohitettu LisŠys on vastaavasti hitaampi (ei voidakaan lisštš aina listan alkuun) Listasta voidaan muodostaa rengas p 17 20 10 13 99 22.1.2002 K2.6 59 4.4 Pino (stack) Pino on abstrakti tietotyyppi, jolle on mššritelty seuraavat operaatiot: Push(x) lisšš pinon pššlle alkion x Pop palauttaa (ja poistaa) pinon pššllimmšisen alkion Toimii samaan tapaan kuin pšydšllš oleva korttipakka Top palauttaa pinon pššllimmšisen alkion (poistamatta sitš) Empty palauttaa tiedon siitš, onko pino tyhjš 22.1.2002 60

Jonokuri LIFO (Last In - First Out) Kaikki pino-operaatiot voidaan toteuttaa vakioajassa (ei riipu pinon koosta) Pino voidaan implementoida eri tavoin, mm. taulukon avulla tai linkitettynš listana Toteutus taulukkona, apuna pino-osoitin, joka osoittaa pinon pššllimmšiseen alkioon:... 7 6 empty: (sp == -1) Taulukkototeutuksessa pinolle varattu tila voi loppua 5 4 3 2 1 0 K2.13 22.1.2002 61 sp Toteutus listana: top K2.14 push: liitš uusi alkio listan alkuun pop: poista ja palauta alkio listan alusta empty: (top == NULL) 22.1.2002 62

Pinon sovelluksia ohjelmointikielessš lausesulkujen tarkastus: kullekin alkusululle lšytyy oikeantyyppinen loppusulku kielessš voi esiintyš useita eri sulkutyyppejš, esim. C- kielessš (), [], { sulkuvirheet voivat usein sotkea kššntšjšn toiminnan pahoin 22.1.2002 63 yksinkertainen tarkistusohjelma luetaan merkki kerrallaan tutkitaan vain sulkumerkkejš alkusulku asetetaan pinoon kohdattaessa loppusulku popataan pinosta pššllimmšinen sulku ü jos pino on tyhjš tai sulku on vššršn tyyppinen => virhe Ohjelman lopussa pinon tulee olla tyhjš 22.1.2002 64

Lausekkeen arvon laskeminen Miten evaluoida lausekkeen arvo? Infix-notaatio: 5 * ( ( 9 + 8 ) * 4 * 6 + 7 ) Miten tallentaa všlitulokset? MikŠ on toimintajšrjestys, kun lauseke luetaan ohjelmalle merkki merkiltš? 22.1.2002 65 Periaate: 1) Muunnetaan lauseke pinon avulla postfix-muotoon: 5 9 8 + 4 * 6 * 7 + * 2) Evaluoidaan postfix-lauseke pinon avulla 22.1.2002 66

INFIX-POSTFIX-muunnos pinon avulla Luetaan Infix-lauseketta merkki kerrallaan ( => asetetaan pinoon (PUSH) *,+ => ensin POPataan ja tulostetaan operaattoreita, joilla on sama tai parempi prioriteetti, sen jšlkeen asetetaan vastaluettu operaattori pinoon. SulkumerkkiŠ Õ(Õ ei koskaan POPata ) => POPataan ja tulostetaan operaattoreita, kunnes lšytyy alkusulku, joka myšs POPataan, mutta ei tulosteta Kun input loppuu, POPataan ja tulostetaan loput operaattorit 22.1.2002 67 Esim. Muunnetaan lauseke 5*((9+8)*4*6+7) muotoon 598+4*6*7+* Input Pino Output 5 5 * * ( *( ( *(( 9 9 + *((+ 8 8 ) *( + * *(* 4 4 * *(* * 6 6 + *(+ * 7 7 ) * + tyhjš * 22.1.2002 68

POSTFIX-lausekkeen arvo voidaan laskea pinon avulla Esim. lauseke 598+4*6*7+* Input Pino 5 5 9 5 9 8 5 9 8 + 5 17 4 5 17 4 * 5 68 6 5 68 6 * 5 408 7 5 408 7 + 5 415 * 2075 empty 22.1.2002 69 Muita pinon sovelluksia: Ajonaikainen pino (aliohjelmakutsut): Kutsuvan ohjelman tila (=rekisterit) ja kutsun paikka (=program counter) pinoon Aliohjelmasta palattaessa voidaan palauttaa alkuperšinen tila Syštevirran kššntšminen pšinvastaiseen jšrjestykseen 22.1.2002 70

4.5 JONO (queue) Jono on abstrakti tietotyyppi, jolle on mššritelty seuraavat operaatiot: Put(x) tai Enqueue(x) lisšš jonon loppuun alkion x Get tai Dequeue palauttaa (ja poistaa) jonon ensimmšisen alkion First palauttaa jonon ensimmšisen alkion Empty kertoo, onko jono tyhjš Jonokuri FIFO (First In First Out) Jono voidaan implementoida eri tavoin, mm. taulukon avulla tai linkitettynš listana. Usein implementoidaan sirkulaarisena taulukkona (indeksit lasketaan modulo N). 22.1.2002 71 Jonon toteutus sirkulaarisena taulukkona last fi rst 0 1 2 3 4 5 6 7 MAX first osoittaa jonon alkuun Jono[0.. MAX-1] put get last osoittaa 1. vapaaseen paikkaan jonossa yksi tyhjš paikka, jota ei kšytetš 22.1.2002 72

Put: Jono[last] =...; last = (last+1) % MAX; if (last == first) error; {Jono ei voi olla tyhjš! Get: Palauta Jono[first]; first = (first+1) % MAX; First = Jono[first]; Empty = (last == first); 22.1.2002 73 Jonon toteutus listana struct node { datatype data; struct node *next; ; Ê typedef struct node * Queue; first last K2.16 22.1.2002 74

Put: temp = (Queue) malloc(sizeof(struct node)); temp->data =...; temp->next = NULL; last->next = temp; last = temp; Get: temp = first; first = first->next; return (temp); First = return(first); Empty = return (first == null); 22.1.2002 75 Jonon sovelluksia Esim. Printterijono Puskuri tiedon všlivarasto tietoa tulee tietoa lšhtee tiedon jšrjestys sšilyy Esim. tulostettava tiedosto menee puskurin kautta Diskreetti simulointi Esim. liikenne, tietoliikenne, palvelut Graafialgoritmit 22.1.2002 76

4.6 PAKKA (deque) = Jonon ja pinon yhdistelmš Alkioita voidaan asettaa rakenteen molempiin pšihin, ja myšs ottaa pois Vrt. korttipakka kšdessš 22.1.2002 77 5. ALGORITMIANALYYSI 5.1 Johdanto 5.2 Tavoitteet 5.3 Algoritmien luokittelu 5.4 KertaluokkamerkinnŠt (Big Oh Notation) 5.5 Algoritmin toteutus 5.6 KertaluokkamerkinnšillŠ laskeminen 5.7 Muita tunnuslukuja 5.8 C-ohjelman kompleksisuus 5.9 RekursioyhtŠlšt 5.10 Kuinka analyysi tarkistetaan? 22.1.2002 78

5.1 Johdanto MIKSI tarvitaan algoritmianalyysiš? Ohjelman resurssitarpeiden ennustaminen CPU-aika muistitila Algoritmien keskinšinen vertailu Sopivan algoritmin valitseminen 22.1.2002 79 MITEN algoritmeja voi analysoida? 1. Empiirinen mittaaminen ja ekstrapolointi Ongelmia: Tulos riippuu syšteaineistosta Tulos riippuu toteutuksesta Ekstrapolointi voi johtaa vššriin pšštelmiin 2. Matemaattinen analyysi Luotettavampi, mutta ei ongelmaton Tulokset voivat olla epškšytšnnšllisiš Voi johtaa analyyttisesti vaikeisiin ongelmiin 22.1.2002 80

5.2 Tavoitteet A) Syšteaineiston laatu ei saa johtaa vššriin tuloksiin Koska tšsmšllinen ennustaminen suoritusajasta ei ole mahdollista, haetaan seuraavia tunnuslukuja: Pahin tapaus (worst case performance) Realistinen tai sitten ei Esim. haetaan tiettyš alkiota listasta. MikŠ on pahin tapaus? KeskimŠŠrŠinen tapaus (average case performance) Usein merkittšvšmpi tulos Analyysi usein vaikeaa Esim. ÓMikŠ on keskimššršinen tekstitiedosto?ó 22.1.2002 81 B) Erotetaan algoritmi ja sen toteutus toisistaan Toteutus vaikuttaa suoritusaikaan vain kertoimen kautta C) EtsitŠŠn 'paras' ylšraja Mahdollisimman lšhellš teoreettista ylšrajaa D) KeskitytŠŠn olennaiseen PŠŠosa CPU-ajasta kuluu vain pienessš osassa ohjelmaa E) TŠsmŠllinen lauseke harvoin tarpeen MŠŠrŠŠvŠ termi riittšš 22.1.2002 82

1 : 5.3 Algoritmien luokittelu kiinteš (vakio) suoritusaika esim. lausekkeen evaluointi log N : logaritminen esim. puolitushaku N 2 : N 3 : nelišllinen esim. sijoituslajittelu kuutiollinen esim. matriisitulo N : lineaarinen esim. lineaarinen haku N*log N : "N log N" esim. Quicksort 2 N : eksponentiaalinen esim. salasanan haku, travelling salesman Eksponentiaaliset algoritmit eivšt ole kšytšnnšssš sovellettavia, mutta niitš esiintyy monien kšytšnnšn probleemien perusratkaisuissa 22.1.2002 83 5.4 KertaluokkamerkinnŠt Funktio T(N) O( f(n) ), jos on olemassa c ja N 0 siten, ettš T(N) < c f(n), kaikille N > N 0 MerkitŠŠn: T(N) = O( f(n) ) TŠmŠ on syštteestš ja toteutuksesta riippumaton ylšraja laskentaan kuluva aika c f(n) T(n) f(n) ongelman koko HUOM! N 0 Kuvaa ÔaskeltenÕ mššršš, EI kulutettuja CPU-sekunteja YlŠraja voi olla turhan epštarkka eli epšrealistinen c ei ole všlttšmšttš pieni N 0 ei ole všlttšmšttš pieni Asymptoottinen kšyttšytyminen ei všlttšmšttš ratkaise "pienillš" N:n arvoilla, esim. 10*N 2 < 1000*N, N < 100 22.1.2002 84

Esim. Tarkastellaan neljšš eri algoritmia, joiden tehokkuusluvut ovat 100N, 5*N 2, N 3 /2 ja 2 N Oletetaan koneet, joista toinen laskee 1000 askelta sekunnissa, toinen 10000 askelta sekunnissa algoritmi N (10 3 s) N (10 4 s) muutos 100*N 10 100 10.0 5*N 2 14 45 3.2 N 3 /2 12 27 2.3 2 N 10 13 1.3 Eksponentiaalisella algoritmilla konetehon kymmenkertaistuminen johtaa siihen, ettš pystytššn kšsittelemššn vain 30% suurempaa ongelmaa! 22.1.2002 85 5.5 Algoritmin toteutus 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.1.2002 86

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.1.2002 87 5.6 KertaluokkamerkinnšillŠ laskeminen f(x) = O(f(x)) Ê f(x) = O(x * f(x)) Ê c * f(x) = O(f(x)) f(x) + c = O(f(x)) f(x) + g(x) = O(MAX[ f(x), g(x) ]) = MAX[ O(f(x)), O(g(x)) ] f(x) * g(x) = O(f(x) * g(x)) N a i *x i = O(x N ) i=0 Ê log 10 x = O(log 2 x) 22.1.2002 88

VIRHEIT : Ê O(f(x)) - O(f(x)) = 0 (p.o. O(f(x)) ) Ê f(x) = O(g(x) / 2) Ê f(x) = O(x 2 + x) Ê O(f(x)) = f(x) Ê f(x) <= O(g(x)) Ê f(x) >= O(g(x)) Ê OK: Ê f(x, M) = O(g(x) + M) 22.1.2002 89 5.7 Muita tunnuslukuja Iso-O (Big-Oh): f on T:lle ÔylŠrajaÕ T(N) = O( f(n) ), jos on olemassa c ja N 0 siten, ettš T(N) < c f(n) kaikille N > N 0 Iso-Omega: f on T:lle ÔalarajaÕ T(N) = W( f(n) ), jos on olemassa c ja N 0 siten, ettš T(N) > c f(n) kaikille N > N 0 Iso-Theta: f kasvaa tšsmšlleen kuin T T(N) = Q( f(n) ) <=> T(N) = O( f(n) ) ja T(N) = W( f(n) ) Pikku-o (Little oh): f on T:n aito ylšraja T(N) = o( f(n) ) <=> T(N) = O( f(n) ) ja T(N) <> Q( f(n) ) Huom! Nyt ei puhuta ylšrajoista tavallisessa mielessš 22.1.2002 90

t c 3 N cn 3 c 0 N 2 T(N) = 7 7+N/ 2 K3.3 c 2 sqrt(n) N T(N) = O(N 2 ) T(N) = O(N 3 ) T(N) = O(N) T(N) = Ω(sqrt(N)) T(N) = Ω(N) T(N) = θ(n) T(N) = o(n 2 ) T(N) = o(n 3 ) Big-Oh on tšrkein tunnusluku. 22.1.2002 91 5.8 C-ohjelman kompleksisuus PerŠkkŠiset lauseet: s= 0; vakio O(1) for (i=0; i<n; i++) O(N) s= s+1; Valitaan maksimi O(N) If-Then-Else Valitaan maksimi For-silmukat for (i=1; i<n; i++) for (j=i+1; j<=n; j++) s= s+1; (N-1)*N/2 = O(N 2 ) 22.1.2002 92

Rekursio: Fibonacci-luvut int fibonacci(int n) { if (n<=1) return 1; else return fibonacci(n-1) + fibonacci(n-2); T(0) = T(1) = 1 T(N) = T(N-1) + T(N-2) + 2 >= fib(n) (3/2) N <= fib(n) <= (5/3) N T(N) on eksponentiaalinen 22.1.2002 93 Rekursio: Kertoma int factorial(int n) { if (n==0) return 1; else return n*factorial(n-1); T(N) = T(N-1) + 1 T(N) = O(N) O() YhtŠ hyvš kuin ei-rekursiivinen Rekursiosta aiheutuu yleiskustannuksia 22.1.2002 94

5.9 RekursioyhtŠlšt Rekursiivinen Òhajota ja hallitseó-algoritmi johtaa usein rekursioyhtšlššn joka olisi ratkaistava: Esim 1. Listan lšpikšynti silmukassa, poista yksi alkio: 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 ) 22.1.2002 95 Esim 2. BinŠŠrihaku, puolita aineisto vakioajassa: T(N) = T(N/2) + 1, T(1) =1 N = 2 k, k = log 2 N T(2 k ) = T(2 k-1 ) + 1 = T(2 k-2 ) + 1 + 1 = T(2 0 ) + k = k +1 T(N) = O(k+1) = O(log N) Esim 3. Puolita aineisto (sitš ennen tutki kaikki): T(N) = T(N/2) + N T(N) = N + N/2 + N/4 + N/8 +... = 2N = O(N) 22.1.2002 96

Esim 4. Jaa aineisto kahteen puolikkaaseen, molemmat kšsitellššn T(N) = 2T(N/2) + N, T(1) = 0 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 = 0 / 1 + k T(N) = T(2 k ) = k 2 k = N log N = O(N log N) 22.1.2002 97 Esim. Potenssiinkorotus: x n = x*x*x*...*x, n-1 kertolaskua => O(n) integer pow(int x, int n){ switch (n) { case 0: return 1; break; case 1: return x; break; default: if (n&1) return pow(sqr(x), n/2)*x; else return pow(sqr(x), n/2); esim. x 9 = (x 2 ) 4 x = ((x 2 ) 2 ) 2 x T(n) = T(n/2) + 2, T(1) = T(0) = 1 T(n) = O(log n) (Ratkaisu: vrt. Esim. kohta 2 edellš) 22.1.2002 98

5.10 Kuinka analyysi tarkistetaan? Empiirisesti Toteuttamalla ohjelma TehdŠŠn koeajoja arvoilla N, 2N, missš N on mahdollisimman suuri 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.1.2002 99 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.1.2002 100

6. PUURAKENTEET 6.1 KŠsitteistšŠ 6.2 BinŠŠripuu (binary tree) 6.3 Puiden esitystapoja 6.4 Puussa kulkeminen (traversing a tree) 6.5 Puiden sovelluksia 22.1.2002 101 6.1 KŠsitteistšŠ Puurakenteen perusmalli on sukupuu ylšs A juuri (root) alas B C G isš (parent) D H L lapsi (child) 22.1.2002 102

KŠsitteitŠ ja ominaisuuksia: Solmu (vertex) on puuhun kuuluva alkio, johon voidaan tallettaa dataa VŠli, sšrmš, kaari (edge) on suora yhteys kahden solmun všlillš Juuri (root) on puun ylin solmu Solmun lšhin edeltšjš on sen isš (father, dad, parent). Kauemmista edeltšjistš kšytetššn nimeš isoisš, esi-isš tai edeltšjš (grandfather, ancestor) Solmun lšhinnš alemmat seuraajat ovat sen lapsia (children). NŠiden lapset vastaavasti lapsenlapsia (grandchildren) Kullakin solmulla on vain yksi isš Juurella ei ole isšš 22.1.2002 103 Solmulla voi olla 0-N kpl lapsia. YleisessŠ puussa lasten mššršš ei ole rajoitettu Saman isšn lapset ovat toistensa sisaruksia (sibling) Lehti (leaf, external node) on solmu, jolla ei ole lapsia Muut solmut ovat puun sisšsolmuja (internal node) Lehdet ovat joskus rakenteeltaan erilaisia kuin sisšsolmut Polku (path) on yhteys kahden solmun všlillš Juuresta mihin tahansa solmuun on vain yksi polku. Vastaavasti jokaisesta solmusta on vain yksi polku mihin tahansa toiseen solmuun Jokainen solmu on oman alipuunsa (subtree) juuri Puiden joukko on metsš (forest) 22.1.2002 104

JŠrjestetyssŠ puussa (ordered tree) lasten jšrjestys on mššrštty Vasen, Oikea EnsimmŠinen, Toinen,...,Viimeinen EI tarkoita sitš ettš solmuihin liittyvš tieto olisi jšrjestyksessš! Solmu on tasolla N (level N), jos polulla siitš juureen on N solmua. Juuren taso on 0. Puun korkeus (height) on sen tasojen mššrš, ts. pisimmšn juuresta lehteen ulottuvan polun pituus 22.1.2002 105 Lause: Jos puussa on N solmua niin siinš on N-1 sšrmšš Todistus: Jokainen solmu kytkeytyy yhdellš sšrmšllš isšsolmuunsa Juurisolmulla ei ole isšš Puun rekursiivinen mššritelmš: Puu on joko yksittšinen solmu tai juurisolmu, joka on kytketty joukkoon muita puita (= alipuita ) Alipuiden tulee olla pareittain pistevieraita 22.1.2002 106

Usein kšytetty merkintš: Solmut palloja Alipuut kolmioita U P U K4.2 Alipuu Alipuu 22.1.2002 107 6.2 BinŠŠripuu (binary tree) BinŠŠripuu (binary tree) on jšrjestetty puu, jossa jokaisella solmulla on tšsmšlleen kaksi lasta: vasen ja oikea (voivat olla tyhjiš) BinŠŠripuu on tšysi (full), jos kaikki puussa olevat tasot ovat tšynnš mahdollisesti alinta lukuunottamatta 22.1.2002 108

BinŠŠripuu on tšydellinen (complete), jos alinta tasoa lukuunottamatta kaikki tasot ovat tšynnš ja alimmalla tasolla solmut ovat vasemmassa reunassa Terminologiassa on pientš horjuvuutta 22.1.2002 109 6.3 Puiden esitystapoja 6.3.1 Dynaaminen tietorakenne Ê struct node { char key; struct node *left; struct node *right; ; typedef struct node * link; left key right Lehtisolmujen linkit voidaan asettaa arvoon NULL 22.1.2002 110

Sama Javalla class TreeNode { private Object data; private TreeNode left, right; Ê TreeNode (Object element) { data = element; left = null; right = null; TreeNode root, p, q; Lehtisolmujen linkit voidaan asettaa arvoon NULL 22.1.2002 111 Joskus juuren kšsittely joudutaan suorittamaan erikoistapauksena Esim. jos kaikkiin solmuihin kohdistettava operaatio viittaa myšs solmun isššn Kannattaa mššritellš ylimššršinen Head-solmu, josta on viittaus juureen Vrt. linkitetty lista Head K4.4 22.1.2002 112

Samoin voidaan mššritellš erityinen z-solmu, johon tyhjšt alipuut eli lehtisolmujen linkit viittaavat (Sedgewick: Algorithms) : z-solmuja on vain yksi kappale z-solmun linkit viittaavat z-solmuun itseensš Head K4.5 Kaikki kerralla kšytšssš olevat dynaamiset tietorakenteet voivat kšyttšš samaa z-solmua Z 22.1.2002 113 Nyt esim voidaan luoda tyhjš puu ja kšsitellš sitš samoilla rutiineilla kuin muitakin puita: Ê link Z = malloc(sizeof(struct node)); Z->left = Z; Z->right = Z; link Head = malloc(sizeof(struct node)); Head->left = Z; Head->right = Z; Head K4.6 Z 22.1.2002 114

TŠmŠ esitystapa mahdollistaa vain liikkumisen puussa alaspšin Jos halutaan liikkua myšs ylšs, voidaan lisštš kolmas linkki, dad, joka osoittaa solmun isššn YleistŠ puuta ei kannata esittšš samalla tavalla, koska lasten mššrš ei ole rajattu 22.1.2002 115 6.3.2 Taulukkoesitys TŠydellinen binššripuu voidaan esittšš yksinkertaisessa taulukossa Juuri on taulukon 1. alkiossa Alkiossa k olevan solmun isš on alkiossa k DIV 2 Alkiossa k olevan solmun lapset ovat alkioissa 2*k ja 2*k+1 EsityksessŠ voi liikkua sekš ylšs ettš alas puussa 22.1.2002 116

6.3.3 IsŠ-linkit tai -taulukko yleiselle puulle Jos puussa tarvitsee liikkua vain ylšspšin, riittšš kussakin solmusta tieto sen isšstš. TŠmŠ voidaan toteuttaa joko dynaamisena tietorakenteena tai taulukkona struct node { char key; struct node *dad; ; Ê typedef struct node * link; A A S E R T E k 1 2 3 4 5 6 7 8 9 10 11 12 M P L E a[k] A S A M P L E T R E E X dad[k] 3 3 10 8 8 8 8 9 10-1 10 11 22.1.2002 117 Solmusta on osoitin vasemman- puolimmaiseen lapseen ja lšhinnš oikealla olevaan veljeen Jos yleisessš puussa halutaan liikkua alaspšin, kytketššn kunkin solmun jšlkelšiset linkitetyksi listaksi. Siten voidaan varata tilaa tarpeen mukaan. A A E R S T M P L E E struct node { char key; struct node *First_child; struct node *Next_sibling; ; Ê typedef struct node * link; => Esitysmuoto palautuu binššripuuksi! 22.1.2002 118

6.4 Puussa kulkeminen (traversing a tree) Monessa tilanteessa pitšš pystyš kšymššn lšpi (traverse) kaikki puussa olevat alkiot LŠpikŠyntijŠrjestyksiŠ on useita esijšrjestys (preorder) sisšjšrjestys (inorder) jšlkijšrjestys (postorder) tasojšrjestys (level order) 22.1.2002 119 EsijŠrjestyksessŠ puu kšydššn lšpi jšrjestyksessš: juuri - vasen alipuu - oikea alipuu P M S A A L E R T E E SisŠjŠrjestyksessŠ puu kšydššn lšpi jšrjestyksessš: vasen alipuu - juuri - oikea alipuu A S A M P L E T R E E P M L S E A A R T E 22.1.2002 E 120

JŠlkijŠrjestyksessŠ puu kšydššn lšpi jšrjestyksessš: vasen alipuu - oikea alipuu Ð juuri A A S M T E E R E L P TasojŠrjestyksessŠ puu kšydššn lšpi kukin taso kerrallaan ylhššltš alkaen P M L S E A A R T E E M P L S E A A R T E E 22.1.2002 121 ÒMuistisŠŠntšÓ: PiirretŠŠn viiva juuren pššltš lšhtien vastapšivššn puun ympšri lšheltš liipaten, tulostetaan solmu kun se ohitetaan vasemmalta => EsijŠrjestys ohitetaan alta => SisŠjŠrjestys ohitetaan oikealta => JŠlkijŠrjestys 22.1.2002 122

Kolmen ensimmšisen lšpikšyntitavan implementaatio on helpointa tehdš rekursion avulla void traverse_preorder(link t) { if (t!= NULL) { visit(t); traverse_preorder(t->left); traverse_preorder(t->right); 22.1.2002 123 void traverse_inorder(link t) { if (t!= NULL) { traverse_inorder(t->left); visit(t); traverse_inorder(t->right); void traverse_postorder(link t) { if (t!= NULL) { traverse_postorder(t->left); traverse_postorder(t->right); visit(t); 22.1.2002 124

EsijŠrjestys pinon avulla: void traverse_preorder(link t) { push(t); do { t = pop; Ê if (t!= NULL) { visit(t); push(t->right); push(t->left); while (!stack_empty); TasojŠrjestyksen implementointi kšy helposti jonorakenteen avulla: void traverse_levelorder(link t) { put(t); do { t = get; Ê if (t!= NULL) { visit(t); put(t->left); put(t->right); while (!queue_empty); 22.1.2002 125 Yleisen puun lšpikšynnissš em. algoritmit yleistetššn A E R E EsijŠrjestys E A A S R T M P L E E A S T M P L E JŠlkijŠrjestys A S A M P L E T R E E Koska yleinen puu on palautettavissa binššripuuksi, sitš koskevat algoritmit voidaan yleistšš binššripuun kšsittelyalgoritmeista 22.1.2002 126

6.4.1 ErŠitŠ lšpikšynnin sovelluksia: EsijŠrjestys sisšllysluettelon tulostaminen tiedostoluettelon tulostaminen SisŠjŠrjestys hakupuun sisšltš aakkostettuna lauseke infix-muodossa JŠlkijŠrjestys tulosyhteenveto lauseke postfix-muodossa 22.1.2002 127 6.4.2 LŠpikŠyntijŠrjestyksen merkityksiš EsijŠrjestys vastaa depth first-hakua ÒetsitŠŠn tietty haara mahdollisimman pitkšlle ennen kuin perššnnytššnó TasojŠrjestys vastaa breadth first Ðhakua ÒetsitŠŠn tietyllš etšisyydellš juuresta olevia solmuja.ó 22.1.2002 128

6.5 Puiden sovelluksia 6.5.1 JŠsennyspuu. Esimerkiksi lauseke voidaan esittšš puurakenteen avulla AlkuperŠinen infix-lauseke: 5 * ( ( 9 + 8 ) * (4 + 6) + 7 ) Kun tšmš puu kšydššn lšpi jšlkijšrjestyksessš, saadaan lauseke postfix-muodossa : 5 9 8 + 4 6 + * 7 + * + 22.1.2002 129 SisŠjŠrjestys antaa lausekkeen alkuperšisessš infixmuodossa, kunhan sulut lisštššn yhteenlaskusolmujen oikeille puolille 5 * ( ( 9 + 8 ) * ( 4 + 6 ) + 7 ) EsijŠrjestys antaa ns. prefix-muodon * 5 + * + 9 8 + 4 6 7 22.1.2002 130

JŠsennyspuun luominen: Luetaan postfix-lauseketta merkki kerrallaan 5 9 8 + 4 6 + * 7 + * Operandi => TehdŠŠn tšstš uuden puun juuri Osoitin uuteen puuhun asetetaan pinoon Operaattori => TehdŠŠn tšstš uuden puun juuri Oikeaksi lapseksi popataan pinon pššllimmšinen Vasemmaksi lapseksi seuraava Osoitin uuteen puuhun pinoon 22.1.2002 131 Esim: 5 8 5 K4.10a 5 9 8 9 + 5 9 5 + 9 8 22.1.2002 132

22.1.2002 133 4 6 8 9 4 + 5 6 8 9 4 + 5 5 8 9 + 6 4 + 5 8 9 + 6 4 + * + * 22.1.2002 134 5 8 9 + 6 4 + * 7 7 5 8 9 + 6 4 + * 7 + +

* 5 * + * 7 + + 9 8 4 6 22.1.2002 135 6.5.2 Hakupuu Tieto voidaan jšrjestšš puuhun siten, ettš haku on nopeaa. Esimerkki: binššrinen hakupuu (binary search tree) K E S C G R U A J T X I 22.1.2002 136

6.5.3 Keko Tieto voidaan jšrjestšš puuhun siten, ettš suurimman (pienimmšn) alkion etsiminen on nopeaa. Esimerkki: keko (heap) X T O G S M N A E R A I 22.1.2002 137