Tieto- ja tallennusrakenteet
Sisältö Tyyppi, abstrakti tietotyyppi, abstraktin tietotyypin toteutus Tallennusrakenteet Taulukko Linkitetty rakenne Abstraktit tietotyypit Lista (Puu) (Viimeisellä viikolla) (Binääripuu)
Tiedosta tietorakenteisiin Tähän asti kurssilla keskitytty ohjausrakenteisiin Käsitelty tieto Ollut yksinkertaista Ei sisäistä rakennetta (kokonaisluku, merkki, jne.) Algoritmeissa yleensä Tavoitteena ratkaista reaalimaailman ongelmia Tieto ei ole irrallista, vaan joukko toisiinsa liittyvää tietoa Tiedot halutaan koota yhteen ja esittää ne tietorakenteena (data structure)
Tyypit ohjelmointikielissä Ohjelmointikielet yleensä tyypitettyjä Jokaisella ohjelman tietoalkiolla on tyyppi Tyyppi koostuu Kaikista mahdollisista arvoista Operaatioista, joita tyypin edustajiin (alkioihin) voidaan kohdistaa Ohjelmointikielissä valmiina Tyypit yksinkertaiselle tiedolle Esim. kokonaisluvut, desimaaliluvut, totuusarvot, jne. Välineet tietorakenteiden konstruoimiseen Pythonissa muuttujan tyyppiä ei tarvitse ilmoittaa Määräytyy siitä, minkä tyyppinen arvo muuttujaan on viimeksi sijoitettu
Tyypin määrittely Esimerkiksi kokonaislukutyyppi määritelty, kun Määritellään pienin ja suurin mahdollinen arvo Määritellään mitä operaatioita voidaan kohdistaa (+, -, *, /, %) ja miten ne toimivat Perustyypit sisäänrakennettu Omia tyyppejä voidaan kuitenkin tehdä Rakennettaessa omia tietorakenteita, operaatiot ja niiden toiminta implementoitava itse
Tallennusrakenne ja abstrakti tietotyyppi Erotellaan tietorakenteen abstrakti malli ja sen tallennusrakenteet Tallennusrakenne (storage structure) kertoo miten tietorakenne on toteutettu ja tallennettu tietokoneen muistiin Tietorakenteen abstrakti malli eli abstrakti tietotyyppi (abstract data type, ADT) taas kuvaa Tietorakenteeseen kohdistettavat operaatiot Operaatioiden toiminnan Riippumattomia ohjelmointikielestä
Abstrakti tietotyyppi Abstrakti tässä tarkoittaa että Tarkastellaan mallin mukaisten alkioiden oleellisia piirteitä Malli on riippumaton ohjelmointikielestä Alkiot kuvataan niiden käytöksen avulla (operaatiot ja niiden vaikutus) Ei siis sen mukaan miltä ne näyttävät (käytetyt tallennusrakenteet) Tietoa mallinnetaan siis ohjelmointikielistä ja tallennusrakenteista riippumattomilla abstrakteilla tietotyypeillä
Tallennusrakenteet ja abstraktit tietotyypit Tallennusrakenteet Taulukko Linkitetyt rakenteet Abstraktit tietotyypit Lista Jono Pino Puu Graafi (Listat eivät ole kattavia)
Tallennusrakenteet - Taulukko
Tallennusrakenteet - Taulukko Taulukko (array) on staattinen, kiinteän kokoinen rakenne Koko voidaan määrätä ohjelman suorituksen aikana Kokoa ei voi myöhemmin muuttaa Taulukon sisältöä (eli komponenttien arvoja) voidaan muuttaa Taulukko koostuu useista samantyyppisistä tietoalkioista Alkiot identifioidaan sijainnin mukaan indeksoimalla Indeksointi järjestysnumeroilla 0, 1, 2 (useissa ohjelmointikielissä) Taulukon alkiot tietokoneen muistissa peräkkäin Käsittely tehokasta ja helppoa Hyvä tallennusrakenne, jos alkioiden lukumäärä kiinteä
Tallennusrakenne - Taulukko Vektori (vector) on yksiulotteinen taulukko Kokoa k olevan taulukon V yksittäisiin alkioihin viitataan notaatiolla V[i], missä 0 i < k i:tä kutsutaan tässä indeksiksi
Ensimmäinen indeksi Elementti (indeksissä 8) Indeksit Vektorin (taulukon) koko on 10 Kuva: docs.oracle.com 353
Tallennusrakenne - Taulukko Matriisi (matrix) on kaksiulotteinen taulukko Indeksoidaan kahdella indeksillä: rivi ja sarake Kokoa nxm (n riviä, m saraketta) olevan matriisin M yksittäisiin alkioihin viitataan notaatiolla M[i][j], missä 0 i < n ja 0 j < m.
Tallennusrakenne - Taulukko j Matriisin indeksointi kun matriisin alkioon viitataan M[i][j] i
Tallennusrakenne - Taulukko Myös useampiulotteiset taulukot mahdollisia Taulukon sisältämää tietoa voidaan käyttää kuten samantyyppisiä muuttujia Taulukolle sallitut operaatiot Tietoalkion tallennus indeksin osoittamaan kohtaan V[2] = 7 M[3][a] = b + 3 Yksittäisen tietoalkion käyttö y = V[4] z = M[1][1]
Tallennusrakenne - Taulukko Taulukon alustus ja arvojen käyttö: taulu = [23, 45] x = taulu[0] y = taulu[1] summa = x + y Alustetaan taulukko. 23 45 0 1
Tallennusrakenne - Taulukko Taulukon alustus ja arvojen käyttö: taulu[0] taulu = [23, 45] x = taulu[0] y = taulu[1] summa = x + y Alustetaan muuttuja x taulukon indeksin 0 arvolla, eli arvolla 23. 23 45 0 1
Tallennusrakenne - Taulukko Taulukon alustus ja arvojen käyttö: taulu[1] taulu = [23, 45] x = taulu[0] y = taulu[1] summa = x + y Alustetaan muuttuja y taulukon indeksin 1 arvolla, eli arvolla 45. 23 45 0 1
Tallennusrakenne - Taulukko Taulukon alustus ja arvojen käyttö: taulu = [23, 45] x = taulu[0] y = taulu[1] summa = x + y Lasketaan muuttujaan summa muuttujien x ja y summa. 23 45 0 1
Tallennusrakenne - Taulukko Taulukon alustus ja arvojen käyttö: taulu = [23, 45] x = taulu[0] y = taulu[1] summa = x + y Lasketaan muuttujaan summa muuttujien x ja y summa. 23 45 0 1 Sama voitaisiin laskea suoraan: summa = taulu[0] + taulu[1]
Tallennusrakenne - Taulukko Taulukon pituuden saa Pythonissa selville funktiolla len, joka ottaa parametrina taulukon Esim: len(taulu) Palauttaa edellisessä esimerkissä 2 Esimerkki: tulostetaan kaikki taulukon T alkiot T = [2, 9, -1, 4] for i in range(len(t)): print Indeksin, i, alkion arvo on + T[i]
Tallennusrakenne - Taulukko T = [2, 9, -1, 4] for i in range(len(t)): print Indeksin, i, alkion arvo on, T[i] Alustetaan muuttujaan T taulukko 2 9-1 4 0 1 2 3
Tallennusrakenne - Taulukko T = [2, 9, -1, 4] for i in range(len(t)): print Indeksin, i, alkion arvo on, T[i] Käydään silmukassa läpi i:n arvot 0,1,2,3 Taulukon pituus len(t) on 4. 2 9-1 4 0 1 2 3
Tallennusrakenne - Taulukko T[0] 2 9-1 4 T = [2, 9, -1, 4] for i in range(len(t)): print Indeksin, i, alkion arvo on, T[i] Ohjelman tulostus: Indeksin 0 alkion arvo on 2 i:n arvolla 0 tulostetaan T[i] eli T[0]:n arvo 2 0 1 2 3
Tallennusrakenne - Taulukko T[1] 2 9-1 4 T = [2, 9, -1, 4] for i in range(len(t)): print Indeksin, i, alkion arvo on, T[i] Ohjelman tulostus: Indeksin 0 alkion arvo on 2 Indeksin 1 alkion arvo on 9 i:n arvolla 1 tulostetaan T[i] eli T[1]:n arvo 9 0 1 2 3
Tallennusrakenne - Taulukko T[2] 2 9-1 4 T = [2, 9, -1, 4] for i in range(len(t)): print Indeksin, i, alkion arvo on, T[i] Ohjelman tulostus: Indeksin 0 alkion arvo on 2 Indeksin 1 alkion arvo on 9 Indeksin 2 alkion arvo on -1 i:n arvolla 2 tulostetaan T[i] eli T[2]:n arvo -1 0 1 2 3
Tallennusrakenne - Taulukko T[3] 2 9-1 4 T = [2, 9, -1, 4] for i in range(len(t)): print Indeksin, i, alkion arvo on, T[i] Ohjelman tulostus: Indeksin 0 alkion arvo on 2 Indeksin 1 alkion arvo on 9 Indeksin 2 alkion arvo on -1 Indeksin 3 alkion arvo on 4 i:n arvolla 3 tulostetaan T[i] eli T[3]:n arvo 4 0 1 2 3
Tallennusrakenteet Linkitetty rakenne
Tallennusrakenteet Linkitetty rakenne Linkitetyssä rakenteessa jokainen alkio sisältää Varsinaisen datan (yhden tai useampia datakenttiä) Tiedon seuraajastaan, eli osoittimen rakenteen seuraavaan alkioon Tai useampia osoittimia rakenteen muihin alkioihin Koko rakenne samaistetaan usein rakenteen ensimmäiseen alkioon eli kuvan alkioon L Linkitetty yhteen suuntaan ketjutettu rakenne
Tallennusrakenteet Linkitetty rakenne Jokainen linkitetty rakenteen alkio tarvitsee kaksi muuttujaa Dataa varten Viittauksen seuraavaan rakenteen alkioon Tallennusrakenne tälle ei ole kurssin kannalta tärkeä, mutta voidaan tehdä esim. luokalla, taulukolla, tai tässä esimerkissä sanakirjalla(dictionary) Esimerkiksi: linkitettyalkio = { data : solmundataa, seuraava : None} # Seuraava voidaan alustaa myöhemmin toiseksi alkioksi. # Syntaksia ei tarvitse tällä kurssilla osata Linkitetty yhteen suuntaan ketjutettu rakenne
Tallennusrakenteet Linkitetty rakenne Linkitetystä rakenteesta useita muunnelmia tarpeen mukaan Kahteen suuntaan ketjutettu rakenne:
Tallennusrakenteet Linkitetty rakenne Useita seuraajia salliva rakenne Jokaisella alkiolla voi olla useita seuraajia Rengasrakenne
Abstraktit tietotyypit Lista
Abstraktit tietotyypit Lista Abstrakti tietotyyppi lista on rakenne Koostuu alkioista, jotka on järjestetty peräkkäin Jokaisella alkiolla (paitsi viimeisellä) on yksikäsitteinen seuraaja Jokaisella alkiolla (paitsi ensimmäisellä) on yksikäsitteinen edeltäjä
Abstraktit tietotyypit Lista Listan operaatioita esimerkiksi: Alkion lisäys ja poisto mielivaltaiseen kohtaan listassa Ensimmäisen alkion ja loppuosan palauttavat operaatiot Lista hyvä rakenne kun tietoalkioita käsitellään peräkkäin
Abstraktit tietotyypit Lista>Jono Listan operaatioita rajoittamalla saadaan tärkeitä tietorakenteita Jono (queue): Määritelty vain operaatiot Alkion lisääminen alkuun Alkion poistaminen lopusta => poistetaan aina samassa järjestyksessä kuin lisättiin Ns. First-In-First-Out periaate (FifO)
Abstraktit tietotyypit Lista>Pino Listan operaatioita rajoittamalla saadaan tärkeitä tietorakenteita Pino (stack): Määritelty vain operaatiot Alkion lisäämiseksi listan lopusta Alkion poistaminen listan lopusta Pinosta poistetaan aina viimeksi lisätty alkio (esim. lautaspino) Ns. Last-In-First-Out periaate (LifO)
Abstraktit tietotyypit Listan toteutus Lista voidaan toteuttaa käyttäen tallennusrakenteina vektoria tai dynaamisia linkitettyjä rakenteita Vektorin käyttöä rajoittaa sen staattisuus Tosin se mahdollistaa helpon viittauksen järjestysnumeron mukaan Jos lista on luonteeltaan vakiokokoinen, kannattaa käyttää vektoria Jos lista aidosti dynaaminen, kannattaa käyttää dynaamisia linkitettyjä rakenteita
Abstraktit tietotyypit Listan toteutus vektorilla Katsotaan miten vektorilla toteutettuun listaan lisätään alkioita Oletetaan että lista on lisäyshetkellä alla esitetyn sisältöinen Lisätään alkio 42 neljänneksi (indeksi 3) alkioksi alla olevaan vektoriin (joka siis on listan tallennusrakenne) Suoritamme siis listan operaation insert(42, 3) 89 53 12 19 43 54 0 1 2 3 4 5 6 7
Abstraktit tietotyypit Listan toteutus vektorilla Katsotaan miten vektorilla toteutettuun listaan lisätään alkioita Lisätään alkio 42 neljänneksi (indeksi 3) alkioksi alla olevaan vektoriin (joka siis on listan tallennusrakenne) Suoritamme siis listan operaation insert(42, 3) 89 53 12 19 43 54 0 1 2 3 4 5 6 7 Lisäyskohta, jossa on jo alkio
Abstraktit tietotyypit Listan toteutus vektorilla Katsotaan miten vektorilla toteutettuun listaan lisätään alkioita Lisätään alkio 42 neljänneksi (indeksi 3) alkioksi alla olevaan vektoriin (joka siis on listan tallennusrakenne) Suoritamme siis listan operaation insert(42, 3) 89 53 12 19 43 54 0 1 2 3 4 5 6 7
Abstraktit tietotyypit Listan toteutus vektorilla Katsotaan miten vektorilla toteutettuun listaan lisätään alkioita Lisätään alkio 42 neljänneksi (indeksi 3) alkioksi alla olevaan vektoriin (joka siis on listan tallennusrakenne) Suoritamme siis listan operaation insert(42, 3) 89 53 12 19 43 54 0 1 2 3 4 5 6 7
Abstraktit tietotyypit Listan toteutus vektorilla Katsotaan miten vektorilla toteutettuun listaan lisätään alkioita Lisätään alkio 42 neljänneksi (indeksi 3) alkioksi alla olevaan vektoriin (joka siis on listan tallennusrakenne) Suoritamme siis listan operaation insert(42, 3) 89 53 12 19 43 54 0 1 2 3 4 5 6 7
Abstraktit tietotyypit Listan toteutus vektorilla Katsotaan miten vektorilla toteutettuun listaan lisätään alkioita Lisätään alkio 42 neljänneksi (indeksi 3) alkioksi alla olevaan vektoriin (joka siis on listan tallennusrakenne) Suoritamme siis listan operaation insert(42, 3) 89 53 12 19 43 54 0 1 2 3 4 5 6 7 Lisäyskohta vihdoin tyhjä
Abstraktit tietotyypit Listan toteutus vektorilla Katsotaan miten vektorilla toteutettuun listaan lisätään alkioita Lisätään alkio 42 neljänneksi (indeksi 3) alkioksi alla olevaan vektoriin (joka siis on listan tallennusrakenne) Suoritamme siis listan operaation insert(42, 3) Taulukon viimeinen alkio indeksissä 7 ei kuulu listaan 89 53 12 42 19 43 54 0 1 2 3 4 5 6 7 Lisätään alkio
Taulukot ja listat Pythonissa 389
Taulukoista Taulukko on kiinteän kokoinen rakenne, joka sisältää samaa tietotyyppiä olevia alkioita Lista sallii lisäyksen mihin tahansa kohtaan listaa, jolloin listan koko muuttuu Pythonissa ei ole taulukoita! Pythonissa käytetään taulukon sijaan listaa, joka sisältää normaaleiden taulukon operaatioiden lisäksi alkioiden lisäämisen, poistamisen ja monia muita Edelliset esimerkit kuitenkin pätevät Pythoniin Pythonin listat voivat sisältää erityyppisiä alkioita
Listan alustus Alustuksessa annettavat arvot saavat olla mitä tahansa lausekkeita lista = [0, 2 + 3, 9 * 7, -2-3] a = 7 lista2= [0, a, 2*a, 3*a] 0 5 63-5 0 1 2 3 0 7 14 21 0 1 2 3
Listan arvojen käyttö ja sijoitus a = 4 t = [9, 8, 7, 6, 5] t[4] = 9 # listassa arvot [9, 8, 7, 6, 9] t[2 + 1] = 8 # listassa arvot [9, 8, 7, 8, 9] t[2] = t[2] - 6 # listassa arvot [9, 8, 1, 8, 9] t[a 1] = 3 # listassa arvot [9, 8, 1, 3, 9] print t[2] # tulostaa 1 print t[t[2]] # tulostaa 8 (indeksi 1) print t[a] # tulostaa 9 (indeksi 4)
Parametrien välityksestä funktioille Kuten viime viikolla näimme: Perustyypit, eli kokonaisluvut, desimaaliluvut, merkkijonot ja totuusarvot välitetään ikään kuin kopioimalla ne funktiolle Tämä johtuu siitä, että nämä perustyypit ovat muuttumattomia (immutable), eli niiden arvo ei voi muuttua Voimme kuitenkin muodostaa niiden arvosta uuden arvon, ja sijoittaa sen muuttujaan Listat sen sijaan ovat muuttuvia (mutable) Listoja ei kopioida, funktio saa viittauksen todellisen parametrin listaan Funktio siis voi muuttaa samaa listaa kuin kutsuja käsittelee! Tämä ei ole kattava selostus välitysmekanismeista Pythonissa, mutta kurssin kannalta riittävä AOP/OOP-kursseilla melkein vastaavaa järjestelmää käsitellään Javassa
Parametrien välityksestä funktioille Esimerkki: def muutalistaa(plista): print "saatiin", plista # tulostaa [1, kaksi, 3] plista[2] = "nelja print "muutettiin:", plista # tulostaa [1, kaksi, nelja ] lista = [1, "kaksi", 3] print ennen:, lista # tulostaa [1, kaksi, 3] muutalistaa(lista) print jalkeen, lista # tulostaa [1, kaksi, nelja ]
Matriisi Useampiulotteisia listoja voidaan määritellä käyttämällä listan arvoina listoja Esim. 2-ulotteinen lista (eli matriisi): # matriisi jossa on 2 riviä, 4 saraketta m = [[0,1,2,3], [4,5,6,7]] 0 1 2 3 0 0 1 2 3 1 4 5 6 7
Matriisi Voidaan jakaa usealle riville visualisoinnin helpottamiseksi # matriisi, jossa on 3 riviä, 2 saraketta m2 = [[2*3, 3*3], [3*7, 9-2], [9+1, 4]] 0 1 0 6 9 1 21 7 2 10 4
Matriisi # matriisi jossa on 2 riviä, 4 saraketta m = [[0, 1, 2, 3], [4, 5, 6, 7]] # matriisi, jossa on 3 riviä, 2 saraketta m2 = [[2*3, 3*3], [3*7, 9-2], [9+1, 4]] m[1][1] # 5 m2[0][0] # 6 m2[m[0][2]][1] # 4
Listan läpikäynti: Tapa 1 Lista voidaan käydä läpi kahdella tavalla, Yksinkertaisesti kun silmukassa ei tarvitse tietää listan indeksejä lista = [4, 6, 2, -4] for luku in lista: print luku Tulostaa 4 6 2-4
Listan läpikäynti: Tapa 2 Toinen tapa, kun tarvitaan listan indeksejä: lista = [4, 2, -4] for i in range(len(lista)): print i,,, lista[i] Tulostaa 0, 4 1, 2 2, -4
Matriisi # matriisi jossa on 2 riviä, 4 saraketta m = [[0, 1, 2, 3], [4, 5, 6, 7]] m[1][1] # 5 m2[1][2] # 6
Matriisin läpikäynti Tarvitaan kaksi sisäkkäistä silmukkaa Esim. m = [[0, 1, 2, 3], [4, 5, 6, 7]] for rivi in m: # käy läpi listan rivit for luku in rivi: # käy läpi rivin arvot print luku
Matriisin läpikäynti Jos tarvitaan rivin ja sarakkeen indeksit, käytetään rangea: m = [[0, 1, 2, 3], [4, 5, 6, 7]] for i in range(len(m)): # käy läpi listan rivit for j in range(len(m[i])): # käy läpi yhden rivin print rivi, i, sarake, j, arvo, m[i][j] Sisemmässä silmukassa otetaan aina yhden rivin leveys, joten rivit voivat olla erikokoisia Huomaa, että len(m) palauttaa 2, koska ulommassa listassa on 2 alkiota. Sen sijaan len(m[0]) palauttaa 4, koska sisemmässä listassa on 4 alkiota
Merkkijonojen läpikäynti silmukassa Merkkijonoja voi käydä läpi for-silmukassa merkki kerrallaan kuten listoja s = fhqwhgads for i in range(len(s)): print s[i] Tai: s = fhqwhgads for merkki in s: print merkki Molemmat tavat tulostavat allekkain merkit yksitellen jonosta fhqwhgads. Erona on, että ylemmässä käytetään indeksejä, kun taas alemmassa käydään läpi merkkejä. 404
Listan muuttaminen Pythonin lista sisältää monia operaatioita Alkioiden lisäys loppuun: lista.append(arvo) Alkioiden lisäys väliin: lista.insert(indeksi, arvo) Alkioiden poisto: lista.remove(arvo) Huom! Poistaa vain ensimmäisen alkion jonka arvo on parametrina saatu arvo Huom 2! Olemattoman luvun poisto aiheuttaa virheen (ValueError)