Esittely latautuu. Ole hyvä ja odota

Esittely latautuu. Ole hyvä ja odota

Tietorakenteet ja algoritmit

Samankaltaiset esitykset


Esitys aiheesta: "Tietorakenteet ja algoritmit"— Esityksen transkriptio:

1 Tietorakenteet ja algoritmit
Pino Pinon määritelmä Pinon sovelluksia Järjestyksen kääntäminen Palindromiprobleema Postfix-lausekkeen laskenta Infix-lausekkeen muunto postfix-lausekkeeksi Sisäkkäiset funktiokutsut Backtracking menetelmä Pinon toteutustapoja Taulukko indeksoinnilla Taulukko osoittimilla © Hannu Laine 11/9/2012

2 Pinon määritelmä (Stack)
Määritelmä. Pino on järjestettyjen alkioiden kokoelma, jossa lisäykset tapahtuvat aina loppuun ja samoin alkion otto on mahdollista vain lopusta. Tässä tapauksessa loppua kutsutaan pinon huipuksi (top). Pinon tapauksessa alkioiden järjestyksen määrää syöttöjärjestys. Pinon operaatiot ovat: initialize (alustaa pinon) push (vie alkion pinon päälle) pop (ottaa alkion pinon päältä) is_empty (testaa, onko pino tyhjä) Vastaavat funktioiden prototyypit voisivat olla void initialize_stack (Tstack *pstack); Tboolean push( Tstack *pstack, Titem item); Tboolean pop( Tstack *pstack, Titem *pitem); int is_empty(const Tstack* pstack); void print_stack (const Tstack *pstack); // apufunktio testaukseen © Hannu Laine 11/9/2012

3 Pinon sovelluksia Järjestyksen kääntäminen
Palindromiprobleeman ratkaisu Laitteen purku ja kasaus Postfix-merkintäisen lausekkeen laskenta Infix-merkintäisen lausekkeen muunto postfix-merkintäiseksi Päällekkäisten menuikkunoiden toteutus käyttöliittymässä Sisäkkäiset funktiokutsut Sisäkkäiset keskeytyspalvelufunktiot Yksinkertainen rivieditori © Hannu Laine 11/9/2012

4 Esimerkki1. Merkkijonon merkkien järjestyksen kääntö
#include ”stack.h” #include <string.h> void kaanna_jarjestys(char* mrk_jono) { Tstack merkkipino; int i, pit; initialize_stack(&merkkipino); for ( i = 0; i < strlen(mrk_jono), i++ push(&merkkipino, mrk_jono[i]); pop(&merkkipino, &mrk_jono[i]); } © Hannu Laine 11/9/2012

5 Esimerkki 2. Palindromiprobleema (periaate)
#include ”stack.h” int onko_palindromi(const char* mrk_jono) { Tstack pino1, pino2, pino3; char mrk1, mrk2, mrk3; // initialisoi kaikki kolme pinoa // vie merkkijonon merkit pinoihin 1 ja 2 // siirrä merkit pinosta 2 pinoon 3 while(!is_empty(&pino2) { pop(&pino2, &mrk); push(&pino3, mrk); } // Otetaan tasatahtiin pinoista 1 ja 3 while(!is_empty(&pino1) { pop(&pino1, &mrk1); pop(&pino3, &mrk2); if(mrk1 != mrk2) return 0; return 1; © Hannu Laine 11/9/2012

6 Infix-merkintäisen lausekkeen laskenta
Infix-merkintäisen lausekkeen laskenta koneellisesti ei ole helppo tehtävä. Tehtävän tekee ongelmalliseksi se, että operaatioita ei voi suorittaa sitä mukaa, kun ne tulevat vastaan. Asioita on pidettävä muistissa ja sitten operaatioita tehtävä niiden vahvuusjärjestyksessä. Ihmiselle tehtävä on melko helppo. Ihminen ”skannaa” lausekkeen läpi ja löytää helposti paikan, josta aloitetaan ja etenee oikeassa järjestyksessä havainnoiden koko ajan koko lauseketta. Esimerkiksi lauseketta * 2 / 3 alusta tulkittaessa ei voida tehdä mitään operaatiota ennen kuin lausekkeessa on edetty viisi askelta! (3 operandia ja 2 operaattoria). Tehtävän koneellinen ratkaisu yksinkertaistuu oleellisesti, kun se jaetaan kahteen vaiheeseen: 1. infix-merkintäisen lausekkeeen muunto postfix-merkintäiseksi 2. postfix-merkintäisen lausekkeen laskenta Molemmissa vaiheissa tarvitaan pinoa muistivarastona! Tarkastellaan näitä vaiheita erikseen ja aloitetaan jälkimmäisestä © Hannu Laine 11/9/2012

7 Postfix-merkintäinen lauseke
RPN-laskimissa käytetään tällaista laskentatapaa. RPN-lyhenne tulee sanoista Reverse Polish Notation (eli käänteinen puolalainen merkitsemistapa) Postfix merkintä tarkoittaa, että operaattori tulee perässä operandien jälkeen. Lausekkeen laskenta koneellisesti on yksinkertaista. Myös lausekkeen merkintä on yleensä lyhyempi, koska sulkeita ei tarvita laskentajärjestyksen määräämiseksi. On myös tällä periaatteella toimivia ohjelmointikieliä, esimerkiksi PostScript-kieli. Esimerkki lausekkeesta: * vastaa infix merkintäistä lauseketta (3 + 5) * (7 – 2) © Hannu Laine 11/9/2012

