1/29. Standard Template Library. Template ek

Méret: px
Mutatás kezdődik a ... oldaltól:

Download "1/29. Standard Template Library. Template ek"

Átírás

1 A cikksorozat célja, hogy felkeltse az érdeklődést az STL (Standard Template Library) iránt, ami egy egyszerűen használható template alapú algoritmus és adatszerkezet gyűjtemény. Az STL segítségével gyorsabb, áttekinthetőbb, és bugmentesebb programot lehet írni C++ nyelven. Ma már szinten minden C++ fordító támogatja a különféle STL verziókat. A cikksorozat célja, hogy felkeltse az érdeklődést az STL (Standard Template Library) iránt, ami egy egyszerűen használható template alapú algoritmus és adatszerkezet gyűjtemény. Az STL segítségével gyorsabb, áttekinthetőbb, és bug mentesebb programot lehet írni C++ nyelven. Ma már szinten minden C++ fordító támogatja a különféle STL verziókat. A sorozat elsősorban gyakorlati oldaláról közelít az STL hez, bemutatja a főbb tárolók használatát, és érint egy két lényeges algoritmust is, valamint a cikksorozat végén gyakorlati példákat ad a használatukra. A cikkben szereplő példákat a GNU C (g++ 3 SGI STL) illetve a free Borland C ös fordítóval (Rogue Wave STL) teszteltem. Standard Template Library A szoftverfejlesztés során általában nem új algoritmusokat és adatszerkezeteket kell kitalálni, hanem a már meglévők közül kell valamilyen szempontból optimálist kiválasztani. Többféle cél alapján optimalizálhatunk a tervezés során, például lehetséges memóriára, sebességre, fejlesztési időre, egyszerűségre, robosztusságra és így tovább. Sokszor, egyszerűbb esetekben azonban a lustaság (a jó programozó lusta : )), vagy az ismereteink szabják meg a kiválasztott adatszerkezetet, illetve algoritmust. Például egy buborékrendezést (bubble sort) bármelyikünk kapásból meg tudna írni, azonban, az általános esetekre optimálisabb, gyorsrendezést (quicksort) már nem mindegyikünk tudná egyből hibátlanul implementálni. Vagy könnyebben használunk egy fix méretű tömböt, semmint egy dinamikusan növekedő illetve zsugorodó tömböt, esetleg láncolt listát, hogy csak az egyszerűbb lehetőségeket említsem, és a fix méretű tömbbel esetleg buffer overrun típusú hibákat rakhatunk egy programban. A bonyolultabb adatszerkezetek és algoritmusok használatának elősegítésében a fejlesztőeszközök is nyújtanak valamilyen segítséget. Például már a K&R féle C ben is könyvtári függvény volt a qsort, bsearch illetve a lsearch, amelyek paraméterezése azonban a C nyelv szépségeihez és lehetőségeihez illően eléggé trükkös mutató konverziókat tesz szükségessé és ezzel kevésbé gyakorlott C programozók számára hibalehetőségeket teremt. Template ek A C++ nyelv e problémák megoldására a generikus programozás lehetőségét nyújtja, a templatek segítségével, amelyek leegyszerűsítve felfoghatók úgy is, mint típusokkal és értékekkel paraméterezett típusok és eljárások. Példaképpen az egyik legegyszerűbb templatet nézzük meg. Biztos mindnyájan találkoztunk már a min makróval, melyekkel két érték közül tudjuk a kisebbet kiválasztani. #define min(a, b) ((a)<(b)? (a) : (b)) Azonban e makró használata során nem kellő odafigyelés esetén, a szöveghelyettesítés miatt, esetleg könnyen írhatunk olyan kódot, ami nem azt teszi, mint aminek látszik. Például mi lesz az a, a b és a c változó értéke? int a=1, b=2, c=min(a++,--b); E mellékhatást ki tudjuk kerülni, ha függvényként írnánk meg, azonban így annyi függvényt kéne 1/29

2 írni, ahány típusra szeretnénk használni a függvényt. Ebben nyújthat segítséget a template ként implementált min függvény, aminek definíciója: template <class T> const T& min(const T& a, const T& b) return (a<b? a : b); Egy kis magyarázat: a paramétereket azért referenciaként veszi át, mivel így kimarad a copy konstruktor hívása, és ezért referencia a visszatérési típus is. A const pedig arra szolgál, hogy használni lehessen a függvény hívásának helyén csak konstansként elérhető változókra is copy konstruktor hívása nélkül. Ez a template egyedül azt követeli meg a típustól, hogy értelmezve legyen rá a kisebb operátor, azaz olyan típusokra tudjuk használni, ami vagy beépítve tartalmazza ezt, mint például az int, double stb., vagy létezik publikus kisebb operátora, amelyik ráadásul const típusú. Azaz például a következő struktúrára szintén lehet használni a min template függvényt: struct Dummy int a; int b; bool operator < (const Dummy& O) const return (a<o.a (a==o.a && b<o.b)); // operator < ; Vagy például két változó értékét kicserélő függvény template alapú implementációja: template <class T> void swap(t& a, T& b) T c = a; // copy constructor a = b; // operator = b = c; // operator =... int a=1, b=2;... swap(a, b); Ez a template azt követeli meg a típustól, hogy jól működő copy konstruktora, destruktora és egyenlőség operátora legyen, más elvárása nincsen. Jó template eket nem túl könnyű írni, mivel ha az ember nem ismeri jól a C++ nyelvet, akkor esetleg olyan dolgokat is megkövetelhet, ami valójában az adott template működése szempontjából felesleges lenne, vagy esetleg nem lesz hatékony a generált kód. Példaképpen nézzük meg, hogy milyen plusz metódusokat igényelnek az alábbi, nem túl hatékony implementációk: template <class T> T minworst(t a, T b) // copy constructor 2* 2/29

3 T RetVal; // constructor if (a<b) // operator < RetVal = a; // operator = else RetVal = b; // operator = return RetVal; // copy constructor // destructor 3* template <class T> T minbad(t a, T b) // copy constructor 2* return ((a<b)? a : b); // operator<, copy constructor // destructor 2* Az STL Az STL azaz a Standard Template Library egy a templatekre épülő adatszerkezet és algoritmus gyűjtemény. Többféle implementációjával lehet találkozni és különféle C++ fordítók alatt működik. Ebből adódóan az egyszer megszerzett tudás és gyakorlat nagy valószínűséggel használható lesz egy másik C++ fordító alatt is. Mivel jól megtervezett és felépített a könyvtár, ezért a kezdeti nehézségeken túljutva könnyen tudjuk használni az esetleg még nem használt új funkciókat is. A különféle implementációk, ahogy már megszokhattuk, a lehetőségeket nem mind implementálják, vagy esetleg plusz lehetőségeket is tartalmaznak. Például a C++ Builderben található (a free Borland C is ugyanezt tartalmazza) mellékelt Rogue Wave féle STL nem tartalmazza a hash alapú tárolókat, de például lehetőség van a memóriafoglalás paraméterezésére define okon keresztül. (Csak elvileg, mert gyakorlatilag pont ebből a részből hiányzik egy ";" karakter, azaz egy kis patch kell hozzá). Az STL t több részre fel lehet osztani: Tárolók Iterátorok Algoritmusok E cikk keretében elsősorban a különféle tárolókkal és a hozzájuk kapcsolódó iterátorokkal fogok foglalkozni. Minden egyes esetben gyakorlati példákon szemléltetve használatukat. Az ismertetésre kerülő tárolók: vector deque list set, multiset map, multimap Minden tárolókban tárolt típussal szemben követelmény a megfelelő copy konstruktor, a destruktor, az operator =, valamint a reference és dereference operátor. 3/29

4 Iterátorokról dióhéjban Az iterátorok szerepe a különféle tárolók adataihoz történő hozzáférés biztosítása. Fajtájukat tekintve léteznek egyirányú, kétirányú, konstans, nem konstans, normál/fordított irányú, stb. iterátorok. Az STL ben megtalálható iterátorfajtákat nem ismertetem részletesen, de a példák során bemutatom használatukat. Az iterátoroknak általában létezik konstans és nem konstans, valamint normál és fordított irányú verziójuk is. A példákban szereplő iterátorok főbb operátorai: Operátor Funkció ++ a következő elemre lép az előző elemre lép * az iterátor által "mutatott" adatot adja vissza == azonos e a két iterátor!= különböző e a két iterátor A véletlen elérésűeknél értelmezett még az összeadás, kivonás hasonlóan a mutatókhoz, illetve némelyiknél az operator >, amivel szintén az adattagot lehet elérni. Ezek alapján egy általános, bármely tároló tartalmát kiíró template et már könnyű írni, feltéve, hogy az adattagra értelmezett a kiírás. Az alábbi függvény szépsége az, hogy akár egy pointer párra is meghívható. #include <iostream> #include <typeinfo> using namespace std; template <class T> void printall(const T& beg, const T& end) cout<<typeid(t).name()<<endl; for (T i = beg; i!=end; i++) cout<<*i<<endl; main() int tomb[] = 1,2,3,4,5,6; printall(tomb+0, tomb+sizeof(tomb)/sizeof(tomb[0])); Közvetlen elérésű iterátorral rendelkező tárolók vector A vector osztály egy dinamikusan nyújtózkodó, illetve zsugorodó C típusú tömbnek fogható fel. Indexelése is ehhez hasonlóan 0 tól a mérete (size()) mínusz egyig terjed. Előnyösen használható bármikor a dinamikusan foglalt memória helyett, ha a jellemző művelet a tömb végéhez új elemek hozzáadása illetve elvétele, és fontos a direkt elérés. A memória felszabadításról az osztály illetve a fordító együttesen gondoskodik, azaz kivétel (exception) fellépte esetén is biztosan felszabadítja a lefoglalt memóriát (nincs több memory leak). A memória allokációs algoritmusa általában mivel 4/29

5 egyes STL verziónkban esetleg külön szabályozható mindig duplázza a lefoglalt memóriát, ha a méret növelésére van szükség, hogy ezzel is minimalizálja a növelésből adódó másolás overhead jét, valamint némely verzióban egy minimális területből indul ki, azaz ha csak egy elemet tartalmaz a vector, akkor is legalább lefoglal memóriát n darabnak, hogy ezzel is csökkentse a kezdeti másolások számát. A memóriafoglalást manuálisan is lehet szabályozni, a reserve() függvénnyel. A vector iterátora valójában egy mutató az elemre, a vector tartalmát a begin() és end() iterátor közötti folytonos memória területen lehet elérni. Létezik egy specializált vector osztály is, a vector<bool>, amelynek memória kezelése kihasználja, hogy egy bool érték ábrázolható egy biten is, és ezért a lefoglalt memória is sokkal kisebb lesz. Erre azonban már nem igaz az, hogy az iterátora egy pointer. Néhány példa a vector template használatára. #include <iostream> #include <vector> #include <algorithm> using namespace std; template <class T> void printall(const T& beg, const T& end) for (T i = beg; i!=end; i++) cout<<*i<<' '; cout<<endl; const char HW[] = "Hello world!\n"; main() // üres vector vector<char> vc1; // vector a Hello world! -al vector<char> vc2(hw+0, HW+sizeof(HW)/sizeof(HW[0])); // kiírás printall(vc2.begin(), vc2.end()); // sorbarendezése sort(vc2.begin(), vc2.end()); // kiírás printall(vc2.begin(), vc2.end()); // "!Hdellloorw" // keresés rendezett tömbben >= -re vector<char>::iterator pc; pc = lower_bound(vc2.begin(), vc2.end(), 'm'); if (pc!=vc2.end()) cout<<"found:'"<<*pc<<"'"<<endl; else cout<<"not found"<<endl; // 100 méretű vector vector<int> vi(5); // feltöltése 5/29

