Bevezetés a Programozásba II 11. előadás. Adatszerkezetek megvalósítása. Adatszerkezetek megvalósítása Adatszerkezetek



Hasonló dokumentumok
Alkalmazott modul: Programozás 9. előadás. Strukturált programozás: dinamikus adatszerkezetek

Bevezetés a programozásba 2

117. AA Megoldó Alfréd AA 117.

Programozás C++ -ban 2007/4

OAF Gregorics Tibor: Minta dokumentáció a 3. házi feladathoz 1.

STL. Algoritmus. Iterátor. Tároló. Elsődleges komponensek: Tárolók Algoritmusok Bejárók

4. Öröklődés. Programozás II

Programozás II gyakorlat. 8. Operátor túlterhelés

Programozás alapjai II. (9. ea) C++ többszörös öröklés, cast, perzisztencia

Osztály és objektum fogalma

3. Gyakorlat Ismerkedés a Java nyelvvel

Emlékeztető: a fordítás lépései. Szimbólumtábla-kezelés. Információáramlás. Információáramlás. Információáramlás.

Informatikai Kar. 3. fejezet. alapismeretek. Giachetta Roberto

Java VI. Egy kis kitérő: az UML. Osztály diagram. Általános Informatikai Tanszék Utolsó módosítás:

Programozás C++ -ban

Pénzügyi algoritmusok

Alkalmazott modul: Programozás

Generikus Típusok, Kollekciók

Eseményvezérelt alkalmazások fejlesztése II. A.NET keretrendszer és a C# programozási nyelv. Objektumorientált programozási nyelvek A Smalltalk nyelv

A C++ öröklés. (Előfeltétel: 12. tétel ismerete)

Alkalmazott modul: Programozás 8. előadás. Strukturált programozás: dinamikus memóriakezelés. Dinamikus memóriakezelés. Dinamikus memóriakezelés

Bevezetés a programozásba Előadás: Tagfüggvények, osztály, objektum

PHP5 Új generáció (2. rész)

Alkalmazott modul: Programozás 10. fejezet. Strukturált programozás: dinamikus memóriakezelés. Giachetta Roberto

Bevezetés a programozásba II. 5. Előadás: Másoló konstruktor, túlterhelés, operátorok

C# osztályok. Krizsán Zoltán

Programozási nyelvek Java

Webes alkalmazások fejlesztése 8. előadás. Webszolgáltatások megvalósítása (ASP.NET WebAPI)

Bevezetés a Programozásba II 2. előadás. Adattípusok megvalósítása egységbe zárással. Adattípusok megvalósítása egységbe zárással

Származtatási mechanizmus a C++ nyelvben

Bevezetés a Programozásba II 12. előadás. Adatszerkezetek alkalmazása (Standard Template Library)

Bevezetés a programozásba I 8. gyakorlat. C++: szövegfolyamok, intelligens tömbök

Statikus adattagok. Statikus adattag inicializálása. Speciális adattagok és tagfüggvények. Általános Informatikai Tanszék

3. Osztályok II. Programozás II

Objektumorientált programozás C# nyelven

Objektumorientált programozás C# nyelven

Objektumelvű alkalmazások fejlesztése 6. gyakorlat. Öröklődés, polimorfizmus. Öröklődés Kódismétlődés objektum-orientált szerkezetben

Objektum elvű alkalmazások fejlesztése. Verem típus osztály-sablonja

Bánsághi Anna

Bevezetés a programozásba I 8. gyakorlat. C++: szövegfolyamok, intelligens tömbök. Adatfolyamok Hibalehetőségek

Bevezetés a Programozásba II 3. előadás. Biztonságos adattípusok megvalósítása

C++ programozási nyelv Struktúrák a C++ nyelvben Gyakorlat

Bevezetés a C++ programozási nyelvbe

500. CC Megoldó Alfréd CC 500.

Objektumok inicializálása

A lista eleme. mutató rész. adat rész. Listaelem létrehozása. Node Deklarálás. Létrehozás. Az elemet nekünk kell bef zni a listába

