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

Samankaltaiset tiedostot
Tietorakenteet ja algoritmit

Tietorakenteet ja algoritmit

Tietorakenteet ja algoritmit

Tietorakenteet ja algoritmit

Tietorakenteet ja algoritmit

Tietorakenteet ja algoritmit

Tietorakenteet ja algoritmit

Tietorakenteet ja algoritmit

Tieto- ja tallennusrakenteet

Algoritmit ja tietorakenteet / HL Copyright Hannu Laine

Tietorakenteet ja algoritmit

Rakenteiset tietotyypit Moniulotteiset taulukot

A TIETORAKENTEET JA ALGORITMIT

Tietorakenteet ja algoritmit Johdanto Lauri Malmi / Ari Korhonen

Tietorakenteet ja algoritmit - syksy

Algoritmit 1. Luento 4 Ke Timo Männikkö

tietueet eri tyyppisiä tietoja saman muuttujan arvoiksi

Tietueet. Tietueiden määrittely

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

Osoitin ja viittaus C++:ssa

TIETORAKENTEET JA ALGORITMIT

815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset

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

Muita linkattuja rakenteita

Algoritmit 2. Luento 2 To Timo Männikkö

Tietorakenteet ja algoritmit

Algoritmit 1. Luento 3 Ti Timo Männikkö

Ohjelmoinnin peruskurssien laaja oppimäärä

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

Lyhyt kertaus osoittimista

Algoritmit 1. Luento 9 Ti Timo Männikkö

Algoritmit 2. Luento 2 Ke Timo Männikkö

Algoritmit 2. Luento 3 Ti Timo Männikkö

Olio-ohjelmointi Syntaksikokoelma

Algoritmi ja abstraktio

Ohjelmointi 1 Taulukot ja merkkijonot

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

811312A Tietorakenteet ja algoritmit II Perustietorakenteet

Ohjelmoinnin perusteet Y Python

Dynaamiset tietorakenteet

Ohjelmoinnin peruskurssien laaja oppimäärä

Loppukurssin järjestelyt C:n edistyneet piirteet

ITKP102 Ohjelmointi 1 (6 op)

18. Abstraktit tietotyypit 18.1

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

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

Algoritmit 1. Luento 6 Ke Timo Männikkö

Algoritmit 2. Luento 3 Ti Timo Männikkö

Osoittimet ja taulukot

Loppukurssin järjestelyt

Pino S on abstrakti tietotyyppi, jolla on ainakin perusmetodit:

Ohjelmoinnin perusteet Y Python

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

15. Ohjelmoinnin tekniikkaa 15.1