6 for (int i=0; i<5; i++) vi[i] = 9-i; // hozzáadás for (int i=5; i<10; i++) vi.push_back(9-i); printall(vi.begin(), vi.end()); // " " // egy részének sorbarendezése sort(vi.begin()+5, vi.end()); printall(vi.begin(), vi.end()); // " " deque A deque hasonlít a vectorhoz, annyi különbséggel, hogy az implementációja miatt mindkét végén, azaz az elején és a végén is, hatékony mind a beszúrás, mind a törlés művelet. A fenti példában a vector t kicserélve deque ra szintén működő kódot kapunk. Ebből is látható, hogyha az igények nőnek, akkor egy helyesen megírt kódot elég könnyen tovább lehet fejleszteni egy nagyobb tudású tárolóra. Egy lényeges különbsége van: mivel a deque egy körkörös buffert tartalmaz az implementáció során, ezért az iterátora nem egy pointer típus, azaz ha valahol szükség van erre, ott csak a vectort lehet használni. A list template egy kétirányú láncolt listás adatábrázolást valósít meg. Ebből adódnak az előnyei és a hátrányai is. Az elemeket csak szekvenciálisan lehet elérni, azaz ha szükség van az n edik elemre, akkor ehhez először le kell kérjük az elsőt, majd n 1 szer a következőre kell lépnünk, hogy elérjük az n ediket. A törlés és a beszúrás költsége konstans, mivel nincs szükség soha a listában szereplő értékek másolására, csak a mutatók átállítására. Visszacsatolás Az előző cikkben bennmaradt egy pontatlanság, amit gondolom néhányan észre is vettek. A deque implementációja fix méretű lefoglalt pufferekből áll. Egy deque lehetséges állapotát az első ábra szemlélteti. 1. ábra 2. ábra A deque ban középen elhelyezkedő pufferek mindig teljesen fel vannak töltve, így a pointer 6/29

7 aritmetika gyors lehet. Ha a végére vagy az elejére kell új elemeket hozzáadni, akkor legrosszabb esetben is csak egy új puffert kell lefoglalni, és a pointer táblában kell másolást végrehajtani. Ha törlési műveletet végzünk a legelején, illetve legvégén, akkor legrosszabb esetben el kell dobni a legutolsó, illetve legelső blokkot. Ha pedig se nem az elejére, se nem a végére vonatkozik a művelet, akkor a meglévő adat egy részét kell másolni a közelebb lévő végéhez, amit a második ábra szemléltet. Látható, hogy a törlés után a piros színű adat "előtt" lévő adatok "feljebb" másolódtak, míg a sárga színű adat esetén a "mögötte" lévő adatokat "lejjebb" másolódtak. Ebből is látható, hogy optimálisabb lehet a deque használata a legtöbb esetben, a vector osztály helyett. Sőt a memória allokáció / sebesség viszonya is kedvezőbb lehet, mivel a vector vagy duplázza mindig a méretét, vagy fix mérettel növeli. Ha duplázza, akkor elég nagy adatterület mehet veszendőbe, ha már nagy méretű a vector, ha pedig fix mérettel növeli, akkor pedig lassú lehet a folyamatos növelése a vectornak a sok másolás miatt. Az STL val foglalkozó dokumentációk általában megemlítik, hogy ha nincs igény arra, hogy az iterátor castolható legyen egy mutatóra, akkor mindig a deque t célszerű használni a vector helyett. Előnyként jelentkezik, hogy a deque iterátora nem válik érvénytelenné akkor, ha csak az elején illetve a végén végzünk műveleteket, és nem töröljük az iterátor által címzett adatot, míg a vector a memória újrafoglalás miatt ezt nem tudja biztosítani. list A list template egy kétirányú láncolt listás adatábrázolást valósít meg. Ebből adódnak az előnyei és a hátrányai is. Az elemeket csak szekvenciálisan lehet elérni, azaz ha szükség van az n edik elemre, akkor ehhez először le kell kérjük az elsőt, majd n 1 szer a következőre kell lépnünk, hogy elérjük az n ediket. A törlés és a beszúrás költsége konstans, mivel nincs szükség soha a listában szereplő értékek másolására, csak a mutatók átállítására. Egy list elemének járulékos memóriaigénye két mutató egy a lista előző és egy a következő elemére. Ennek az adatszerkezetnek megvan az az előnye, hogy az iterátorok nem válnak érvénytelenné a beszúrás/törlés hatására, nem úgy, mint a vector illetve a deque esetén. A STL tartalmaz egy sort metódust is a listhez, mivel a generikus sort algoritmus véletlen elérésű iterátort vár, illetve néhány hasznos függvényt rendezett listákra. A vectoros példaprogram list alapú implementációja: #include <iostream> #include <list> #include <algorithm> #include <functional> using namespace std; const char HW[] = "Hello world!\n"; main() // üres list list<char> lc1; // lista a Hello world! -al list<char> lc2(hw+0, HW+sizeof(HW)/sizeof(HW[0])); 7/29

8 // kiírás copy(lc2.begin(), lc2.end(), ostream_iterator<char,char>(cout," ")); cout<<endl; // sorbarendezése lc2.sort(); // kiírás copy(lc2.begin(), lc2.end(), ostream_iterator<char,char>(cout," ")); // "!Hdellloorw" cout<<endl; // keresés rendezett list-ben >= -re (nem kisebbre) list<char>::iterator pc; pc = find_if(lc2.begin(), lc2.end(), bind1st(less<char>(), 'm')); if (pc!=lc2.end()) cout<<"found:'"<<*pc<<"'"<<endl; else cout<<"not found"<<endl; // 5 méret? list list<int> li(5), li1; list<int>::iterator pi; // feltöltése pi=li.begin(); for (unsigned int i=0; i<li.size(); i++, pi++) *pi = 9-i; pi = li.end(); pi--; // hozzáadás for (int i=5; i<10; i++) li.push_back(9-i); copy(li.begin(), li.end(), ostream_iterator<int,char>(cout," ")); // " " cout<<endl; // egy részének sorbarendezése // 1. kivágom a sorbarendezendő részt li1.splice(li1.end(), li, ++pi, li.end()); copy(li.begin(), li.end(), ostream_iterator<int,char>(cout," ")); // "98765" cout<<endl; copy(li1.begin(), li1.end(), ostream_iterator<int,char>(cout," ")); // "43210" cout<<endl; // 2. sorbarendezem a kivágottat li1.sort(); copy(li1.begin(), li1.end(), ostream_iterator<int,char>(cout," ")); // "01234" cout<<endl; // 3. visszaillesztem a végére li.splice(li.end(), li1); 8/29

9 copy(li.begin(), li.end(), ostream_iterator<int,char>(cout," ")); // " " cout<<endl; Amint látható ez a megoldás már egy fokkal bonyolultabb, és kevésbé hatékony, mint a vector alapú implementáció. Például az 'm' betűnél nagyobb egyenlő keresése itt lineáris kereséssel működik, szemben a lower_bound ban implementált bináris kereséssel. Kevés elemszám esetén e kettő sebessége között azonban minimális a különbség. Ezért is fontos, hogy ismerjük a lehetőségeket, és azok közül ki tudjuk választani, a célnak leginkább megfelelőt. Nincs általánosan jó megoldás. Ha például egy olyan struktúrát akarunk tárolni, aminek a copy constructora időigényes művelet, és nem biztosítható, hogy nem kell törölni illetve beszúrni a tároló közepére, akkor célszerűbb lehet kerülni a vector és a deque tárolót. Azonban ha kevés elem van, akkor célszerűbb lehet az egyszerűbb, rövidebben kódolható, ergo hibamentesebb megoldást választani, függetlenül esetleg az implementáló adatszerkezet bonyolultságára. stack, queue A stack (LIFO), queue (FIFO) nem külön adatszerkezetek, hanem csak egy viselkedés implementálása más adatszerkezetek segítségével. Alapértelmezett esetben mindkettő a deque t használja az implementáció során, azonban el lehet ettől térni. A queue esetén nem célszerű használni a vectort, mivel utóbbi használata esetén nem túl hatékony a pop művelet, ami a vector elejéről töröl elemet, és ennek hatására a vector teljes tartalma másolásra kerül. A stack illetve a queue főbb műveletei: Művelet jelentés stack esetén jelentése queue esetén bool empty() const üres e üres e unsigned size() hány elem van benne const hány elem van benne T& top() a legutoljára beletett elem referenciáját adja vissza push(const T&) egy új elemet helyez el egy új elemet helyez el void pop() a legutoljára beletett elemet a legrégebben beletett elemet eltávolítja eltávolítja T& front() a legrégebben beletett elem referenciáját adja vissza T& back() a legutoljára beletett elem referenciáját adja vissza Az alábbi egyszerű kifejezés kiértékelő szemlélteti a stack egy lehetséges használatát (lásd még 9/29

10 #include <iostream> #include <vector> #include <deque> #include <stack> #include <Exception> using namespace std; class ExprEvalError : public exception private: vector<char> Error; public: ExprEvalError(const char *in_error) while (*in_error) Error.push_back(*in_Error++); Error.push_back('\0'); const char * what () const return Error.begin(); ; class ExprEval private: enum TOperations opadd, opsub, opmul, opdiv, opneg, opvalue ; deque<long int> Values; deque<toperations> Ops; void Expr(const char* &expr, const int Level); void skipspaces(const char* &expr) while (*expr==' ' *expr=='\n' *expr=='\r' *expr=='\t') expr++; public: 10/29

11 ExprEval(const char* expr); long int operator() () const; ; // a Level jelzi a precedenciát void ExprEval::Expr(const char* &expr, const int Level) skipspaces(expr); switch (Level) case 0: // '+' '-' Expr(expr, Level+1); while (*expr=='+' *expr=='-') TOperations op = (*expr++=='+'? opadd : opsub); Expr(expr, Level+1); Ops.push_back(op); case 1: // '*' '/' Expr(expr, Level+1); while (*expr=='/' *expr=='*') TOperations op = (*expr++=='/'? opdiv : opmul); Expr(expr, Level+1); Ops.push_back(op); case 2: // '-' if (*expr=='-') expr++; Expr(expr, Level+1); Ops.push_back(opNeg); else Expr(expr, Level+1); case 3: // '(' Expr ')', ertek if (*expr=='(') Expr(++expr, 0); if (*expr++!=')') throw ExprEvalError("')' missing in expression"); else // parse number only [0..9]+ form if (*expr=='\0') 11/29