STL gyakorlat C++ Izsó Tamás május 9. Izsó Tamás STL gyakorlat/ 1

128. AA Megoldó Alfréd AA 128.

500. DD Megoldó Alfréd DD 500.

Programozás II gyakorlat. 7. Példák a polimorfizmus alkalmazásaira

1. Template (sablon) 1.1. Függvénysablon Függvénysablon példányosítás Osztálysablon

OBJEKTUM ORIENTÁLT PROGRAMOZÁS JAVA NYELVEN. vizsgatételek

Objektumorientált programozás C# nyelven

.AA Megoldó Alfréd AA.

Bevezetés a Programozásba II 3. előadás. Biztonságos adattípusok megvalósítása. Biztonságos adattípusok megvalósítása

Bevezetés a Programozásba II 8. előadás. Polimorfizmus Giachetta Roberto

Fejlett programozási nyelvek C++ Iterátorok

Programozási alapismeretek :: beadandó feladat. Felhasználói dokumentáció. Molnár Tamás MOTIABT.ELTE

Programozás II. 4. Dr. Iványi Péter

ISA szimulátor objektum-orientált modell (C++)

Bevezetés a Programozásba II 10. előadás. Dinamikus memóriakezelés

Programozás C++ -ban

PHP II. WEB technológiák. Tóth Zsolt. Miskolci Egyetem. Tóth Zsolt (Miskolci Egyetem) PHP II / 19

0. Megoldó Manó 0. Programozás alapjai 2. (inf.) pót zárthelyi gyak. hiányzás: 2 n/kzhp: n/11,5. ABCDEF IB.028/2.

Programozás. C++ osztályok. Fodor Attila. Pannon Egyetem Műszaki Informatikai Kar Villamosmérnöki és Információs Rendszerek Tanszék

Adatstruktúrák, algoritmusok, objektumok

INFORMATIKAI ALAPISMERETEK

Java és web programozás

SZERVER OLDALI JAVASCRIPT. 3. hét Javascript nyelvi elemek

Elemi Alkalmazások Fejlesztése II.

Objektumorientált programozás C# nyelven III.

Dr. Pétery Kristóf: Excel 2007 feladatok és megoldások 2.

500. AA Megoldó Alfréd AA 500.

Bevezetés a programozásba. 12. Előadás: 8 királynő

503.AA Megoldo Arisztid 503.A

Egységes és objektumközpontú adatbázis-kezelés (2. rész)

Java és web programozás

Eddig még nem használt vezérlőket is megismerünk: PlaceHolder, RadioButtonList.

Információs Technológia

Az alábbi példában a Foo f(5); konstruktor hívása után mennyi lesz f.b értéke? struct Foo { int a, b; Foo(int c):a(c*2),b(c*3) {} };

Kutatói tájékoztató Útmutató a KSH kutatószobai környezetében folyó kutatómunkához

.Net adatstruktúrák. Készítette: Major Péter

Informatikai Kar. 4. fejezet. Giachetta Roberto

INFORMATIKAI ALAPISMERETEK

8. Mohó algoritmusok Egy esemény-kiválasztási probléma. Az esemény-kiválasztási probléma optimális részproblémák szerkezete

C++ programozási nyelv Konstruktorok-destruktorok

500.AJ Megoldó Magyar Magdolna 500.J

Programozás alapjai II. (4. ea) C++

Access adatbázis elérése OLE DB-n keresztül

NAV nyomtatványok xml szerkezete. (v6.7)

C++ programozási nyelv

A feladat lényege egy felhasználói típusnak a zsák típusnak a megvalósítása.

C++ programozási nyelv

Utasítások. Excel VII. Visual Basic programozás alapok. A Visual Basic-kel megoldható feladatok típusai Objektumok, változók Alprogramok

Pelda öröklődésre: import java.io.*; import java.text.*; import java.util.*; import extra.*;

Internet programozása. 3. előadás

Elemi alkalmazások fejlesztése IV. Adatbázis-kezelő GUI alkalmazás készítése 3. Összetett tábla karbantartása