(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ä.

Ohjelmoinnin jatkokurssi, kurssikoe

Ohjelmassa muuttujalla on nimi ja arvo. Kääntäjä ja linkkeri varaavat muistilohkon, jonne muuttujan arvo talletetaan.

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

Ohjelmoinnin perusteet Y Python

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

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

15. Ohjelmoinnin tekniikkaa 15.1

C-ohjelmoinnin peruskurssi. Pasi Sarolahti

Taulukot. Jukka Harju, Jukka Juslin

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

12 Mallit (Templates)

ITKP102 Ohjelmointi 1 (6 op)

Algoritmit 2. Luento 4 Ke Timo Männikkö

3. Binääripuu, Java-toteutus

Algoritmit 1. Luento 10 Ke Timo Männikkö

Algoritmit. Ohjelman tekemisen hahmottamisessa käytetään

Harjoitus 6 (viikko 42)

Algoritmit 2. Luento 4 To Timo Männikkö

Ohjelmoinnin perusteet Y Python

815338A Ohjelmointikielten periaatteet Harjoitus 6 Vastaukset

Tähtitieteen käytännön menetelmiä Kevät 2009 Luento 4: Ohjelmointi, skriptaus ja Python

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

5. HelloWorld-ohjelma 5.1

Pythonin alkeet Syksy 2010 Pythonin perusteet: Ohjelmointi, skriptaus ja Python

ELM GROUP 04. Teemu Laakso Henrik Talarmo

Java-kielen perusteet

Harjoitus 6. Käytä String-luokasta vain charat- ja length-operaatioita.

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

Algoritmit 2. Luento 7 Ti Timo Männikkö

D-OHJELMOINTIKIELI. AA-kerho, 33. Antti Uusimäki. Arto Savolainen

Ohjelmoinnin perusteet Y Python

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

Ohjelmoinnin peruskurssien laaja oppimäärä

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

812347A Olio-ohjelmointi, 2015 syksy 2. vsk. X Poikkeusten käsittelystä

1. Omat operaatiot 1.1

ITKP102 Ohjelmointi 1 (6 op)

815338A Ohjelmointikielten periaatteet Harjoitus 7 Vastaukset

TIE448 Kääntäjätekniikka, syksy Antti-Juhani Kaijanaho. 27. lokakuuta 2009

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

Chapel. TIE Ryhmä 91. Joonas Eloranta Lari Valtonen

Ohjelmoinnin perusteet Y Python

1. Olio-ohjelmointi 1.1

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

Ohjelmoinnin perusteet Y Python

Transkriptio:

Algoritmit ja tietorakenteet / HL 1 Lista Yleistä Lista, pino ja jono ovat abstrakteja tietotyyppejä, joilla on yleistä käyttöä. Niitä voidaan hyödyntää mitä erilaisimmissa probleemoissa ja sovelluksissa. Tällaiset tietorakenteet vastaavat ohjelmistotekniikassa laitetekniikan komponentteja. Laitetekniikassa samoja komponentteja käytetään hyvinkin erilaisten laitteiden rakennuspalikoina. Myös ohjelmistotekniikassa pyritään yhä enemmän tilanteeseen, jossa olisi mahdollisimman paljon käytettävissä valmiita komponentteja, joista rakentamalla tehdään sovelluksia. Ohjelmistotekniikassa alimman tason rakennuspalikat ovat käytettävän ohjelmointikielen käskyjä. Jos kaikki sovellukset tehtäisiin aina puhtaalta pöydältä, jouduttaisiin uusien sovellusten sellaisiakin osia, jotka ovat toistuneet jo ainakin samantyyppisinä edellisissä projekteissa, toteuttamaan uudelleen. Tämä merkitsee tietysti jo kerran tehdyn työn tekemistä uudelleen. Tehtyä ohjelmistoa voitaisiin alkeellisimmalla tasolla yrittää käyttää hyväksi kopioimalla jo toteutetuista ohjelmista koodin osia uuteen sovellukseen. Tämä on kuitenkin hankalaa, jos ohjelman uudelleenkäyttöä ei ole ollenkaan suunniteltu sitä tehtäessä. Seuraavaa tasoa uudelleenkäytön huomioimisessa edustaa ajattelumalli, jossa ohjelmisto jaetaan aliohjelmiin (funktioihin). Uusissa sovelluksissa käytetään sitten hyväksi näitä funktioita. Etuna edellä mainittuun kopioimismenettelyyn nähden on, että funktioiden toteutuksia ei tarvitse ottaa mukaan uuden sovelluksen lähdekoodiin. Tarvittavat funktiot voidaan linkata uuteen sovellukseen. Näin kerran tehtyjä funktioita voidaan käyttää hyväksi ylemmällä abstraktiotasolla. Toinen etu, joka saadaan toteuttamalla uudelleenkäytettävät osat funktioina on se, että funktiot voidaan ohjelmoida uudelleen paremmin, esimerkiksi tehokkaammalla algoritmilla, vähemmän muistitilaa vievällä algoritmilla tai virheettömällä algoritmilla, jos siinä on havaittu virhe. Funktion uudelleen ohjelmointi ei vaikuta mitään tehdyn sovelluksen lähdekoodiin, mikäli funktion prototyyppi (interface) säilyy samana. Kolmatta tasoa uudelleenkäytön huomioimisessa edustaa abstrakti tietotyyppi. Siinä, kuten aikaisemmin on todettu, kootaan yhteen asiaan liittyvät tiedot yhdeksi tietotyypiksi ja kaikki tähän asiaan liittyvät toiminnat ohjelmoidaan funktioiksi. Tällä tavalla saadaan uudelleenkäytön abstraktiotasoa edelleen nostettua, koska siihen sisällytetään myös tiedot. Samalla tällaisen komponentin toteutuksen muutettavuus paranee huomattavasti, koska nyt voidaan muuttaa abstraktin tietotyypin tiedon sisäistä esitystapaa ja tiedon käsittelyyn tarkoitettujen funktioiden toteutustapaa siten, että tietotyyppiä käyttävään sovellukseen ei tarvita muutoksia. Tämä edellyttää, että uudessa abstraktin tietotyypin toteutuksessa säilytetään interface (tietotyypin nimi ja operaatiofunktioiden prototyypit). Neljättä tasoa uudelleenkäytön huomioimisessa edustaa olio. Olio on itse asiassa abstrakti tietotyyppi. Olio-ohjelmoinnissa tulee esille uusia käsitteitä. Ehkä tärkein uusi piirre on periyttäminen. Periyttämisen avulla olioon voidaan lisätä uusia piirteitä ilman, että tarvitsee muuttaa olion alkuperäistä toteutusta. Periyttäminen edustaa erikoistumista. Tässä yhteydessä tutustumme yleisiin tietorakenteisiin lista, pino ja jono. Niillä on paljon sovelluksia. Toteutukset tehdään abstrakteina tietotyyppeinä. Tulemme esittämään samalle abstraktille tietotyypille useita erilaisia toteutuksia. Näillä kaikilla säilytämme saman liityntärajapinnan, jolloin eri toteutukset ovat vaihtokelpoisia ohjelmistokomponentteja sovelluksissa. Ne vastaavat siis laitepuolen komponentteja sillä tavalla, että laitteeseen voidaan asentaa uusi komponentti vanhan tilalle, jos sen liitäntäspeksi vastaa ennen käytetyn komponentin tietoja. Lista pino ja jono ovat kaikki niin sanottuja säiliöitä (container). Niitä kutsutaan säiliöiksi, koska niihin voidaan tallentaa muita tietoalkioita. Periaatteessa taulukko

Algoritmit ja tietorakenteet / HL 2 on yksinkertaisin säiliö, koska sinne voidaan tallentaa esimerkiksi useita floating-point lukuja (vaikkapa mittausarvoja). Lineaarinen lista (Ordered List or List) Määritelmä. Lineaarinen lista on sellaisten alkioiden kokoelma, joiden kesken on määritelty lineaarinen järjestys. Lisäksi tälle kokoelmalle on määritelty seuraavat operaatiot: list) item) alusta lista tyhjäksi (initialize list) testaa onko lista tyhjä (test if empty) selvitä listan pituus eli alkioiden määrä (find the lenght of the list) hae listasta i:s alkio (retrieve the i:th element) selvitä onko listassa tietty alkio (determine whether or not a given item is in selvitä alkion järjestysnumero listassa (determine the order number of the lisää uusi alkio listaan (store a new value to the list) poista alkio listasta paikalta i (delete an item at position i) Määritelmässä mainittiin, että listan alkioiden kesken on määritelty lineaarinen järjestys. Tämä järjestys voi olla esimerkiksi syöttöjärjestys, nouseva suuruusjärjestys, laskeva suuruusjärjestys, aakkosjärjestys tai joku muu järjestys. Siitä että alkioiden kesken on määritelty järjestys seuraa, että käsitteet ensimmäinen alkio ja viimeinen alkio voidaan määritellä formaalisesti. Toinen määritelmä lineaariselle listalle. Edellisessä määritelmässä on osa Lineaarinen lista on sellaisten alkioiden kokoelma, joiden kesken on määritelty lineaarinen järjestys. Tämän lauseen määrittelemää kokoelmaa sanotaan usein sarjaksi (sequence). Sarja voidaan määritellä myös toisella tavalla rekursiivisesti seuraavasti: (i) Tyhjä joukko on sarja. (ii) Jos S on sarja ja a on alkio, niin (S,a) on sarja. Lineaarinen lista on siis sarja, jolle on määritelty edellisessä määritelmässä mainitut operaatiot. Listan toteutustavat Kuten alussa mainittiin, abstrakti tietotyyppi voidaan toteuttaa eri tavoilla siten, että toteutustapa ei vaikuta sitä käyttäviin sovelluksiin. Myös lineaarinen lista voidaan toteuttaa useilla eri tavoilla. Pääasialliset erot seuraavissa toteutuksissa ovat siinä, millä tavalla tiedot esitetään tietokoneen muistissa. Puhumme tiedon tallennusrakenteesta. Lineaarisen listan tapauksessa on jollakin tavalla esitettävä itse alkiot ja niiden järjestys. Pääasialliset tavat, joita voidaan käyttää tallennettaessa listan (ja muidenkin säiliöiden) tietoja ovat taulukko linkattu taulukko dynaamisesti varattu linkattu rakenne Näiden päätapojen sisällä on vielä useita erilaisia variaatioita. Yllä olevat otsikot eivät yksikäsitteisesti selvitä, minkälaisista tallennusrakenteista on kysymys. Seuraavassa esitetään, mitä kullakin rakenteella tarkoitetaan.

Algoritmit ja tietorakenteet / HL 3 Taulukkototeutus. Taulukkototeutuksessa lineaarisen listan alkiot esitetään tavallisen ohjelmointikielen taulukon alkioissa. Järjestys määräytyy tässä tapauksessa alkion tallennuspaikasta taulukossa. Taulukon alkiothan on varattu muistista peräkkäisistä muistipaikoista. Tässä toteutustavassa järjestyksessä ensimmäinen alkio on talletettuna ensimmäiseen varattuun muistipaikkaan, järjestyksessä toinen alkio toiseen muistipaikkaan jne. Tässä toteutustavassa on ratkaistava lisäksi, miten esitetään alkioiden lukumäärä (todellisen tilanteen mukainen lukumäärä ja maksimilukumäärä). Taulukko voi olla staattinen taulukko tai dynaamiselta muistialueelta varattu taulukko. Nämä yksityiskohdat voidaan hoitaa eri tavoilla, ja näin saadaan erilaisia variaatioita tämän pääratkaisun sisällä. Operaatiofunktioiden toteutuksesta tulee myös melko lailla erilaiset riippuen siitä, onko järjestys määritelty syöttöjärjestyksenä vai esimerkiksi suuruusjärjestyksenä. Kaikissa toteutuksissa kaikki listaan liittyvät tiedot on paketoitava yhdeksi tietotyypiksi abstraktin tietotyypin määritelmän mukaisesti. Liitteenä on esimerkki lineaarisen listan toteutukselle taulukkona. Siinä järjestys määräytyy syöttöjärjestyksen mukaisesti, eli uusi syötettävä alkio viedään aina listan loppuun. Alkion tietotyyppi on esimerkissä merkki (char), mutta on huomattava, että se voi olla mikä tahansa tietotyyppi (integer, varaosa, henkilo, jne). Tästä syystä esimerkissä on käytetty alkion tyyppinä yleistä muotoa Titem. Jos Titem muutetaan typedef määrittelyllä esimerkiksi tietueeksi, joka sisältää kaikki varaosan tiedot, niin lineaarisen listan operaatiofunktiot pysyvät täysin muuttumattomina! Silloin voidaan käsitellä varaosien listaa! Tämä edellyttää, että abstraktioajattelua on käytetty myös alemmalla tasolla, eli että listan alkioita on käsitelty abstraktina tietotyyppinä ja niille on omat operaatiofunktiot kuten esimerkissä read_item ja print_item. Esimerkkiohjelman tiedon tallennusrakenne, jonka tietotyyppi on Tlist, on seuraavan mallin mukainen: Tlist count array Tietotyyppi Tlist on määritelty seuraavasti: #define N 100 typedef... Titem; typedef struct { int count; Titem array[n]; } Tlist;

Algoritmit ja tietorakenteet / HL 4 Linkattu taulukkototeutus. Edellä olevalla taulukkototeutuksella on haittapuolena se, että alkioita poistettaessa täytyy kaikkia seuraavia alkioita siirtää taulukossa alkuun päin, jos vapaa tila halutaan säilyttää taulukon lopussa, mikä lienee järkevintä, jos listan järjestys määräytyy syöttöjärjestyksestä. Jos järjestys määräytyy suuruusjärjestyksen mukaan, myös lisäyksen yhteydessä tietoja joudutaan siirtämään taulukossa. Ainakin suurten tietomäärien kyseessä ollessa tällainen tietojen siirtäminen vie paljon prosessoriaikaa. Linkattu taulukko on ratkaisu, jolla päästään poistojen ja lisäysten yhteydessä tarvittavasta tietojen siirtämisestä. Ratkaisussa käytetään edelleen taulukkoa, mutta nyt taulukon alkioon sisällytetään myös alkion järjestystä kuvaava järjestysnumero. Tlist first free item next array Arrayitem Arrayitem item next Arrayitem Tietotyyppi Tlist on määritelty seuraavasti: #define N 100 typedef... Titem; typedef struct { Titem item; int next; } Tarrayitem; typedef struct { int first; int free; Tarrayitem array[n]; } Tlist; Listan alkiot saadaan tulostettua aloittamalla taulukon paikasta, jonka indeksi saadaan kentästä first, ja etenemällä taulukon alkioiden next-kentän mukaan. Taulukon vapaat paikat on myös ketjutettu samalla tavalla ja ensimmäisen vapaan paikan indeksi on kentässä free. Dynaamisesti linkatun listan toteutus. Edellä olevissa listan toteutuksissa on molemmissa haittapuolena, että niissä taulukon koko tulee määrätyksi jo ohjelman käännösvaiheessa, koska listan alkiot talletetaan staattisesti muistista varattuun taulukkoon. Asiaa voitaisiin parantaa osittain siten, että taulukolle varattaisiin sopiva tila dynaamiselta muistialueelta listan alustusoperaation yhteydessä. Tässäkin tapauksessa tarvittavan tilan maksimimäärä pitäisi olla tiedossa ennen kuin listaan aletaan lisäämään alkioita. Dynaamisesti linkattu

Algoritmit ja tietorakenteet / HL 5 listarakenne on sellainen, että kullekin alkiolle varataan tila vasta alkion lisäyksen yhteydessä. Tässä on etuna se, että alkioiden määrän ylärajaa ei tarvitse tietää etukäteen ja toisaalta se, että muistissa ei ole koskaan varattuna hukkatilaa, koska tilaa on varattu kullakin hetkellä juuri sille määrälle alkioita kuin niitä tosiasiassa on. Tällaisessa ratkaisussa alkioiden järjestys esitetään alkioon liitettyinä linkkeinä. Kussakin alkiossa on linkki, joka on järjestyksessä seuraavan alkion osoite. Seuraavasta kuvasta selviää periaate. Staattinen muistialue Lista 1 Dynaaminen muistialue 7 3 Dynaamisesti linkatun listan toteutus käsitellään myöhemmin. Toteutuksen yleisyysnäkökohtia Tässä tarkastellaan vielä lisää toteutetun listan yleisyysvaatimuksia ja yleisyyden edellytyksiä. Tarkastelu tehdään käyttäen esimerkkinä ylläesitettyä ja verkossa täydellisenä olevaa listan toteutusta (list5.c). Tämä yleisyystarkastelu sopii silti kaikkiin myös myöhemmin esiteltäviin säiliöihin. Asetamme säiliölle seuraavat yleisyystavoitteet: Säiliötä voidaan käyttää uudelleen uusissa sovelluksissa (ja uusilla sovellusalueilla). Säiliötä käyttävä sovellus on riippumaton säiliön toteutustavasta Säiliön toteutus on riippumaton säilöttävän alkion tyypistä Ensimmäinen vaatimus tarkoittaa, että tehtyä säiliötä voidaan helposti käyttää uudelleen sellaisenaan muissakin ohjelmistoprojekteissa. Käytön helppous tarkoittaa sitä, että uudelleenkäyttö tapahtuu "inkluudaamalla" listan otsikkotiedosto (.h) ja linkkaamalla sen toteutus (.obj tai.lib tiedosto) sovellukseen. Tässä oletamme vielä, että uusissa sovelluksissa säiliöön tallennetaan sitä tyyppiä olevia tietoalkioita, johon säiliö on suunniteltu. Tämä yleisyystavoite saadaan täytetyksi sillä, että listasta tehdään abstrakti tietotyyppi, ja että tehdään operaatiovalikoima niin täydelliseksi, että sillä pystyy ratkaisemaan mitä erilaisimpia probleemoita. Toinen yleisyysvaatimus voidaan selventää seuraavalla esimerkkitapauksella. Oletetaan että säiliöllä on jo toteutettu tietty sovellus. Tämä sovellus ei kuitenkaan toimi riittävän tehokkaasti. Tiedon poisto listasta kestää liian kauan. Toinen yleisyysvaatimus tarkoittaa, että voidaan ohjelmoida säiliölle uusi toteutus, nyt vaikkapa dynaamisesti linkattua rakennetta käyttäen, siis aivan toisenlaisella tekniikalla. Sovellukseen tämä uusi listan toteutus saadaan muuttamatta sovelluksessa mitään! Ainoat tarvittavat toimenpiteet ovat, että sovellus käännetään ja linkataan uudelleen. Käännös joudutaan tekemään koska listan otsikkotiedosto (.h) on muuttunut ja linkkaus joudutaan tekemään, koska listan operaatiofunktioiden konekielinen koodi on tietysti muuttunut aivan täysin. Mutta todella suuri etu, että sovelluksen source-koodiin ei tarvitse tehdä muutoksia voidaan saavuttaa. Tämän tekeminen mahdolliseksi edellyttää asioita sekä säiliön tekijältä (komponenttiohjelmoija) ja sovelluksen tekijältä (sovellusohjelmoijalta). Komponenttiohjelmoijan puolelta edellytyksenä on, että hän on noudattanut toteutuksessa abstraktin tietotyypin mallia ja tehnyt kattavan operaatiofunktiovalikoiman. Sovellusohjelmoijan pitää noudattaa hyvää ohjelmointitapaa käyttäessään säiliötä eli hän ei saa viitata suoraan tietotyypin sisäisiin kenttiin vaan hänen tulee pitäytyä säiliön operaatiofunktioissa. Muussa tapauksessa säiliön toteutuksen vaihtaminen uuteen merkitsee todennäköisesti valtavaa päivitystyötä sovellusohjelmassa.

Algoritmit ja tietorakenteet / HL 6 Kolmas yleisyysvaatimus tai -tavoite on säiliön toteutuksen riippumattomuus säiliöön tallennettavan tietoalkion tyypistä. Tämä tarkoittaa sitä, että listan toteutusta source-tasolla ei tarvitse muuttaa, vaikka säilöttävän alkion tyyppi muutetaan vaikka merkistä henkilöksi! Huomautus. On jopa niin, että myöskään sovellusta ei tarvitse muuttaa yllämainitussa tapauksessa, jos sovelluksen toimintalogiikka säilyy ennallaan! Jotta tämä säiliön riippumattomuus säilöttävän alkion tyypistä toteutuisi, edellytyksenä on, että alkiota käsitellään (sovelluksen tasolla ja) säiliön tasolla ADT:nä eli vain alkion omilla operaatioilla. On siis huomattava, että nyt puhutaan abstraktista tietotyypistä tietoalkioille ja abstraktista tietotyypistä säiliölle. Näitä alkion operaatioita esimerkkiohjelmassa (list5.c) ovat read_item, print_item ja compare_item. Jos halutaan vaihtaa säilöttävän alkion tyyppi, niin säiliön source-koodiin ei tarvita muutoksia. Muutos saadaan aikaan määrittelemällä alkion tietotyyppi Titem uudelleen ja kirjoittamalla operaatiofunktiot uudelle alkiotyypille. Kun toteutuksissa on käytetty puhdasta C-kieltä ja säiliö on tehty jollekin yksinkertaiselle (kielestä valmiina löytyvälle tietotyypille), kuten merkeille meidän esimerkissämme, yleisyysongelma piilee seuraavissa asioissa : syöttöön on käytetty scanf-funktiota, tulostukseen on käytetty printf funktiota, vertailu on tehty vertailuoperaattorilla ja sijoitus sijoitusoperaattorilla. Nämä ovat ongelmia siksi, että syöttö- ja tulostusfunktioiden kutsumuodot ovat riippuvaisia käsiteltävän tiedon tyypistä ja vielä pahempaa, että niitä ei voi käyttää rakenteellisten tietotyyppien tulostamiseen. Vertailu on myös ongelmallista, koska sitäkään ei voi käyttää rakenteisille tietotyypeille. Pelkkä sijoituskin saattaa olla ongelmallinen (vertaa aikaisemmin käsitelty aihe: matalakopiointi / syväkopiointi). Jos näille ongelmaoperaatioille tehdään omat operaatiofunktiot (read_item, print_item, compare_items ja copy_item), niin niille voidaan aina kirjoittaa kulloisellekin alkiotyypille toimiva toteutus. Tätä ajattelumallia käyttäen säiliöstä saadaan siis yleinen säilöttävän alkiotyypin suhteen. Muutokseen tarvitaan kuitenkin säiliön source-koodi, koska se on käännettävä uudelleen. Käännös tarvitaan siksi, koska siihen inkluudattava alkion otsikkotiedosto on muuttunut alkion uuden määrittelyn vuoksi. Jossakin vaiheessa myös alkion uudet operaatiofunktiot on linkattava sovellukseen. Huomautus. C:ssä siis yleisyyden saavuttaminen vaatii tietyllä tavalla totutuista tavoista luopumista, koska alkeistyypille pitää tehdä omat syöttö ja tulostusfunktiot samoin kuin omat vertaus- ja mahdollisesti sijoitusfunktiot. C++:ssa myös syöttö ja tulostus ovat operaattoreita (>> ja <<). Koska C++:ssa kaikki operaattorit ovat ylikuormitettavissa, niin silloin C++:n perustapa on sellaisenaan yleistettävissä mielivaltaiselle tyypille (luokalle). Tässäkin tapauksessa itse funktiot on kirjoitettava, mutta niitä voidaan kutsua samalla tavalla kuin alkeistyyppien yhteydessä. Verkosta löytyy myös ohjelma lista5.cpp, joka on listan C++ versio ja jossa on toteutettu ym. operaattoreiden ylikuormitukset (tämä esimerkki ei kuulu varsinaisesti kurssiin). Esimerkkiohjelmassa (list5.c) käytettiin alkiotyypille, joka nyt sattui olemaan merkki (char), tyyppinimeä Titem ja alkio operaatiofunktioiden niminä read_item, print_item, compare_item. nämä nimet ovat hyvin yleisiä eivätkä mitenkään ilmaise juuri kyseisessä esimerkissä käytössä ollutta merkkiä. Yleisiä nimiä käytettiin tässä korostamaan sitä, että kaikki ratkaisut olivat riippumattomia alkion tyypistä. Uusi tilanne syntyy, jos samassa ohjelmassa tarvitaan listaa 1 alkiotyypille 1 ja listaa 2 alkiotyypille 2. Edellä nähtiin, että listojen toteutukset ovat source-kooditasolla identtisiä, mutta konekielitasolla ei. Kysymys on siitä, että ainoa ero näissä funktioissa on tyyppien nimissä. Olisi siis kaksi sarjaa operaatiofunktioita jotka ovat muuten samanlaisia, mutta niissä olevat tyyppinimet ovat eri nimiä.. Kyseessä on vain nimeämiskysymys. C:ssä pitää myös funktioille antaa eri nimet. C++:ssa riittää pelkkä tyyppinimen ero eri funktioissa, koska ns. funktioiden ylikuormitus on mahdollista.

Algoritmit ja tietorakenteet / HL 7 C:ssä tämä säiliön koodin generointi uudelle alkiotyypille( headerien ja toteutusten generointi) voidaan tehdä automaattisesti makroilla (tietysti sama asia voidaan tehdä myös editorissa (Ensin Copy / Paste ja Sitten Search / Replace). C++:ssa kääntäjä voidaan saada generoimaan nämä määrittelemällä säiliö ns. template-luokaksi. C++:n template luokkien ajatus perustuu juuri tässä käsiteltyihin asioihin. Lisävalaistuksena vielä yllä olevaan asiaan seuraava. Jos ohjelmassa tarvitaan merkkilista ja pistelistaa, niin merkeille on omat operaatiofunktiot: void read_char(char *); void print_char(char ); int compare_char(char c1, char c2); ja vastaavasti pisteelle omansa: void read_point(tpoint *); void print_pointr(tpoint ); int compare_point(tpoint p1, Tpoint p2); Vastaavasti tarvitaan tietotyypit listoille, esimerkiksi TCharList ja TPointList. Ja vielä operaatiofunktiot listoille. Merkkilistan operaatiofunktiot voisivat olla vaikka tyyliä: void initialize_char_list(tcharlist *list);... ja pistelistan operaatiot tyyliä: void initialize_point_list(tpointlist *list);... C++:ssa riittää siis tyyppinimien vaihto funktioiden otsikoissa, koska usealla funktiolla voi olla sama nimi, kunhan niiden parametrilistat ovat erilaisia. Tätä kutsutaan funktioiden ylikuormittamiseksi. Asia perustuu siihen, että C++-kääntäjä generoi funktioon nimikirjoituksen (signature) parametrilistan perusteella. Säiliöiden yleisyyden lisäämiskeinoja opitaan lisää myöhemmin. Näitä ovat mm. se, että tallennetaan itse tiedon sijasta sen osoitin. Tällöin toteutus tehdään siten, että tallennettavan alkion tietotyyppinä on void*. Tällä yleisyyden lisäämiskeinolla on myös hintansa. C++:n luokat ja periyttäminen antaa myös hyödyllisen lisämahdollisuuden säiliöiden yleisyyden lisäämiseksi. Tämä ajatus perustuu siihen, että säilöttävän alkion tyypiksi laitetaan tässäkin osoitin ns. kantaluokkaan. Ns. polymorfismin takia tällaiseen säiliöön voidaan tallentaa myös osoittimia, jotka osoittavat olioon, joka edustaa kantaluokasta perittyä oliota. Tällöin samaankin säiliöön voidaan tallentaa erityyppisiä alkioita, kunhan ne ovat yhteisenkantaluokan perillisiä. Tämä aihe ei kuitenkaan kuulu kurssiin, vaan siihen palataan olio-ohjelmoinnin kurssissa.