12 throw ExprEvalError("Not terminated correctly," " or empty expression"); long int Value = 0; while (*expr>='0' && *expr<='9') // not too perfect Value = Value*10 + (*expr++ - '0'); Values.push_back(Value); Ops.push_back(opValue); skipspaces(expr); ExprEval::ExprEval(const char* expr) Expr(expr, 0); if (*expr!='\0') char * ErrorStr = "Unexpected character ' ' in expression."; char * c = ErrorStr; while (*c!='\'') c++; c++; *c = *expr; throw ExprEvalError(ErrorStr); long int ExprEval::operator()() const stack<long int> EvalStack; long int V2; deque<long int>::const_iterator vi = Values.begin(); for (deque<toperations>::const_iterator opi = Ops.begin(); opi!= Ops.end(); opi++) switch (*opi) case opadd: V2 = EvalStack.top(); EvalStack.pop(); EvalStack.top() += V2; case opsub: V2 = EvalStack.top(); EvalStack.pop(); EvalStack.top() -= V2; case opmul: V2 = EvalStack.top(); EvalStack.pop(); EvalStack.top() *= V2; case opdiv: V2 = EvalStack.top(); EvalStack.pop(); 12/29

13 EvalStack.top() /= V2; case opneg: EvalStack.top() *= -1; case opvalue: EvalStack.push(*vi++); return EvalStack.top(); main() try cout << ExprEval(" / 3 + -(60-59) * 7")() << endl; catch (ExprEvalError &e) cerr << e.what() << endl; cout << endl; A következő fejezetben az asszociatív tárolókat fogom bemutatni, és azok segítségével kibővítem a fenti kifejezés kiértékelőt, változók függvények kezelésével. A számítástechnikában nagyon fontos szerepet töltenek be a hierarchikus adatszerkezetek, melyeknek egyik talán legismertebb reprezentációja a könyvtárszerkezet. Az STL ben többféle hierarchikus adatszerkezet található, ezek közül ismertet néhányat ez a cikk. Bevezetés A számítástechnikában nagyon fontos szerepet töltenek be a hierarchikus adatszerkezetek. Egyik talán legismertebb reprezentációja a könyvtárszerkezet, amely a tároló eszközökön található erőforrások elérését könnyíti meg. Vagy például az adatbázis kezelők működésében is kitüntetett szerepe van a B fa néven ismert indexszerkezetnek, amelyik szintén egy hierarchikus adatszerkezet. Ebben a cikkben csak a rendezett bináris fával fogunk találkozni, amelynek az a jellemzője, hogy egy elemnek maximum kettő "gyereke" lehet, és valamilyen összefüggés fent áll a "szülő" és a "gyereke" i között. A bináris fák nagyon jól használhatók keresésre és rendezésre, mivel a legtöbb művelet futási idejének felső korlátja arányos a fa mélységével, ami ideális esetben lg(n), ahol n a fában található elemek száma. priority_queue A priority_queue egy speciális adatszerkezeten, a kupacon (heap) alapuló template. A kupac egy olyan bináris fa, amelyik egy tömbben van ábrázolva. Egy lehetséges állapotot a következő táblázat illetve ábra szemlélteti. 13/29

14 A kupac rendező elve az, hogy a szülő elem kisebb egyenlő (vagy nagyobb egyenlő) a gyerekeinél. Egy elem indexéből a gyerekeinek indexe, illetve a szülejének az indexe egyszerűen és gyorsan számolható: #define LEFTCHILD(i) ((i)*2+1) #define RIGHTCHILD(i) (((i)+1)*2) #define PARENT(i) (((i)-1)/2) A tömb mindig teljesen kitöltött, azaz üres hely nincs benne, ebből adódóan a fa mélysége n elem esetén lg(n). Előnye ennek a szerkezetnek, hogy bármely tömb lineáris időben kupaccá rendezhető, illetve a beszúrás és törlés művelet időigénye a fa mélységével arányos, ami lg(n). A priority_queue a beszúrás során a beszúrandó elemet elhelyezi a tömb végén, majd "felutaztatja" a helyére, törlés során, a törölt elem helyére rakja legutolsót, és a tömb méretének csökkentése után, "leutaztatja" az elemet a helyére. A "fel " illetve "leutazás" során az aktuális elem illetve gyerekei közül kiválasztja a minimális elemet (maximális elemet), és ha ez nem a szülő, akkor cserét hajt végre, és folytatja tovább ezt az algoritmust a cserében részt vevő ágon. Az implementáláshoz használható alap struktúrák, a vector és a deque. A metódusai megegyeznek a stack metódusaival. A jellemző felhasználási területe a prioritás alapú ütemezés, azaz egy általános programban nem túl gyakori a használata : ). vörös fekete fa (red black tree) A bináris fák egy nagy csoportját alkotják a bináris keresőfák. A bináris keresőfa rendező elve, hogy a szülőnél kisebb (vagy nem nagyobb, vagy nem kisebb, vagy nagyobb) elemek mind a baloldali részfában találhatók, így elég egyszerű maximum a fa mélységének megfelelő lépésszámú feladat egy elem megkeresése. Egy új elem beszúrása szintén a fa mélységével arányos lépésszámban elvégezhető. Először meg kell keresni a helyét, majd a feltételnek megfelelő üres helyre felfűzni. A törlés egy picivel bonyolultabb, de természetesen ennek a lépésszáma is a fa mélységével arányos, azaz miután megvan a törlendő elem, meg kell nézni, hogy van e bal illetve jobboldali részfája. Ha egyik sincs, akkor törölhető. Ha csak baloldali, vagy jobboldali van, akkor a gyereke kerül a helyére. Egyébként pedig a jobboldali gyerekének kell a legkisebb elemét megkeresni, és a törölt helyére áthelyezni. Egy lehetséges bináris keresőfát ábrázol a következő ábra. 14/29

15 A bináris keresőfának azonban van egy problémás tulajdonsága, könnyen előfordulhat, hogy "elfajul", azaz egy szülő baloldali részfájának a mélysége jóval nagyobb, vagy kisebb lesz, mint a jobboldalié. Sőt az is előfordulhat, hogy egy bináris keresőfa átváltozik láncolt listává, azaz ha például csak baloldali, illetve jobboldali ágak vannak benne. Ez történik például akkor, ha rendezett adatokat szúrunk egy üres fába. Ennek elkerülésére több megoldás is született, ezek közül az egyik a vörös fekete fa. Az alapműveletek nem változtak, csak kiegészültek elfajulást megelőző (kiegyensúlyozó) kóddal. A vörös fekete fa rendezőelve a következő: Minden elemnek van színe, ami vagy vörös, vagy fekete. Az üres mutató (NULL) színe fekete. Bármely vörös elem mindkét gyerekének a színe fekete. Bármely elemtől induló, üres mutatóig vezető úton a fekete csúcsok száma azonos. Ha egy fára igazak ezek a szabályok, akkor a teljesül az, hogy a fa magassága maximum kétszerese az ideális fa magasságának, ebből következően a beszúrás, törlés, keresés lépésszáma arányos lg(n) el. Az STL a vörös fekete fákat használja a rendezett asszociatív tárolók (map, multimap, set, multiset) megvalósítására. A vörös fekete fa egy eleménél a fa fenntartásához szükséges járulékos memória igény (overhead) három mutató kettő a gyerekek felé, illetve egy a szülő felé illetve egy színinformációt hordozó változó. Ez az x86 os platformon 32 bites rendszert használva 16 byte. set, multiset A set egymástól különböző objektumok tárolására, rendezésére és ezek között keresésre szolgál. A tárolt típusra vagy értelmezve kell lennie a kisebb operátornak, vagy egy összehasonlító objektumot kell átadni a konstruktorban. A set/multiset legfontosabb függvényei: Művelet Jelentése bool empty() const üres e unsigned size() hány elem van benne const pair<iterator, bool> insert(const T&) új elemet ad hozzá, és visszatér az új elemre egy iterátorral és igazzal, illetve ha nem történt hozzáadás, akkor hamissal és a megtalált elemre egy iterátorral, ami set esetén fordulhat elő akkor, ha már volt benne ilyen elem 15/29

16 size_type erase(const T&) kitörli a megadott értékű elemeket, és visszaadja, hány törlés történt void erase(iterator) kitörli a megadott elemet void clear() iterator find(const T&) const size_type count(const T&) const pair<iterator, iterator> equal_range(const T&) const iterator begin() const kiürítés megkeresi a kért elemet, multiset esetén a legkisebb ilyet megszámolja, hogy hány adott értékű elem található visszaadja a megadott értékű elemnél nagyobb egyenlő (lower_bound), nagyobb (upper_bound) intervallumot egy iterátort ad a legelső mivel rendezett a set, ezért a legkisebb elemre iterator end() const egy iterátort ad vissza a legutolsó elem utáni pozicióra A multiset abban különbözik a set től, hogy azonos értékű (azaz amelyik se nem kisebb, se nem nagyobb) elemből több is lehet benne. Például set esetén a count vagy nullát, vagy egyet ad vissza, míg multiset esetén vagy nullát, vagy nagyobb, mint nullát. map, multimap A map kulcsok, és a kulcsokhoz hozzátartozó adatok tárolására szolgál. A kulcsra ugyanaz vonatkozik, mint ami a set et alkotó adatokra, míg kulcshoz tartozó adat tetszőleges típus lehet, azonban természetesen erre is jól kell működnie a copy kontruktornak, egyenlőség operátornak és a destruktornak. Egy map felfogható úgy is, és a belső megvalósítása valójában ennek megfelelő, mint egy kulcsból és adatból álló pár (megvalósításban pair<key, Value>), amire értelmezve van az összehasonlítás operátor, ami a kulcs részt hasonlítja össze. Annyi a különbség, hogy a keresési műveleteket nem az összetett struktúrával kell meghívni, hanem csak a kulccsal. A map/multimap legfontosabb függvényei hasonlóak a set/multiset nél megismertekhez (a kulcs típusa K, az értéké V, a kulcs és érték összetett adat típusa KV :), amire van egy typedef e is a map nek value_type néven): Művelet bool empty() const unsigned size() const pair<iterator, bool> insert(const KV&) V& operator[] Jelentése üres e hány elem van benne új kulcs és érték párt ad hozzá, és visszatér az új elemre egy iterátorral és igazzal, illetve, ha nem történt hozzáadás, hamissal és a megtalált elemre egy iterátorral, ami map esetén fordulhat elő akkor, ha már volt benne ilyen kulcsú elem csak map esetén! megkeresi a megadott kulcsú elemet, és 16/29

