Standard Template Library. Adatstruktúrák és algoritmusok a C++ nyelvhez

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

Fejlett programozási nyelvek C++ Iterátorok

C++ Standard Template Library (STL)

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

Bevezetés a programozásba 2

C++11 TÓTH BERTALAN C++ PROGRAMOZÁS STL KONTÉNEREKKEL

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

500. AA Megoldó Alfréd AA 500.

500. CC Megoldó Alfréd CC 500.

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

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

500. DD Megoldó Alfréd DD 500.

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

Programozási technológia

Generikus Típusok, Kollekciók

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?

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.

Fejlett programozási nyelvek C++ Sablonok és adatfolyamok

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

Algoritmusok és adatszerkezetek gyakorlat 06 Adatszerkezetek

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

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

C++ Standard Template Library

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

1. Bevezetés A C++ nem objektumorientált újdonságai 3

Bevezetés a programozásba I.

117. AA Megoldó Alfréd AA 117.

Challenge Accepted:C++ Standard Template Library

128. AA Megoldó Alfréd AA 128.

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

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

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

1.AA MEGOLDÓ BERCI AA 1.

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

1. Alapok. Programozás II

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

3. Osztályok II. Programozás II

.AA Megoldó Alfréd AA.

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

228. AA Default Konstruktor AA 228.

503.AA Megoldo Arisztid 503.A

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

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

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

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.

Dinamikus láncolt lista 4. GYAKORLAT

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

Collections. Összetett adatstruktúrák

Maximum kiválasztás tömbben

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

C++ Gyakorlat jegyzet 10. óra.

Programozás II. 6.Öröklés Dr. Iványi Péter

PROGRAMOZÁSI NYELVEK - CPP. GYAKORLAT JEGYZET

S02-3 Multiparadigma programozás és Haladó Java 2

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

feladat pont min elért

Programozás C++ -ban 2007/4

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

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

1000.AA Megoldo Alfréd 1000.A

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

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

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

500.AA Megoldo Arisztid 500.A

Komputeralgebra Rendszerek

111. AA Megoldó Alfréd AA 111.

Smalltalk 2. Készítette: Szabó Éva

Pénzügyi algoritmusok

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

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

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

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

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

Programozás módszertan

Programozás C++ -ban 2007/7

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

Bevezetés a programozásba Előadás: A const

Pénzügyi algoritmusok

Bevezetés a programozásba Előadás: Objektumszintű és osztályszintű elemek, hibakezelés

Programozás C++ -ban

Ugrólisták. RSL Insert Example. insert(22) with 3 flips. Runtime?

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

C++ programozási nyelv

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

C++ programozási nyelv Konstruktorok-destruktorok

Pénzügyi algoritmusok

Bevezetés a programozásba. 11. Előadás: Esettanulmány

Globális operátor overloading

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

OOP #14 (referencia-elv)

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

PROGRAMOZÁSI NYELVEK - CPP. GYAKORLAT JEGYZET

Programozás C++ -ban

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

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

C++ Gyakorlat jegyzet 7. óra

end function Az A vektorban elõforduló legnagyobb és legkisebb értékek indexeinek különbségét.. (1.5 pont) Ha üres a vektor, akkor 0-t..

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

5. Gyakorlat. struct diak {

INFORMATIKA javítókulcs 2016

Átírás:

Standard Template Library Adatstruktúrák és algoritmusok a C++ nyelvhez

Bevezetés A Hewlett-Packard Company által fejlesztett sablonkönyvtár -> bekerült a C++98-ba Általánosított osztály- és függvénysablonokat tartalmaz a leggyakrabban alkalmazott adatstruktúrák és algoritmusok használatára Standard Template Library Programmer's Guide: http://www.sgi.com/tech/stl/ Tóth Bertalan: C++ programozás STL konténerekkel http://www.zmgzeg.sulinet.hu/bemutatkozunk/tan konyv/progismhalado/ccpp/c11stl.pdf

Az STL részei Konténerek (tárolók) - adatstruktúrák Iterátorok (bejárók) Algoritmusok - az adattárolók elemeinek elérése - az alapvető algoritmusok megvalósítása (sorba rakás, keresés, szélsőértékek )

Az STL részei Konténerek Allokátorok Helyfoglaló Iterátorok Adapterek Illesztő Algoritmusok Funktorok Függvényobjektum (functors) Adapter tárolók Adatfolyamok (stream) String adatstruktúrára alapozott egyszerű kezelésű adatstruktúrák I/O C++

Példa Tároló Bejáró Algoritmus #include <vector> #include <algorithm> using namespace std; vector<int> vect; // a vect adatainak megadása sort(vect.begin(),vect.end());

Tárolók Soros array<> vector<> deque<> forward_list<> list<> Az elemek sorrendjét a tárolás sorrendje határozza meg. Rendezett set<> multiset<> map<> multimap<> Asszociatív Nem rendezett unordered_set<> unordered_multiset<> unordered_map<> unordered_multimap<> Az adatokat egy kulccsal azonosítva tárolják.

Az STL elemek fejállományai Leggyakoribb elemek Algoritmusok: rendezés, keresés, másolás stb. Asszociatív tárolók: rendezett halmazok (elemismétlődéssel multiset, illetve elemismétlődés nélkül - set) Asszociatív tárolók: kulcs/érték adatpárok kulcs szerint rendezett tárolása 1:1 (map), illetve 1:n (multimap) kapcsolatban Asszociatív tárolók: nem rendezett halmazok (elemismétlődéssel unordered_multiset, illetve elemismétlődés nélkül unordered_set) Asszociatív tárolók: kulcs/érték adatpárok nem rendezett tárolása (elemismétlődéssel unordered_multimap, illetve elemismétlődés nélkül unordered_map) Függvényobjektumok ( function(), bind() ) Iterátorelemek, előre definiált iterátorok, adatfolyam-iterátorok Műveleti elemek, move(), swap(), a pair (adatpár) struktúra Numerikus műveletek a konténerekben tárolt adatokon Soros tároló adapter: verem (statck) Soros tároló adapterek: sor (queue), prioritásos sor (priority_queue) Soros tároló: egydimenziós statikus tömb (array) Soros tároló: egyirányú lineáris lista (forward_list) Soros tároló: kétirányú lineáris lista (list) Soros tároló: kettősvégű sor (deque) Soros tároló: egydimenziós dinamikus tömb (vector) Fejállomány <algorithm> <set> <map> <unordered_set> <unordered_map> <functional> <iterator> <utility> <numeric> <stack> <queue> <array> <forward_list> <list> <deque> <vector>

Soros és asszociatív tárolok tulajdonságai mindegyiknek van default és copy (értékekre) konstruktora, = operátora, a.swap(b) tagfüggvénye és swap(a,b) algoritmusa, == és!= operátora (azonos elemek azonos sorrendben), sorrendiség (az első nem azonos elem határozza meg), begin() bejáró a kezdetre (rbegin() a kétirányúnál ), end() bejáró a végére (rend() a kétirányúnál), size() méret, empty() üres? maxsize() maximálisan tárolható elemszám tagok (értékek, referenciák, const referenciák, bejárók (vissza is)), konstans bejárók (vissza is), helyzet-különbségek, méretek)