8 Postfix-merkintäisen lausekkeen laskenta
Kuten edellisellä sivulla jo sanottiin, postfix-merkintäisen lausekkeen laskenta koneellisesti on helppoa. Lausekkeen laskenta perustuu operandien pinoon. Se on helppoa siksi, että lauseketta voidaan edetä vasemmalta oikealle ja päätös siitä mitä seuraavaksi tehdään, voidaan tehdä aina välittömästi. Käsittelysäännöt ovat tässä: Kun lausekkeesta löytyy operandi, se viedään aina pinoon Kun lausekkeesta löytyy operaattori, pinosta otetaan kaksi operandia ja niille tehdään operaattorin määräämä operaatio. Tulos viedään pinoon Lopuksi pinossa on vain yksi arvo, joka on lopputulos. Taululla käydään läpi kuinka esimerkiksi lauseke * lasketaan (vastaten lauseketta (3 + 5) * (7 – 2) ). © Hannu Laine 11/9/2012

9 Infix-merkintäisen lausekkeen muunto postfix-merkintäiseksi
Myös infix-lausekkeen muuntaminen postfix-muotoon on koneellisesti helppoa, kun käytetään operaattorien pinoa. Nytkin lauseketta voidaan edetä vasemmalta oikealle ja päätös siitä mitä seuraavaksi tehdään, voidaan tehdä aina välittömästi. Käsittelysäännöt ovat: Kun infix-lausekkeesta löytyy operandi, se viedään suoraan postfix-lausekkeeseen. Kun infix-lausekkeesta löytyy operaattori, se viedään aina pinoon, mutta sitä ennen pinosta otetaan pois ja viedään postfix-lausekkeeseen kaikki operaattorit, joilla on korkeampi tai sama prioriteetti. Lopuksi pinosta viedään postfix-lausekkeeseen kaikki siellä olevat operaattorit. Taululla käydään läpi kuinka esimerkiksi lauseke (3 + 5) * (7 – 2) muunnetaan postfix-muotoon. © Hannu Laine 11/9/2012

10 Sisäkkäiset funktiokutsut
Tietokoneessa käytetään pinomuistia (stack segment) funktioiden parametrien ja paikallisten muuttujien tallennuspaikkana. Se tekee mahdolliseksi sisäkkäiset funktiokutsut. Esimerkki int main(void) { int loc; f1(loc); } void f1(int par1) { int loc1; f2(loc1); void f2(int par2) { int loc2; Stack segment loc par1 loc1 par2 loc2 f2 f1 main © Hannu Laine 11/9/2012

11 Yksinkertainen taulukkototeutus indeksoinnilla
#define N 8 typedef Titem; typedef struct { Titem array[N]; int top; } Tstack; Täydellinen toteutus verkossa (Esimerkki 1, Moniste 4) Edut: Yksinkertainen Havainnollinen Tehokas Tstack 7 6 5 4 array 3 2 b 1 a top 1 © Hannu Laine 11/9/2012

12 Yksinkertainen taulukkototeutus osoittimilla
#define N 8 typedef Titem; typedef struct { Titem array[N]; Titem* top; Titem* maxpointer; Titem* minpointer; } Tstack; Täydellinen toteutus verkossa (Esimerkki 3, Moniste 4) Edut: Yksinkertainen Havainnollinen Vielä tehokkaampi Tstack 1 2 3 4 5 6 7 array b a maxpointer top minpointer © Hannu Laine 11/9/2012

13 Yleisyys Palautetaan mieleen, että säiliön toteutus on riippumaton säilöttävän alkion tyypistä. Myös nähdyt pinon toteutukset ovat source-kooditasolla riippumattomia ”pinottavien” alkioiden tyypistä! © Hannu Laine 11/9/2012

14 Backtracking menetelmä
Käytämme backtracking menetelmän esittelyssä esimerkkinä reitinhakuohjelmaa ”tieverkossa”. Alla on tieverkon kuvaus graafisesti ja taulukkoesityksenä. int graph[][2] ={ { 1,2},{1,3},{1,4}, {2,5},{2,6}, {3,7}, {4,8}, {4, 9}, {5,-1}, {6,10},{6,11}, {7,12},{7,13}, {8,-1}, {9,14},{9,15},{9,16}, {10,-1}, {11,17},{11,18}, {12,-1}, {13,-1}, {14,19},{14,20}, {15,21}, {16,-1}, {17,-1},{18,-1},{19,-1},{20,-1},{21,-1} }; 1 2 3 5 6 10 11 17 13 7 12 18 4 14 9 15 16 21 19 20 8 Ohjelma, joka etsii reitin annetusta solmupisteestä toiseen annettuun solmupisteeseen löytyy verkosta. © Hannu Laine 11/9/2012


Lataa ppt "Tietorakenteet ja algoritmit"

Samankaltaiset esitykset


Iklan oleh Google