1000.AA Megoldo Alfréd 1000.A

Infokommunikáció (PF10IK511L) kérdései

1. mérés - LabView 1

Átírás:

Pázmány Péter Katolikus Egyetem Információs Technológiai és Bionikai Kar Bevezetés a Programozásba II 11. előadás 2014.05.12. Giachetta Roberto groberto@inf.elte.hu http://people.inf.elte.hu/groberto Adatszerkezetek Adatszerkezetnek nevezzük adott típusú adatok valamilyen megadott struktúrában felépített halmazát A főbb adatszerkezetek a legtöbb programozási nyelvben definiáltak, ezeket gyűjteményeknek (collection) nevezzük pl. tömb, verem, sor, lista, asszociatív tömb az adatszerkezetek rendszerint szabványos osztályok, amelyeket a nyelvi könyvtárban valósítottak meg lehetővé teszik többféle típus kezelését sablonokkal könnyű használatot biztosítanak operátorok segítségével kihasználják a dinamikus memóriakezelés adta lehetőségeket PPKE ITK, Bevezetés a programozásba II 11:2 Sablonok Sokszor előfordul, hogy egy adott osztályt, különösen adatszerkezetet több elemtípussal is meg akarunk valósítani (pl. számmal, szöveggel, vagy egyéb típussal) ehhez több, művelethalmazában megegyező, de értékhalmazában különböző típus szükséges A megoldás az, hogy felveszünk egy behelyettesíthető típust, egy úgynevezett sablont (template) a sablont tetszőleges helyen felhasználhatjuk az osztályban példányosításakor behelyettesítünk a használni kívánt konkrét típussal használatát template<class <név> > jelöli az osztálynál PPKE ITK, Bevezetés a programozásba II 11:3 Sablonok template <class T> // T sablon használata private: int _intvalue; // rögzített típusú érték T _tvalue; // T típusú érték, ahol T cserélhető void tmethod(t param){ // T paraméterű metódus _tvalue = param; ; MyClass<float> mtf; // T helyettesítése float-tal mtf.tmethod(3.5); // a paraméter float típusú lesz PPKE ITK, Bevezetés a programozásba II 11:4 Sablonok működése A sablonok biztosítják adatszerkezetek esetén a típusfüggetlenséget, hiszen így az elemtípus tetszőleges lehet, pl. vector<float> fvector; Sablonos típus létrehozásával igazából típusmintát hozunk létre, amely a sablon behelyettesítésével válik igazán típussá azaz egy típusmintából több típus is létrejöhet ekkor a sablonból fakadó hibák fordítási időben kiderülnek MyClass<T> T = float T = Rational MyClass<float> MyClass<Rational> Sablonok alkalmazása Mivel a sablonos típus nem igazi típus, csak minta, a kódja nem helyezhető el forrásfájlban, csak fejlécfájlban (ezért a sablonos típusok egy fájlból állnak) Minden osztálybeli hivatkozásnál a sablont is meg kell adnunk (vagy általános, vagy konkrét típussal) Amennyiben leválasztjuk a metódusok definícióját, a definícióban ismét kell jelölnünk a sablont, pl.: template <class T> // T sablon használata ; template <class T> // ismét jelöljük a sablont void MyClass<T>::tMethod(T param){ PPKE ITK, Bevezetés a programozásba II 11:5 PPKE ITK, Bevezetés a programozásba II 11:6 1

