Algoritmi ja abstraktio

Samankaltaiset tiedostot
Tietorakenteet ja algoritmit

Tietorakenteet ja algoritmit

Tietorakenteet ja algoritmit

tietueet eri tyyppisiä tietoja saman muuttujan arvoiksi

Tietueet. Tietueiden määrittely

Tietorakenteet ja algoritmit

Tietorakenteet ja algoritmit

Tietorakenteet ja algoritmit

Ohjelmoinnin perusteet Y Python

Tietorakenteet ja algoritmit

Algoritmit ja tietorakenteet / HL 1 Copyright Hannu Laine. Lista. Yleistä

Osoitin ja viittaus C++:ssa

C-kielessä taulukko on joukko peräkkäisiä muistipaikkoja, jotka kaikki pystyvät tallettamaan samaa tyyppiä olevaa tietoa.

13/20: Kierrätys kannattaa koodaamisessakin

Lyhyt kertaus osoittimista

Merkkijono määritellään kuten muutkin taulukot, mutta tilaa on varattava yksi ylimääräinen paikka lopetusmerkille:

Tietorakenteet ja algoritmit

Loppukurssin järjestelyt

Tietuetyypin määrittely toteutetaan C-kielessä struct-rakenteena seuraavalla tavalla:

Perusteet. Pasi Sarolahti Aalto University School of Electrical Engineering. C-ohjelmointi Kevät Pasi Sarolahti

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

Loppukurssin järjestelyt C:n edistyneet piirteet

Ohjelmointi 2. Jussi Pohjolainen. TAMK» Tieto- ja viestintäteknologia , Jussi Pohjolainen TAMPEREEN AMMATTIKORKEAKOULU

Tutoriaaliläsnäoloista

Perusteet. Pasi Sarolahti Aalto University School of Electrical Engineering. C-ohjelmointi Kevät Pasi Sarolahti

811120P Diskreetit rakenteet

TIETORAKENTEET JA ALGORITMIT

812341A Olio-ohjelmointi, I Johdanto

Algoritmit 1. Luento 1 Ti Timo Männikkö

1. Olio-ohjelmointi 1.1

Rakenteiset tietotyypit Moniulotteiset taulukot

Tiedostot. Tiedostot. Tiedostot. Tiedostot. Tiedostot. Tiedostot

Ohjelmiston toteutussuunnitelma

IDL - proseduurit. ATK tähtitieteessä. IDL - proseduurit

Tietotekniikan valintakoe

Ohjelmistojen mallintaminen, mallintaminen ja UML

ATK tähtitieteessä. Osa 3 - IDL proseduurit ja rakenteet. 18. syyskuuta 2014


A TIETORAKENTEET JA ALGORITMIT

Ohjelmoinnin perusteet Y Python

etunimi, sukunimi ja opiskelijanumero ja näillä

Algoritmit 1. Luento 3 Ti Timo Männikkö

Ohjelmoinnin perusteet Y Python

Tietorakenteet ja algoritmit - syksy

Rekursiolause. Laskennan teorian opintopiiri. Sebastian Björkqvist. 23. helmikuuta Tiivistelmä

Tietokanta (database)

811120P Diskreetit rakenteet

Sisällys. JAVA-OHJELMOINTI Osa 7: Abstrakti luokka ja rajapinta. Abstraktin luokan idea. Abstrakti luokka ja metodi. Esimerkki

Tietorakenteet ja algoritmit

Tietorakenteet ja algoritmit Johdanto Lauri Malmi / Ari Korhonen

Tietorakenteet ja algoritmit

Ohjelmoinnin perusteet, 1. välikoe

Ohjelmoinnin peruskurssi Y1

Olio-ohjelmoinnissa luokat voidaan järjestää siten, että ne pystyvät jakamaan yhteisiä tietoja ja aliohjelmia.

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet, syksy 2006

Solidity älysopimus ohjelmointi. Sopimus suuntautunut ohjelmointi

20. Javan omat luokat 20.1

7/20: Paketti kasassa ensimmäistä kertaa

Sisällys. 20. Javan omat luokat. Java API. Pakkaukset. java\lang

Kielioppia: toisin kuin Javassa

Concurrency - Rinnakkaisuus. Group: 9 Joni Laine Juho Vähätalo

Muistin käyttö. Muistin käyttö. Muistin käyttö. Muistin käyttö. Muistin käyttö. Muistin käyttö. Muistin käyttö C-ohjelmassa

815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset

Ohjelmoinnin perusteet Y Python

Ohjelmiston testaus ja laatu. Ohjelmistotekniikka elinkaarimallit

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

Yhtälöryhmä matriisimuodossa. MS-A0004/A0006 Matriisilaskenta. Tarkastellaan esimerkkinä lineaarista yhtälöparia. 2x1 x 2 = 1 x 1 + x 2 = 5.