A vector: #include <vector> Elemek sorban (dinamikus tömbökkel megvalósítva) Folytonos adatterületen pointerrel és bejáróval is bejárható Automatikusan növekszik és csökken a tárolási mérete Az elemek könnyen elérhetők pozíció alapján (állandó idővel) Az elemek sorban bejárhatók (lineáris idővel) Elemek illeszthetők/törölhetők a végéről (konstans idővel) Elemek beilleszthetők és törölhetők is, azonban erre mások (deque, list) jobb időt produkálnak Memóriamodell:

A vector: #include <vector> Konstruktorok (vector<tip>) // üres tip típusú vektor vector<tip> vektor_0; vector<tip> vektor_0 {}; // db elemű vektor a típus alapértelmezett elemeivel vector<tip> vektor_1 (db); // db elemű vektor ertek elemekkel vector<tip> vektor_2 (db,ertek); // inicializáló lista alapján vector<tip> vektor_3 {init. lista}; // iterátor vektor-ból [begin,end) tartomány átmásolásával vector<tip> vektor_4 (vektor.begin(), vektor.end()); vector<tip> vektor_4 {vektor.begin(), vektor.end()}; // másolás vektor-ból (másoló konstruktor) vector<tip> vektor_5 (vektor); vector<tip> vektor_5 {vektor}; // átmozgatás vektor-ból vector<tip> vektor_5 (move(vektor)); vector<tip> vektor_5 {move(vektor)};

A vector: #include <vector> Bejárók (vector<tip>::iterator) vector<tip>::iterator v; // iterátora begin() // kezdet end() // vég 1 2 3 3 2 1 vector<tip>::reverse_iterator rv; // fordított irányú iterátor rbegin() // vissza kezdet rend() // vissza vég &v[0] (*v) v++ rv++ // pointer a memóriára // maga a vektor elem, mintha pointer lenne // következő elemre lépés // fordított irány esetén is ez adja a következő // elemet nem a rv--

A vector: #include <vector> Tulajdonságok operator[i], at(i) // az i. elem, at() ellenőriz is front() // az első elem referenciája back() // az utolsó elem referenciája tip* data() // visszaadja az első elem pointerét C++11 Méretek size() resize(n[,val]) capacity() reserve(n) Módosítók push_back(val) pop_back() // az elemek aktuális száma // n-re méretez val [vagy default] elemmel feltöltve // a férőhelyek száma (automatikusan is nő) // a férőhelyek számának növelése n-re // a val az utolsó elem mögé kerül // törli az utolsó elemet és visszatér az értékével // adott pozícióba helyez, nem hatékony iterator insert ( iterator position, const T& x )

A vector: #include <vector> Törlés bool empty ( ) const; erase(iterator tol, iterator ig) void clear() // üres-e // tol ig töröl // mindent töröl Keresés (#include <algorithm>) vector<tip>::iterator find(vector< tip>::iterator tol, vector< tip >::iterator ig, tip adat); vector<tip>::iterator search(vector< tip>::iterator tol, vector< tip >::iterator ig, vector< tip >::iterator elemtol, vector< tip >::iterator elemig); bool binary_search(vector< tip>::iterator tol, vector< tip >::iterator ig, tip ert); Műveletek elvégzése elemeken fvtip for_each(vector< tip>::iterator tol, vector< tip >::iterator ig, fvtip fvg);

A vector: #include <vector> A konténer elemeinek bejárása iterátorok segítségével: vector<int> vect {20,30,40,50}; vector<int>::iterator v; for (v = begin(vect); v!= vect.end(); v++) cout << *v << endl; v = begin(vect); while(v!= vect.end()) { cout << *(v++) << endl; } for (auto v2 = begin(vect); v2!= vect.end(); v2++) cout << *v2 << endl; //C++11