Sablonok lehetőségei Egy típus több sablonnal is rendelkezhet, ekkor azokat vesszővel választjuk el, pl.: template <class T1, class T2> ; A sablonok számos további lehetőséget kínálnak nem csak típusok, de tetszőleges alprogramok megjelölhetőek sablonnal értékek is megadhatóak, amik lehetnek sablonosak is a sablonos művelet specializálható konkrét típusokra Egy másik lehetséges sablonmegoldás a generikus típus (generic, pl. Java), ahol a sablon behelyettesítése futási időben történik PPKE ITK, Bevezetés a programozásba II 11:7 Indexelés Saját típusainkhoz lehetőségünk van indexelő operátort készíteni az indexelő [ ] operátorban egy tetszőleges típusú értéket adhatunk meg (az operátoron belül), ez kerül át a paraméterbe amennyiben több értékkel szeretnénk indexelni (pl. mátrix esetén sor/oszlop), használhatjuk a ( ) funktor operátort, amely zárójelezéssel hívható meg, tetszőleges sok paraméter adható át indexelés esetén külön kell ügyelni a beállítás, illetve a lekérdezés kérdésére, ezért az operátort túl kell terhelni (a túlterhelést a const kulcsszó fogja biztosítani) PPKE ITK, Bevezetés a programozásba II 11:8 Indexelés private: int _values[100]; // értékek tömbje int operator[](int index) const { // indexelő operátor lekérdezéshez return _values[index]; // értéket ad vissza int& operator[](int index) { // indexelő operátor értékadáshoz return _values[index]; // referenciát ad vissza PPKE ITK, Bevezetés a programozásba II 11:9 Dinamikus memóriakezelés A dinamikus memóriakezelés lehetővé teszi, hogy programfutás közben allokáljuk területeket a memóriából a new és delete operátorok segítségével több terület is foglalható egyszerre (dinamikus tömb) a lefoglalt területeket mutatók segítségével kezeljük Saját típusokban is felhasználhatjuk a dinamikus memóriakezelés adta lehetőséget elhelyezhetünk bennük mutatókat, mint mezőket, amelyekre dinamikusan allokálhatunk memóriaterületet az allokálást többször is elvégezhetjük a programfutás során PPKE ITK, Bevezetés a programozásba II 11:10 Dinamikus méretezés A dinamikusan allokált tömb alkalmas arra, hogy futás közben szabályozzunk méretet pl. tömb esetén allokálunk egy területet, amely egy részét fogja kitenni a vektor tényleges tartalma teljes lefoglalt terület Dinamikus méretezés A dinamikusan lefoglalt terület nem méretezhető át, de lehetőségünk van új területet foglalni, és arra lecserélni a régit A következő lépéseket kell elvégeznünk: 1. új tömb dinamikus lefoglalása 2. az elemek átmásolása az új tömbbe 3. a régi tömb törlése, lecserélése az újra (mutató átállítás) kihasznált rész probléma, hogy így akkor is nagy területet kell allokálni, ha jórészt kevéssé használjuk ki Ez jelentős műveletigényt jelent, ezért ritkán alkalmazzuk, nem egyesével növeljük a méretet, hanem duplájára Fordítva is alkalmazható, felezhetünk is méretet (így nem foglalunk felesleges memóriát) PPKE ITK, Bevezetés a programozásba II 11:11 PPKE ITK, Bevezetés a programozásba II 11:12 2

