Muita linkattuja rakenteita



Samankaltaiset tiedostot
Tietorakenteet ja algoritmit

Tietorakenteet ja algoritmit

Algoritmit 1. Luento 6 Ke Timo Männikkö

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

Algoritmit 2. Luento 4 Ke Timo Männikkö

Algoritmit 2. Luento 4 To Timo Männikkö

Algoritmit 2. Luento 2 To Timo Männikkö

A TIETORAKENTEET JA ALGORITMIT

Algoritmit 2. Luento 2 Ke Timo Männikkö

Algoritmit 1. Luento 8 Ke Timo Männikkö

Tietorakenteet ja algoritmit

Algoritmit 2. Luento 7 Ti Timo Männikkö

A TIETORAKENTEET JA ALGORITMIT

Algoritmit 1. Luento 7 Ti Timo Männikkö

Hakupuut. tässä luvussa tarkastelemme puita tiedon tallennusrakenteina

Tietorakenteet ja algoritmit

Tietorakenteet ja algoritmit

ALGORITMIT 1 DEMOVASTAUKSET KEVÄT 2012

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

Tietorakenteet ja algoritmit Johdanto Lauri Malmi / Ari Korhonen

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

3. Binääripuu, Java-toteutus

Tietorakenteet ja algoritmit - syksy

Tietorakenteet ja algoritmit

Lyhyt kertaus osoittimista

811312A Tietorakenteet ja algoritmit II Perustietorakenteet

Tieto- ja tallennusrakenteet

Tietorakenteet ja algoritmit

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

2. Seuraavassa kuvassa on verkon solmujen topologinen järjestys: x t v q z u s y w r. Kuva 1: Tehtävän 2 solmut järjestettynä topologisesti.

18. Abstraktit tietotyypit 18.1

Kysymyksiä koko kurssista?

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

Algebralliset tietotyypit ym. TIEA341 Funktio ohjelmointi 1 Syksy 2005

TIETORAKENTEET JA ALGORITMIT

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

Rakenteiset tietotyypit Moniulotteiset taulukot

1.1 Tavallinen binäärihakupuu

Algoritmit 1. Luento 4 Ke Timo Männikkö

Algoritmit 2. Luento 5 Ti Timo Männikkö

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

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.

Algoritmit 2. Luento 6 To Timo Männikkö

Tietueet. Tietueiden määrittely

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

Algoritmit 1. Luento 9 Ti Timo Männikkö

Dynaamiset tietorakenteet

811312A Tietorakenteet ja algoritmit, , Harjoitus 5, Ratkaisu

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

TKT20001 Tietorakenteet ja algoritmit Erilliskoe , malliratkaisut (Jyrki Kivinen)

811312A Tietorakenteet ja algoritmit V Hash-taulukot ja binääriset etsintäpuut

Algoritmit 2. Luento 3 Ti Timo Männikkö

Algoritmit 2. Luento 3 Ti Timo Männikkö

Jokaisella tiedostolla on otsake (header), joka sisältää tiedostoon liittyvää hallintatietoa

Tietorakenteet, laskuharjoitus 7, ratkaisuja

Algoritmit 1. Luento 3 Ti Timo Männikkö

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

Algoritmit 2. Luento 6 Ke Timo Männikkö

811312A Tietorakenteet ja algoritmit, , Harjoitus 7, ratkaisu

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

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

Algoritmit 1. Luento 5 Ti Timo Männikkö

Algoritmit 2. Luento 5 Ti Timo Männikkö

Olio-ohjelmointi Syntaksikokoelma

TAMPEREEN TEKNILLINEN YLIOPISTO

Algoritmit ja tietorakenteet / HL Copyright Hannu Laine

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

Algoritmit 2. Luento 9 Ti Timo Männikkö

815338A Ohjelmointikielten periaatteet Harjoitus 7 Vastaukset

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

811312A Tietorakenteet ja algoritmit, , Harjoitus 5, Ratkaisu

Tietorakenteet, laskuharjoitus 6,

Luku 6. Dynaaminen ohjelmointi. 6.1 Funktion muisti

Ohjelmoinnin perusteet Y Python