A vector: #include <vector> A konténer elemeinek bejárása iterátorok nélkül: for (auto elem: vect) // csak olvasható C++11 cout << elem << endl; for (auto& elem: vect) // írható/olvasható C++11 elem+=10; A konténer elemeinek bejárása for_each segítségével: void myfunc(int elem) { cout << elem << endl; } // elemeket kiíró függvény vector<int> vect {20,30,40,50}; for_each (vect.begin(), vect.end(), myfunc); //fgv. meghívása az elemekre

A vector: #include <vector> Megjegyzések: A beírás elrontja az iterátorokat: vector<int>::iterator beg = vect.begin(); vector<int>::iterator end = vect.end(); vect.push_back(12); vector<int>::iterator p=find(beg, end,12); Szükséges hely bővítése: // elrontja // futási hiba Ha ismert az elemek száma, akkor mindig használjuk a mérettel rendelkező konstruktort, mert ha új elem behelyezésekor elfogy a lefoglalt hely, akkor automatikusa átméreteződik (új helyre másolódik) a tartalom, ez nagy elemszám esetén belassítja a működést. vector<int> vect; for (int i = 0; i < 1000; i++) { vect.push_back(i); // üres vektor kerül bővítésre // bővítés cout << "merete:"<<vect.size()<<" helye:"<<vect.capacity()<< endl; } // másolások száma: 18

#include <stdlib.h> #include <vector> #include <algorithm> #include <iostream> using namespace std; void myfunc (int i) { cout << " " << i; } int main(){ vector<int> vect(2,0); vect[0]=1; // a vect adatainak megadása 1 vect[1]=2000; for (int i=0; i<8; i++) // a vect adatainak megadása 2 vect.push_back((i+1)*5); // a vect adatainak kiírása 1 vector<int>::iterator vit; // iterator vectorra for (vit=vect.begin(); vit!=vect.end(); vit++) cout<<*(vit)<<endl; cout<<endl; cout<<"merete:"<<vect.size()<<" helye:"<<vect.capacity()<<endl; //10 13 // a vect adatainak kiírása 2 for (int i=0; i<vect.size(); i++) cout<<vect[i]<<endl; cout<<endl; sort(vect.begin(),vect.end()); // rendező algoritmus // a vect adatainak kiírása 3 C++11 for (auto& elem : vect) cout << elem << endl; cout<<endl; // keresés vector<int>::iterator it = find (vect.begin(), vect.end(), 2000); if (it!= vect.end()) cout << "van: " << *(it) << endl; // a vect adatainak kiírása 4 for_each (vect.rbegin(), vect.rend(), myfunc); // 2000 40 35 30 25 20 15 10 5 1 int *p = vect.data(); // az első elemre mutató pointer lekérdezése C++11 return 0;}

Az array: #include <array> C típusú tömb osztályba foglalása C++11-ben Létrehozás: array<tip,méret> Elemek sorban meghatározott elemszámmal foglalnak helyet Folytonos adatterületen pointerrel és bejáróval is bejárható Az elemek könnyen elérhetők pozíció alapján (állandó idővel) Az elemek sorban bejárhatók (lineáris idővel) Memóriamodell: Előnye a hagyományos tömbbel szemben, hogy rendelkezik bejáróval és tagfüggvényekkel, valamint alkalmazhatók rá az algoritmusok.

Az array: #include <array> Hátránya, hogy függvényeknél a típusnak és a méretnek is egyeznie kell. //Összeg fgv. csak 10 elemű int típusú array-ra double szum(array<int, 10> a) { double szum = 0; for (int i = 0; i < 10; i++) szum += a[i]; return szum; } array<int, 10> tomb; tomb.fill(20); szum(tomb); //eltérő méret esetén fordítási hiba

A deque: #include <deque> Kétősvégű sor, amely mindkét végén növelhető Konstans idő alatt adhatunk hozzá, illetve távolíthatunk el elemet a sor végeiről: push_front(val), pop_front() Nem folytonos adatterületen helyezkedik el (nincs capacity() és reserve(n)), egydimenziós tömböt tartalmazó listában tárolódik Az elemek könnyen elérhetők pozíció alapján (állandó idővel) Az elemek sorban bejárhatók (lineáris idővel) Lassabb, mint a sor (queue) Memóriamodell:

Az egyszeres láncolatú lista: #include <forward_list> Csak az elején lehet bővíteni: push_front(val) Az elemek nem érhetőek el az indexelés operátorral (nincs [] és at()) Tetszőleges pozícióba beszúrhatunk (insert_after()) és törölhetünk (erase_after()) konstans idő alatt A beszúrás és törlés művelet nem rontja el az iterátorokat Memóriamodell:

A list: #include <list> Kétirányban láncolt lista, mindkét végéhez hozzáadhatunk és törölhetünk elemeket Az elemek nem érhetőek el az indexelés operátorral (nincs [] és at()) Tetszőleges pozícióba beszúrhatunk (insert()) és törölhetünk (erase()) konstans idő alatt A beszúrás és törlés művelet nem rontja el az iterátorokat Memóriamodell:

A list: #include <list> Tagfüggvényei: lst1.splice(i1,lst2) // lst2 összes elem törlődik és lst1-be // insertálódik i1-től lst1.merge(lst2) // sorba rendezett listák összefésülése lst1.sort() // növekvő sorba rendezés lst1.sort(hasonlító) // sorba rendezés Hasonlító fgv.objektum szerint lst1.revers() // sorrend megfordítása lst1.remove(adat) // minden adat értékű elem törlése lst1.unique() // egymást követő ismétlődő elemek törlése iterator insert (iterator position,const value_type& val); //beszúrás Egyszerű példa: persze: int-el mindig, minden működik Joe list<int> lista1{ 10, 5, 8, 23, 8 }; lista1.sort();//5 8 8 10 23 lista1.unique(); // 5 8 10 23 list<int> lista2{ 0, 15, 8, 23, 8 }; lista2.sort(); //0 8 8 15 23 lista2.merge(lista1); //0 5 8 8 8 10 15 23 23 lista1 üres lett lista2.insert(lista2.begin(), 34); // 34 0 5 8 8 8 10 15 23 23 lista1.splice(lista1.begin(), lista2); // lista2 üres lett

