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

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

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

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

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

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

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

Osztályok. 4. gyakorlat

Informatikai Kar. 3. fejezet. alapismeretek. Giachetta Roberto

OOP #14 (referencia-elv)

3. Osztályok II. Programozás II

Programozási nyelvek Java

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

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

Programozás C++ -ban

Programozás II. 3. gyakorlat Objektum Orientáltság C++-ban

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

Programozás I gyakorlat

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

Bevezetés, a C++ osztályok. Pere László

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

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

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

Programozási nyelvek Java

Programozási nyelvek Java

C++ programozási nyelv

A C programozási nyelv V. Struktúra Dinamikus memóriakezelés

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

Szoftvertechnológia 3. előadás. Objektumorientált tervezés: alapismeretek. Giachetta Roberto. Eötvös Loránd Tudományegyetem Informatikai Kar

Pénzügyi algoritmusok

Programozás BMEKOKAA146. Dr. Bécsi Tamás 5. előadás

Bevezetés a programozásba I 10. gyakorlat. C++: alprogramok deklarációja és paraméterátadása

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

C++ programozási nyelv Konstruktorok-destruktorok

8. gyakorlat Pointerek, dinamikus memóriakezelés

OOP: Java 11.Gy: Enumok, beágyazott osztályok. 13/1 B ITv: MAN

Programozás C++ -ban 2007/4

Programozás C++ -ban

Visual C++ osztály készítése, adattagok, és metódusok, láthatóság, konstruktor, destruktor. Objektum létrehozása, használata, öröklés.

500. DD Megoldó Alfréd DD 500.

Objektumelvű programozás

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.

Objektumok inicializálása

JAVA PROGRAMOZÁS 2.ELŐADÁS

5. Gyakorlat. struct diak {

Mutatók és mutató-aritmetika C-ben március 19.

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

Programozás módszertan

Programozás C++ -ban 2007/7

Java és web programozás

Generikus Típusok, Kollekciók

Alkalmazott modul: Programozás 6. előadás. Strukturált programozás: újrafelhasználható adattípusok

Pénzügyi algoritmusok

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

500. CC Megoldó Alfréd CC 500.

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

Programozási technológia

Bevezetés a programozásba 2

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

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

C++ programozási nyelv Konstruktorok Gyakorlat

Generikus osztályok, gyűjtemények és algoritmusok

Szövegek C++ -ban, a string osztály

C programozási nyelv Pointerek, tömbök, pointer aritmetika

Algoritmusok és adatszerkezetek gyakorlat 06 Adatszerkezetek

Amortizációs költségelemzés

Adatszerkezetek Adatszerkezet fogalma. Az értékhalmaz struktúrája

C++ Gyakorlat jegyzet 5. óra. A C++ szabvány több memóriatípust különít el. Ezek közül elsősorban a stack-et használtuk eddig.

A verem (stack) A verem egy olyan struktúra, aminek a tetejéről kivehetünk egy (vagy sorban több) elemet. A verem felhasználása

A lista adatszerkezet A lista elemek egymásutániságát jelenti. Fajtái: statikus, dinamikus lista.

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

Java és web programozás

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

Miután létrehoztuk, szeretnénk neki beszédesebb nevet adni. A név változtatásához a következőt kell tenni:

500. AA Megoldó Alfréd AA 500.

Kivételkezelés, beágyazott osztályok. Nyolcadik gyakorlat

Programozási Nyelvek: C++

Adatszerkezetek 1. Dr. Iványi Péter

Tömbök kezelése. Példa: Vonalkód ellenőrzőjegyének kiszámítása

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.

Java és web programozás

Programozás. Osztályok, Származtatott osztályok. Fodor Attila

Számítógép és programozás 2

Adatszerkezetek Tömb, sor, verem. Dr. Iványi Péter

Elemi Alkalmazások Fejlesztése II.

Globális operátor overloading

228. AA Default Konstruktor AA 228.

128. AA Megoldó Alfréd AA 128.

Alkalmazott Modul III 4. előadás. Objektumorientált programozás: objektumok és osztályok. Procedurális programozás Koncepció

Bánsághi Anna 2014 Bánsághi Anna 1 of 33

Memóriakezelés, dinamikus memóriakezelés

Bevezetés a programozásba. 8. Előadás: Függvények 2.

Programozás. (GKxB_INTM021) Dr. Hatwágner F. Miklós április 4. Széchenyi István Egyetem, Gy r

Járműfedélzeti rendszerek II. 4. előadás Dr. Bécsi Tamás

.AA Megoldó Alfréd AA.

Programozás alapjai C nyelv 8. gyakorlat. Mutatók és címek (ism.) Indirekció (ism)

Mutatók és címek (ism.) Programozás alapjai C nyelv 8. gyakorlat. Indirekció (ism) Néhány dolog érthetőbb (ism.) Változók a memóriában

Fejlett programozási nyelvek C++ Iterátorok

mul : S T N 1 ha t S mul(s, t) := 0 egyébként Keresés Ezt az eljárást a publikus m veletek lenti megvalósításánál használjuk.

Java programozási nyelv 4. rész Osztályok II.

Bevezetés a programozásba. 9. Előadás: Rekordok

Átírás:

Eötvös Loránd Tudományegyetem Informatikai Kar Alkalmazott modul: Programozás 9. előadás Strukturált programozás: dinamikus adatszerkezetek Giachetta Roberto groberto@inf.elte.hu http://people.inf.elte.hu/groberto

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 mezőként, amelyekre dinamikusan allokálhatunk memóriaterületet az allokálást többször is elvégezhetjük a programfutás során ELTE IK, Alkalmazott modul: Programozás 9:2

Dinamikus méretezés A dinamikusan allokált tömb alkalmas arra, hogy futás közben szabályozzunk méretet pl. verem esetén allokálunk egy területet, amely egy részét fogja kitenni a verem tényleges tartalma _values kihasznált rész (_top = 2) probléma, hogy így akkor is nagy területet kell allokálni, ha jórészt kevéssé használjuk ki ELTE IK, Alkalmazott modul: Programozás 9:3

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ása) Ez jelentős műveletigényt jelent, ezért ritkán alkalmazzuk, nem egyesével növeljük a méretet, hanem rögtön duplájára Fordítva is alkalmazható, felezhetünk is méretet (így nem foglalunk felesleges memóriát) ELTE IK, Alkalmazott modul: Programozás 9:4