TAMPEREEN TEKNILLINEN YLIOPISTO

Ohjelmointi 1 Taulukot ja merkkijonot

A ja B pelaavat sarjan pelejä. Sarjan voittaja on se, joka ensin voittaa n peliä.

Ohjelmoinnin peruskurssien laaja oppimäärä

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

2. Perustietorakenteet

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

Algoritmit 1. Luento 1 Ti Timo Männikkö

tietueet eri tyyppisiä tietoja saman muuttujan arvoiksi

puuta tree hierarkkinen hierarchical

811312A Tietorakenteet ja algoritmit Kertausta jälkiosasta

Algoritmit 1. Demot Timo Männikkö

815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset

Tietorakenteet, laskuharjoitus 3, ratkaisuja

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

Algoritmit 2. Luento 14 Ke Timo Männikkö

Tietorakenteet ja algoritmit

Algoritmit 1. Demot Timo Männikkö

(a) L on listan tunnussolmu, joten se ei voi olla null. Algoritmi lisäämiselle loppuun:

Binäärihaun vertailujärjestys

811312A Tietorakenteet ja algoritmit Kertausta kurssin alkuosasta

Luku 8. Aluekyselyt. 8.1 Summataulukko

815338A Ohjelmointikielten periaatteet Harjoitus 6 Vastaukset

Algoritmit 1. Luento 14 Ke Timo Männikkö

Tietorakenteet ja algoritmit Puurakenteet Ari Korhonen

811312A Tietorakenteet ja algoritmit III Lajittelualgoritmeista

Transkriptio:

1 Muita linkattuja rakenteita Johdanto Aikaisemmin on käsitelty listan, jonon ja pinon toteutus dynaamisesti linkattuna rakenteena. Dynaamisella linkkauksella voidaan toteuttaa mitä moninaisimpia rakenteita. Seuraavassa annetaan muutamia esimerkkejä. Kaikissa esimerkeissä kiinnitetään huomiota myös abstraktioon. Tämä merkitsee, että dynaamisesti linkattuja rakenteita pidetään yhtenä toteutusvaihtoehtona erilaisille abstrakteille tietotyypeille. Niille voitaisiin esittää myös taulukkoon perustuva toteutus. Tässä käsiteltävät esimerkit ovat renkaaksi linkitetty lista, kaksoislinkattu lista, ns. harva matriisi, ja binäärinen etsintäpuu. Renkaaksi linkitetty lista Renkaaksi linkitetty lista tarkoittaa tavallista listaa, jossa viimeiseen alkioon ei laiteta NULLosoitetta, vaan sinne laitetaan ensimmäisen alkion osoite. Renkaaksi linkitetty lista näyttää silloin seuraavalta: cll 11.0 12.0 13.0 Eräänä sovelluksena voidaan mainita vaikkapa mittaustietojen suodatus. Yllämainitun kuvan renkaaksi linkitetty lista voisi palvella sovellusta, jossa mittausarvoja suodatetaan laskemalla aina kolmen viimeisen mittauksen keskiarvo. Uuden mittausarvon tallennus ja keskiarvon laskenta käyvät kätevästi, kun osoitin osoittaa aina vanhinta mittausta. Tällöin uusi mittaus tallennetaan aina osoittimen osoittamaan paikkaan ja osoittimelle päivitetään uusi arvo, joka saadaan vanhan solmun next-kentästä. Yleisyyttä voidaan lisätä paketoimalla tietotyypin Tcll (tyyppi circularly linked list) sisälle renkaaseen kulloinkin kuuluvien mittausten määrä. Lukija voi miettiä, millä tavalla tällaiseen renkaaksi linkitettyyn listaan lisätään uusi alkio ja uusi mittausarvo ja miten lasketaan siellä olevien mittausten keskiarvo. Oletetaan, että kuvan mukaisessa tilanteessa solmun tietotyyppi on määritelty seuraavasti: typedef struct node { float mittaus; struct node *next; Tnode; Silloin uusi mittausarvo (ei siis uusi solmu) lisätään renkaaseen seuraavasti cll->mittaus = uusi_arvo; cll = cll->next; Kaksoislinkattu lista

2 Aikaisemmin on käsitelty dynaamisesti linkattu lista. Siinä linkkien avulla voidaan kulkea ensimmäisestä alkiosta viimeiseen. Kaksoislinkatun listan ajatus on siinä, että solmuihin laitetaan linkki seuraavaan solmuun ja edelliseen solmuun. Tällöin toista linkkiketjua pitkin päästään kulkemaan lista alusta loppuun ja toista linkkiketjua pitkin lopusta alkuun. Kaksoislinkattu lista näyttää käytännössä seuraavalta. dbll first last a e g Kun abstraktiovaatimus huomioidaan, määritellään esimerkiksi tietotyyppi Tdbll (tyyppi double linked list), jolle sitten määritellään asiaan kuuluvat operaatiofunktiot, kuten void alusta(tdbll *dbll); void lisaa_alkio(titem alkio, Tdbll *dbll); void poista_alkio(titem *alkio, Tdbll *dbll); Kaksoislinkattua listaa kannattaa käyttää sovelluksissa, joissa pitää päästä liikkumaan sekä eteenpäin, että taaksepäin. Eräs sovellus on vaikkapa määrittelemättömän pituisten lukujen esittäminen ja laskutoimitukset niille. Luvun numerot tallennetaan kaksoislinkattuun listaan. Lukua syötettäessä lista rakennetaan alusta loppuun. Lukua tulostettaessa lista käydään myös alusta loppuun. Lukuja laskettaessa yhteen listaa käydään läpi lopusta alkuun. Harva matriisi Taulukkolaskentaohjelmissa käyttäjälle tarjotaan laskentaa varten taulukkopohja, jossa on paljon soluja (jopa miljoonia soluja). Jokaiseen soluun liittyy paljon tietoja, esimerkiksi solun varsinainen tietosisältö ja sen muotoilutiedot. Kuitenkin vain pieni osa taulukon soluista on yleensä kerrallaan käytössä. Tämän takia ei muistista kannata varata tilaa kaikille alkioille heti alussa, vaan sitä mukaa, kuin taulukosta otetaan alkioita käyttöön. Samanlaista periaatetta voidaan käyttää lukumatriisien esittämiseen, joilla suurin osa alkioista on arvoltaan 0. Tällaista matriisia kutsutaan harvaksi matriisiksi. Alla on esimerkki harvasta matriisista. 5 0 0 1 0 3 0 0 0 0 6 7 0 0 0 9 Harvan matriisin esittämisessä tietokoneen muistissa voidaan säästää tilaa, kun nolla-alkioita ei esitetä ollenkaan muistissa. Seuraava kuva esittää periaatteen, jolla tällainen matriisi voidaan esittää. Muistista on varattu tilaa vain nollasta poikkeaville alkioille. Alla oleva kuva esittää edellä olevaa 4x4-matriisia.

3 matrix 1 1 5 4 1 2 2 3 3 3 6 4 7 4 4 9 Kun matriisia tarkastellaan abstraktina tietotyyppinä, sille on määriteltävä tietotyyppi Tmatrix ja operaatiofunktiot, joista seuraavat esimerkit: void alusta(tmatrix *matrix); void lue_matriisi(tmatrix *matrix); void tulosta_matriisi(tmatrix matrix); int onko_nelio(tmatrix matrix); float determinantti(tmatrix matrix); int palauta_rivi_maara(tmatrix matrix); int palauta_sarake_maara(tmatrix matrix); void summaa(tmatrix a, Tmatrix b, Tmatrix *c); void kerro(tmatrix a, Tmatrix b, Tmatrix *c); Binäärinen etsintäpuu Puu on yksi perustavaa laatua oleva tietorakenne tietojenkäsittelytekniikassa. Puu tarjoaa esimerkiksi tavan etsiä tietoa nopeasti. Sitä käytetään mm. hakemistoissa ja kielen prosessointisovelluksissa (ilmaisupuut, expression trees). Puu on monimutkaisempi tietorakenne kuin useimmat muut ADT:t. On olemassa useita puiden toteutustapoja, jotka voivat perustua sekä taulukkoon että linkattuihin rakenteisiin. Ennen kuin määrittelemme binäärisen etsintäpuun, määritellään binääripuu (binary tree): Binääripuu on äärellinen joukko solmuja, joka on joko tyhjä tai muodostuu juurisolmusta ja kahdesta erillisestä binääripuusta, joita kutsutaan vasemmaksi alipuuksi ja oikeaksi alipuuksi. Puun solmu voi sisältää tietoa, jonka luonne riippuu sovelluksesta. Kuten muutkin säiliöt myös puun toteutus voidaan tehdä riippumattomaksi solmuihin tallennettavan tiedon tyypistä. Huomaa, että binääripuun määritelmä on rekursiivinen. Oppitunnilla testataan määritelmän toimivuus käytännössä. Määritelmä. Binäärinen etsintäpuu on binääripuu, jossa kaikki arvot vasemman alipuun solmuissa ovat pienempiä kuin arvo juurisolmussa ja kaikki arvot oikean alipuun solmuissa ovat suurempia kuin arvo juurisolmussa. Lisäksi binäärisen etsintäpuun molemmat alipuut ovat binäärisiä etsintäpuita.

4 Puun läpikäynnillä (traverse a binary tree) tarkoitetaan prosessia, jolla käydään puun jokaisessa solmussa jonkin systemaattisen järjestyksen mukaan. Seuraavassa määritellään kolme tunnettua tapaa puun läpikäymiseen (huomaa, että määritelmät ovat rekursiivisia): Etujärjestys (Preorder traversal): 1. Käydään juuressa 2. Käydään läpi vasen alipuu 3. Käydään läpi oikea alipuu Välijärjestys (Inorder traversal): 1. Käydään läpi vasen alipuu 2. Käydään juuressa 3. Käydään läpi oikea alipuu Jälkijärjestys (Postorder traversal): 1. Käydään läpi vasen alipuu 2. Käydään läpi oikea alipuu 3. Käydään juuressa Binäärisen etsintäpuun läpikäynti välijärjestyksessä merkitsee puussa olevien tietojen läpikäyntiä suuruusjärjestyksessä (treesort). Binääripuuta sanotaan täydelliseksi, jos sen oikeassa ja vasemmassa alipuussa on yhtä monta solmua ja lisäksi sen molemmat alipuut ovat täydellisiä. Onnistunut etsintä täydellisestä binääripuusta vaatii noin lg N vertailua. Menetelmä on paras mahdollinen silloin, kun aika riippuu vertailujen lukumäärästä (eikä levysiirtojen lukumäärästä). Ongelma sinänsä on, kuinka voidaan taata, että binäärinen etsintäpuu pysyy lisäyksissä ja poistoissa riittävän pensasmaisena? Samasta tietoaineistosta voidaan rakentaa useita erilaisia etsintäpuita (mutta ei täydellisiä). Jos lisäys puuhun tehdään yksinkertaisella tavalla ilman mitään tasapainon säilyttämiseen pyrkivää algoritmia, puun muoto riippuu siitä, missä järjestyksessä tiedot on lisätty puuhun. Kuten yllä on sanottu binäärinen etsintäpuu voidaan toteuttaa eri tavoilla. Se voidaan toteuttaa esimerkiksi taulukolla tai dynaamisesti linkatulla rakenteella. Dynaamisesti linkattu rakenne on helppo toteuttaa. Ainoastaan operaatio DeleteNode vaatii enemmän vaivaa ja pohdintaa ja samoin lisäys siinä tapauksessa, että halutaan varmistaa puun tasapainoisuus. Liitteenä on esimerkki. Tarvittavat tietomäärittelyt ovat typedef??? Titem; //määritellään puuhun tallennettava tiedon tyyppi typedef struct node *Tpointer; typedef struct node { Tpointer left; Titem item; Titem right; Tnode; typedef Tpointer Tree; muutamia esimerkkejä puun operaatioista: Ttree Create(); void PutItemToTree(Tree *tree, Titem item); int IsItemInTree(Tree tree, Titem item);

5 void in_order_traverse( Ttree tree ); jne. Seuraavassa on puun alkioiden läpikäynnin välijärjestyksessä toteuttava funktio. Tämä ensimmäinen versio lähtee siitä, että rekursiota ei käytetä. Sen sijaan käytetään omaa osoittimien pinoa niiden solmujen tallentamiseen, jotka ovat tulleet vastaan ja joissa ei vielä saa käydä. void in_order_traverse( Ttree tree ) { TStack pointerstack; Ttreenode *p; initialize_stack(&pointerstack); p = tree; while ( (p!= NULL)!is_stack_empty(&pointerstack)) { while (p!= NULL) { push(&pointerstack, p); p = p->left; pop(&pointerstack, &p); printf("%d ", p->item); p = p->right; Seuraavassa on puun alkioiden läpikäynnin välijärjestyksessä toteuttava funktio rekursiivisena. Huomataan, että tämä funktio on erittäin selkeä. Koska puun määritelmä jo oli rekursiivinen, rekursiiviset funktiot sopivat erittäin hyvin puun operaatioiden toteuttamiseen. void in_order_traverse( Ttree tree ) { if (!is_tree_empty(tree)) { in_order_traverse( tree -> left); printf(" %c", tree->item); in_order_traverse ( tree -> right); Dynaamisesti linkatun rakenteen ja taulukkorakenteen vertailu Dynaamisesti linkatussa rakenteessa alkioiden järjestys esitetään erillisten linkkien avulla. Taulukkorakenteessa järjestys esitetään alkion sijaintipaikalla muistissa. Taulukkorakenteessa kaikki alkiot sijaitsevat vierekkäisissä muistipaikoissa ja taulukolle varattu tila muodostaa siksi yhtenäisen alueen tietokoneen muistissa. Taulukkoa kutsutaan tämän takia englanniksi myös nimellä contiguous list, kun taas dynaamisesti linkattua listaa kutsutaan dynamically linked list. Huomaa siis, että taulukko ja dynaamisesti varattu linkattu lista ovat vaihtoehtoisia toteutustapoja listan määrittelyssä esiintyvälle joukolle tietoalkioita, joiden kesken on määritelty järjestys. Seuraavassa verrataan näiden toteutusten ominaisuuksia. Ominaisuus Muistin varaus Dynaamisesti linkattu lista Ei ylivuotoa. Kaikki koneen vapaa muisti on Taulukko Muisti varattava kokonaan ennen kuin käyttö alkaa,

6 Tiedon haku Järjestyksen ilmaisutapa käytettävissä. Vain peräkkäishaku mahdollista. Järjestys osoitetaan linkeillä. jolloin muisti voi loppua kesken tai sitä on varattuna liikaa. Myös suorahaku on mahdollista, kun järjestysnumero tiedetään. Järjestys ilmaistaan sijainnilla muistissa. Operaatioiden vaatima prosessoriteho Lisäykset väliin ja poistot välistä ovat helppoja.. Lisäyksissä ja poistoissa väliin tarvitaan tietojen siirtoa. Ohjelmointi Vaatii vähän harjoittelua. On helppoa. Yhteenveto abstraktien tietotyyppien käytöstä On käsitelty standardeja abstrakteja tietotyyppejä, jotka ovat yleiskäyttöisiä, sovellusalueesta riippumattomia komponentteja. Tällaisia ovat esimerkiksi listat jono pino joukko merkkijono puu jne Ohjelmiston kehitysprojekteissa voidaan tehdä sovellusaluekohtaisia abstrakteja tietotyyppejä. Niiden rakentamisessa voidaan käyttää usein hyväksi edellä mainittuja yleisiä abstrakteja tietotyyppejä. Esimerkkeinä sovellusaluekohtaisista abstrakteista tietotyypeistä ovat mm. mittaukset (katso labraharjoitus) kolmio kompleksiluku matriisi urheilulaji_kilpailussa dynaaminen muisti jne Abstraktien tietotyyppien käytöllä saavutetaan mm seuraavia etuja: Ohjelmat ja niiden laatiminen yksinkertaistuu. Ohjelmointityö voidaan jakaa kätevästi useammalle henkilölle. Ohjelmiin ei tule niin helposti virheitä. Ohjelmien testaus helpottuu. On helpompi tuottaa uudelleenkäytettävää koodia.