Dinamikus méretezés int* values = new int[10]; // 10 méretű dinamikus tömb // 10 elemet behelyeztünk, szeretnénk 11-et is int* t = new int[20]; // új tömb lefoglalása for (int i = 0; i < 10; i++) t[i] = values[i]; // elemek áthelyezése // 11. elem behelyezése delete[] values; // régi tömb törlése values = t; // a mutató átállításával lecserélődik a tömb PPKE ITK, Bevezetés a programozásba II 11:13 Feladat: Valósítsuk meg az intelligens dinamikus vektor (vector) típust, amelyet futás közben lehet bővíteni. a vektor sablonos lesz, primitív dinamikus tömbbel ábrázoljuk, amely automatikusan méreteződik mindig egy részét használjuk ki a teljes tömb kapacitásának (hasonlóan, mint a verem esetében), a konstruktor paraméterben kapja meg a kezdeti méretet a push_back(t) művelettel bővíthető, a pop_back() művelettel redukálható, a clear() művelettel üríthető, méretét a size() művelettel kérdezhetjük le az elemek elérését/beállítását a [ ] indexelő operátor biztosítja (ezért két változatban írjuk meg) PPKE ITK, Bevezetés a programozásba II 11:14 Tervezés: Megoldás (vector.hpp): template <class T> vector<t>::vector(int size) { if (size > 10) // kezdeti kapacitás beállítása _capacity = size * 2; else _capacity = 10; _size = size; // méret átvétele _values = new T[_capacity]; // tömb dinamikus létrehozása PPKE ITK, Bevezetés a programozásba II 11:15 PPKE ITK, Bevezetés a programozásba II 11:16 Megoldás(vector.hpp): template <class T> void vector<t>::push_back(t value) { if (_size == _capacity) // ha már nincs hely resize(2 * _capacity); // átméretezés a duplájára _values[_size] = value; // behelyezzük az elemet _size++; // növeljük az elemszámot Példányok másolása Értékek másolásakor két változatot különböztetünk meg: mély másolat (deep copy): a teljes példány minden mezőjével lemásolódik a memóriában egy ugyanakkora memóriaterületre lassú, mert teljes másolatot kell végezni a másolaton végzett műveletek nem hatnak az eredetire sekély másolat (shallow copy): a példány nem, csak annak hivatkozása másolódik a memóriában gyors, csak a memóriacímet másoljuk a másolaton végzett műveletek kihatnak az eredetire ehhez használjuk a referenciaorerátort, illetve mutatókat PPKE ITK, Bevezetés a programozásba II 11:17 PPKE ITK, Bevezetés a programozásba II 11:18 3

Példányok másolása Azonban dinamikus adatszerkezetek mély másolata problémás az alapértelmezett mély másolat a mezőkről készít másolatot, a mezőkre ráállított dinamikus területekről nem egy köztes állapotot kapunk, amely több a sekély másolatnál, de kevesebb a mély másolatnál, pl.: vector<int> v1; vector<int> v2 = v1; // mély másolat (reméljük) v1.push_back(1); v2.push_back(2); // a két hozzáadásnak // függetlennek kéne lennie cout << v1.pop_back() << endl; // eredménye: 2, vagyis mégse volt független // a két hozzáadás Példányok másolása nem csupán téves viselkedéshez, de programhiba is keletkezhet a hibás másolás miatt, pl.: vector<int> v1; v1.push_back(1); { // programblokk vector<int> v2 = v1; // mély másolat a lokális változóba // a v2 megsemmisül, lefut a destruktora, // vagyis törlődik a dinamikus tömb cout << v1.pop_back() << endl; // programhiba, a tömb már nem létezik Ahhoz, hogy ezt megoldjuk, felül kell definiálnunk az alapértelmezett másolást PPKE ITK, Bevezetés a programozásba II 11:19 PPKE ITK, Bevezetés a programozásba II 11:20 Másoló konstruktor A példányok másolását két művelet, a másoló konstruktor (copy constructor), illetve az értékadás operátor (=) valósítja meg A másoló konstruktor egy már létező példány alapján hoz létre újat paraméterben megkapja egy ugyanolyan típusú példány referenciáját, törzsében elvégzi a másoló műveleteket amennyiben nincs dinamikus tartalom a mezőkben, az alapértelmezett másoló konstruktor megfelelő amennyiben van dinamikus tartalom, azt létre kell hozni, és az értékeket megfelelően belemásolni Másoló konstruktor private: int* _value; MyClass(int v = 0){ // konstruktor _value = new int; *_value = v; MyClass(const MyClass& other) { // másoló k. _value = new int; // a dinamikus taralom létrehozása *_value = *other._value; // érték másolása ; PPKE ITK, Bevezetés a programozásba II 11:21 PPKE ITK, Bevezetés a programozásba II 11:22 Másoló konstruktor A másoló konstruktor törzsében tud hivatkozni a másolandó példány mezőire általában ezeket egyenként értékül adjuk az új objektumnak ha mutató is van az mezők között, akkor az általa mutatott objektumot is le kell másolnunk természetesen további inicializálásokat is végezhetünk A másoló konstruktor a következő esetekben fut le: közvetlen meghívás: MyClass b(a); deklaráció értékadással: MyClass b = a; érték szerinti paraméterátadás PPKE ITK, Bevezetés a programozásba II 11:23 Értékadás operátor Amennyiben nem a változó deklarálásakor kap értéket, hanem később, az értékadás operátor fut le: MyClass a, b; b = a; Az értékadás operátor paraméterben kapja meg a másolandó példányt (konstans referenciaként), és hasonló műveleteket végez, mint a másoló konstruktor fontos, hogy már léteznek a dinamikusan létrehozott értékek, így azokat törölni kell ellenőrizni kell, hogy a paraméterben kapott változó nem-e saját maga (a memóriacím segítségével) a többszörös értékadás használatához vissza kell adnia az aktuális példány (*this) referenciáját PPKE ITK, Bevezetés a programozásba II 11:24 4