17 (const K&) size_type erase(const K&) void erase(iterator) void clear() iterator find(const K&) visszaadja a hozzátartozó értéket; ha nem talál ilyet, akkor beilleszt egy új elemet a map be aminek a kulcsa a megadott, az értéke pedig a default konstruktor által adott érték (azaz kell hozzá a paraméterek nélküli konstruktor) kitörli a megadott kulcsú elemeket, és visszaadja, hány törlés történt kitörli a megadott elemet kiürítés const megkeresi a kért kulcsú elemet, multimap esetén a legkisebb ilyet size_type const megszámolja, hogy hány elem kulcsa egyezik meg a count(const K&) megadott kulcs értékével pair<iterator, const visszaadja a megadott kulcsú elemnél nagyobb egyenlő iterator> (lower_bound), nagyobb (upper_bound) intervallumot equal_range(con st K&) iterator begin() const egy iterátort ad a legelső mivel rendezett a map, ezért a legkisebb elemre iterator end() const egy iterátort ad vissza a legutolsó elem utáni pozicióra A map és multimap között annyi a különbség, hogy a map ben a kulcs egyedi, míg a multimap ben nem. Példák az asszociatív template k használatára A megismert asszociatív template k nagyon hasznosak tudnak lenni a mindennapi programozási munka során. Például adatbázis kezelő program írása közben biztos néhányunkban felvetődött már, hogy jó lenne az adatok egy statikus, vagy nagyon ritkán változó részét kliens (legalábbis az adatbázis kiszolgáló szempontjából) oldalon is tárolni (cache elni), és ezzel gyorsítani az alkalmazás futását. Nézzünk egy példát egy adatbázis egy táblájának a kliens oldali cache elésére: Az adatbázis táblája mondjuk, tartalmazza az országok kódját, nevét, és az ország telefonos előtagját, a területét, és az egy főre jutó GDP t, azaz a következő SQL script feleljen meg neki: create table country ( kod varchar(3) not null primary key, nev varchar(30) not null unique, telprefix varchar(10), terulet integer, GDP_p_fo numeric(15,2) -- oracle esetén number(15,2) ) Kliens oldalon tároljuk a teljes táblát, a nem kitöltött adatok helyett legyen üres string és nulla, és adjunk lehetőséget a kód és név szerinti elérésre, rendezett lista lekérése név, kód és GDP alapján. 17/29

18 Az ennek megfelelő struktúra és osztály interface: struct TCountryData string kod; string nev; string telprefix; int terulet; double GDP_p_fo; ; class TCountryCache... public: void InsorUpd(const TCountryData &Data); void Delete(const string &kod); // ha nem talált, akkor false bool Find(const string &kod, TCountryData &Data) const; // ha nem talált, akkor false bool FindByNev(const string &nev, TCountryData &Data) const; vector<tcountrydata> GetListByKod() const; vector<tcountrydata> GetListByNev() const; vector<tcountrydata> GetListByGDP() const; ; A definíció alapján szükséges egy tároló, ami tárolja az adatokat. Azt, hogy miben tároljuk ezt a struktúrát (map vagy set), inkább a kényelem szabja meg. Ha map et használunk, akkor az ország kódját kétszer tároljuk, vagy az eltárolt struktúrában nem tároljuk a kódot, és így két struktúrára van szükség (mivel nem használhatjuk a TCountryData t), de ezért cserében egyszerű keresés az adatok között kód alapján. Ha set et használunk, akkor csak egy struktúra van, amire vagy megírjuk a <operátort, vagy írunk hozzá egy kód alapján összehasonlító osztályt, de keresés esetén mindig egy teljes struktúrával kell keresni. A kód alapján, akár map, akár a set template t használjuk is, már könnyen és hatékonyan tudunk keresni, mivel ez a kulcsa a tároló struktúrának. Azonban szükség van a név alapján történő keresésre is. Erre szintén több lehetőség is létezik. Lehet a lineáris keresést használni a tároló template n, ami nem túl hatékony, de ha kevés adat van, akkor megfelelő, sőt kevés ország (kb ) esetén az egész problémát célszerűbb így megoldani, azaz deque/list/vector template segítségével tárolni az országok információit, és lineáris keresést használni. A másik kézenfekvő megoldás, hogy egy map et (ha nem egyedi az index, akkor multimap et) használunk, aminek a kulcsa az indexnek a mezőiből áll, és az adat része pedig valamilyen elérési információ a tárolt adatra. Ez lehet egy iterator (16 byte), lehet egy mutató (4 byte), de akár lehet az adat kulcsa is. Válasszuk most a mutatót használó megoldást, bár ennél a tesztpéldánál bármelyik jó lenne, mivel nincs sok adat, de sok adat esetén a járulékos memória használat (overhead) már számíthat. Ezek után nézzünk példát a map alapú implementációra: class TCountryCache private: typedef map<string, TCountryData> TData; 18/29

19 typedef map<string, const TCountryData*> TNevIdx; TData Data; TNevIdx NevIdx; // a GDP alapján történő rendezés használja struct GDPComp bool operator() (const TCountryData& x, const TCountryData &y) const return x.gdp_p_fo < y.gdp_p_fo; ; public:... void TCountryCache::InsorUpd(const TCountryData &AData) pair<tdata::iterator, bool> ir; ir = Data.insert(TData::value_type(AData.kod, AData)); if (!ir.second) // módosítás // a régi érték törlése az indexből NevIdx.erase(ir.first->second.nev); // a tárolóban az adat felülírása ir.first->second = AData; // beszúrás az indexbe is NevIdx.insert(TNevIdx::value_type(AData.nev, &(ir.first- >second))); void TCountryCache::Delete(const string &kod) TData::iterator i = Data.find(kod); if (i!= Data.end()) NevIdx.erase(i->second.nev); Data.erase(i); bool TCountryCache::Find(const string &kod, TCountryData &AData) const TData::const_iterator i = Data.find(kod); if (i!= Data.end()) AData = i->second; return (i!= Data.end()); 19/29

20 bool TCountryCache::FindByNev(const string &nev, TCountryData &AData) const TNevIdx::const_iterator i = NevIdx.find(nev); if (i!= NevIdx.end()) AData = *(i->second); return (i!= NevIdx.end()); vector<tcountrydata> TCountryCache::GetListByKod() const vector<tcountrydata> RetVal; RetVal.reserve(Data.size()); for (TData::const_iterator i = Data.begin(); i!= Data.end(); i+ +) RetVal.push_back(i->second); return RetVal; vector<tcountrydata> TCountryCache::GetListByNev() const vector<tcountrydata> RetVal; RetVal.reserve(Data.size()); for (TNevIdx::const_iterator i = NevIdx.begin(); i!= NevIdx.end(); i++) RetVal.push_back(*(i->second)); return RetVal; vector<tcountrydata> TCountryCache::GetListByGDP() const vector<tcountrydata> RetVal = GetListByKod(); sort(retval.begin(), RetVal.end(), GDPComp()); return RetVal; Vagy ugyanaz példa, de az adattároláshoz a set template-t használva (csak a különböző függvények szerepelnek): class TCountryCache private: struct TCountryDatakodComp bool operator() (const TCountryData& x, const TCountryData &y) const return x.kod < y.kod; ; typedef set<tcountrydata, TCountryDatakodComp> TData;... void TCountryCache::InsorUpd(const TCountryData &AData) 20/29

21 pair<tdata::iterator, bool> ir; ir = Data.insert(AData); if (!ir.second) // módosítás // a régi érték törlése az indexből NevIdx.erase(ir.first->nev); // a tárolóban az adat felülírása // az SGI féle STL-ben a set iterátora mindig const, szemben // például a Rogue Wave féle STL-el const_cast<tcountrydata&>(*(ir.first)) = AData; // beszúrás az indexbe is NevIdx.insert(TNevIdx::value_type(AData.nev, &(*(ir.first)))); void TCountryCache::Delete(const string &kod) TCountryData tmp; tmp.kod = kod; TData::iterator i = Data.find(tmp); if (i!= Data.end()) NevIdx.erase(i->nev); Data.erase(i); bool TCountryCache::Find(const string &kod, TCountryData &AData) const TCountryData tmp; tmp.kod = kod; TData::const_iterator i = Data.find(tmp); if (i!= Data.end()) AData = *i; return (i!= Data.end());... vector<tcountrydata> TCountryCache::GetListByKod() const vector<tcountrydata> RetVal; RetVal.reserve(Data.size()); for (TData::const_iterator i = Data.begin(); i!= Data.end(); i+ +) RetVal.push_back(*i); return RetVal;... Egy másik érdekes kis felhasználási lehetőség, ha sok string et akarunk tárolni, és az adatok között sok az ismétlődés, akkor memóriát lehet megtakarítani, ha a referencia számolt string osztályra 21/29

22 alapozva írunk egy kis segéd osztályt, amelyik eltárolja az ismétlődő stringeket. Példaképpen nézzük meg az alábbi program memóriafoglalását mindkét esetben (gcc vel fordítva, win32 platformon a memóriafoglalás aránya 1132 kb/10228 kb). #include <iostream> #include <string> #include <vector> #include <set> using namespace std; // implement singleton pattern class stringref private: set<string> strings; stringref() public: static const string& get(const string& s); ; const string& stringref::get(const string& s) static stringref sr; return *(sr.strings.insert(s).first); string getstring(int n, bool useref) string s; for (int i=0; i<n; i++) s+="a"; return (useref? stringref::get(s) : s); main(int argc) vector<string> strings(100000); if (argc==1) cout << "Using stringref::get." << endl; else cout << "Not using stringref::get." << endl; cout << "Press Enter key to continue" << endl; cin.ignore(); cout << "Running..." << endl; for (unsigned i=0; i<strings.size(); i++) strings[i] = getstring(i%100, argc==1); cout << "Test completed. Press Enter key to exit" << endl; cin.ignore(); 22/29

23 Végül a múltkori cikkben megígért kifejezés kiértékelő függvény, kibővítve változó kezeléssel és egy illetve két operandust kezelő függvényekkel. #include <iostream> #include <vector> #include <deque> #include <stack> #include <map> #include <Exception> using namespace std; class ExprEvalError : public exception private: vector<char> Error; public: ExprEvalError(const char *in_err1, const char *in_err2 = NULL) while (*in_err1) Error.push_back(*in_Err1++); while (in_err2 && *in_err2) Error.push_back(*in_Err2++); Error.push_back('\0'); const char * what () const return Error.begin(); ; typedef long int (*func1)(long int); typedef long int (*func2)(long int, long int); class ExprEval private: enum TOperations opadd, opsub, opmul, opdiv, opneg, opvalue, opvar, opfunc1, opfunc2 ; 23/29

24 union TOpData long int Value; func1 f1; func2 f2; long int* PVar; ; struct TOperation TOperations Op; TOpData Data; TOperation(TOperations AOp) Op = AOp; Data.Value = 0; ; typedef map<string, long int> tvars; typedef map<string, func1> tfunc1s; typedef map<string, func2> tfunc2s; deque<toperation> Ops; tvars vars; tfunc1s func1s; tfunc2s func2s; locale loc; void Expr(const char* &expr, const int Level); void ExprCmpx(const char* &expr); void skipspaces(const char* &expr) while (isspace(*expr, loc)) expr++; public: // a következő függvények törlik a parse-olt kifejezést void definefunc1(const string& name, func1 f); void definefunc2(const string& name, func2 f); void definevar(const string& name, long int val=0); void clear(); void parse(const char* expr); long int setvar(const string& name, long int val); long int operator() () const; ; // a Level jelzi a precedenciát void ExprEval::Expr(const char* &expr, const int Level) skipspaces(expr); 24/29

25 switch (Level) case 0: // '+' '-' Expr(expr, Level+1); while (*expr=='+' *expr=='-') TOperations op = (*expr++=='+'? opadd : opsub); Expr(expr, Level+1); Ops.push_back(op); case 1: // '*' '/' Expr(expr, Level+1); while (*expr=='/' *expr=='*') TOperations op = (*expr++=='/'? opdiv : opmul); Expr(expr, Level+1); Ops.push_back(op); case 2: // '-' if (*expr=='-') expr++; Expr(expr, Level+1); Ops.push_back(opNeg); else Expr(expr, Level+1); case 3: // '(' Expr ')', ertek if (*expr=='(') Expr(++expr, 0); if (*expr++!=')') throw ExprEvalError("')' missing in expression"); else // parse funcs, vars and numbers (only [0..9]+) ExprCmpx(expr); skipspaces(expr); void ExprEval::ExprCmpx(const char* &expr) if (*expr=='\0') throw ExprEvalError("Not terminated correctly," 25/29