jotakin käyttötarkoitusta varten laadittu kokoelma toisiinsa liittyviä säilytettäviä tietoja

Tieto- ja tallennusrakenteet

Sisällys. 1. Omat operaatiot. Yleistä operaatioista. Yleistä operaatioista

17. Javan omat luokat 17.1

Ongelma(t): Miten mikro-ohjelmoitavaa tietokonetta voisi ohjelmoida kirjoittamatta binääristä (mikro)koodia? Voisiko samalla algoritmin esitystavalla

Ohjelmassa henkilön etunimi ja sukunimi luetaan kahteen muuttujaan seuraavasti:

1. Omat operaatiot 1.1

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

Ohjelmistojen mallintaminen

Alkuarvot ja tyyppimuunnokset (1/5) Alkuarvot ja tyyppimuunnokset (2/5) Alkuarvot ja tyyppimuunnokset (3/5)

Metodit. Metodien määrittely. Metodin parametrit ja paluuarvo. Metodien suorittaminen eli kutsuminen. Metodien kuormittaminen

Lohkot. if (ehto1) { if (ehto2) { lause 1;... lause n; } } else { lause 1;... lause m; } 16.3

Yhtälöryhmä matriisimuodossa. MS-A0007 Matriisilaskenta. Tarkastellaan esimerkkinä lineaarista yhtälöparia. 2x1 x 2 = 1 x 1 + x 2 = 5.

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

11/20: Konepelti auki

T Olio-ohjelmointi Osa 3: Luokka, muodostin ja hajotin, this-osoitin Jukka Jauhiainen OAMK Tekniikan yksikkö 2010

Ohjelmoinnin perusteet Y Python

C-ohjelmointi, syksy Modulaarinen ohjelmointi. Luento C-ohjelmointi Syksy

Modulaarinen ohjelmointi

811312A Tietorakenteet ja algoritmit I Johdanto

Ohjelmointiharjoituksia Arduino-ympäristössä

Ohjelmoinnin peruskurssi Y1

AS C-ohjelmoinnin peruskurssi 2013: C-kieli käytännössä ja erot Pythoniin

Sisällys. 15. Lohkot. Lohkot. Lohkot

Esimerkki 1: Kahviautomaatti.

Ongelma(t): Mikä on Turingin kone? Miten Turingin kone liittyy funktioihin ja algoritmeihin? Miten Turingin kone liittyy tietokoneisiin?

Ohjeita Siemens Step7, Omron CX Programmer käyttöön

Pong-peli, vaihe Aliohjelman tekeminen. Muilla kielillä: English Suomi. Tämä on Pong-pelin tutoriaalin osa 3/7. Tämän vaiheen aikana

Tietotyypit ja operaattorit

Ohjelmointi 1. Kumppanit

Lohkot. if (ehto1) { if (ehto2) { lause 1;... lause n; } } else { lause 1;... lause m; } 15.3

JAVA-PERUSTEET. JAVA-OHJELMOINTI 3op A JAVAN PERUSTEET LYHYT KERTAUS JAVAN OMINAISUUKSISTA JAVAN OMINAISUUKSIA. Java vs. C++?

Transkriptio:

Algoritmit ja tietorakenteet / HL 1 Algoritmi ja abstraktio Algoritmin määrittely yleisesti Algoritmi on täsmällisesti määritelty äärellinen sarja toimenpiteitä, jotka toteuttamalla saadaan aikaan jonkin määrätyn tehtävän suoritus tai määrätyn probleeman ratkaisu. Algoritmi tietotekniikassa Tietotekniikassa tutkitaan sellaisia algoritmeja, joissa toimenpiteiden suorittajana on tietokone. Useimmiten kuitenkin algoritmien kirjoittajana on ihminen. Ohjelmointikieli on algoritmien kuvauskieli. Tietotekniikkatiedettä (Computer science) voidaan kutsua laajasti algoritmitieteeksi (algorithm science). Tietokone on kone, joka on suunniteltu suorittamaan algoritmeja (HW). Ohjelma on algoritmin kuvaus (SW). Miten suunnitellaan ohjelma, joka ratkaisee annetun ongelman? Usein perinteisessä proseduraalisessa ajattelutavassa ajatellaan ohjelman laatimisen olevan karkeasti kaksivaiheisen seuraavasti: 1. Suunnitellaan algoritmi, joka ratkaisee annetun ongelman. Tässä tulee käyttää ilmaisukieltä, joka sopii ihmiselle, jotta ihminen kykenee kehittämään ongelman ratkaisun kannalta oikean algoritmin (ei siis tietokoneen kannalta katsoen oikean). Ratkaisualgoritmi on riippumaton ohjelmointikielestä. 2. Toteutetaan algoritmi ohjelmointikielellä. Algoritmi muunnetaan tietokoneen ohjelmointikielelle. Kysymys: Millä tavalla voitaisiin lähentää vaihetta 1 ja 2, ts. millä tavalla ohjelmaa kirjoitettaessa voitaisiin pysyä mahdollisimman lähellä ihmisen kieltä ja ihmisen helposti ymmärtämää ilmaisutapaa siten, että kohdassa 1 syntynyt algoritmi, olisi jo hyvin lähellä ohjelmointikielen ilmaisua. Vastaus: Käyttämällä abstraktiota. Abstraktio yleensä Ihminen käyttää kaikessa ajattelussa abstraktiota. Abstraktio on väline hallita monimutkaisia asioita. Ihminen ei pidä mielessään monimutkaisten asioiden kaikkia yksityiskohtia yhtäaikaa, vaan hän käyttää abstraktioita. Monimutkaisilla asioilla voi olla useita abstraktiotasoja. Ylimmällä abstraktiotasolla koko monimutkaisuus korvataan yhdellä käsitteellä (esim. auto). Autoa ajettaessa käytetään erilaista abstraktiomallia kuin autosta vikaa etsittäessä. Abstraktiomalli on hierarkkinen. Ohjelmoinnissa voidaan ja kannattaa käyttää abstraktiota. Se tarkoittaa, että monimutkaiset toiminnat jaetaan osatehtäviin ja ne edelleen osatehtäviin jne. Samalla tavalla yhteen kuuluvat tiedot muodostavat ylimmän abstraktiotason ja tiedot voidaan jakaa alaryhmiin, jotka taas voidaan jakaa alaryhmiin jne.