Értékadás operátor MyClass& operator=(const MyClass& other){ if (this == &other) // ha ugyanazt a példányt kaptuk return *this; // nem csinálunk semmit ; *_value = *(other._value); // különben a megfelelő módon másolunk return *this; // visszaadjuk a referenciát Típusok megvalósítása Amennyiben dinamikusan lefoglalt memóriaterületet használunk a típusban, minden esetben meg kell valósítani a destruktort, a másoló konstruktort, és az értékadás operátort ha nincs dinamikus tartalom, akkor is előfordulhat, hogy használjuk őket mindhárom művelet csak metódusként írható meg az értékadás operátor teljesen független az értékmódosító operátoroktól (+=, *=, ), amelyek megvalósíthatók a típuson kívül is ha a másolást, vagy értékadást rejtetté tesszük, azzal letiltjuk ezt a funkcionalitást (a leszármazott osztályokra is) PPKE ITK, Bevezetés a programozásba II 11:25 PPKE ITK, Bevezetés a programozásba II 11:26 Feladat: Valósítsuk meg az intelligens dinamikus vektor (vector) típust, amelyet futás közben lehet bővíteni. Tervezés: a vektor sablonos lesz, primitív dinamikus tömbbel ábrázoljuk, amely automatikusan méreteződik a push_back(t) művelettel bővíthető, a pop_back() művelettel redukálható, a clear() művelettel üríthető, méretét a size() művelettel kérdezhetjük le az elemek elérését/beállítását a [ ] indexelő operátor biztosítja (ezért két változatban írjuk meg) biztosítjuk a megfelelő másolást a másoló konstruktor és az értékadás operátor megvalósításával PPKE ITK, Bevezetés a programozásba II 11:27 PPKE ITK, Bevezetés a programozásba II 11:28 Megoldás (vector.hpp): template <class T> vector<t>::vector(const vector<t>& other) { _capacity = other._capacity; // átmásoljuk az egyszerű értékeket _size = other._size; _values = new T[_capacity]; // létrehozzuk a dinamikus tömböt Feladat: Használjuk fel a saját vektor típusunkat a grafikus felületű programcsomagunkban. csupán ki kell cserélnünk a hivatkozásokat a beépített vektorra emellett, az alkalmazásban már található dinamikusan foglalt tartalom, de a vezérlő valamely leszármazottjában is előfordulhat, nekünk egyelőre csak az Application osztállyal kell törődnünk for (int i = 0; i < _size; i++) _values[i] = other._values[i]; // átmásoljuk a hasznos értékeket ugyanakkor az alkalmazás, illetve a vezérlők másolása nem célravezető, hiszen minden vezérlő egy dedikált célt szolgál, alkalmazásból pedig csak egy van, ezért inkább tiltsuk le a funkcionalitást PPKE ITK, Bevezetés a programozásba II 11:29 PPKE ITK, Bevezetés a programozásba II 11:30 5

Megoldás (application.hpp): class Application // grafikus alkalmazás { private: // letiltjuk a másolást Application(const Application&) { Application& operator=(const Application&) { return *this; // ez a viselkedés úgyse kerül // végrehajtásra, ezért a törzs igazából // lényegtelen PPKE ITK, Bevezetés a programozásba II 11:31 6