26 " or empty expression"); TOperation Op(opValue); if (isdigit(*expr, loc)) Op.Data.Value = 0; while (isdigit(*expr, loc)) // not too perfect Op.Data.Value = Op.Data.Value*10 + (*expr++ - '0'); else string name; while (isalnum(*expr, loc)) name += *expr++; skipspaces(expr); if (*expr=='(') // functions Expr(++expr, 0); if (*expr == ',') // func/2 Expr(++expr, 0); if (*expr++!=')') throw ExprEvalError("')' missing in expression"); Op.Op = opfunc2; tfunc2s::iterator i = func2s.find(name); if (i == func2s.end()) throw ExprEvalError("Unknown function/2:", name.c_str()); Op.Data.f2 = i->second; else // func/1 if (*expr++!=')') throw ExprEvalError("')' missing in expression"); Op.Op = opfunc1; tfunc1s::iterator i = func1s.find(name); if (i == func1s.end()) throw ExprEvalError("Unknown function/1:", name.c_str()); Op.Data.f1 = i->second; else // variable Op.Op = opvar; tvars::iterator i = vars.find(name); if (i == vars.end()) throw ExprEvalError("Unknown variable:", name.c_str()); 26/29

27 Op.Data.PVar = &(i->second); Ops.push_back(Op); void ExprEval::parse(const char* expr) Ops.clear(); Expr(expr, 0); if (*expr!='\0') throw ExprEvalError("Unexpected character in expression:", expr); long int ExprEval::operator()() const stack<long int> EvalStack; long int V1; long int V2; if (Ops.size()==0) throw ExprEvalError("Empty expression"); for (deque<toperation>::const_iterator opi = Ops.begin(); opi!= Ops.end(); opi++) switch (opi->op) case opadd: V2 = EvalStack.top(); EvalStack.pop(); EvalStack.top() += V2; case opsub: V2 = EvalStack.top(); EvalStack.pop(); EvalStack.top() -= V2; case opmul: V2 = EvalStack.top(); EvalStack.pop(); EvalStack.top() *= V2; case opdiv: V2 = EvalStack.top(); EvalStack.pop(); EvalStack.top() /= V2; case opneg: EvalStack.top() *= -1; case opvalue: EvalStack.push(opi->Data.Value); 27/29

28 case opfunc1: EvalStack.top() = opi->data.f1(evalstack.top()); case opfunc2: V2 = EvalStack.top(); EvalStack.pop(); EvalStack.top() = opi->data.f2(evalstack.top(), V2); case opvar: EvalStack.push(*opi->Data.PVar); return EvalStack.top(); void ExprEval::definefunc1(const string& name, func1 f) if (!func1s.insert(tfunc1s::value_type(name, f)).second) throw ExprEvalError("Function/1 already exists:", name.c_str()); Ops.clear(); void ExprEval::definefunc2(const string& name, func2 f) if (!func2s.insert(tfunc2s::value_type(name, f)).second) throw ExprEvalError("Function/2 already exists:", name.c_str()); Ops.clear(); void ExprEval::definevar(const string& name, long int val) if (!vars.insert(tvars::value_type(name, val)).second) throw ExprEvalError("Variable already exists:", name.c_str()); Ops.clear(); void ExprEval::clear() Ops.clear(); func1s.clear(); func2s.clear(); vars.clear(); long int ExprEval::setvar(const string& name, long int val) long int RetVal; tvars::iterator i = vars.find(name); 28/29

29 if (i == vars.end()) throw ExprEvalError("Variable doesn't exist:", name.c_str()); RetVal = i->second; i->second = val; return RetVal; long int myabs(long int a) if (a<0) return -a; else return 0; long int mymul(long int a, long int b) return a*b; main() try ExprEval ee; ee.definevar("a"); ee.definefunc1("abs", myabs); ee.definefunc1("mul", mymul); ee.setvar("a", 2); ee.parse("a + abs(20 / 3) - abs(mul(-(60-59), 8))"); cout << ee() << endl; ee.setvar("a", 5); cout << ee() << endl; catch (ExprEvalError &e) cerr << e.what() << endl; cout << endl; Látható, hogy az STL segítségével a feladatra lehetett koncentrálni (kifejezés elemzés és kiértékelés), és a járulékos kódmennyisége minimális szinten volt tartható. Ha megnézzük a változó és függvénykezelő kódot, akkor látható, hogy milyen egyszerű volt a map segítségével megoldani ezt a feladatot, mindössze néhány sor az egész. Szinte fel sem vetődik, hogy helyes e program memória kezelése, azaz például mindig felszabadul e a lefoglalt memória, mivel erről a fordító és az STL együttesen gondoskodik. A mutató konverziók miatti hibalehetőségek száma is minimális, ami egy hasonló feladatot ellátó c programról már nem feltétlen mondható el. 29/29

C++ Standard Template Library (STL)

C++ Standard Template Library (STL) Programozási Nyelvek és Fordítóprogramok Tanszék Programozási Nyelvek I. Témák 1 STL alapok 2 STL fogalmak 3 Konténerek 4 Iterátorok 5 Funktorok C++ STL Ne fedezzük fel újra spanyolviaszt! Sok adatszerkezet/algoritmus

Részletesebben

Algoritmusok és adatszerkezetek gyakorlat 06 Adatszerkezetek

Algoritmusok és adatszerkezetek gyakorlat 06 Adatszerkezetek Algoritmusok és adatszerkezetek gyakorlat 06 Adatszerkezetek Tömb Ugyanolyan típusú elemeket tárol A mérete előre definiált kell legyen és nem lehet megváltoztatni futás során Legyen n a tömb mérete. Ekkor:

Részletesebben

Fejlett programozási nyelvek C++ Iterátorok

Fejlett programozási nyelvek C++ Iterátorok Fejlett programozási nyelvek C++ Iterátorok 10. előadás Antal Margit 2009 slide 1 Témakörök I. Bevezetés II. Iterátor definíció III. Iterátorok jellemzői IV. Iterátorkategóriák V. Iterátor adapterek slide

Részletesebben

XIII. STL. Tároló Bejáró Algoritmus. XIII.1 A vector #include <vector> #include <vector> #include <algorithm> using namespace std;

XIII. STL. Tároló Bejáró Algoritmus. XIII.1 A vector #include <vector> #include <vector> #include <algorithm> using namespace std; XIII. STL Tároló Bejáró Algoritmus #include #include using namespace std; vector vect; // a vect adatainak megadása sort(vect.begin(),vect.end()); XIII.1 A vector #include

Részletesebben

Pénzügyi algoritmusok

Pénzügyi algoritmusok Pénzügyi algoritmusok A C++ programozás alapjai Tömbök (3. rész) Konstansok Kivételkezelés Tömbök 3. Többdimenziós tömbök Többdimenziós tömbök int a; Többdimenziós tömbök int a[5]; Többdimenziós tömbök

Részletesebben

1. Alapok. Programozás II

1. Alapok. Programozás II 1. Alapok Programozás II Elérhetőség Név: Smidla József Elérhetőség: smidla dcs.uni-pannon.hu Szoba: I916 2 Irodalom Bjarne Stroustrup: A C++ programozási nyelv 3 Irodalom Erich Gamma, Richard Helm, Ralph

Részletesebben

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

STL. Algoritmus. Iterátor. Tároló. Elsődleges komponensek: Tárolók Algoritmusok Bejárók STL Elsődleges komponensek: Tárolók Algoritmusok Bejárók Másodlagos komponensek: Függvény objektumok Adapterek Allokátorok (helyfoglalók) Tulajdonságok Tárolók: Vektor (vector) Lista (list) Halmaz (set)

Részletesebben

Programozás C++ -ban

Programozás C++ -ban Programozás C++ -ban 4. Bevezetés az osztályokba 4.1 Az adatokhoz való hozzáférés ellenőrzése Egy C programban a struktúrák minden része mindig elérhető. Ugyanakkor ez nem a legkedvezőbb helyzet. Több

Részletesebben

Programozási technológia

Programozási technológia Programozási technológia Generikus osztályok Gyűjtemények Dr. Szendrei Rudolf ELTE Informatikai Kar 2018. Generikus osztályok Javaban az UML paraméteres osztályainak a generikus (sablon) osztályok felelnek

Részletesebben

Programozás C++ -ban 2007/4

Programozás C++ -ban 2007/4 Programozás C++ -ban 2007/4 1. Az adatokhoz való hozzáférés ellenőrzése Egy C programban a struktúrák minden része mindig elérhető. Ugyanakkor ez nem a legkedvezőbb helyzet. Több szempontból is hasznos

Részletesebben

Algoritmusok és adatszerkezetek gyakorlat 07

Algoritmusok és adatszerkezetek gyakorlat 07 Algoritmusok és adatszerkezetek gyakorlat 0 Keresőfák Fák Fa: összefüggő, körmentes gráf, melyre igaz, hogy: - (Általában) egy gyökér csúcsa van, melynek 0 vagy több részfája van - Pontosan egy út vezet

Részletesebben

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

Programozás alapjai C nyelv 8. gyakorlat. Mutatók és címek (ism.) Indirekció (ism) Programozás alapjai C nyelv 8. gyakorlat Szeberényi Imre BME IIT Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.11.07. -1- Mutatók és címek (ism.) Minden változó és függvény

Részletesebben

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

Programozás II. 4. Dr. Iványi Péter Programozás II. 4. Dr. Iványi Péter 1 inline függvények Bizonyos függvények annyira rövidek, hogy nem biztos hogy a fordító függvényhívást fordít, hanem inkább az adott sorba beilleszti a kódot. #include

Részletesebben

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