Algoritmit ja tietorakenteet / HL 2 Toimintojen abstraktio Esimerkkinä toimintojen abstraktiosta käsitellään neliöjuuren laskeminen Newtonin menetelmän avulla. Tehtävässä on useita vaiheita, mutta ylimmällä abstraktiotasolla kyseessä on neliöjuuren laskenta. Neliöjuuren laskenta Newtonin menetelmällä voidaan kuvata matematiikan kielellä seuraavasti: x i+1 = (a/x i + x i ) / 2, missä a on juurrettava ja x i on i:s approksimaatio juurelle. Approksimaatio x i+1 voidaan hyväksyä juureksi, jos x i 2 - a < Laskenta Newtonin menetelmällä voidaan jakaa osatehtäviin, joita ovat juurrettavan_luku alkuapproksimaation_luku approksimaation_parannus approksimaation_testaus juuren_tulostus Tarkoitus on nyt toteuttaa algoritmi yllä olevalla abstraktiotasolla. Algoritmin rakennuspalikat ovat tunnetusti: peräkkäisrakenne, ehtorakenne ja toistorakenne. Näillä rakenteilla ilmaistaan siis säännöt, joiden mukaan yllämainittuja osatehtäviä suoritetaan. Osatehtävät toteutetaan ohjelmointikielen funktioilla (aliohjelmilla). Tällä tasolla on vielä ratkaistava, mitä tietoja kukin yllämainituista osatehtävistä tarvitsee ja mitä tietoja se tuottaa. Nämä tiedot ilmaistaan funktioiden parametreillä. Tässä vaiheessa laadimme siis algoritmia siten, että syntyy samalla lopullista ohjelmaa. Algoritmin kuvaus (C-kielinen/ suomenkielinen pääohjelma) on alla: void main (void) { float juurrettava, approksimaatio; int riittavan_hyva; lue(&juurrettava); lue(&approksimaatio); testaa(approksimaatio, juurrettava, &riittavan_hyva) while (!riittavan_hyva) { paranna(&approksimaatio, juurrettava); testaa(approksimaatio,juurrettava, &riittavan_hyva); tulosta(approksimaatio); Tässä vaiheessa on huomattava, että algoritmin kuvauksessa (ohjelmassa) ei ole vielä otettu mitään kantaa seuraaviin asioihin: miten juurrettava ja approksimaatio luetaan, miten approksimaation hyvyys testataan tai miten approksimaatiota parannetaan. Suunnittelija on siis tässä vaiheessa vapautettu näiden yksityiskohtien pohtimisesta. Nämä asiat ratkaistaan seuraavalla alemmalla abstraktiotasolla. Tällöin on huomattava, että osatehtävien suoritustapa on riippumaton toisten osatehtävien suoritustavasta. Tämä merkitsee sitä, että kun siirrytään alemmalle abstraktiotasolle, voidaan kerrallaan keskittyä yhteen pieneen muusta ympäristöstä riippumattomaan osatehtävään. Funktio (aliohjelma) on toimintojen abstraktioväline ohjelmointikielessä.

Algoritmit ja tietorakenteet / HL 3 Tehtävä. Kirjoita edellisessä ohjelmassa olevien funktioiden toteutus ja testaa ohjelma kokonaisuudessaan. Tässä esimerkkitehtävässä käsiteltävät tiedot ovat hyvin yksinkertaisia. Niiden hallintaan ei kummempia abstraktiomalleja tarvita. Näin ei kuitenkaan useimmiten ole asia vaan, käsiteltävien tietojenkin hallintaan tarvitaan abstraktiomallia. Tähän palataan hiukan myöhemmin. Yhteenvetona vielä tällaisen ohjelman kehittämisen vaiheet ovat: 1. Jaetaan tehtävä osiin (ensimmäinen taso) 2. Tehdään osista funktiot 3. Selvitetään näiden osien suoritussäännöt -peräkkäisrakenne (funktiokutsut peräkkäin) -ehtorakenne (if-rakenne) -toistorakenne (while) 4. Lisätään ohjelmaan tiedot (muuttujat) 5. Selvitetään funktioiden input/output-tiedot (parametrit) 6. Ohjelman ylin taso on valmis. Siirrytään taso alaspäin eli toteutetaan funktiot yksi kerrallaan. Tällaista lähestymistapaa sanotaan proseduraaliseksi, koska siinä päähuomio keskittyy toimintoihin. Käsiteltävän tiedon esitystapaan kiinnitetään vain toissijaista huomiota. Seuraavaksi tutustutaan tietojen abstraktioon. Lopulta kun sitten yhdistetään nämä molemmat ja probleemaa tarkastellaan tietojen kokonaisuuksina ja toimintojakin tarkastellaan näiden tietokokonaisuuksien operaationa päästään ns. olioperustaiseen tarkastelutapaan. Mutta nyt menemme seuraavaksi tietojen abstraktioon yksinkertaisen esimerkin avulla. Tietojen abstraktio Toiminnat kohdistuvat yleensä aina tietoihin. Suuren tietomäärän hallinta on samalla tavalla monimutkaista kuin laajan toimintojen kokonaisuuden. Jos käytämme abstraktiota vain toiminnoissa eikä tiedoissa, syntyy ohjelman selkeydessä selvä ristiriita, jota seuraava esimerkkiohjelma valaisee. Ohjelma on ns. suunnistajan ohjelma. Ohjelma lukee aluksi lähtöpisteen koordinaatit ja päätepisteen koordinaatit. Sitten ohjelma tulostaa mihin suuntaan on kuljettava ja kuinka pitkä matka, jotta lähtöpisteestä päästäisiin päätepisteeseen. Suunnistajan ohjelman toteutus ilman tietoabstraktiota: void main(void) { float x1, y1, x2, y2, suunta, et; lue_lahtotiedot(&x1, &y1, &x2, &y2); laske_matka(x1, y1, x2, y2, &et); laske_suunta(x1, y1, x2, y2, &suunta); tulosta_tiedot(suunta, et); Tässä ohjelma vastaa toimintojen osalta kutakuinkin ihmisen käyttämää alkuperäistä abstraktiomallia probleemasta ja toimintojen abstraktiovälineenä on taas käytetty funktiota. Siksi ohjelman kulun seuraaminen on helppoa. Tiedot sen sijaan ovat "sotkua". Kukaan ei ajattele tässä tilanteessa pisteitä neljänä lukuna vaan kahtena pisteenä. Ohjelma ei siis ole yksinkertaisen abstraktiomallin mukainen. Asia voidaan korjata käyttämällä toimintojen abstraktion lisäksi tietojen abstraktiota. Tällöin ohjelma näyttää seuraavalta; Suunnistajan ohjelman toteutus siten, että on käytetty tietoabstraktiota: void main(void) { Tpiste p1, p2;

Algoritmit ja tietorakenteet / HL 4 float suunta, et; lue_lahtotiedot(&p1, &p2); laske_matka(p1, p2, &et); laske_suunta(p1, p2, &suunta); tulosta_tiedot(suunta, et); Näemme, että ohjelma on nyt kaikin puolin selkeä ja helppolukuinen sekä käsiteltävien tietojen, että toimintojen suhteen. Tietojen abstraktiovälineenä käytetään tietuetta (record, structure). Ihminen käyttää kahden luvun muodostamasta kokonaisuudesta tässä asiayhteydessä abstraktiota piste tai koordinaatti. Yllämainittuun suunnistajan ohjelmaan päästään nostamalla tiedon abstraktiota pisteen tasolle ja määrittelemällä tietotyyppi Tpiste seuraavasti: typedef struct { float x; float y; Tpoint; Huomautus 1. Tunnilla tarkastellaan myös kuinka funktioiden toteutukset tehdään tässä tilanteessa. Huomautus 2. Jos tarkasteluun otetaan mukaan toteutettujen komponenttien yleisyys ja uudelleenkäytettävyys, ei yllä oleva suunnistajan ohjelma ole ollenkaan optimaalinen vielä. Esimerkiksi se, että lähtöpiste ja päätepiste molemmat luetaan yhdessä funktiossa ei ole hyvä ratkaisu. Tämä funktio soveltuu vain tilanteeseen, jossa luetaan kaksi pistettä. Jos pisteitä pitäisi jossakin tilanteessa lukea 1 tai 3. ei toteutettua funktiota voi silloin hyödyntää. Jos lähtötietojen lukemiseen olisikin tehty yleinen funktio, joka lukee yhden pisteen ja jolle voidaan antaa kehoteteksti parametrinä, olisi saatu yleiskäyttöisyydeltään paljon parempi funktio. Suunnistajan ohjelmassa sitä olisi voinut käyttää siten, että luetaan ensin lähtöpiste ja sitten samalla funktiolla päätepiste. Tällöin funktiokutsun lue_lahtotiedot(&p1, &p2); sijasta kirjoitettaisiin lue_piste(&p1, Anna lähtöpiste ); lue_piste(&p2, Anna tavoitepiste ); Funktion lue_piste toteutus olisi silloin seuraavanlainen. void lue_piste(tpoint *p, const char *prompt) { printf( %s, prompt); scanf( f%f, &p->x, &p->y); Abstrakti tietotyyppi Tietotyyppi Tpoint ja sen käsittelyyn tarkoitetut funktiot (lue_piste, laske_matka, laske_suunta, tulosta_piste, ja mahdollisesti muut) yhdessä muodostavat abstraktin tietotyypin piste. Määritelmä. Abstrakti tietotyyppi on tietotyyppi, joka sisältää kaikki jonkin asian kuvaamiseksi tarvittavat tietokentät ja tämän tietotyypin käsittelyyn tarvittavat funktiot ns. operaatiofunktiot. Hyvän ohjelmointitavan mukaan abstraktin tietotyypin tietokenttiin ei viitata ohjelmassa suoraan, vaan ainoastaan tietotyypin operaatiofunktioissa. Tällöin noudatetaan tiedon yksityiskohtien kätkemisen periaatetta (Information Hiding). Tiedon ja toimintojen

Algoritmit ja tietorakenteet / HL 5 yksityiskohdat kätketään. Käytetään vain sallittua liityntää tiedon käsittelyyn. Tämä liityntä ilmaistaan funktioiden prototyyppeinä ja (C-kielessä) tietotyypin määrittelynä. Käyttäjälle liityntä on tietotyypin nimi ja operaatiofunktioiden prototyypit. Käyttäjän ei tarvitse tietää tietotyypin sisäistä rakennetta eikä operaatiofunktioiden sisäistä toteutusta. Tässä on kysymyksessä myös ns. Black Box -ajattelu. Käytännössä abstraktit tietorakenteet voivat olla hierarkisia. Esimerkkinä tällaisesta hierarkkisesta rakenteesta nähdään tämän monisteen lopussa kolmio, jonka toteutuksessa voidaan käyttää hyväksi abstraktia tietotyyppiä piste. Käytännön esimerkkinä hyvän ohjelmointitavan vastaisesta abstraktin tietotyypin käytöstä on alla oleva esimerkki. void main(void) { Tpiste p1; lue_piste(&p1, Anna lähtöpiste ); // Tämä olisi oikein printf( Anna lähtöpiste: ); scanf ( %f%f, &p1.x, &p1.y); // TÄMÄ RIKKOO HYVÄÄ //OHJELMOINTITAPAA Ongelmana tässä on se, että viitataan suoraan abstraktin tietotyypin kenttiin x ja y. Jos tässä tapauksessa ADT:n toteutusta muutetaan, joudutaan muuttamaan myös sitä käyttävää sovellusta eli yllä olevaa ohjelmaa. Abstrakti tietotyyppi on ohjelmistokomponentti Samoin kuin elektroniikan (ja muidenkin tekniikan alueiden) laitevalmistuksessa pyritään käyttämään komponentteja eli rakentamaan laitteita komponenteista. Kun puhutaan komponenteista, tulee ensimmäisenä mieleen ainakin seuraavat ominaisuudet, jotka vaaditaan komponentilta: 1) Voidaan käyttää (uudelleen) sellaisenaan rakennuspalikkana erilaisissa laitteissa. 2) Komponentilla on selkeästi määritelty rajapinta (interface), joka esimerkiksi elektroniikkakomponentin kohdalla tarkoittaa mekaanisia ja sähköisiä speksejä. 3) Komponentin käyttöön riittää sen interface-tiedot. Tietoa siitä mitä on komponentin sisällä eli kuinka se on toteutettu, ei tarvita. 4) Komponentti voidaan vaihtaa toiseen parempaan tai eritavalla toteutettuun komponenttiin muuttamatta muuta laitteistoa sen ympärillä kunhan vai uudella komponentilla on samanlainen interface. 5) Komponentti on koteloitu eli käyttäjälleen ns. musta laatikko (Black Box). Komponentin sisäistä toteutusta ei siis edes näy päällepäin. Voidaan osoittaa, että abstraktilla tietotyypillä on kaikki nämä ominaisuudet ohjelmistossa edellyttäen, että sen suunnittelussa ja käytössä on huomioitu tietyt asiat. Tarkastellaan nyt näiden vaatimusten täyttymistä ja ehtoja niiden täyttymiselle. Esimerkkeinä kuinka ADT pistettä voidaan käyttää sellaisenaan erilaisissa sovelluksissa (vaatimus 1) ovat vaikkapa: reitinlaskentaohjelma, peliohjelma (pisteellä esitetään esim. laivan paikkaa), grafiikkaohjelma (piste voi esittää vaikka ympyrän keskipistettä), maanmittausohjelma, jne. ADT:n tekeminen mahdollisimman yleiskäyttöiseksi ei ole itsestään selvä asia. Se edellyttää esimerkiksi, että tyypille on tehty riittävän kattava funktiovalikoima. Myös yksittäisten funktioiden suunnittelulla on ratkaiseva merkitys siihen, kuinka hyvin niitä voidaan käyttää erilaisissa tilanteissa. Tunnilla yksinkertaisena esimerkkinä tästä tarkastellaan suunnistajan ohjelman pisteiden lukemisfunktion toteuttamista erilaisilla tavoilla funktion yleiskäyttöisyyttä silmällä pitäen.

Algoritmit ja tietorakenteet / HL 6 ADT pisteen interface-tietoja ovat sen tyyppinimi ja operaatiofunktioiden prototyypit. Sovelluksen kirjoittamisessa ei tarvita muuta tietoa. Tietotyypin nimi siis riittää. Samoin funktioista riittää niiden otsikkotieto (prototyyppi). Tietoa siitä, kuinka funktio on toteutettu, ei tarvita. Tämän takia myös vaatimukset 2 ja 3 ovat voimassa. Myös vaatimus 4 on voimassa edellyttäen, että komponentin käytössä on noudatettu hyvää ohjelmointitapaa eli tietotyypin sisäistä toteutusta ei todellakaan käytetä sovelluksessa, vaan tietotyyppiä käytetään vain sen operaatiofunktioilla. Esillä olleessa suunnistajan ohjelmassa tämä tarkoittaa, että pääohjelmassa ei ole suoria viittauksia tietueen Tpoint kenttiin x tai y. Jos siis pääohjelmassa olisi esimerkiksi luettu lähtöpiste muodossa scanf( %f%f, &p1.x, &p1.y); siihen ei enää voida vaihtaa uudella tavalla toteutettua pistettä (esimerkiksi napakoordinaateissa sisäisesti esitettävää toteutusta) ilman, että tehtäisiin muutos myös itse sovellukseen eli tässä tapauksessa main-funktioon. Jos sen sijaan hyvää ohjelmointitapaa on noudatettu, niin muutettaessa pisteen sisäinen tai vaikka myös ulkoinen esitys napakoordinaatteihin, muutos tehdään vain itse komponenttiin, mutta ei sitä käyttävään ympäristöön. ADT:n toteutus saadaan myös koteloitua mustaan laatikkoon käyttämällä erillistä kääntämistä ja linkkaamalla toteutus sitten objektitiedostona sovellukseen. Todellisen kätkemisen periaate Edellä kuvattu tiedon kätkeminen voidaan tehdä oikeasti siten, että tietotyypin määrittelyt ja operaatiofunktioiden prototyypit laitetaan omaan tiedostoon, ns. header-tiedostoon. Lisäksi operaatiofunktioiden toteutus laitetaan omaan tiedostoon, joka käännetään erikseen objektimuotoon. Tämän jälkeen sovellusohjelma-tiedostossa ei tarvitse pitää mukana funktioiden määrittelyjä ja prototyypit otetaan mukaan #include-direktiivillä. Funktioiden toteutus saadaan lopulliseen sovellukseen linkkaamalla siihen aikaisemmin käännetty objekti-tiedosto. Liitteenä oleva kuva valaisee tätä menettelyä. Huomautus. Aikaisemmin esiintuotu ajatus, että käytettäessä abstraktia tietotyyppiä sovellusten rakentamiseen, ei tarvita tietoa sen sisäisestä toteutuksesta, tulee ulottaa myös headerien käyttöön. Sovelluksen rakentajan tulee voida incluudata aina sellaiset headerit sovellukseen (ja missä järjestyksessä tahansa), jotka sisältävät käytettävien ADT:eiden interface-tiedot. Jotta tämä saadaan sovellusohjelmoijalle helpoksi, tarvitaan headerien rakennuksessa ns. ehdollisen kääntämisen mahdollistavia esikääntäjän direktiivejä. Näiden käytöstä puhutaan enemmän tunnilla. Oliolähestymistapa Tässä opintojaksossa käytetään C-kieltä ja yllämainittua hyvää ohjelmointitapaa. Olioperustaisessa lähestymistavassa usein ei ole mahdollisuutta rikkoa tätä hyvää ohjelmointitapaa. Kääntäjä antaa virheilmoituksen hyvän tavan rikkomisesta (esimerkiksi viittauksesta suoraan abstraktin tietorakenteen tietokenttiin). Olio-ohjelmointitavassa operaatiofunktiot sisällytetään tietotyypin määrittelyyn, joka onkin luonnollista, koska ne niin oleellisesti liittyvät abstraktin tietorakenteen määrittelyyn. Oliokielissä siis oikeastaan tietotyypillä (jota nyt kutsutaan luokaksi) määritellään abstrakti tietorakenne. Liitteenä on informatiivisena kolmio-esimerkki oliototeutuksena C++-kielellä. Tietueen määrittely ja ominaisuudet

Algoritmit ja tietorakenteet / HL 7 Huomautus. Tietueen ominaisuuksista ja ominaisuuksien vertailusta taulukon ominaisuuksiin on myös oma laajempi erillinen moniste. Yllä olevassa esimerkissä tietotyyppi Tpoint määriteltiin muodossa typedef struct { float x; float y; Tpoint; Tämä määrittely käyttää hyväksi ansi-standardin määrittelemää typedef-avainsanaa, jolla saadaan aikaan käyttäjän määrittelemiä tietotyyppejä. Tietuetyyppiä voidaan käyttää myös vanhanaikaisella tavalla eli kielen suunnittelijoiden Kernighan ja Ritchie käyttämällä tavalla. Kolmantena tapana on vielä C++-kielen tapa silloin kun käytetään C++-kääntäjää. C- kieltä käytettäessä on suositeltavaa käyttää typedef-määritettä hyödyntävää tapaa. Tunnilla tarkastellaan muut tavat lähinnä siksi, että niiden merkitys tulisi tunnetuksi. Kannattaa muistaa, että tietueen sijoitus on taattu ansi-standardin mukaan. Tämä tarkoittaa, että jos meillä on ohjelmassa kaksi tietuetta, esimerkiksi kaksi pistettä, määriteltynä ja alustettuna seuraavasti: Tpiste p1, p2 = {1.0, 2.0 ; //pisteelle p2 alustetaan arvot (1.0, 2.0) p1 = p2; //tietueen kaikki kentät kopioidaan. Toisella rivillä oleva sijoitus tarkoittaa, että tietueen x kenttä ja y-kenttä molemmat saavat arvon tietueessa p1. Tietuetta ei siis tarvitse sijoittaa kenttä kentältä erikseen. Huomautus 1. Vertailun vuoksi tunnilla tarkastellaan myös taulukon sijoitusta. Huomautus 2. Tunnilla tarkastellaan myös tietueen sijoitusta, kun tietueen kenttänä on taulukko. Huomautus 3. Tunnilla tarkastellaan myös tietueen sijoitusta, kun tietueen kenttänä on osoitin, joka edustaa taulukkoa ( matalakopiointi ja syväkopiointi ). Tietojen abstraktiosta lisää: useampitasoinen abstraktiomalli Esimerkkinä tapauksesta, jossa tiedon hierarkiamalli on useampitasoinen, käsitellään ohjelmaa, joka käsittelee kolmioita. Kolmiot määritellään tässä kärkipisteidensä avulla. Ohjelma lukee ensin kolmion määrittelytiedot ja selvittää sitten, onko kolmio tasasivuinen. Mikäli kolmio on tasasivuinen, ohjelma laskee ja tulostaa sen pinta-alan. Lähdemme heti siitä, että toimintojen abstraktio on kunnossa. Tämän takia pääohjelmassa kutsuttavat funktiot kohdistuvat kolmioon eikä esimerkiksi pisteisiin. Pääohjelma näyttää silloin seuraavalta //Kolmiotehtävä ilman data-abstraktiota void main (void) { float x1, y1, x2, y2, x3, y3; float area; read_triangle(&x1, &y1, &x2, &y2, &x3, &y3); if (sides_equal(x1,y1,x2,y2,x3,y3)) { area = triangle_area(x1,y1,x2,y2,x3,y3); printf("area is %5.2f", area); else printf("\n Sides are not equal");

Algoritmit ja tietorakenteet / HL 8 Ohjelmassa on toimintojen abstraktio OK ja tapahtumien kulkua on helppo seurata ohjelmasta. Sen sijaan pisteiden käsittely on sotkua eikä se vastaa ihmisen käyttämää abstraktiota eli pyrkimystä yksinkertaistaa. Ihminen ei ajattele kolmea pistettä kuutena erillisenä lukuna, vaan kolmena pisteenä. Ihminen käyttää kahden luvun yhdistelmästä abstraktiota piste kuten jo edellä näimme. Muutamme nyt ohjelman vastaamaan tätä ajattelumallia. Nyt siis nostetaan tiedon abstraktiota pisteen tasolle. Käytössä on nyt edellä määritelty tietotyyppi Tpoint. //Kolmiotehtävä ensimmäisen tason data-abstraktiolla void main (void) { Tpoint p1,p2,p3; read_triangle(&p1, &p2, &p3); if (sides_equal(p1, p2, p3)) { area = triangle_area(p1, p2, pt3); printf("area is %5.2f", area); else printf("\n Sides are not equal"); Laajat tietokokonaisuudet saadaan hallintaan käyttämällä ryhmittelyä ja luokittelua. Näin pääsemme yksittäiseen tietoon hierarkkista polkua pitkin, kun tiedämme mihin kokonaisuuteen se kuuluu, mihin kokonaisuuden osaan se kuluu jne. Nostamme nyt tiedon abstraktiotasoa edelleen kolmion tasolle. Ohjelmassa käsitellään kolmioita. Määrittelemme tietotyypin Ttriangle ja käytämme ohjelmassa muuttujaa, jolla on tietotyyppi Ttriangle. Tällöin kaikki kolmiota käsittelevät funktiot saavat parametrin, joka on tyyppiä Ttriangle (tai osoitin sellaiseen). Tietotyyppi Ttriangle määritellään seuraavasti: typedef struct { Tpoint apex1; Tpoint apex2; Tpoint apex3; Ttriangle; Ohjelma näyttää nyt seuraavalta: //Kolmiotehtävä toisen tason data-abstraktiolla void main (void) { Ttriangle triangle; read_triangle(&triangle); if (sides_equal(triangle)) { area = triangle_area(triangle); printf("area is %5.2f", area); else printf("\n Sides are not equal"); Tarkastellaan seuraavana myös abstraktin tietotyypin triangle toteutusta. Nyt siis ADT kolmion toteutuksessa käytetään hyväksi ADT pistettä. Se mitä aikaisemmin on sanottu hyvästä ohjelmointitavasta, pätee tietysti edelleen. Kolmion operaatiofunktioiden toteutuksissa kolmionkärkipisteitä pitää siis käsitellä vain pisteen omilla operaatiofunktioilla. Tämä tarkoittaa myös sitä, että abstraktiotasoja ei saa ylittää. Ylemmän tason komponentin

Algoritmit ja tietorakenteet / HL 9 operaatiofunktion toteutuksessa sen alakomponenttia saa käsitellä vain alakomponentin omilla operaatiofunktioilla. Tarkastellaan esimerkkinä kolmion funktion read_triangle toteutusta. void read_triangle (Ttriangle *t) { lue_piste(&t->apex1, Anna 1. kärkipiste ); lue_piste(&t->apex2, Anna 2. kärkipiste ); lue_piste(&t->apex3, Anna 3. kärkipiste ); Huomautus. Kolmio-ohjelmien täydelliset toteutukset ovat liitteenä.

Algoritmit ja tietorakenteet / HL 10 Liite 1 Algoritmit ja tietorakenteet Hannu Laine Abstraktion edut monimutkaisuuden hallinta helpottuu tekee mahdolliseksi laatia laajoja ohjelmia tekee mahdolliseksi paloitella tehtävä pienempiin osiin tekee mahdolliseksi jakaa ohjelmointityö ja edetä askelittain ohjelmista tulee luettavampia ohjelmien verifiointi tulee mahdolliseksi testaus helpottuu ohjelmien ylläpito ja jatkokehitys helpottuu tehtyjen ohjelmanosien uudelleenkäyttö tehostuu (ohjelmiston rakennuskomponentit) Muita nimityksiä samalle asialle abstraction information hiding black box thinking programming in large

Algoritmit ja tietorakenteet / HL 11 Separate compiling and linking together Liite 2 Datatype definition typedef... Tadt; Function prototypes... function1(tadt a,...);... function2(tadt *pa,...); Header file adt.h #include "adt.h" #include "adt.h" void main (void) { Tadt a; function1(a,...); function2(&a,...); #include "adt.h" Function bodies... function1(tadt a,...) { Main application program applicat.c ADT implementation file adt.c compile compile applicat.obj adt.obj link applicat.exe... function2(tadt *pa,...) {