Összetettebb példa: class Auto{ private: string tipus; string rendszam; public: Auto(string tip, string rsz) :tipus(tip), rendszam(rsz){}; void Kiir() const { cout << tipus << "\t" << rendszam << endl; } string Rszam() const {return rendszam;} string Tipus() const {return tipus;} bool operator < (const Auto& masik) const { return tipus < masik.tipus;} bool operator == (const Auto& masik) const { return tipus == masik.tipus;} }; bool AutotHasonlit(const Auto& bal, const Auto& jobb) { //rendező függvény return bal.rszam() < jobb.rszam(); } list<auto> Kocsik{ { "Volvo", "DFR-356" }, { "Renault", "MER-637" } }; Kocsik.push_back(Auto("Opel", "HIK-123")); Kocsik.push_front(Auto("Suzuki", "GDS-145")); Kocsik.push_front(Auto("Suzuki", "GDS-145")); Kocsik.push_front(Auto("Opel", "MKL-785")); list<auto>::iterator it; for (it = Kocsik.begin(); it!= Kocsik.end(); it++) it->kiir(); Kocsik.sort(); // Sorba rendezés az alapértelmezett < operátorral for (it = Kocsik.begin(); it!= Kocsik.end(); it++) it->kiir(); Kocsik.sort(AutotHasonlit); // Sorba rendezés függvénnyel, rendszám alapján for (it = Kocsik.begin(); it!= Kocsik.end(); it++) it->kiir(); Kocsik.unique(); // Azonos elemek törlése == operátorral for (it = Kocsik.begin(); it!= Kocsik.end(); it++) it->kiir();

Asszociatív tárolók A hozzáférés nem az elem pozíciója, hanem egy kulcs értéke alapján történik. Rendezett konténer esetén a műveletek általában logaritmikus végrehajtási idejűek Minden lehetséges kulcsérték legalább egyszer előfordul. Léteznek kulcsismétlést megengedő változatok (multiset, multimap), a keresés ebben az esetben lineáris végrehajtási idejű

A set #include <set> A tárolt adatokat kulcsként használja set esetén a kulcsoknak egyedinek kell lennie multiset esetén ismétlődhetnek a kulcsok Konstruktorok (set<tip,compare>) set<tip> set_0; // üres (tip1) típusú set tip tomb[]= {t0, t1, t2}; set<tip> set_1(tomb,tomb+3); // iteratív pointerekkel set<tip> set_2(set_1.begin(),set_1.end()); // iterációs létrehozás set<tip> set_3(set_1); // másoló konstruktor // Lehet definiálni az összehasonlítást default: std::less<tip> Bejárók (set<tip>::iterator) begin() // kezdet end() // vég rbegin() // vissza kezdet rend() // vissza vég set<tip>::iterator m; (*m) // maga az elem, mintha pointer lenne 1 3 5 6 7 1 3 3 7 7

A set #include <set> Méretek size() max_size() Módosítók insert(iterator,const tip & x); Törlés bool empty ( ) const; erase(iterator tol, iterator ig) clear() Keresések (#include <algorithm>) NINCS operator[] // az elemek aktuális száma // az elemek maximális száma // beszúr // üres-e // tol ig töröl // mindent töröl set<tip>::iterator find(const tip& x); // az adott kulcsú elem size_type count ( const key_type& x ) const; //adott elem száma pair<itb,ite> equal_range ( const key_type& x ); //adott kulcsú elem tartománya iterator lower_bound ( const key_type& x ); // nem kisebb, mint x elem iterátora iterator upper_bound ( const key_type& x ); // nagyobb, x elem iterátora

A set #include <set> Tárolása bináris fájlként történik Elem beszúrása: 7 ->

A set #include <set> Példák: set<int> set_0; int tomb[] = { 8, 3, 10, 1 }; set<int> set_1(tomb, tomb + 4); set<int> set_2(set_1.begin(), set_1.end()); set<int> set_3(set_1); // üres (int) típusú set // iteratív pointerekkel // iterációs létrehozás // másoló konstruktor set<int>::iterator it_s; for (it_s = set_1.begin(); it_s!= set_1.end(); it_s++) // set elemek kiírása cout << " " << *it_s; // 1 3 8 10 cout << endl; cout << "size:" << set_1.size() << endl; // meret 4 cout << "maxsize:" << set_1.max_size() << endl; // max meret 214748364 set_1.insert(set_1.begin(), 6); // beilleszt az 1. helyre for (it_s = set_1.begin(); it_s!= set_1.end(); it_s++) cout << (*it_s) << endl; // 1 3 6 8 10 if (set_1.find(10)!= end(set_1)) // tartalmaz 10-et cout << set_1.count(10) << " db. 10-es" << endl; // 1 db. 10-es pair<set<int>::iterator,set<int>::iterator> par = set_1.equal_range(20); cout<<"a 6-nal nem kisebb kulcsu elem:"<<(*par.first) << endl; //6 cout<<"a 6-nal nem kisebb kulcsu elem:"<<(*set_1.lower_bound(20)) << endl; //6 cout<<"a 6-nal nagyobb kulcsu elem:"<<(*par.second) << endl; //8 cout<<"a 6-nal nagyobb kulcsu elem:"<<(*set_1.upper_bound(20)) << endl; //8

A set #include <set> #include <iostream> #include <vector> #include <algorithm> #include <set> #include <functional> using namespace std; int tomb[] = { 5,6,7,7,6,5,5,6 }; vector<int> v(tomb, tomb + 8); // 5 6 7 7 6 5 5 6 sort(v.begin(), v.end()); // 5 5 5 6 6 6 7 7 vector<int>::iterator also, felso; also = lower_bound(v.begin(), v.end(), 6); felso = upper_bound(v.begin(), v.end(), 6); cout << "6 also hatar poz.: " << (also - v.begin()) << endl;// 3 cout << "6 felso hatar poz.: " << (felso - v.begin()) << endl;// 6 multiset<int, greater<int>> ms(tomb, tomb + 8); // 7 7 6 6 6 5 5 5 multiset<int, greater<int>>::iterator malso, mfelso; malso = ms.lower_bound(6); mfelso = ms.upper_bound(6); cout << "6 also hatar poz.: " << distance(ms.begin(), malso) << endl;// 2 cout << "6 felso hatar poz.: " << distance(ms.begin(), mfelso) << endl;// 5

A set #include <set> Saját adattípus, vagy osztály esetén meg kell adni a rendezést : 1. Függvény pointerrel: multiset<auto, bool(*) (const Auto &, const Auto &)> Autok(AutotHasonlit); 2. Osztálysablon alapján: (#include <functional>) multiset<auto, less<auto>> Autok; //operátor < alapján 3. Függvényobjektum alkalmazásával: struct Rendez { bool operator () (const Auto & bal, const Auto & jobb) { return bal.rszam() < jobb.rszam();} }; multiset<auto, Rendez> Autok; Autok.insert(Auto("Opel", "HIK-123")); Autok.insert(Auto("Suzuki", "GDS-145")); Autok.insert(Auto("Renault", "MER-637")); Autok.insert(Auto("Opel", "HIK-123")); for (auto it2 = Autok.begin(); it2!= Autok.end(); it2++) it2->kiir(); //Auto(*it).Kiir();

A map #include <map> Adatpárok tárolódnak (kulcs, érték), a pair sablon alapján first -> kulcs second -> adat template <class T1, class T2> struct pair { T1 first; T2 second; pair() : first(t1()), second(t2()) {} }; A map elemei a kulcs alapján rendezettek 1 2 5 7 8 A multimap esetén megengedett a kulcsismétlés 1 2 5 5 5

A map #include <map> Konstruktorok (map<tip1,tip2,compare>) map<tip1,tip2> map_0; // üres (tip1,tip2) típusú map map<tip1,tip2> map_1(map_0.begin(),map_0.end()); // iterációs létrehozás map<tip1,tip2> map_2(map_1); // másoló konstruktor // Lehet definiálni az összehasonlítást kulcsra és értékre is Bejárók (map<tip1,tip2>::iterator) begin() // kezdet end() // vég rbegin() // vissza kezdet rend() // vissza vég map<tip1,tip2> ::iterator m; // maga az elem, mintha pointer lenne (*m).first a kulcs m->second - az érték Tulajdonságok operator[] // az adott kulcsú elem, ha nem létezik létrehozza a kulcsot érték nélkül

Keresések (#include <algorithm>) map<tip1,tip2>::iterator find(const tip1& x); size_type count ( const key_type& x ) const; pair<itb,ite> equal_range ( const key_type& x ); //adott kulcsú elem tartománya iterator lower_bound ( const key_type& x ); // nem kisebb, x kulcsú elem it. iterator upper_bound ( const key_type& x ); // nagyobb, x kulcsú elem it. A map #include <map> Méretek size() max_size() // az elemek aktuális száma // az elemek maximális száma Módosítók insert(iterator,pair<tip1,tip2>(kulcs,ertek)); Törlés bool empty ( ) const; // üres-e erase(iterator tol, iterator ig) // tol ig töröl clear() // mindent töröl

Példák: A map #include <map> map<char,int> map_0; // az alap konstruktor map<char,int>::iterator m0_it; // iterátor map_0['c']=99; map_0['b']=98; map_0['a']=97; map_0['d']=100;// feltöltés m0_it=map_0.begin(); cout<<m0_it->first<<endl; // az első elem kulcsa - a cout<<(*m0_it).second<<endl; // az első elem értéke - 97 map<char,int> map_1 (map_0.begin(),map_0.end()); // iteratív feltöltés map<char,int> map_2 (map_1); // másoló konstruktor for (m0_it=map_0.begin(); m0_it!=map_0.end(); m0_it++) // a map elemek kiírása cout<<(*m0_it).first<<" : "<<(*m0_it).second<<endl; // a : 97, b : 98 cout<<"size:"<<map_0.size()<<endl; // a méret 4 cout<<"maxsize:"<<map_0.max_size()<<endl; // a maximális méret - 178956970 m0_it=map_0.begin(); map_0.insert(m0_it,pair<char,int>('a',65)); // beszúrás for (m0_it=map_0.begin(); m0_it!=map_0.end(); m0_it++) // cout<<(*m0_it).first<<" : "<<(*m0_it).second<<endl; // A : 65, a: 97, cout<<map_0.count('a')<< " db. a kulccsal"<<endl; // 1 cout<<"a legkisebb 'a' kulcsu elem:" <<(*map_0.lower_bound('a')).second<<endl; // 97 cout<<"az 'a' kulcsu elem felso hat:" <<(*map_0.upper_bound('a')).second<<endl; // 98

A map #include <map> map<char, string> Morse; Morse['A'] = ".-"; Morse['N'] = "-."; Morse['1'] = ".----"; Morse['B'] = "-..."; Morse['O'] = "---"; Morse['2'] = "..---"; Morse['C'] = "-.-."; Morse['P'] = ".--."; Morse['3'] = "...--"; Morse['D'] = "-.."; Morse['Q'] = "--.-"; Morse['4'] = "...-"; Morse['E'] = "."; Morse['R'] = ".-."; Morse['5'] = "..."; Morse['F'] = "..-."; Morse['S'] = "..."; Morse['6'] = "-..."; Morse['G'] = "--."; Morse['T'] = "-"; Morse['7'] = "--..."; Morse['H'] = "..."; Morse['U'] = "..-"; Morse['8'] = "---.."; Morse['I'] = ".."; Morse['V'] = "...-"; Morse['9'] = "----."; Morse['J'] = ".---"; Morse['W'] = ".--"; Morse['0'] = "-----"; Morse['K'] = "-.-"; Morse['X'] = "-..-"; Morse['L'] = ".-.."; Morse['Y'] = "-.--"; Morse['M'] = "--"; Morse['Z'] = "--.."; string input = "SOS Korszeru Informatika"; for (int i = 0; i< input.length(); i++) cout << Morse[toupper(input[i])];

Rendezetlen asszociatív tárolók A set, multiset, map, multimap tárolók rendezetlen megfelelői. (unordered_set, unordered_map ) Az elemeket egy hasító függvény alapján osztják szét halmokra. Az elemeket a hasító tábla alapján érjük el. Például: szám % 10 10 halom jön létre A beépített alaptípusok mindegyikének van egy hasító függvénye. Saját adattípus esetén a hasító és az összehasonlító függvényeket nekünk kell elkészíteni. hash<auto>(const Auto & obj); // hasító fgv. equals_to<auto>(const Auto & obj1, const Auto & obj2); // == operátor vagy fgv. objektum

Példák: Az unordered_set #include <unordered_set> struct AutoHasher //Hasító fgv. objektum { size_t operator()(const Auto & obj) const { return hash<string>()(obj.tipus()); // Típusból képzett hasító fgv. } }; struct AutoComparator //Összehasonlító fgv. objektum { bool operator()(const Auto & obj1, const Auto & obj2) const { return obj1.rszam() == obj2.rszam(); // Rendszámok egyezése } }; unordered_set<auto,autohasher,autocomparator> usetautok; usetautok.insert(auto("opel", "HIK-123")); usetautok.insert(auto("suzuki", "GDS-145")); usetautok.insert(auto("renault", "MER-637")); usetautok.insert(auto("opel", "FGH-578")); usetautok.insert(auto("opel", "HIK-123")); //azonos rendszám miatt nem kerül be for (auto it2 = usetautok.begin(); it2!= usetautok.end(); it2++) it2->kiir();

Tároló adapterek vector<> deque<> list<> Soros Tároló Tároló adapter stack<> queue<> priority_queue<> Soros tárolókra épülő osztálysablonok, melyek egyszerű kezelésű adatstruktúrákat valósítanak meg. Az adapterek elemein nem lehet végiglépkedni, ezért nem használhatóak rajtuk az algoritmusok sem.

A stack #include <stack> Last-in, first-out, LIFO működést valósít meg Adaptálható deque,vector, list konténerekre építve (amiknek van back(), push_back() és pop_back() művelete). top() verem pop() push()

A stack #include <stack> Konstruktorok (stack<tip, tarolo<tip>>) stack<tip,vector<tip> > stack_0; // üres stack vector-t használ vector<tip> vek (2,200); // vektor 2 elemmel stack<tip,vector<tip> > stack_1 (vek); // stack vektorral inicializálva Kezelés bool empty ( ) const void push(const tip & x) void pop() tip & top() size_type size() const // üres-e // a stack-be tölt // leveszi a felső elemet // visszaadja a felső elemet // a méret; Példák stack<int,vector<int> > stack_0; // üres stack vector-t használ vector<int> vek (2,200); // vektor 2 elemmel stack<int,vector<int> > stack_1 (vek); // stack vektorral inicializálva for (int i=1; i<5; i++) stack_1.push(i);// tölti az elemeket for (int i=1; i<3; i++){ cout<<stack_1.top()<<endl; // kiírja és stack_1.pop(); // leveszi a felsőt - 4 3 } cout<<stack_1.size()<<endl; // a meret 4 (2+4-2)

A stack #include <stack> Mi a kimenet? int szam = 11; stack<int> verem; while (szam > 0) { verem.push(szam % 2); szam /= 2; } while(!verem.empty()) { cout << verem.top(); verem.pop(); }

A queue #include <queue> First-in, first-out, FIFO működésű sort valósít meg Adaptálható deque vagy list konténerekre építve (amiknek van front(), back(), push_back() és pop_front() művelete). Az alapműveletek mindegyikéhez konstans idő szüksége back() front() push() sor pop()

A queue #include <queue> Konstruktorok (queue<tip, tarolo<tip>>) queue<tip,list<tip>> que_0; // üres queue list-t használ list<tip> lst (2,200); // list 2 elemmel queue<tip,list<tip>> que_1 (lst); // queue list-tel inicializálva Kezelés bool empty ( ) const; // üres-e void push(const tip & x) // a queue végére tölt void pop() // leveszi a legrégebbi elemet tip & front() // visszaadja a legújabb elemet tip & back() // visszaadja a legrégebbi elemet size_type size() const // a méret; Példák list<int> lst (2,200); // lista 2 elemmel queue<int,list<int>> que_1 (lst); // queue list-tel inicializálva queue<int,deque<int>> que_0; // üres queue deque-t használ for (int i=1; i<10; i++) que_0.push(i); // tölti az elemeket for (int i=1; i<4; i++){ cout<<que_0.front()<<endl; // 1 2 3 que_0.pop(); // leveszi a felsőt } cout<<que_0.size()<<endl; // 6 (9-3)

A priorty_queue #include <queue> Best-in, first-out, BIFO működésű sort valósít meg, ahol a legjobb a legnagyobb prioritású elem Adaptálható vector vagy deque konténerekre építve Az elsőbbséget egy rendezési előírás definiálja A sor elején mindig a legnagyobb prioritású elem helyezkedik el top() prioritásos sor pop()

A priorty_queue #include <queue> Konstruktorok (priority_queu<tip, tarolo<tip>, class Compare>) priority_queu<tip,vector<tip>> pque_0; // üres p_queue vector-ral vector<int> v{ 1, 34, 43, 20 }; // vector elemekkel priority_queue<int, vector<int>> pque_1(v.begin(), v.end()); Kezelés bool empty ( ) const; // üres-e void push(const tip & x) // a queue végére tölt void pop() // leveszi a legrégebbi elemet tip & front() // visszaadja a legújabb elemet size_type size() const // a méret; Példák priority_queue<int, vector<int>> psor; // üres prioritási sor vector-ra psor.push(100); // feltöltés psor.push(20); psor.push(200); while (!psor.empty()) { cout << psor.top() << endl; // kiíratás 200 100 20 psor.pop(); // leveszi a felsőt }

Segítség a konténer választáshoz: Forrás: Tóth Bertalan: C++ programozás STL konténerekkel

Iterátorok #include <iterator> Az adathalmaz bejárására alkalmas objektumok. Egy pozíciót határoz meg a tárolóban. Forrás: Tóth Bertalan: C++ programozás STL konténerekkel

Iterátorok #include <iterator> Iterátorokra alkalmazható függvénysablonok: begin(), end() C tömbre készít bejárót advance(n) előre mozgat n lépéssel distance(itb, ite) két iterátor közötti elemek száma next(it) egyel lépteti előre az iterátort prev(it) egyel visszalépteti az itereátort next(it,n), prev(it,n) n szer léptet előre/vissza

Input és Output iterátorok #include <iterator> istream_iterator: a konténer elemeinek beolvasására használható: vector<double> adatok(3, 0); cout << "Kerek 3 szamot: "; istream_iterator<double> polvaso(cin); for (int i = 0; i < 3; i++) { adatok[i] = *polvaso; if (i < 2) polvaso++; } for (double elem : adatok) cout << elem << "\t";

Input és Output iterátorok #include <iterator> ostream_iterator: a kimeneti adatfolyam használatával kiíratások végezhetők el az algoritmusokból vector<double> adatok(3, 0); cout << "Kerek 3 szamot: "; istream_iterator<double> polvaso(cin); for (int i = 0; i < 3; i++) { adatok[i] = *polvaso; if (i < 2) polvaso++; } copy(begin(adatok), end(adatok), ostream_iterator<double>(cout, "\t"));

Algoritmusok #include <algorithm> Globális függvénysablonok, amelyek iterátorok segítségével férnek hozzá a konténerben tárolt adatokhoz Az algoritmusok függetlenek a konténerektől, az iterátorok feladata ismerni a konténert Ha a tároló valamilyen algoritmus saját tagfüggvénnyel is meg tud valósítani, akkor célszerű inkább azt használni (hatékonyabb és biztonságosabb) A végrehajtott algoritmus működési eredményét többféleképpen is megkaphatjuk Konténerben Iterátorként Adatként

Algoritmusok #include <algorithm> Nem módosító algoritmusok: nem változtatják meg az elemeket, sem azok tárolási sorrendejét equal(), find(), for_each(), max(), min(), mismatch(), search() Módosító algoritmusok: copy(), fill(), for_each(), merge(), move(), replace(), swap(), transform() Eltávolító algoritmusok: elemek törlésére remove(), unique() Átalakító algoritmusok: elemsorrend megváltoztatáshoz partition(), reverse(), rotate() Rendező algoritmusok: partition(), sort() Rendezett tartomány algoritmusai: binary_search(), equal_range(), lower_bound(), upper_bound(), merge()

Függvényobjektumok Az algoritmusok működése testre szabható, meghatározhatjuk, hogy milyen művelet hajtódjon végre az elemeken Hagyományos függvénymutató is lehet, de legtöbbször objektum A függvényobjektum olyan típus, amely megvalósítja a függvényhívás () operátorát Létezik egyoperandusú (unary) és kétoperandusú (binary) függvényobjektum

Függvényobjektumok Hagyományos függvény: bool Paros(int x){ return (x % 2) == 0; } Functional: #include <functional> class Paros{ public: bool operator () (int x) const{ return (x % 2) == 0; } } p1; bool x = p1(1); //mintha függvény lenne

Függvényobjektumok void Novel(double &elem){ elem++;} struct Osszeg{ Osszeg(double osszeg = 0):osszeg(osszeg) { } void operator()(double szam){ osszeg += szam; } double osszeg; }; vector<double> szamok{ 2, 3, 6, 9, 35 }; for (double e : szamok) cout << e <<" "; cout << endl; //függvény for_each(begin(szamok), end(szamok), Novel); for (double e : szamok) cout << e <<" "; cout << endl; //függvény obj. Osszeg szum=for_each(begin(szamok), end(szamok), Osszeg()); cout << szum.osszeg<< endl;

Függvényobjektumok (C++98) Unáris függvény: template <class Arg, class Result> struct unary_function { typedef Arg argument_type; typedef Result result_type; }; Példa: class fact: public unary_function<int, long> { public: long operator () (int a) { long f=1; for (int i=2; i<=a; i++) f*=i; return f; } };

Függvényobjektumok (C++98) Bináris függvény: template <class Arg1, class Arg2, class Result> struct binary_function { typedef Arg1 first_argument_type; typedef Arg2 second_argument_type; typedef Result result_type; }; Példa: template <class T> struct plus : binary_function <T,T,T> { T operator() (const T& x, const T& y) const { }; } return x+y;

Függvényobjektumok C++11-ben leegyszerűsítették: class Negyzet{ public: int operator() (int a) { return a*a; }; } int init[3] = {3,5,7}; deque<int> f(init, end(init)); // vége: init +3 vector<int> c(5); // üres vektor // a deque elemek négyzete transform(f.begin(), f.end(), c.begin(), Negyzet()); for (deque<int>::iterator i=f.begin(); i<f.end(); i++) cout<<(*i)<<" "; // 3 5 7 cout<<endl; for (vector<int>::iterator i=c.begin(); i<c.end(); i++) cout<<(*i)<<" "; // 9 25 49 0 0 cout<<endl;

Függvényobjektumok Általánosítva: template <class T> class Negyzet{ public: T operator() (T a) { return a*a; }; } int init[3] = {3,5,7}; deque<int> f(init, end(init)); // vége: init +3 vector<int> c(5); // üres vektor // a deque elemek négyzete transform(f.begin(), f.end(), c.begin(), Negyzet<int>()); for (deque<int>::iterator i=f.begin(); i<f.end(); i++) cout<<(*i)<<" "; // 3 5 7 cout<<endl; for (vector<int>::iterator i=c.begin(); i<c.end(); i++) cout<<(*i)<<" "; // 9 25 49 0 0 cout<<endl;

Függvényobjektumok Kétoperandusú esetben (binary function): template <class T> class Add{ public: T operator() (T a, T b) { return a+b; } }; double A[5]={ 2, 3, 6, 9, 35 }; vector<double> B(5); fill(b.begin(), B.end(), 10); deque<double> C(5); transform(begin(a), end(a), B.begin(), C.begin(), Add<double>()); for (double e : C) cout << e << " "; cout << endl; //12 13 16 19 45

Függvényobjektumok Előre definiált függvényobjektumok: #include <functional> int adatok[5] = { 35, 1, 3, 12, 23 }; sort(begin(adatok), end(adatok), greater<int>()); //35 23 12 3 1 vector<int> B(5); vector<int> C(5); iota(begin(b), end(b), 1);// 1 2 3 4 5 transform(begin(adatok), end(adatok), B.begin(), C.begin(), plus<int>()); for (double e : C) cout << e << " "; cout << endl; //36 25 15 7 6

Függvényobjektumok Alkalmazhatunk lambda-kifejezéseket is, amelyek névtelen függvényobjektumok vector<double> szamok{ 2, 3, 6, 9, 35 }; list<double> lista(5); for (double e : szamok) cout << e <<" "; cout << endl; for_each(begin(szamok), end(szamok), [](double &x)-> double {return x*x; }); double szum = 0; for_each(begin(szamok), end(szamok), [&szum](double x){szum += x; }); cout << szum << endl; transform(szamok.begin(), szamok.end(), lista.begin(), [](double x) -> double{ return x*x; }); for_each(lista.begin(), lista.end(), [](double x){cout << x << " "; });

Összetettebb példa: class Hallgato { public: Hallgato(string nev,string neptun,int kor=19):nev(nev),neptun(neptun),kor(kor) {} string Nev() const { return nev; } string Neptun() const { return neptun; } int Kor() const { return kor; } bool operator < (const Hallgato & h) { return nev < h.nev; } private: string nev, neptun; int kor; }; deque<hallgato> Tankor; Tankor.push_back(Hallgato("Kiss Petra", "B0SIFJ")); Tankor.push_back(Hallgato("Nagy Peter", "FG45TH")); Tankor.push_back(Hallgato("Kovacs Vilmos", "ASA47G")); Tankor.push_back(Hallgato("Molnar Kata", "DFRH7K")); string nev = "Kiss Petra"; bool KeresNev(const Hallgato & a) { return a.nev() == nev; } deque<hallgato>::iterator di; di = find_if(tankor.begin(), Tankor.end(), KeresNeptun("FG45TH")); if (di!= Tankor.end()) cout << di->nev() << endl; class KeresNeptun { public: string neptun; KeresNeptun(string neptun) { this->neptun = neptun; } bool operator ()(const Hallgato & h) { return neptun == h.neptun(); } }; string nept = "DFRH7K"; di = find_if(tankor.begin(), Tankor.end(), [nept](hallgato &h) -> bool {return h.neptun() == nept; }); if (di!= Tankor.end()) cout << di->nev() << endl;

Ismétlés Mi a kimenet? int tomb[] = { 5,6,7,7,6,5,5,6 }; deque<int> v(tomb + 2, tomb + 8); sort(v.begin(), v.end()); v.empty(); v.push_front(8); for (auto elem : v) elem += 10; deque<int>::reverse_iterator it = v.rbegin(); while (it!= v.rend() - 1) { cout << *it << " "; it++; }