1. Template (sablon) 1.1. Függvénysablon Függvénysablon példányosítás Osztálysablon 1. Template (sablon) 1.1. Függvénysablon Maximum függvény megvalósítása függvénynév túlterheléssel. i n l i n e f l o a t Max ( f l o a t a, f l o a t b ) { return a>b? a : b ; i n l i n e double Max (

Részletesebben

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

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 Programozás alapjai C nyelv 8. gyakorlat Szeberényi mre BME T Programozás alapjai. (C nyelv, gyakorlat) BME-T Sz.. 2005.11.07. -1- Mutatók és címek (ism.) Minden változó és függvény

Részletesebben

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

Programozás II. 2. Dr. Iványi Péter Programozás II. 2. Dr. Iványi Péter 1 C++ Bjarne Stroustrup, Bell Laboratórium Első implementáció, 1983 Kezdetben csak precompiler volt C++ konstrukciót C-re fordította A kiterjesztés alapján ismerte fel:.cpp.cc.c

Részletesebben

A programozás alapjai előadás. [<struktúra változó azonosítók>] ; Dinamikus adatszerkezetek:

A programozás alapjai előadás. [<struktúra változó azonosítók>] ; Dinamikus adatszerkezetek: A programozás alapjai 1 Dinamikus adatszerkezetek:. előadás Híradástechnikai Tanszék Dinamikus adatszerkezetek: Adott építőelemekből, adott szabályok szerint felépített, de nem rögzített méretű adatszerkezetek.

Részletesebben

Tartalom Keresés és rendezés. Vektoralgoritmusok. 1. fejezet. Keresés adatvektorban. A programozás alapjai I.

Tartalom Keresés és rendezés. Vektoralgoritmusok. 1. fejezet. Keresés adatvektorban. A programozás alapjai I. Keresés Rendezés Feladat Keresés Rendezés Feladat Tartalom Keresés és rendezés A programozás alapjai I. Hálózati Rendszerek és Szolgáltatások Tanszék Farkas Balázs, Fiala Péter, Vitéz András, Zsóka Zoltán

Részletesebben

1. Mi a fejállományok szerepe C és C++ nyelvben és hogyan használjuk őket? 2. Milyen alapvető változókat használhatunk a C és C++ nyelvben?

1. Mi a fejállományok szerepe C és C++ nyelvben és hogyan használjuk őket? 2. Milyen alapvető változókat használhatunk a C és C++ nyelvben? 1. Mi a fejállományok szerepe C és C++ nyelvben és hogyan használjuk őket? 2. Milyen alapvető változókat használhatunk a C és C++ nyelvben? 3. Ismertesse a névtér fogalmát! 4. Mit értünk a "változó hatóköre"

Részletesebben

Globális operátor overloading

Globális operátor overloading Programozás II. 9. gyakorlat Operátor overloading 2: Unáris operátorok, globálisan megvalósított operátorok, > operátorok Kivételkezelés, IO library Globális operátor overloading Előző alkalommal

Részletesebben

Keresés és rendezés. A programozás alapjai I. Hálózati Rendszerek és Szolgáltatások Tanszék Farkas Balázs, Fiala Péter, Vitéz András, Zsóka Zoltán

Keresés és rendezés. A programozás alapjai I. Hálózati Rendszerek és Szolgáltatások Tanszék Farkas Balázs, Fiala Péter, Vitéz András, Zsóka Zoltán Keresés Rendezés Feladat Keresés és rendezés A programozás alapjai I. Hálózati Rendszerek és Szolgáltatások Tanszék Farkas Balázs, Fiala Péter, Vitéz András, Zsóka Zoltán 2016. november 7. Farkas B., Fiala

Részletesebben

Programozás alapjai II. (7. ea) C++ Speciális adatszerkezetek. Tömbök. Kiegészítő anyag: speciális adatszerkezetek

Programozás alapjai II. (7. ea) C++ Speciális adatszerkezetek. Tömbök. Kiegészítő anyag: speciális adatszerkezetek Programozás alapjai II. (7. ea) C++ Kiegészítő anyag: speciális adatszerkezetek Szeberényi Imre BME IIT M Ű E G Y E T E M 1 7 8 2 C++ programozási nyelv BME-IIT Sz.I. 2016.04.05. - 1

Részletesebben

Egyirányban láncolt lista

Egyirányban láncolt lista Egyirányban láncolt lista A tárhely (listaelem) az adatelem értékén kívül egy mutatót tartalmaz, amely a következő listaelem címét tartalmazza. A láncolt lista első elemének címét egy, a láncszerkezeten

Részletesebben

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

Programozás II gyakorlat. 8. Operátor túlterhelés Programozás II gyakorlat 8. Operátor túlterhelés Kezdő feladat Írjunk egy Vector osztályt, amely n db double értéket tárol. A konstruktor kapja meg az elemek számát. Írj egy set(int idx, double v) függvényt,

Részletesebben

Speciális adatszerkezetek. Programozás alapjai II. (8. ea) C++ Tömbök. Tömbök/2. N dimenziós tömb. Nagyméretű ritka tömbök

Speciális adatszerkezetek. Programozás alapjai II. (8. ea) C++ Tömbök. Tömbök/2. N dimenziós tömb. Nagyméretű ritka tömbök Programozás alapjai II. (8. ea) C++ Kiegészítő anyag: speciális adatszerkezetek Szeberényi Imre BME IIT Speciális adatszerkezetek A helyes adatábrázolás választása, a helyes adatszerkezet

Részletesebben

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

Bevezetés a Programozásba II 12. előadás. Adatszerkezetek alkalmazása (Standard Template Library) Pázmány Péter Katolikus Egyetem Információs Technológiai és Bionikai Kar Bevezetés a Programozásba II 12. előadás (Standard Template Library) 2014.05.19. Giachetta Roberto groberto@inf.elte.hu http://people.inf.elte.hu/groberto

Részletesebben

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

.Net adatstruktúrák. Készítette: Major Péter .Net adatstruktúrák Készítette: Major Péter Adatstruktúrák általában A.Net-ben számos nyelvvel ellentétben nem kell bajlódnunk a változó hosszúságú tömbök, listák, sorok stb. implementálásával, mert ezek

Részletesebben

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

Programozás alapjai II. (7. ea) C++ Programozás alapjai II. (7. ea) C++ Kiegészítő anyag: speciális adatszerkezetek Szeberényi Imre BME IIT M Ű E G Y E T E M 1 7 8 2 C++ programozási nyelv BME-IIT Sz.I. 2016.04.05. - 1

Részletesebben

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

Adatszerkezetek Adatszerkezet fogalma. Az értékhalmaz struktúrája Adatszerkezetek Összetett adattípus Meghatározói: A felvehető értékek halmaza Az értékhalmaz struktúrája Az ábrázolás módja Műveletei Adatszerkezet fogalma Direkt szorzat Minden eleme a T i halmazokból

Részletesebben

Elemi adatszerkezetek

Elemi adatszerkezetek 2017/12/16 17:22 1/18 Elemi adatszerkezetek < Programozás Elemi adatszerkezetek Szerző: Sallai András Copyright Sallai András, 2011, 2014 Licenc: GNU Free Documentation License 1.3 Web: http://szit.hu

Részletesebben

117. AA Megoldó Alfréd AA 117.

117. AA Megoldó Alfréd AA 117. Programozás alapjai 2. (inf.) pót-pótzárthelyi 2011.05.26. gyak. hiányzás: kzhpont: MEG123 IB.028/117. NZH:0 PZH:n Minden beadandó megoldását a feladatlapra, a feladat után írja! A megoldások során feltételezheti,

Részletesebben

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

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 A lista eleme 0 adat rész mutató rész Listaelem létrehozása p: Node 0 0 3 0 Az elemet nekünk kell bef zni a listába Deklarálás struct Node { int int value; Node* next; next; adattagok Létrehozás Node*

Részletesebben

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

Generikus osztályok, gyűjtemények és algoritmusok Programozási, gyűjtemények és algoritmusok bejárása Informatikai Kar Eötvös Loránd Tudományegyetem 1 Tartalom 1 bejárása 2 bejárása 2 Java-ban és UML-ben bejárása Az UML-beli paraméteres osztályok a Java

Részletesebben

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

OOP: Java 11.Gy: Enumok, beágyazott osztályok. 13/1 B ITv: MAN OOP: Java 11.Gy: Enumok, beágyazott osztályok 13/1 B ITv: MAN 2019.04.24 ArrayList Rugalmas tömb A tömbök korlátai Fix méret, nem lehet menet közben megnövelni Ha túl nagyra választjuk, fölösleges helyfoglalás

Részletesebben

Generikus Típusok, Kollekciók

Generikus Típusok, Kollekciók Generikus Típusok, Kollekciók Tóth Zsolt Miskolci Egyetem 2013 Tóth Zsolt (Miskolci Egyetem) Generikus Típusok, Kollekciók 2013 1 / 26 Tartalomjegyzék 1 Enumeráció 2 Generikus Típusok 3 Kollekciók System.Collections

Részletesebben

A C++ Standard Template Library rövid összefoglalás

A C++ Standard Template Library rövid összefoglalás A C++ Standard Template Library rövid összefoglalás 2016-17. 1 Miről is van szó Alább összefoglaljuk, amely ismeretét feltesszük a félév során. Mivel mint megszokott az egyes verziók több-kevesebb mértékben

Részletesebben

500. AA Megoldó Alfréd AA 500.

500. AA Megoldó Alfréd AA 500. Programozás alapjai 2. NZH 2010.05.13. gyakorlat: / Hiány:0 ZH:0 MEGOLD IB.027/51. Hftest: 0 Minden beadandó megoldását a feladatlapra, a feladat után írja! A megoldások során feltételezheti, hogy minden

Részletesebben

Dinamikus csatolású függvénykönyvtár készítése és használata Plugin-szerű betöltés Egyszeű C++ osztályok készítése

Dinamikus csatolású függvénykönyvtár készítése és használata Plugin-szerű betöltés Egyszeű C++ osztályok készítése FEJLETT PROGRAMOZÁSI NYELVEK, 2009 2. GYAKORLAT - Linux alatti C/C++ programozás Cél: Dinamikus csatolású függvénykönyvtár készítése és használata Plugin-szerű betöltés Egyszeű C++ osztályok készítése

Részletesebben

500. CC Megoldó Alfréd CC 500.

500. CC Megoldó Alfréd CC 500. Programozás alapjai 2. PótZH 2010.05.20. gyakorlat: G1/IB.146 Hiány:3 ZH:7,71 MEGOLD SCH/500. Hftest: 0 ZHp: Minden beadandó megoldását a feladatlapra, a feladat után írja! A megoldások során feltételezheti,

Részletesebben

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

STL gyakorlat C++ Izsó Tamás május 9. Izsó Tamás STL gyakorlat/ 1 STL gyakorlat C++ Izsó Tamás 2016. május 9. Izsó Tamás STL gyakorlat/ 1 Komponensek kapcsolata Deklarálja az alábbi osztálydiagramon szereplő osztályok közül az A, AA és AB osztályokat! A konstruktorokat

Részletesebben

C++ programozási nyelv Konstruktorok-destruktorok

C++ programozási nyelv Konstruktorok-destruktorok C++ programozási nyelv Konstruktorok-destruktorok Nyugat-Magyarországi Egyetem Faipari Mérnöki Kar Informatikai Intézet Soós Sándor 2004. szeptember A C++ programozási nyelv Soós Sándor 1/20 Tartalomjegyzék

Részletesebben

Programozás I. - 11. gyakorlat

Programozás I. - 11. gyakorlat Programozás I. - 11. gyakorlat Struktúrák, gyakorlás Tar Péter 1 Pannon Egyetem M szaki Informatikai Kar Rendszer- és Számítástudományi Tanszék Utolsó frissítés: November 16, 2009 1 tar@dcs.vein.hu Tar

Részletesebben

Adatszerkezetek 2. Dr. Iványi Péter

Adatszerkezetek 2. Dr. Iványi Péter Adatszerkezetek 2. Dr. Iványi Péter 1 Hash tábla A bináris fáknál O(log n) a legjobb eset a keresésre. Ha valamilyen közvetlen címzést használunk, akkor akár O(1) is elérhető. A hash tábla a tömb általánosításaként

Részletesebben

Bevezetés a programozásba 2

Bevezetés a programozásba 2 Bevezetés a programozásba 2 7. Előadás: STL konténerek, sablonok http://digitus.itk.ppke.hu/~flugi/ Vector int int main() { vector v(10); int int sum=0; for for (int i=0;i

Részletesebben

Programozás II. 2. gyakorlat Áttérés C-ről C++-ra

Programozás II. 2. gyakorlat Áttérés C-ről C++-ra Programozás II. 2. gyakorlat Áttérés C-ről C++-ra Tartalom Új kommentelési lehetőség Változók deklarációjának helye Alapértelmezett függvényparaméterek Névterek I/O műveletek egyszerűsödése Logikai adattípus,

Részletesebben

PROGRAMOZÁSI NYELVEK - CPP. GYAKORLAT JEGYZET

PROGRAMOZÁSI NYELVEK - CPP. GYAKORLAT JEGYZET PROGRAMOZÁSI NYELVEK - CPP. GYAKORLAT JEGYZET Szerkesztette: Balogh Tamás 2013. április 12. Ha hibát találsz, kérlek jelezd a info@baloghtamas.hu e-mail címen! Ez a Mű a Creative Commons Nevezd meg! -

Részletesebben

C++ programozási nyelv

C++ programozási nyelv C++ programozási nyelv Gyakorlat - 13. hét Nyugat-Magyarországi Egyetem Faipari Mérnöki Kar Informatikai Intézet Soós Sándor 2004. december A C++ programozási nyelv Soós Sándor 1/10 Tartalomjegyzék Objektumok

Részletesebben

Miről lesz ma szó? A PROGAMOZÁS ALAPJAI 1. Dinamikus adatszerkezetek. Dinamikus adatszerkezetek. Önhivatkozó struktúrák. Önhivatkozó struktúrák

Miről lesz ma szó? A PROGAMOZÁS ALAPJAI 1. Dinamikus adatszerkezetek. Dinamikus adatszerkezetek. Önhivatkozó struktúrák. Önhivatkozó struktúrák 2012. március 27. A PROGAMOZÁS ALAPJAI 1 Vitéz András egyetemi adjunktus BME Híradástechnikai Tanszék vitez@hit.bme.hu Miről lesz ma szó? Dinamikus adatszerkezetek Önhivatkozó struktúra keresés, beszúrás,

Részletesebben

3. Osztályok II. Programozás II

3. Osztályok II. Programozás II 3. Osztályok II. Programozás II Bevezető feladat Írj egy Nevsor osztályt, amely legfeljebb adott mennyiségű nevet képes eltárolni. A maximálisan tárolható nevek számát a konstruktorban adjuk meg. Az osztályt

Részletesebben

Programozás. C++ típusok, operátorok. Fodor Attila

Programozás. C++ típusok, operátorok. Fodor Attila Programozás C++ típusok, operátorok Fodor Attila Pannon Egyetem Műszaki Informatikai Kar Villamosmérnöki és Információs Rendszerek Tanszék foa@almos.vein.hu 2010. március 4. Deklaráció és definíció C++

Részletesebben

Algoritmuselmélet. 2-3 fák. Katona Gyula Y. Számítástudományi és Információelméleti Tanszék Budapesti Műszaki és Gazdaságtudományi Egyetem. 8.

Algoritmuselmélet. 2-3 fák. Katona Gyula Y. Számítástudományi és Információelméleti Tanszék Budapesti Műszaki és Gazdaságtudományi Egyetem. 8. Algoritmuselmélet 2-3 fák Katona Gyula Y. Számítástudományi és Információelméleti Tanszék Budapesti Műszaki és Gazdaságtudományi Egyetem 8. előadás Katona Gyula Y. (BME SZIT) Algoritmuselmélet 8. előadás

Részletesebben

Programozás I. 3. gyakorlat. Szegedi Tudományegyetem Természettudományi és Informatikai Kar

Programozás I. 3. gyakorlat. Szegedi Tudományegyetem Természettudományi és Informatikai Kar Programozás I. 3. gyakorlat Szegedi Tudományegyetem Természettudományi és Informatikai Kar Antal Gábor 1 Primitív típusok Típus neve Érték Alap érték Foglalt tár Intervallum byte Előjeles egész 0 8 bit

Részletesebben

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

A feladat lényege egy felhasználói típusnak a zsák típusnak a megvalósítása. Feladat Készítsen egy egész számokat tartalmazó zsák típust! A zsákot dinamikusan lefoglalt tömb segítségével ábrázolja! Implementálja a szokásos műveleteket (elem betevése, kivétele, üres-e a halmaz,

Részletesebben

Pénzügyi algoritmusok

Pénzügyi algoritmusok Pénzügyi algoritmusok A C++ programozás alapjai Sztringek Osztályok alapjai Sztringek Szöveges adatok kezelése Sztring Karakterlánc (string): Szöveges adat Karaktertömbként tárolva A szöveg végét a speciális

Részletesebben

C# nyelv alapjai. Krizsán Zoltán 1. Objektumorientált programozás C# alapokon tananyag. Általános Informatikai Tanszék Miskolci Egyetem

C# nyelv alapjai. Krizsán Zoltán 1. Objektumorientált programozás C# alapokon tananyag. Általános Informatikai Tanszék Miskolci Egyetem C# nyelv alapjai Krizsán Zoltán 1 Általános Informatikai Tanszék Miskolci Egyetem Objektumorientált programozás C# alapokon tananyag Tartalom Bevezetés Lokális változó Utasítások Szójáték Why do all real

Részletesebben

Programozás C és C++ -ban

Programozás C és C++ -ban Programozás C és C++ -ban 2. További különbségek a C és C++ között 2.1 Igaz és hamis A C++ programozási nyelv a C-hez hasonlóan definiál néhány alap adattípust: char int float double Ugyanakkor egy új

Részletesebben

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

C programozási nyelv Pointerek, tömbök, pointer aritmetika C programozási nyelv Pointerek, tömbök, pointer aritmetika Dr. Schuster György 2011. június 16. C programozási nyelv Pointerek, tömbök, pointer aritmetika 2011. június 16. 1 / 15 Pointerek (mutatók) Pointerek

Részletesebben

B-fa. Felépítés, alapvető műveletek. Programozás II. előadás. Szénási Sándor.

B-fa. Felépítés, alapvető műveletek. Programozás II. előadás.  Szénási Sándor. B-fa Felépítés, alapvető műveletek előadás http://nik.uni-obuda.hu/prog2 Szénási Sándor szenasi.sandor@nik.uni-obuda.hu Óbudai Egyetem,Neumann János Informatikai Kar B-fa Felépítése Beszúrás művelete Törlés

Részletesebben

Láncolt listák. Egyszerű, rendezett és speciális láncolt listák. Programozás II. előadás. Szénási Sándor

Láncolt listák. Egyszerű, rendezett és speciális láncolt listák. Programozás II. előadás.  Szénási Sándor Láncolt listák Egyszerű, rendezett és speciális láncolt listák előadás http://nik.uni-obuda.hu/prog2 Szénási Sándor szenasi.sandor@nik.uni-obuda.hu Óbudai Egyetem,Neumann János Informatikai Kar Láncolt

Részletesebben

Bevezetés a programozásba I.

Bevezetés a programozásba I. Bevezetés a programozásba I. 9. gyakorlat Intelligens tömbök, mátrixok, függvények Surányi Márton PPKE-ITK 2010.11.09. C++-ban van lehetőség (statikus) tömbök használatára ezeknek a méretét fordítási időben

Részletesebben

Programozás alapjai. 10. előadás

Programozás alapjai. 10. előadás 10. előadás Wagner György Általános Informatikai Tanszék Pointerek, dinamikus memóriakezelés A PC-s Pascal (is) az IBM PC memóriáját 4 fő részre osztja: kódszegmens adatszegmens stackszegmens heap Alapja:

Részletesebben

Programozás C++ -ban 2007/7

Programozás C++ -ban 2007/7 Programozás C++ -ban 2007/7 1. Másoló konstruktor Az egyik legnehezebben érthető fogalom C++ -ban a másoló konstruktor, vagy angolul "copy-constructor". Ez a konstruktor fontos szerepet játszik az argumentum

Részletesebben

Java II. I A Java programozási nyelv alapelemei

Java II. I A Java programozási nyelv alapelemei Java II. I A Java programozási nyelv alapelemei Miskolci Egyetem Általános Informatikai Tanszék Utolsó módosítás: 2008. 02. 19. Java II.: Alapelemek JAVA2 / 1 A Java formalizmusa A C, illetve az annak

Részletesebben

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

Bevezetés, a C++ osztályok. Pere László Programozás módszertan II. p. Programozás módszertan II. Bevezetés, a C++ osztályok Pere László (pipas@linux.pte.hu) PÉCSI TUDOMÁNYEGYETEM TERMÉSZETTUDOMÁNYI KAR INFORMATIKA ÉS ÁLTALÁNOS TECHNIKA TANSZÉK

Részletesebben

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

Szövegek C++ -ban, a string osztály Szövegek C++ -ban, a string osztály A string osztály a Szabványos C++ könyvtár (Standard Template Library) része és bár az objektum-orientált programozásról, az osztályokról, csak később esik szó, a string

Részletesebben

Programozási nyelvek Java

Programozási nyelvek Java Programozási nyelvek Java 11.gyakorlat Operációsrendszertől függő tulajdonságok PATH elválasztó Unix ":" Windows ";" final String PATH_SEPARATOR = File.pathSeparator; Ugyanaz, csak karakterkent final char

Részletesebben

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

Bevezetés a Programozásba II 11. előadás. Adatszerkezetek megvalósítása. Adatszerkezetek megvalósítása Adatszerkezetek 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

Részletesebben

PROGRAMOZÁSI NYELVEK - CPP. GYAKORLAT JEGYZET

PROGRAMOZÁSI NYELVEK - CPP. GYAKORLAT JEGYZET PROGRAMOZÁSI NYELVEK - CPP. GYAKORLAT JEGYZET Szerkesztette: Balogh Tamás 2013. március 31. Ha hibát találsz, kérlek jelezd a info@baloghtamas.hu e-mail címen! Ez a Mű a Creative Commons Nevezd meg! -

Részletesebben

List<String> l1 = new ArrayList<String>(); List<Object> l2 = l1; // error

List<String> l1 = new ArrayList<String>(); List<Object> l2 = l1; // error Generics Egyszerűbb példák (java.util csomagból): public interface List { void add(e x); Iterator iterator(); public interface Iterator { E next(); boolean hasnext(); E - formális típusparaméter,

Részletesebben

Felhasználó által definiált adattípus

Felhasználó által definiált adattípus Felhasználó által definiált adattípus C++ Izsó Tamás 2017. február 24. Izsó Tamás Felhasználó által definiált adattípus/ 1 Irodalom Izsó Tamás Felhasználó által definiált adattípus/ 2 Programtervezési

Részletesebben

Informatika terméktervezőknek

Informatika terméktervezőknek Informatika terméktervezőknek C# alapok Névterület (namespace) using Osztály (class) és Obejtumok Metódus (function, procedure, method) main() static void string[] arg Szintaxis // /* */ \n \t Névadások

Részletesebben

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

Bevezetés a programozásba Előadás: Tagfüggvények, osztály, objektum Bevezetés a programozásba 2 1. Előadás: Tagfüggvények, osztály, objektum Ismétlés int main() { string s; s; s= bla ; cout

Részletesebben

Programozás II gyakorlat. 6. Polimorfizmus

Programozás II gyakorlat. 6. Polimorfizmus Programozás II gyakorlat 6. Polimorfizmus Típuskonverziók C-ben: void * ptr; int * ptr_i = (int*)ptr; Ez működik C++-ban is. Használjuk inkább ezt: int * ptr_i = static_cast(ptr); Csak egymással

Részletesebben

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

Mutatók és mutató-aritmetika C-ben március 19. Mutatók és mutató-aritmetika C-ben 2018 március 19 Memória a Neumann-architektúrában Neumann-architektúra: a memória egységes a címzéshez a természetes számokat használjuk Ugyanabban a memóriában van:

Részletesebben

Láncolt Listák. Adat1 Adat2 Adat3 ø. Adat1 Adat2 ø Adat3

Láncolt Listák. Adat1 Adat2 Adat3 ø. Adat1 Adat2 ø Adat3 Láncolt Listák Adatszerkezetek Adatszerkezet: Az adatelemek egy olyan véges halmaza, amelyben az adatelemek között szerkezeti összefüggések vannak Megvalósítások: - Tömb, Láncolt lista, Fa, Kupac, Gráf,

Részletesebben

Programozás alapjai. 5. előadás

Programozás alapjai. 5. előadás 5. előadás Wagner György Általános Informatikai Tanszék Cserélve kiválasztásos rendezés (1) A minimum-maximum keresés elvére épül. Ismétlés: minimum keresés A halmazból egy tetszőleges elemet kinevezünk

Részletesebben

és az instanceof operátor

és az instanceof operátor Java VIII. Az interfacei és az instanceof operátor Krizsán Zoltán Miskolci Egyetem Általános Informatikai Tanszék Utolsó módosítás: 2005. 10. 24. Java VIII.: Interface JAVA8 / 1 Az interfészről általában

Részletesebben

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

Programozás II. 3. gyakorlat Objektum Orientáltság C++-ban Programozás II. 3. gyakorlat Objektum Orientáltság C++-ban Tartalom OOP ismétlés Osztályok létrehozása Adattagok láthatóságai, elnevezési ajánlások Konstruktor, destruktor this pointer Statikus és dinamikus

Részletesebben

Algoritmizálás + kódolás C++ nyelven és Pascalban

Algoritmizálás + kódolás C++ nyelven és Pascalban Algoritmizálás + kódolás nyelven és ban Motiváció A Programozási alapismeretek tárgyban az algoritmizáláshoz struktogramot, a kódoláshoz nyelvet használunk, a Közismereti informatikában (a közoktatásban

Részletesebben

Java VIII. Az interfacei. és az instanceof operátor. Az interfészről általában. Interfészek JAVA-ban. Krizsán Zoltán

Java VIII. Az interfacei. és az instanceof operátor. Az interfészről általában. Interfészek JAVA-ban. Krizsán Zoltán Java VIII. Az interfacei és az instanceof operátor Krizsán Zoltán Miskolci Egyetem Általános Informatikai Tanszék Utolsó módosítás: 2005. 10. 24. Java VIII.: Interface JAVA8 / 1 Az interfészről általában

Részletesebben

OOP #14 (referencia-elv)

OOP #14 (referencia-elv) OOP #14 (referencia-elv) v1.0 2003.03.19. 21:22:00 Eszterházy Károly Főiskola Információtechnológia tsz. Hernyák Zoltán adj. e-mail: aroan@ektf.hu web: http://aries.ektf.hu/~aroan OOP OOP_14-1 - E jegyzet

Részletesebben

500. DD Megoldó Alfréd DD 500.

500. DD Megoldó Alfréd DD 500. Programozás alapjai 2. (inf.) zárthelyi 2009.05.21. gyakorlat: / Érdemjegy: QBX734 () IB319/32. Hftest: Minden beadandó megoldását a feladatlapra, a feladat után írja! A megoldások során feltételezheti,

Részletesebben

Programozási Nyelvek (C++) Összefoglaló

Programozási Nyelvek (C++) Összefoglaló Programozási Nyelvek (C++) Összefoglaló Somogyi Krisztián gondozásában 2009-12-22 1. tétel: Fordítás [fordítási egység; warning; error; g++ kapcsolók] A teljes programot általában lehetetlen egy fájlban

Részletesebben

A számítástudomány alapjai. Katona Gyula Y. Számítástudományi és Információelméleti Tanszék Budapesti Műszaki és Gazdaságtudományi Egyetem

A számítástudomány alapjai. Katona Gyula Y. Számítástudományi és Információelméleti Tanszék Budapesti Műszaki és Gazdaságtudományi Egyetem A számítástudomány alapjai Katona Gyula Y. Számítástudományi és Információelméleti Tanszék Budapesti Műszaki és Gazdaságtudományi Egyetem Bináris keresőfa, kupac Katona Gyula Y. (BME SZIT) A számítástudomány

Részletesebben

5. Gyakorlat. struct diak {

5. Gyakorlat. struct diak { Rövid elméleti összefoglaló 5. Gyakorlat Felhasználó által definiált adattípusok: A typedef egy speciális tárolási osztály, mellyel érvényes típusokhoz szinonim nevet rendelhetünk. typedef létező_típus

Részletesebben

Programozási nyelvek Java

Programozási nyelvek Java Programozási nyelvek Java Kozsik Tamás előadása alapján Készítette: Nagy Krisztián 13. előadás Throwable Error Exception RuntimeException IOException Saját (általában) Nem ellenörzött kivételek (Unchecked

Részletesebben

Pénzügyi algoritmusok

Pénzügyi algoritmusok Pénzügyi algoritmusok A C++ programozás alapjai Az Integrált Fejlesztői Környezet C++ alapok Az Integrált Fejlesztői Környezet Visual Studio 2013 Community Edition Kitekintés: fordítás Preprocesszor Fordító

Részletesebben

Gelle Kitti Algoritmusok és adatszerkezetek gyakorlat - 07 Hasítótáblák

Gelle Kitti Algoritmusok és adatszerkezetek gyakorlat - 07 Hasítótáblák Algoritmusok és adatszerkezetek gyakorlat - 07 Hasítótáblák Gelle Kitti 2017. 10. 25. Gelle Kitti Algoritmusok és adatszerkezetek gyakorlat - 07 Hasítótáblák 2017. 10. 25. 1 / 20 Hasítótáblák T 0 h(k 2)

Részletesebben

Láncolt listák. PPT 2007/2008 tavasz.

Láncolt listák. PPT 2007/2008 tavasz. Láncolt listák szenasi.sandor@nik.bmf.hu PPT 2007/2008 tavasz http://nik.bmf.hu/ppt 1 Témakörök Láncolt listák elvi felépítése Egyirányú egyszerű láncolt lista Egyirányú rendezett láncolt lista Láncolt

Részletesebben

1. Öröklés Rétegelés Nyilvános öröklés - isa reláció Korlátozó öröklődés - has-a reláció

1. Öröklés Rétegelés Nyilvános öröklés - isa reláció Korlátozó öröklődés - has-a reláció 1. Öröklés Az objektum orientált tervezés fontos sarkköve, az osztályok viszonyainak a megtervezése. 1.1. Rétegelés c l a s s Address {..... c l a s s Name {..... c l a s s P e r s o n { Name name ; Address

Részletesebben

félstatikus adatszerkezetek: verem, várakozási sor, hasítótábla dinamikus adatszerkezetek: lineáris lista, fa, hálózat

félstatikus adatszerkezetek: verem, várakozási sor, hasítótábla dinamikus adatszerkezetek: lineáris lista, fa, hálózat Listák félstatikus adatszerkezetek: verem, várakozási sor, hasítótábla dinamikus adatszerkezetek: lineáris lista, fa, hálózat A verem LIFO lista (Last In First Out) angolul stack, románul stivă bevitel

Részletesebben

C# Nyelvi Elemei. Tóth Zsolt. Miskolci Egyetem. Tóth Zsolt (Miskolci Egyetem) C# Nyelvi Elemei / 18

C# Nyelvi Elemei. Tóth Zsolt. Miskolci Egyetem. Tóth Zsolt (Miskolci Egyetem) C# Nyelvi Elemei / 18 C# Nyelvi Elemei Tóth Zsolt Miskolci Egyetem 2013 Tóth Zsolt (Miskolci Egyetem) C# Nyelvi Elemei 2013 1 / 18 Tartalomjegyzék 1 Object 2 Típusok 3 String 4 RegEx Tóth Zsolt (Miskolci Egyetem) C# Nyelvi

Részletesebben

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

Bevezetés a programozásba II. 5. Előadás: Másoló konstruktor, túlterhelés, operátorok Bevezetés a programozásba II 5. Előadás: Másoló konstruktor, túlterhelés, operátorok Emlékeztető struct Vektor { int meret, *mut; Vektor(int meret); int szamlal(int mit); }; int Vektor::szamlal(int mit)

Részletesebben

10. előadás Speciális többágú fák

10. előadás Speciális többágú fák 10. előadás Adatszerkezetek és algoritmusok előadás 2018. április 17., és Debreceni Egyetem Informatikai Kar 10.1 A többágú fák kezelésére nincsenek általános elvek, implementációjuk elsősorban alkalmazásfüggő.

Részletesebben

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

Statikus adattagok. Statikus adattag inicializálása. Speciális adattagok és tagfüggvények. Általános Informatikai Tanszék Speciális adattagok és tagfüek Miskolci Egyetem Általános Informatikai Tanszék CPP7 / 1 Statikus adattagok Bármely adattag lehet static tárolási osztályú A statikus adattag az osztály valamennyi objektuma

Részletesebben

Challenge Accepted:C++ Standard Template Library

Challenge Accepted:C++ Standard Template Library Challenge Accepted: C++ Standard Template Library ELTE Informatikai Kar, Programozási Nyelvek és Fordítóprogramok Tanszék patakino@elte.hu Szakmai Esti Mesék C++ Standard Template Library Felépítése konténerek:

Részletesebben

Programozás C++ -ban

Programozás C++ -ban 8. Dinamikus objektumok Programozás C++ -ban Ahhoz hogy általános prolémákat is meg tudjunk oldani, szükség van arra, hogy dinamikusan hozhassunk létre vagy szüntethessünk meg objektumokat. A C programozási

Részletesebben

A szemantikus elemzés helye. A szemantikus elemzés feladatai. A szemantikus elemzés feladatai. Deklarációk és láthatósági szabályok

A szemantikus elemzés helye. A szemantikus elemzés feladatai. A szemantikus elemzés feladatai. Deklarációk és láthatósági szabályok A szemantikus elemzés helye Forrásprogram Forrás-kezelő (source handler) Lexikális elemző (scanner) A szemantikus elemzés feladatai Fordítóprogramok előadás (A, C, T szakirány) Szintaktikus elemző (parser)

Részletesebben

Alprogramok, paraméterátadás

Alprogramok, paraméterátadás ELTE Informatikai Kar, Programozási Nyelvek és Fordítóprogramok Tanszék October 24, 2016 Programozási nyelvek Alprogramok Függvények, eljárások Metódusok Korutinok stb. Alprogramok Alprogram: olyan nyelvi

Részletesebben

Dinamikus láncolt lista 4. GYAKORLAT

Dinamikus láncolt lista 4. GYAKORLAT Dinamikus láncolt lista 4. GYAKORLAT Szekvenciális adatszerkezet A szekvenciális adatszerkezet olyan rendezett pár, amelynél az R reláció tranzitív lezártja teljes rendezési reláció. Szekvenciális

Részletesebben