Dinamikus méretezés Pl.: 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 ELTE IK, Alkalmazott modul: Programozás 9:5

Példa Feladat: Módosítsuk úgy a verem típust, hogy futás közben automatikusan átméreteződjön. ha megtelik, a duplájára méretezzük, ha negyedénél kevesebb eleme lesz, a felére méretezzük, ehhez felvesszük a resize(int) műveletet rejtett metódusként, ezt hívjuk meg a push(t) és pop() műveletekben az átméretezéskor létrehozunk egy új tömböt, a hasznos elemeket belehelyezzük (a _top indexig), majd lecseréljük a régi tömböt kezdetben a 100-as alapértelmezett méretet adjuk neki, ezért nem kell méretet adni a konstruktorban ELTE IK, Alkalmazott modul: Programozás 9:6

Példa Megoldás: template <class T> // elemtípus sablonja class Stack { // verem típus private: void resize(int newsize); // átméretezés megadott méretre public: enum Exceptions { STACK_EMPTY }; // kivételek felsorolási típusa }; Stack(); ELTE IK, Alkalmazott modul: Programozás 9:7

Példa Megoldás: template <class T> void Stack<T>::resize(int newsize) { T *temp = new T[newSize]; // új tömb lefoglalása for (int i = 0; i < _top; i++){ temp[i] = _values[i]; // értékek átmásolása } delete[] _values; // régi tömb törlése } _values = temp; // új tömb beállítása _size = newsize; // eltároljuk az új méretet ELTE IK, Alkalmazott modul: Programozás 9:8

Példányok másolása Értékek másolásakor két változatot különböztetünk meg: sekély másolat (shallow copy): a típuspéldány mezőivel együtt lemásolásra kerül egy új memóriaterületre dinamikus tartalommal rendelkező típusok esetén olyan másolat készül, amely részben az eredeti példányból épül fel mély másolat (deep copy): a típuspéldány minden mezőjével, és az azok által lefoglalt memóriaterülettel együtt lemásolásra kerül egy új memóriaterületre dinamikus tartalommal rendelkező típusok esetén csak ez garantálja az eredetitől teljesen független másolat készítését ELTE IK, Alkalmazott modul: Programozás 9:9

Példányok másolása Pl.: Stack<int> s1; Stack<int> s2 = s1; // (sekély) másolat s1.push(1); s2.push(2); // független elembehelyezések cout << s1.pop() << endl; // eredménye: 2 // azaz az értékadások mégse voltak függetlenek ELTE IK, Alkalmazott modul: Programozás 9:10

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 ELTE IK, Alkalmazott modul: Programozás 9:11

Másoló konstruktor Pl.: class MyType { private: int* _value; public: MyType(int v = 0){ // konstruktor _value = new int; *_value = v; } MyType(const MyType& other) { // másoló konstr. _value = new int; // a dinamikus taralom létrehozása *_value = *other._value; // érték másolása } }; ELTE IK, Alkalmazott modul: Programozás 9:12

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 (összetett típusok esetén meghívódik azok másoló konstruktora) 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: MyType b(a); kezdeti értékadás: MyType b = a; érték szerinti paraméterátadás ELTE IK, Alkalmazott modul: Programozás 9:13

Példány hivatkozások Egy típuspéldányban elérhető annak valamennyi mezője és metódusa, akár rejtett, akár nem Ugyanakkor lehetőség van magát a teljes példányt is elérni a típuson belül a this kulcsszó használatával ez egy mutatót ad vissza az aktuális példányra ugyanúgy használható, mint bármely más mutató, amelyet az példányra állítottunk lekérdezhető általa az összes tag: this-><tagnév> lehetőséget ad a példány hivatkozásának visszaadására ha a konkrét példányra van szükségünk, akkor lekérjük a memóriacím tartalmát (*this) ELTE IK, Alkalmazott modul: Programozás 9:14

Példány hivatkozások Pl.: class MyType { public: void SetValue(int value){ *_value = value; // ugyanez hosszabban: // *(this->_value) = value; } MyType* ReturnMyPointer(){ return this; // visszaadja a mutatót a példányra } ELTE IK, Alkalmazott modul: Programozás 9:15

Példány hivatkozások Pl.: MyType ReturnMyself (){ return *this; // visszaadja magát a példányt } private: int *_value; }; MyType t; MyType* tp = t.returnmypointer(); tp->setvalue(10); // másként: t.setvalue(10); ELTE IK, Alkalmazott modul: Programozás 9:16

Értékadás operátor Amennyiben a változó értékét a későbbiekben módosítjuk, az értékadás operátor fut le: MyType a, b; b = a; // értékadás Az értékadás operátor megkapja a másolandó példány (konstans) referenciáját, és biztosítja tartalmának átmásolását 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 ELTE IK, Alkalmazott modul: Programozás 9:17

Értékadás operátor Pl.: class MyType { public: MyType& operator=(const MyType& 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 ELTE IK, Alkalmazott modul: Programozás 9:18

Dinamikus típusok műveletei 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 mindhárom műveletnek publikusnak kell lennie 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 ELTE IK, Alkalmazott modul: Programozás 9:19

Példa Feladat: Módosítsuk a verem típus úgy, hogy lehessen megfelelő mély másolatot készíteni. megvalósítjuk a másoló konstruktort és az értékadás operátort Megoldás: template <class T> // elemtípus sablonja class Stack { // verem típus private: Stack(const Stack<T>& other); Stack<T>& operator=(const Stack<T>& other); ELTE IK, Alkalmazott modul: Programozás 9:20

Példa Megoldás: template <class T> Stack<T>::Stack(const Stack& other) { _size = other._size; // átmásoljuk az egyszerű értékeket _top = other._top; } _values = new T[_size]; // létrehozzuk a dinamikus tömböt for (int i = 0; i < _top; i++) _values[i] = other._values[i]; // átmásoljuk a hasznos értékeket ELTE IK, Alkalmazott modul: Programozás 9:21

Példa Megoldás: template <class T> Stack<T>& Stack<T>::operator=(const Stack<T>& other) { if (this == &other) // amennyiben a két memóriacím megegyezik return *this; // nem kell semmit csinálni } delete[] _values; // eddig használt dinamikus tömb törlése return *this; ELTE IK, Alkalmazott modul: Programozás 9:22

Indexelés Saját típusainkhoz lehetőségünk van indexelő ([]) operátort készíteni az indexelő operátornak 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) ELTE IK, Alkalmazott modul: Programozás 9:23

Indexelés Pl.: class MyType { private: int _values[100]; // értékek tömbje public: 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 } ELTE IK, Alkalmazott modul: Programozás 9:24

Példa 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 az indexelő operátor biztosítja ELTE IK, Alkalmazott modul: Programozás 9:25

Példa Megoldás: template <class T> class vector { // dinamikus vektor típusa public: vector(int size = 0); // konstruktor vector(const vector<t>& other); // másoló konstruktor ~vector(); // destruktor void push_back(t value); // elem beszúrása a vektor végébe T pop_back(); // utolsó elem törlése int size() const; // méretlekérdezés void clear(); // kiürítés ELTE IK, Alkalmazott modul: Programozás 9:26

Példa Megoldás: T& operator[](int index); // indexelő operátor beírásra T operator[](int index) const; // indexelő operátor lekérdezésre vector<t>& operator=(const vector<t>& other); // értékadás enum Exceptions { SIZE_INVALID, VECTOR_EMPTY, INDEX_OUT_OF_RANGE }; // kivételek private: void resize(int newcapacity); // tömb átméretezése ELTE IK, Alkalmazott modul: Programozás 9:27

Példa Megoldás: T* _values; // értékek tömbjének mutatója int _size; // vektor aktuális mérete int _capacity; // vektor kapacitása (teljes mérete) }; template <class T> T& vector<t>::operator[](int index) { if (index < 0 index >= _size) // ellenőrizzük az indexet throw INDEX_OUT_OF_RANGE; return _values[index]; } ELTE IK, Alkalmazott modul: Programozás 9:28

Típusok dinamikus kezelése Saját típusainkat is létrehozhatjuk, illetve törölhetjük dinamikusan: <típusnév> *<mutatónév> = new <típusnév>; delete <mutatónév>; amennyiben a saját típusunk konstruktorparaméterekkel rendelkezik, azokat meg kell adnunk a létrehozáskor: <mutatónév> = new <típusnév>(<paraméterek>); Továbbra is lehetőségünk van hivatkozni a típusunk adattagjaira (*<mutatónév>).<tagnév> formában a zárójel az operátor precedencia miatt kell mivel ez elég összetett jelölés, lehet egyszerűsíteni a -> operátorral: <mutatónév>-><tagnév> ELTE IK, Alkalmazott modul: Programozás 9:29

Típusok dinamikus kezelése Pl.: struct MyType { int value; void print() { cout << Value; } MyType() { Value = 0; } // konstruktorok MyType(int v) { Value = v; } }; MyType *d1, *d2; // mutató létrehozása d1 = new MyType; // példányosítás konstruktorral d1->print(); // 0, ugyanez: (*d1).print() d2 = new MyType(10); // paraméteres konstruktorral d2->print(); // 10 delete d1; delete d2; // törlések ELTE IK, Alkalmazott modul: Programozás 9:30

Láncolás A típuson belül lehetőségünk a típusnak a mutatóját, azaz egy reflexív mutatót mezőként elhelyezni, pl.: struct MyType { MyType* mypointer; // mutató ugyanarra a típusra } MyType mt; mt.mypointer = new MyType; // a mutatóra ráhelyezhetünk egy új példányt mt.mypointer->mypointer = new MyType; // annak a mutatójára is ráhelyezhetünk egy // új példányt ELTE IK, Alkalmazott modul: Programozás 9:31

Láncolás A reflexív mutatók segítségével összeállított elemek sorozatát nevezzük láncolt sorozatnak, ha pedig adatszerkezet elemeit valósítjuk meg így, akkor a struktúrát láncolt adatszerkezetnek a láncolt adatszerkezet elemei olyan rekordok, amelyek tartalmaznak legalább egy mutatót a saját típusra, e mentén láncolhatóak a láncolás előnye, hogy a láncba könnyű beszúrni/kitörölni elemet, tehát tetszőleges ponton módosítható a lánc a láncolt adatszerkezet pontosan annyi elemet tárol, mint amennyit ténylegesen hasznosítunk, így nincs felesleges memóriafoglalás (a rekordban lévő mutatókon kívül) ELTE IK, Alkalmazott modul: Programozás 9:32

Láncolás Pl.: struct MyRecord { int value; MyRecord* next }; MyRecord * r = new MyRecord; r->value = 1; // mezők beállítása r->next = NULL; r 1 i next ELTE IK, Alkalmazott modul: Programozás 9:33

Láncolás Pl.: struct MyRecord { int value; MyRecord* next }; MyRecord * r = new MyRecord; r->value = 1; // mezők beállítása r->next = NULL; r->next = new MyRecord; // új rekord r r->next 1 i next i next ELTE IK, Alkalmazott modul: Programozás 9:34

Láncolás Pl.: struct MyRecord { int value; MyRecord* next }; MyRecord * r = new MyRecord; r->value = 1; // mezők beállítása r->next = NULL; r->next = new MyRecord; // új rekord r->next->value = 2; // új rekord mezői r->next->next = NULL; r r->next 1 2 0 i next i next ELTE IK, Alkalmazott modul: Programozás 9:35

Láncolás bejárása A láncolt adatszerkezet bejárása (pl. másolásnál) nem történhet indexeléssel, hiszen a memóriában tetszőleges helyen helyezkedhetnek el az elemek, ezért mutatót kell használnunk a mutatót beállítjuk az első elemre addig haladunk, amíg NULL értékre nem lépünk a következő elem mutatóját használjuk a lépéshez pl.: for (MyRecord* p = r; p!= NULL; p = p->next){ // a p mutatóval lépkedünk előre az r által // mutatott láncon cout << p->value << endl; } ELTE IK, Alkalmazott modul: Programozás 9:36

Láncolt adatszerkezetek Láncolt adatszerkezetek esetén létre kell hozni az elemtípust is általában egyszerű rekord (struct) beágyazva deklaráljuk, azaz a típuson belül, pontosabban a rejtett elemek között (így csak a típuson belül lesz használható) A láncolt adatszerkezet mindig csak mutatót tárol, erre hozzuk létre dinamikusan az elemeket másolásnál egyenként kell átmásolni az értékeket az újonnan lefoglalt elemekbe törlés esetén ügyelni kell, hogy minden elemet megsemmisítsünk ELTE IK, Alkalmazott modul: Programozás 9:37

Verem láncolt megvalósítása A verem adatszerkezetet is meg lehet valósítani láncolással, itt a verem mutatója a legfelső elemre (top) mutat az adatszerkezetben, és azt követik a továbbiak ha fel szeretnénk venni egy új elemet (push), akkor a többi elem elé kell tennünk a láncban, azaz létrehozzuk az új rekordot, ráfűzzük a többit, és ráállítjuk a verem mutatóját a verem mutatóján át hivatkozhatunk a tetőelemre (top) ha ki szeretnénk venni a tetőelemet (pop), akkor egy segédváltozóval ki kell emelnünk az értéket, majd a veremből ki kell venni az első rekordot ehhez újabb segédváltozó kell, amit törlünk, miután a veremmutatót átállítottuk ELTE IK, Alkalmazott modul: Programozás 9:38

Verem láncolt megvalósítása A verem reprezentációja: top Beszúrás a verembe: top Kivétel a veremből: top ELTE IK, Alkalmazott modul: Programozás 9:39

Példa Feladat: Valósítsuk meg a verem adatszerkezetet láncolt reprezentációval. megvalósítjuk a veremelem típust (StackItem), amely tárolja az adatot és a következő elem mutatóját a típusban csak a tetőelem mutatóját (_top) és a méretet (_size) tároljuk el, utóbbi csak a méretlekérdezéshez szükséges beszúrásnál dinamikusan létrehozzuk az elemet, kivételnél töröljük a kiürítés (és a destruktor) voltaképpen a törlés alkalmazása az összes elemre ELTE IK, Alkalmazott modul: Programozás 9:40

Példa Megoldás: template <class T> // elemtípus sablonja class Stack { // verem típus private: struct StackItem { // veremelem típusa, mint beágyazott típus T _value; // a tárolt érték StackItem* next; // következő elem mutatója }; }; StackItem* _top; // a tetőelem mutatója int _size; // méret (csak a lekérdezéshez kell) ELTE IK, Alkalmazott modul: Programozás 9:41

Példa Megoldás: template <class T> void Stack<T>::push(T value) { StackItem* item = new StackItem; // létrehozzuk az új elemet item->_value = value; // beállítjuk az értékét item->next = _top; // ráhelyezzük a lánc eddigi részét _top = item; // berakjuk az elejére _size++; } ELTE IK, Alkalmazott modul: Programozás 9:42

Példa Megoldás: template <class T> T Stack<T>::pop() { if (_size > 0) { // ha van elem T data = _top->_value; // lekérdezzük az elemet StackItem* temp = _top; // segédmutató (a törléshez) _top = _top->next; // átállítjuk az első elemet delete temp; // kitöröljük az elemet _size--; return data; // visszaadjuk az értéket ELTE IK, Alkalmazott modul: Programozás 9:43

Reprezentációja Az aritmetikai (tömbös) reprezentáció előnyei: az elemek egymás után helyezkednek el, ezért indexelhetőek nincs szükség további mutató tárolására az elemek behivatkozására a műveletek könnyen megfogalmazhatóak A láncolt ábrázolás előnyei: mindig annyi helyfoglalás történik, ahány elem van tetszőleges ponton bővíthető/módosítható az adatszerkezet nincs költsége az átméretezésnek a láncolás több irányba is történhet ELTE IK, Alkalmazott modul: Programozás 9:44