4. Sekvenssit Astetta soveltavat sekvenssit

Samankaltaiset tiedostot
Sekvenssi: kokoelma peräkkäisiä alkioita (lineaarinen

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

useampi ns. avain (tai vertailuavain) esim. opiskelijaa kuvaavassa alkiossa vaikkapa opintopistemäärä tai opiskelijanumero

3. Pinot, jonot ja linkitetyt listat

Algoritmit 2. Luento 2 To Timo Männikkö

Pino S on abstrakti tietotyyppi, jolla on ainakin perusmetodit:

3. Pinot, jonot ja linkitetyt listat

Algoritmit 2. Luento 2 Ke Timo Männikkö

Algoritmit 1. Luento 3 Ti Timo Männikkö

Tietorakenteet ja algoritmit Johdanto Lauri Malmi / Ari Korhonen

811312A Tietorakenteet ja algoritmit II Perustietorakenteet

Algoritmit 1. Luento 4 Ke Timo Männikkö

Algoritmit 2. Luento 7 Ti Timo Männikkö

Tietorakenteet ja algoritmit - syksy

Algoritmit 1. Luento 6 Ke Timo Männikkö

Algoritmit 1. Luento 10 Ke Timo Männikkö

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

18. Abstraktit tietotyypit 18.1

A TIETORAKENTEET JA ALGORITMIT

Tieto- ja tallennusrakenteet

8. Lajittelu, joukot ja valinta

Algoritmit 1. Luento 5 Ti Timo Männikkö

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

3. Pinot, jonot ja linkitetyt listat

f(n) = Ω(g(n)) jos ja vain jos g(n) = O(f(n))

Algoritmit 1. Luento 12 Ti Timo Männikkö

Algoritmit 1. Demot Timo Männikkö

Algoritmit 2. Luento 3 Ti Timo Männikkö

811312A Tietorakenteet ja algoritmit Kertausta kurssin alkuosasta

Algoritmit 2. Luento 4 To Timo Männikkö

Tietorakenteet ja algoritmit

Olio-ohjelmointi Syntaksikokoelma

811312A Tietorakenteet ja algoritmit, , Harjoitus 7, ratkaisu

Algoritmit 1. Luento 12 Ke Timo Männikkö

Listarakenne (ArrayList-luokka)

Algoritmit 1. Luento 1 Ti Timo Männikkö

Algoritmit 2. Luento 3 Ti Timo Männikkö

Tietorakenteet ja algoritmit

Tietorakenteet, laskuharjoitus 3, ratkaisuja

(p j b (i, j) + p i b (j, i)) (p j b (i, j) + p i (1 b (i, j)) p i. tähän. Palaamme sanakirjaongelmaan vielä tasoitetun analyysin yhteydessä.

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

private TreeMap<String, Opiskelija> nimella; private TreeMap<String, Opiskelija> numerolla;

Taulukot. Taulukon määrittely ja käyttö. Taulukko metodin parametrina. Taulukon sisällön kopiointi toiseen taulukkoon. Taulukon lajittelu

Algoritmit 2. Luento 4 Ke Timo Männikkö

TIETORAKENTEET JA ALGORITMIT

Algoritmit 1. Luento 14 Ke Timo Männikkö

Algoritmit 2. Luento 14 Ke Timo Männikkö

Algoritmit 1. Luento 10 Ke Timo Männikkö

Algoritmit 1. Luento 9 Ti Timo Männikkö

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

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Informaatioteknologian laitos Olio-ohjelmoinnin perusteet / Salo

58131 Tietorakenteet ja algoritmit (kevät 2014) Uusinta- ja erilliskoe, , vastauksia

Algoritmit 1. Demot Timo Männikkö

Algoritmit 1. Luento 2 Ke Timo Männikkö

Lyhyt kertaus osoittimista

8. Lajittelu, joukot ja valinta

A TIETORAKENTEET JA ALGORITMIT

Algoritmit 2. Luento 5 Ti Timo Männikkö

10. Painotetut graafit

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

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

A TIETORAKENTEET JA ALGORITMIT

TAMPEREEN TEKNILLINEN YLIOPISTO

Ohjelmoinnin jatkokurssi, kurssikoe

ITKP102 Ohjelmointi 1 (6 op)

811312A Tietorakenteet ja algoritmit Kertausta kurssin alkuosasta

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.

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

ALGORITMIT 1 DEMOVASTAUKSET KEVÄT 2012

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

Luku 8. Aluekyselyt. 8.1 Summataulukko

Algoritmit 1. Luento 7 Ti Timo Männikkö

A TIETORAKENTEET JA ALGORITMIT

58131 Tietorakenteet ja algoritmit (kevät 2013) Kurssikoe 1, , vastauksia

Tietorakenteet ja algoritmit

2. Perustietorakenteet

STL:n uudistukset. Seppo Koivisto TTY Ohjelmistotekniikka

1. (a) Seuraava algoritmi tutkii, onko jokin luku taulukossa monta kertaa:

TAMPEREEN TEKNILLINEN YLIOPISTO

Algoritmit 2. Luento 6 To Timo Männikkö

811312A Tietorakenteet ja algoritmit, , Harjoitus 3, Ratkaisu

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Taulukot & Periytyminen

4. Joukkojen käsittely

1. Mitä tehdään ensiksi?

puuta tree hierarkkinen hierarchical

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssi Y1

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Rajapinnat ja sisäluokat

Tietorakenteet. JAVA-OHJELMOINTI Osa 5: Tietorakenteita. Sisällys. Merkkijonot (String) Luokka String. Metodeja (public)

58131 Tietorakenteet ja algoritmit (syksy 2015)

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 8 To Timo Männikkö

Rakenteiset tietotyypit Moniulotteiset taulukot

4 Tehokkuus ja algoritmien suunnittelu

Algoritmit 1. Demot Timo Männikkö

Mukautuvat järjestämisalgoritmit

Tarkennamme geneeristä painamiskorotusalgoritmia

Transkriptio:

4. Sekvenssit Sekvenssit edustavat lineaarisesti järjestettyä alkioiden kokoelmaa, jolle on määritelty metodit alkion saantia, lisäystä ja poistoa varten. Täten sen jokaisella alkiolla on edeltäjä, paitsi ensimmäisellä, ja seuraaja, paitsi viimeisellä. Sekvenssi on yleistetty listarakenne verrattuna edellä kuvattuihin rajoitettuihin listoihin, so. pinoon, jonoon ja kaksiiseen jonoon, joissa päästiin suoraan vain ensimmäiseen tai viimeiseen alkioon käsiksi. Tässä osassa annetaan kaksi toteutustapaa sekvenssitietorakenteelle, taulukko ja kaksoislinkitetty lista. Esitellään käsitteet aste (rank) ja paikka (position). Aste osoittaa olion suhteellista järjestystä sekvenssissä, ja paikka kuvaa olioiden sijainnin sekvenssissä. 4.1. Astetta soveltavat sekvenssit Sekvenssin S kaikkiin n alkioihin e liittyy kokonaisluku aste väliltä [0,n-1] ollen sama kuin alkiota e edeltävien alkioiden lukumäärä. On huomattava, että tämä yhteys ei kuitenkaan merkitse, että välttämättä taulukkoa käytettäisiin toteutusvälineenä. Jos alkion aste on r, niin sen edeltäjän aste on r-1 ja seuraajan r+1, mikäli nämä ovat olemassa. Aste voi muuttua päivityksen takia. Mm. lisättäessä uusi alkio sekvenssin alkuun kaikkien muiden alkioiden aste kasvaa yhdellä. Aste on yksinkertainen, mutta tehokas käsite, sillä sillä voidaan määrätä, mihin sekvenssissä lisätään uusi alkio tai mistä sieltä poistetaan. Sekvenssin alkion aste on ajan ja sijainnin funktio, ja alkio asetetaan sekvenssiin näiden perusteella eikä alkion arvon. 4. kappale 121 4. kappale 122 Esim. 4.1. Oheisena on sarja asteeseen perustuvia lisäyksiä ja poistoja alunperin tyhjään sekvenssiin S. operaatio tulos S lisää 7 astetta 0 - (7) lisää 4 astetta 0 - (4,7) palauta alkio astetta 1 7 (4,7) lisää 2 astetta 2 - (4,7,2) palauta alkio astetta 3 virhe (4,7,2) poista alkio astetta 1 7 (4,2) lisää 5 astetta 1 - (4,5,2) lisää 3 astetta 1 - (4,3,5,2) lisää 9 astetta 4 - (4,3,5,2,9) palauta alkio astetta 2 5 (4,3,5,2,9) 4. kappale 123 Astetta soveltavan sekvenssin abstrakti tietotyyppi Sekvenssiin s liittyvät seuraavat perusmetodit. elematrank(r): Palauttaa sekvenssistä S alkion astetta r. Mikäli on r<0 tai r>n-1, jossa n on alkioiden määrä, annetaan virheilmoitus. Syöte: kokonaisluku Tulos: alkio replaceelematrank(r,e): Korvaa alkiolla e alkion astetta r ja palauttaa tämän. Mikäli on r<0 tai r>n-1, jossa n on alkioiden määrä, annetaan virheilmoitus. Syöte: kokonaisluku r ja alkio e Tulos: alkio insertelematrank(r,e): Lisää uuden alkion e r-asteisena sekvenssiin S. Mikäli on r<0 tai r>n, jossa n on alkioiden määrä, annetaan virheilmoitus. Syöte: kokonaisluku r ja alkio e 4. kappale 124

removeelematrank(r): Poistaa r-asteisen alkion sekvenssistä S. Mikäli on r<0 tai r>n-1, jossa n on alkioiden määrä, annetaan virheilmoitus. Syöte: kokonaisluku Tulos: alkio Lisäksi tarvitaan tavanomaiset metodit size() ja isempty(). Metodien joukko on vähäinen, mutta riittävä toteuttamaan kaksiisen jonon abstraktin tietotyypin. Seuraavassa ovat vastaavuudet. Taulukkoon perustuva toteutus kaksiisen jonon metodi size() isempty() first() last() insertfirst(e) insertlast(e) removefirst() removelast() toteutus sekvenssillä size() isempty() elematrank(0) elematrank(size()-1) insertelematrank(0,e) insertelematrank(size(),e) removeelematrank(0) removeelematrank(size()-1) 4. kappale 125 Astetta soveltavan sekvenssin tietotyyppi on helppo toteuttaa taulukolla S, jossa S[i] sisältää astetta i olevan alkion tai viittauksen tähän. Taulukon koko N valitaan riittävän suureksi, ja alkioiden määrästä n pidetään tietoa yllä. Sekvenssin abstraktin tietotyypin metodien toteutukset ovat varsin yksinkertaisia. Esimerkiksi lisäyksen ja poiston (koodi 4.1.) yhteydessä käsitellään astetta r olevaa alkiota ja siirretään sen jälkeisiä alkioita yhden asteen verran jompaankumpaan suuntaan (kuva 4.1.). 4. kappale 126 Algorithm insertelematrank(r,e): if r n-1 for i = n-1, n-2,.., r do S[i+1] S[i] S[r] e n n+1 Algorithm removeelematrank (r): e S[r] for i = r, r+1,, n-2 do S[i] S[i+1] n n-1 return e S S 0 1 2 r n-1 N-1 (a) 0 1 2 r n-1 N-1 (b) Kuva 4.1. Taulukkoon perustuva sekvenssin toteutus: (a) siirto eteenpäin taulukossa lisäystä varten asteessa r ja (b) siirto takaisinpäin poistoa asteessa r varten. Koodi 4.1. Taulukkoon perustuvat 4. sekvenssin kappale lisäys- ja poistometodit. 127 4. kappale 128

Taulukossa on kuvattujen metodien pahimman tapauksen suoritusajat. Esim. metodin insertelematrank(e,r) suoritusaika pahimmassa tapauksessa on O(n) sillä, kun r=0, on siirrettävä kaikki alkiot eteenpäin taulukossa. Samoin on poistossa. On myös Θ(n), koska keskimäärin on siirrettävä n/2 alkiota. Toteutuksen käyttämä tila on O(N). Taulukko 4.1. Astetta soveltavan sekvenssin taulukkototeutuksen suoritusajat. metodi size, isempty elematrank, replaceelematrank insertelematrank, removeelematrank suoritusaika O(1) O(1) O(n) Tällöin kaksiisen jonon toteutus metodien insertlast ja removelast osalta toimivat ajassa O(1), mutta metodien insertfirst ja removefirst osalta ajassa O(n). Taulukkoon perustuvaa toteutusta pystytään kuitenkin muokkaamaan niin, että sekä lisäykset että poistot sekvenssin alussa ja lopussa voidaan suorittaa vakioajassa. Tämän suunnittelu jääköön harjoitustehtäväksi. Javassa on sisäänrakennettu luokka (Vector), jossa on käytettävissä samankaltaisia metodeja kuin astetta soveltavan sekvenssin. Se on taulukkopohjainen tietorakenne, joka sallii olioiden astetta soveltavan saannin, lisäyksen ja poiston. Taulukon kokoa voidaan siinä dynaamisesti kasvattaa, eli ylivuodon uhatessa kopioidaan alkiot kooltaan tavallisesti kahdennettuun taulukkoon. 4. kappale 129 4. kappale 130 alku Toteutus käyttäen kaksoislinkitettyä listaa Astetta soveltava sekvenssi voidaan toteuttaa myös kaksoislinkitetyllä listalla, mutta tällöin alkioiden astetta ei talleteta eksplisiittisesti sekvenssiin. Operaation elematrank(r) suorittamiseksi pitää lähteä listan jommastakummasta päästä ja kulkea haluttuun alkioon. Tehokkainta on valita näistä lyhyempi reitti, jolloin saanti tapahtuu ajassa O(min(r+1, n-r)), joka on O(n). Pahin tapaus sattuu, kun r = n/2. alku Baltimore Pariisi Providence (a) Baltimore Pariisi Providence Operaatiot insertelematrank(r,e) ja removeelematrank(r) lisäystä ja poistoa varten vaativat myös kulkemisen päästä kyseiseen alkioon asti, jonka aste on r. Niiden suoritusaika on vastaavasti O(min(r+1, n-r+1)), joka on O(n). Nämä on esitetty kuvassa 4.2. 4. kappale 131 New York (b) Kuva 4.2. Kaksoislinkitetyn listan (mukana alku- ja solmu vartijoina) päivitysoperaatiot: (a) ennen solmun lisäystä ja (b) uuden solmun luonti. 4. kappale 132

alku alku alku Baltimore New York Pariisi Providence (c) Baltimore New York Pariisi Providence (d) Kaksoislinkitetty lista vaatii tilaa vain O(n), kun taas taulukkototeutus ei ollut tässä niin taloudellinen. Huonona puolena on, että metodi elematrank vaatii ajan O(n) pahimmassa tapauksessa, kun taulukkototeutuksessa se oli O(1). Muuten suoritusajat olivat samat molemmissa toteutuksissa. Toisaalta muunlaisia lisäyksiä ja poistoja voidaan tehdä nopeasti kaksoislinkitetyssä listassa. 4.2. Paikkasekvenssit Baltimore New York Providence (e) Kuva 4.2. Kaksoislinkitetyn listan (mukana alku- ja solmu vartijoina) päivitysoperaatiot (jatkoa): (c) solmun lisäyksen jälkeen ja ennen solmun poistoa, (d) solmun poisto sekä (e) poiston jälkeen. Asteet eivät ole ainoa tapa viitata paikkaan, jossa alkio on sekvenssissä. Olkoonpa sekvenssi toteutettu taulukkona tai linkitettynä listana, on luonnollista käyttää solmuja (node) asteiden sijasta. Nyt esitetään menettely kuvata abstraktisti alkion paikka sekvenssissä, mikä on toteutustavasta riippumatonta. 4. kappale 133 4. kappale 134 Paikat Solmuja käyttävät operaatiot Olkoon S kaksoislinkitettyyn listaan perustuva sekvenssi. Haluaisimme määritellä metodeja listalle S käyttäen listan solmuja parametreina. Esim. haluaisimme määritellä metodin, joka poistaisi listan solmuun v talletetun alkion Solmua käyttäen parametrina voitaisiin poistaa alkio ajassa O(1) linkittämällä ulos solmu edeltäjä- ja seuraajalinkkit (next ja prev) päivittämällä (ks. kuvaa 4.2.). Vastaavasti voitaisiin hoitaa lisäys. Edellistä varten otetaan käyttöön käsite sekvenssin paikka (position), joka esittää alkion sijainnin suhteessa toisiin sekvenssissä. Käsite paikka kapseloidaan, mikä sallii hyödynnettävän kaksoislinkitetyn listan tehokkuutta rikkomatta mitenkään olio-ohjelmoinnin sääntöä, että tietorakenteen käyttäytyminen abstrahoidaan pois toteutuksestaan. Tätä varten otetaan käyttöön alkioiden säiliö (container), joka käsittää alkiot määrätyissä paikoissaan ja pitää nämä lineaarisessa järjestyksessä. Paikka on abstrakti tietotyyppi seuraavine metodeineen: element(): Palauttaa alkion paikastaan. Tulos: alkio container(): Palauttaa sekvenssin, joka sisältää kyseisen alkion. Tulos: sekvenssi 4. kappale 135 4. kappale 136

Paikkasekvenssin abstrakti tietotyyppi Paikkaa soveltaen määritellään abstrakti tietotyyppi metodeineen: first(): Palauttaa S:n ensimmäisen alkion paikan. Virhe seuraa S:n ollessa tyhjä. Tulos: paikka last(): Palauttaa S:n viimeisen alkion paikan. Virhe seuraa S:n ollessa tyhjä. Tulos: paikka before(p): Palauttaa S:n paikan p alkiota edeltävän alkion paikan. Virhe seuraa, jos on p on ensimmäinen alkio. Tulos: paikka after(p): Palauttaa S:n paikan p alkiota seuraavan alkion paikan. Virhe seuraa, jos p on viimeinen alkio. Tulos: paikka Edelliset metodit sallivat viittauksen sekvenssin suhteellisiin paikkoihin ja siirtymisen niiden välillä. Niiden ja säiliön metodien size ja isempty lisäksi käytetään seuraavia päivitysmetodeja, jotka saavat parametreinaan paikkaolioita tai palauttavat näitä: replace(p,e): Korvaa paikan p alkion alkiolla e ja palauttaa paikan aiemman alkion. Syöte: paikka p ja alkio e Tulos: alkio swap(p,q): Vaihtaa paikkojen p ja q alkiot keskenään. Syöte: kaksi paikkaa 4. kappale 137 4. kappale 138 insertfirst(e): Lisää uuden alkion e sekvenssin S ensimmäiseksi alkioksi. Syöte: alkio e Tulos: lisätyn alkion e paikka insertlast(e): Lisää uuden alkion e sekvenssin S viimeiseksi alkioksi. Syöte: alkio e Tulos: lisätyn alkion e paikka insertbefore(p,e): Lisää uuden alkion e sekvenssiin S paikkaa p edeltäväksi. Syöte: alkio e ja paikka p Tulos: lisätyn alkion e paikka insertafter(p,e): Lisää uuden alkion e sekvenssiin S paikkaa p seuraavaksi. Syöte: alkio e ja paikka p Tulos: lisätyn alkion e paikka remove(p): Poistaa sekvenssistä S alkion paikasta p. Syöte: paikka Tulos: poistettu alkio 4. kappale 139 Esim. 4.2. Oheisena kuvataan sarja operaatioita alunperin tyhjään paikkasekvenssiin S. Muuttujilla p i viitataan paikkoihin. Sulkeissa esitetään talletettava olio. operaatio tulos S insertfirst(8) p 1 (8) (8) insertafter(p 1,5) p 2 (5) (8,5) insertbefore (p 2,3) p 3 (3) (8,3,5) insertfirst(9) p 4 (9) (9,8,3,5) before(p 3 ) p 1 (8) (9,8,3,5) last() p 2 (5) (9,8,3,5) remove(p 4 ) 9 (8,3,5) swap(p 1, p 2 ) - (5,3,8) replace(p 3, 7) 3 (5,7,8) insertafter(first(),2) p 5 (2) (5,2,7,8) 4. kappale 140

Paikkasekvenssin taulukkototeutus Tässä tapauksessa ei ole mielekästä suoraan tallettaa sekvenssin alkioita taulukkoon, sillä esim. lisättäessä taulukon alkuun uusi alkio ei ole keinoa ilmoittaa muille alkioille niiden asteen kasvaneen yhdellä (paikka määritellään aina suhteessa naapuripaikkoihin eikä niiden asteisiin). Baltimore New York Rooma Providence Edellisen sijasta talletetaan paikkaoliot taulukkoon ja alkiot paikkoihin. Viittauksien sekvenssiin S ja indeksiin i lisäksi paikkaolio p = A[i] käsittää p:hen liittyvän alkion. Tämä tietorakenne (kuva 4.3.) mahdollistaa taulukon selauksen muuttujan i päivittämiseksi niiden paikkojen osalta, joiden aste muuttuu lisäyksen tai poiston tähden. Tällöin paikkasekvenssin toteutukset toimivat ajassa O(n) metodeille insertfirst, insertbefore, insertafter ja remove, koska paikkaolioita on siirrettävä tilan tekemiseksi uutta alkiota varten tai poistetun jättämän tilan täyttämiseksi. Kaikki muut metodit toimivat ajassa O(1). 4. kappale 141 S 0 1 2 3 0 1 2 3 N-1 Kuva 4.3. Paikkasekvenssin taulukkototeutus. 4. kappale 142 Taulukkoa voidaan jälleen hyödyntää rengasrakenteena. Nyt on mahdollista muokata metodia insertfirst niin, että se toimii ajassa O(1). Muut metodit pysyvät sitä vastoin suoritusajoiltaan entisellään. Lisäyksen tai poiston pahin tapaus esiintyy alkion ollessa astetta n/2. Paikkasekvenssin metodien suoritusajat rengasrakennetta soveltavan taulukon tilanteessa on kuvattu taulukossa 4.3. Paikkasekvenssin toteutus kaksoislinkitetyn listan avulla Vastaavasti kuin taulukon tapauksessa listassa solmut sisältävät viittauksen sekvenssiä edustavaan olioon. Käytössä on metodi, joka palauttaa solmuihin talletetut varsinaiset tietoalkiot. Solmut toimivat itsessään paikkoina. Listasta katsottuna ne ovat sen solmuja, mutta ulkoapäin katsoen ne ovat geneerisiä paikkoja. Esimerkiksi sekvenssin S paikka p lähtötietona voidaan toteuttaa metodi before(p) antamalla p.prev paitsi, jos tämä on ensimmäinen solmu, jolloin pitää antaa virheilmoitus. 4. kappale 143 Paikkasekvenssin kaikki metodit ovat toteutettavissa suoritusajassa O(1) kaksoislinkitetyn listan avulla, joka on näin ollen suositeltava toteutusmuoto (taulukko 4.3.). Tätä tarkempaa kuvausta ei tässä esitetä. Taulukko 4.3. Paikkasekvenssin taulukkoon (rengasrakenne) ja kaksoislinkitettyyn listaan perustuvien toteutusten vertailu, kun n on sekvenssin alkioiden määrä. Tilavaatimus listalle on O(n) ja taulukolle O(N), kun N on taulukon koko. operaatiot taulukko lista size, isempty, first, last, before, after O(1) O(1) replace, swap, insertfirst, insertlast O(1) O(1) insertafter, insertbefore, remove O(n) O(1) 4. kappale 144

4.3. Yleiset sekvenssit Yleistetty sekvenssi käsittää kaikki sekä astetta soveltavan että paikkasekvenssin metodit sisältäen siis asteen ja paikan monipuolista käyttöä. Sekvenssin abstrakti tietotyyppi Yleistetyn sekvenssin abstrakti tietotyyppi tukee kaikkien edellä kuvattujen sekvenssimetodien lisäksi myös seuraavia, asteen ja paikan käyttöä yhdistäviä metodeja: atrank(r): Palauttaa astetta r olevan alkion paikan. Syöte: kokonaisluku Tulos: paikka rankof(p): Palauttaa paikan p alkion asteen. Syöte: paikka Tulos: kokonaisluku 4. kappale 145 Tämän abstraktin tietotyypin määritelmä käy moniperinnän esimerkistä, koska se perii metodeja kahdesta ylitietotyypistä eli se on unioni kahdesta abstraktista tietotyypistä. Sekvenssitoteutusten vertailua Taulukko 4.4. esittää yleistetyn sekvenssin taulukkototeutuksen (rengasrakenteena) ja kaksoislinkitetyn listan toteutuksen suoritusaikojen vertailun. Tilavaatimus listalle on O(n) ja taulukolle O(N), kun N on taulukon koko. operaatiot taulukko lista size, isempty, first, last, before, after, O(1) O(1) replace, swap, insertfirst, insertlast atrank, rankof, elematrank, O(1) O(n) replaceelematrank insertafter, insertbefore, remove O(n) O(1) insertelematrank, removeelematrank O(n) O(n) 4. kappale 146 Toteutusvaihtoehdon voi valita sen mukaan, mitä metodeja pääasiassa sovelluksessa tarvitaan. Huomattavaa on myös tilan käyttö, jossa suhteessa listavaihtoehto on usein edullisempi, vaikka siinä tarvitaan hieman lisätilaa alkioidenvälisiä osoittimia varten. 4.4. Tapausesimerkki: sekvenssipohjainen kuplalajittelu Kuvataan sekvenssiä soveltava toteutus kuplalajittelua (bubble sort) varten. Kuplalajittelualgoritmi Tarkastellaan sekvenssiä, jossa mitä tahansa kahta perättäistä alkiota voidaan verrata keskenään ja asettaa suuruusjärjestykseen. Tämä algoritmi on ensimmäinen yksinkertainen menetelmä, jota käsitellään tärkeää lajitteluongelmaa silmällä pitäen. 4. kappale 147 Lajittelussa (sorting) on tehtävänä järjestää syötealkiot niin, että ne tulevat joko kasvavaan tai vähenevään järjestykseen. Tässä yhteydessä käsitellään ei-vähenevää eli tarkemmin ilmaisten kasvavaa tai osin samansuuruisten perättäisten alkioparien sekvenssiä. Alkiot voivat olla toki muitakin kuin lukuja, esim. leksikograafisesti järjestettäviä (tekstiä), mutta niiden välillä pitää olla jokin järjestysrelaatio voimassa, kuten tässä pienempi tai yhtä suuri. Kuplalajittelualgoritmi ratkaisee lajitteluongelman yksinkertaisella, mutta samalla asymptoottisesti melko tehottomalla tavalla. Siinä suoritetaan sarja vaiheita (pass) sekvenssissä (kuva 4.4.). Kussakin vaiheessa alkiot selataan astetta kasvattaen asteesta 0 vielä lajittelemattomien alkioiden sekvenssin un. Vaiheen jokaisessa paikassa alkiota verrataan naapuriinsa ja nämä kaksi perättäistä alkiota vaihdetaan keskenään, mikäli suhteellinen järjestys on väärä, so. edeltävä alkio on seuraavaa suurempi. Sekvenssi lajitellaan suorittamalla n tällaista vaihetta. 4. kappale 148

vaihe vaihdot sekvenssi (5, 7, 2, 6, 9, 3) 1. 7 2, 7 6, 9 3 (5, 2, 6, 7, 3, 9) 2. 5 2, 7 3 (2, 5, 6, 3, 7, 9) 3. 6 3 (2, 5, 3, 6, 7, 9) 4. 5 3 (2, 3, 5, 6, 7, 9) Kuva 4.4. Kuplalajittelu kokonaislukujen sekvenssille, jossa kunkin vaiheen vaihdot on esitetty ja sekvenssi vaihtojen jälkeen. Itse asiassa vaiheita on näiden jälkeen vielä kaksi, mutta niitä ei ole esitetty, koska niissä ei tapahdu vaihtoja. Olkoon n sekvenssin alkioiden lukumäärä. Kuplalajittelualgoritmilla on seuraavat ominaisuudet: Ensimmäisessä vaiheessa sen jälkeen, kun suurin alkio on saavutettu, jatketaan vaihtamista, kunnes päästään sekvenssin viimeiseen paikkaan. Toisessa vaiheessa, kun toiseksi suurin alkio on saavutettu, jatketaan vaihtamista, kunnes päästään toiseksi viimeiseen paikkaan. Eo. menettelyä toistetaan niin kauan, kunnes kaikki alkiot on käyty läpi. Täten i:nnen vaiheen lopussa sekvenssin i oikeanpuolimmaista alkiota (asteesta n-1 alas asteeseen n-i) ovat lopullisissa paikoissaan. Tämä osoittaa, että n vaihetta riittää alkioiden lajittelemiseksi ja kussakin vaiheessa i riittää lajitella ensimmäiset n-i+1 alkiota. 4. kappale 149 4. kappale 150 Sekvenssipohjaisen kuplalajittelun analyysi Oletetaan sekvenssin toteutuksen sallivan yksittäisten alkioiden saannin ja vaihdon ajassa O(1). Tällöin i:nnen vaiheen suoritusaika on O(ni+1). Kokonaissuoritusajaksi tulee siten n O( ( n i+ 1)). i= 1 Edellisestä saadaan summan n n( n+ 1) i= 2 i= 1 Tämä voidaan kirjoittaa muotoon O( n+ ( n 1) +... + 2+ 1) = O( i). n i= 1 perusteella tulos O(n 2 ) suoritusajaksi edellyttäen, että vaihdot ja saanti olivat vakioaikaisia. Koodi 4.2. käsittää kaksi kuplalajittelun toteutusta lajiteltaessa kokonaislukuja. Ne eroavat alkion saannissa ja sekvenssin muuttamisessa käytettävien metodien suhteen. 4. kappale 151 4. kappale 152

Metodi bubblesort1 hakee alkiot rajapintametodin atrank kautta. Se on astetta soveltava toteutus ja sovelias ainoastaan sekvenssin taulukkototeutuksessa, jossa atrank tarvitsee ajan O(1). Tällöin metodin kokonaissuoritusaika on O(n 2 ). Jos algoritmi toteutettaisiin kaksoislinkitetyn listan avulla, silloin jokainen metodin atrank kutsu vaatisi ajan O(n) pahimmassa tapauksessa ja kokonaissuoritusaika olisi O(n 3 ). Metodi bubblesort2 saa alkiot sekvenssistä metodien first ja after avulla. Se on paikkaa käyttävä toteutus ja sopiva sekä taulukkoa että kaksoislinkitettyä listaa hyödynnettäessä. Näin on, koska molemmat tavat tuottavat vakiollisen suoritusajan metodeille first ja after. Koko suoritusaika on Θ(n 2 ) sekvenssin toteutustavasta riippumatta. Kuplalajittelu on hyvin yksinkertainen, mutta se on myös varsin tehoton lajiteltavien määrän n kasvaessa aikakompleksisuuden ollessa neliöllinen. Myöhemmin palataan lajitteluun, jolle on olemassa merkittävästi tehokkaampia algoritmeja aikakompleksisuudeltaan O(n log n). 4. kappale 153 public void static bubblesort1(integersequence s) { int n = s.size(); for (int i=0; i<n; i++) // i:s vaihe for (int j=1; j<n-i; j++) if (s.atrank(j-1).element().intvalue() > s.atrank(j).element().intvalue()) swap(s.atrank(j-1), s.atrank(j)); } Koodi 4.2. Kuplalajittelun ensimmäinen toteutusversio. 4. kappale 154 public void static bubblesort2(integersequence s) { int n = s.size(); IntegerSequencePosition prec, succ; for (int i=0; i<n; i++) { // i:s vaihe prec = s.first(); for (int j=0; j<n-i; j++) { succ = s.after(prec); if (prec.element().intvalue() > succ.element().intvalue()) swap(prec,succ); prec = succ; } } } Koodi 4.2. (jatkoa) Kuplalajittelun toinen toteutusversio. 4.5. Iteraattorit Tyypillinen sekvenssin käyttötapa on käydä alkiot järjestyksessä läpi esim. jonkin alkion etsimiseksi tai muun toimenpiteen suorittamiseksi. Iteraattori (iterator) on käsite, joka abstrahoi tällaisen selausprosessin. Yleensä iteraattori sisältää sekvenssin, tiedon paikasta, jossa kulloinkin ollaan, ja menetelmän siirtyä seuraavaan paikkaan, josta tulee uusi nykyinen paikka. Niinpä tämä on tehokasta toteuttaa paikkasekvenssinä. Javassa on yksinkertaistettu iteraattori, abstrakti tietotyyppi enumeration. 4. kappale 155 4. kappale 156