1 / 94

STL (Standard Template Library)

STL (Standard Template Library). Curs 14. STL. biblioteca C++ care contine clase pentru containere, algoritmi si iteratori Furnizeaza majoritatea algoritmilor de baza si structurilor de date necesare in dezvoltarea de programe

malina
Télécharger la présentation

STL (Standard Template Library)

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. STL (Standard Template Library) Curs 14

  2. STL • biblioteca C++ care contine clase pentru containere, algoritmi si iteratori • Furnizeaza majoritatea algoritmilor de baza si structurilor de date necesare in dezvoltarea de programe • STL este o bibiblioteca generica – componentele sunt parametrizate – aproape fiecare componenta din STL este template

  3. Containere • Vector • List • Deque • Queue • Stack • Priority queue • Set • Map • Multiset • Multimap • Bitset Containere secventiale Adaptori de containere Containere asociative (cheie-valoare)

  4. Vector • Elimina problema realocarii dinamice a spatiului de memorie • Se redimensioneaza in partea finala astfel incat sa poata fi realizata adaugarea de noi elemente • Compusi dintr-un bloc de memorie alocata secvential • Folosit cand se fac adaugari/stergeri de la sfarsit • Ineficient cand depasirile de memorie alocata pot determina copierea intregului vector • Constrangeri asupra lui T: T();T(const T&); ~T(); T& operator=(const T&); #include <vector> std::vector<int> myvector; std:: vector<int>::iterator it; Declaratie vector de intregi Declaratie iterator pe vector de intregi

  5. Operatii pe vector

  6. Operatii pe vector

  7. Operatii pe vector

  8. List • Compuse din obiecte care au anterior-info-urmator • Nu detin ownership asupra elementelor • Folosite cand se fac inserari/stergeri oriunde in cadrul listei • Cerinte pentru tipul T: • T(); T(const T&); ~T(); T& operator=(const T&); T* operator&(); int operator < (const T&, const T&); int operator==(const T&, const T&); #include <list> std::list<int> identifier; std::list<int>::iterator identifier; Declaratie lista de intregi Declaratie iterator pe lista de intregi

  9. Operatii pe tipul list

  10. Operatii pe tipul list

  11. Operatii pe tipul list

  12. Deque (deck) • deque=double ended queue • Nu e FIFO • Permite adaugarea/stergerea elementelor la ambele capete • Permite inserarea sau stergerea de elemente la pozitii arbitrare • Accesul la elemente de poate realiza similar vectorilor, cu operatorul [] sau metoda at() • #include <deque> • std::deque<int> dequeOfIntegers; • std::deque<int>::iterator itr; Declaratie coada de intregi Declaratie iterator coada de intregi

  13. Deque

  14. Deque

  15. Deque

  16. Vector sau deque? • Deque permite inserarea/stergerea elementelor de la inceputul/sfarsitul cozii in timp constant • Vectorul permite inserarea/stergerea elementelor doar la sfarsit in timp constant • Deque permite inserarea/stergerea de elemente la pozitii arbitrare mai eficient decat vectorul, dar nu in timp constant • Accesul aleator la elemente este mai rapid la vector decat la deque • Pentru secvente mari de elemente vectorul va aloca o zona mare de memorie contigua, pe cand deque va aloca mai multe blocuri de memorie de dimensiuni mai mici – mai eficient din punctul de vedere al sistemelor de operare • Deque se comporta atat ca o stiva, cat si ca o coada • Deque se expandeaza mai eficient decat vectorii

  17. Stack • LIFO • Ca implementare, in STL, o stiva e un adaptor (implementare a sablonului de proiectare Adapter – vezi curs 11) – preia ca parametru al templateului un container secvential si lasa vizibile doar operatiile care sunt asociate unei stive • #include <stack> • #include <C> - C containerul care dorim sa fie adaptat la stiva #include <stack> #include <list> std::stack<int, std::list<int> > myStack; Implicit deque (lista consuma prea multa memorie, vectorii de expandeaza costisitor) std::stack<int> myStack;

  18. Stack

  19. Set • Cotainer in care toate elementele sunt distincte • Pastreaza elementele sortate!! • Functia find() are complexitate logaritmica #include <set> std::set<int> s; std::set<int>::iterator it=s.begin(); Declaratie multime de intregi Declaratie iterator multime de intregi #include <set> #include <iostream> using namespace std; int main(){ set<int> intSet; for(int i=0;i<25;i++) for(int j=0;j<10;j++) intSet.insert(j); set<int>::iterator it=intSet.begin(); while(it!=intSet.end()) {cout<<*it<<" "; it++; } return 0; } 0 1 2 3 4 5 6 7 8 9

  20. Multiset • Accepta aparitii multiple ale unui element #include <set> #include <iostream> using namespace std; int main(){ multiset<int> intSet; for(int i=0;i<25;i++) for(int j=0;j<10;j++) intSet.insert(j); multiset<int>::iterator it=intSet.begin(); while(it!=intSet.end()) {cout<<*it<<" "; it++; } return 0; } 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9

  21. Operatii pe Set

  22. Operatii pe Set

  23. Map • Asociaza chei de un anumit tip cu valori de alt tip • Elementele sunt accesate direct, pe baza cheii • aMap["John Doe"] = 3.2; • Cheile trebuie sa fie unice • Atentie la utilizarea operatorului [] – algoritm: • Cauta cheia in dictionar • Daca e gasita se returneaza o referinta spre valoarea asociata • Daca nu e gasita se creeaza un nou obiect de tipul valorii si se returneaza o referinta spre el • Pentru a verifica apartenenta unui element la dictionar se foloseste metoda find() – nu creeaza un obiect daca cheia nu exista • Find returneaza un iterator pe o pereche de obiecte (cheie, valoare) daca cheia exista, altfel returneaza end() #include <map> std::map<string, double> aMap; std::map<string,double>::iterator it; Declaratie dictionar Declaratie iterator pe dictionar

  24. Map-pair • pair este o clasa template care are doua date membre publice accesbile folosind pair::first (cheia), respectiv pair::second (valoarea) • Definita in <utility> • Pentru a crea un obiect de tip pair – functia template make_pair care are 2 parametri • Cerinte asupra tipului cheilor/valorilor – sa aiba operatorul = supraincarcat • Tipul cheilor trebuie sa respecte urmatoarele constrangeri (ordine stricta): • a<a e fals • Egalitatea se poate determina din expresia (!(a<b)&&!(b<a)) • Daca a<b si b<c, atunci a<c • Tipul valorilor trebuie sa aiba definit un constructor implicit • pair<string,double> p; • p = make_pair(string("Microsoft Share Price"), double(85.27));

  25. Operatii pe Map

  26. Operatii pe Map

  27. Multimap • Permite existenta aceleiasi chei de mai multe ori • Pentru a gasi toate perechile cheie valoare corespunzatoare unei chei, vom folosi 2 iteratori-unul setat pe prima pereche din dictionar si altul setat pe ultima pereche din dictionar care corespunde cheii #include <map> multimap<string, int> mMap; multimap<string, int>::iterator itr; • multimap<string, int>::iterator itr; • multimap<string, int>::iterator lastElement; • itr = mMap.find(key); • if (itr == mMap.end()) return; • cout << "The following values are associated with the key " << key << endl; • lastElement = mMap.upper_bound(key); • for ( ; itr != lastElement; ++itr) cout << itr->second << endl;

  28. Operatii pe multimap

  29. Operatii pe multimap

  30. Iteratori • Similari pointerilor in sensul ca elementele indicate sunt accesate indirect • o abstractizare intre container si utilizatorul sau (putem scrie algoritmi pe containere fara sa stim reprezentarea acestora) • Determina reducerea cuplarii (GRASP-low coupling) intre functii si containere accesate de acestea • Pentru a accesa elementul, iteratorul trebuie dereferentiat • Clase de iteratori: • Inainte (forward)-operator ++ - 3 categorii: • Input (read-only) • Output(write-only) • Random access (read/write) • Bidirectional – permit traversarea inainte/inapoi – operatorii ++/--, acces read/write • Acces aleator (random access) –permite acces la oricare element al containerului folosind operatorii +/- si ++/--

  31. Iteratori • Majoritatea containerelor accepta iteratori, cu exceptia stivei, cozii si cozii cu prioritati • Parcurgerea elementelor containerului folosind iteratori: • Accesul la elementul curent: • Folosind * sau -> (daca obiectul referit este un agregat) • *itr=3; • struct pair { int first, second; }; • itr->first = 5; itr->second = 6; <container>::iterator <container>::const_iterator Declaratie iteratori • for (itr = container.begin(); itr!=container.end();++itr) • @proceseaza(*itr);

  32. Container reversibil – produce iteratori care merg de la sfarsit spre inceput Toate containerele standard permit existenta iteratorilor reversibili Pentru initializare: rbegin(), rend() #include <vector> #include <iostream> using namespace std; int main(){ vector<int> v; v.push_back(3); v.push_back(4); v.push_back(5); vector<int>::reverse_iterator rit=v.rbegin(); while (rit<v.rend()) { cout<<*rit<<endl; ++rit; } return 0; } Iteratori pe containere reversibile <container>::reverse_iterator <container>::const_reverse_iterator 5 4 3

  33. Destinati automatizarii unor sarcini comune (curente) STL furnizeaza metode de aplicare a unor algoritmi generici care sa inlocuiasca nevoia de a itera prin containere Un iterator pe stream foloseste un stream fie pentru intrare, fie pentru iesire ostream_iterator istream_iterator #include <iostream> #include <fstream> #include <iterator> #include <vector> using namespace std; int main () { vector<int> myvector; int value; cout << "Please, insert values: (CTRL+Z to stop) "; istream_iterator<int> eos; // end-of-stream iterator istream_iterator<int> iit (cin); // stdin iterator while (iit!=eos) { myvector.push_back(*iit); iit++; } ifstream fin("date.in"); istream_iterator<int> fiit (fin); //file iterator while (fiit!=eos) { myvector.push_back(*fiit); fiit++; } ostream_iterator<int> out_it (cout,", "); copy ( myvector.begin(), myvector.end(), out_it ); ofstream fout("date.out"); ostream_iterator<int> fout_it(fout,"|"); copy ( myvector.begin(), myvector.end(), fout_it ); return 0; } Iteratori pe streamuri

  34. Iteratori de inserare (insertion/insert iterators) • x iterator • *x=3 • Daca x e un insert iterator *x=3 genereaza adaugarea elementului 3 la secventa pe care itereaza • Necesari unor algoritmi care au scopul de umplere a containerele, nu de suprascriere • insert_iterator – permite inserarea de elemente in mijlocul unei secvente • 2 clase adaptor: • front_inserter– containerul trebuie sa aiba metoda push_front • back_inserter - containerul trebuie sa aiba metoda push_back • Constructorii iau un container secvential (vector, list,deque) si produc un iterator care apeleaza push_back sau push_front Suprascrie valoarea existenta

  35. #include <iostream> #include <iterator> #include <vector> using namespace std; int main () { vector<int> firstvector, secondvector; for (int i=1; i<=5; i++) { firstvector.push_back(i); secondvector.push_back(i*10); } back_insert_iterator< vector<int> > back_it (firstvector); copy (secondvector.begin(),secondvector.end(),back_it); ostream_iterator<int> out_it (cout,", "); copy ( firstvector.begin(), firstvector.end(), out_it ); return 0; } back_insert_iterator back_it 1 2 3 4 5 first 10 20 30 40 50 second 1, 2, 3, 4, 5, 10, 20, 30, 40, 50 first

  36. front_insert_iterator #include <iostream> #include <iterator> #include <deque> using namespace std; int main () { deque<int> firstdeque, seconddeque; for (int i=1; i<=5; i++) { firstdeque.push_back(i); seconddeque.push_back(i*10); } front_insert_iterator< deque<int> > front_it (firstdeque); copy (seconddeque.begin(),seconddeque.end(),front_it); deque<int>::iterator it; ostream_iterator<int> oit(cout,","); copy(firstdeque.begin(),firstdeque.end(),oit); return 0; } front_it 1 2 3 4 5 firstdeque 10 20 30 40 50 seconddeque 50, 40, 30, 20, 10, 1, 2, 3, 4, 5 firstdeque

  37. #include <iostream> #include <iterator> #include <list> using namespace std; int main () { list<int> firstlist, secondlist; for (int i=1; i<=5; i++) { firstlist.push_back(i); secondlist.push_back(i*10); } list<int>::iterator it; it = firstlist.begin(); advance (it,3); insert_iterator< list<int> > insert_it (firstlist,it); copy (secondlist.begin(),secondlist.end(),insert_it); for ( it = firstlist.begin(); it!= firstlist.end(); ++it ) cout << *it << " "; cout << endl; return 0; } insert_iterator it 1 2 3 4 5 firstlist 10 20 30 40 50 secondlist 1 2 3 10 20 30 40 50 4 5 firstlist

  38. Algoritmi generici • Operatii care nu modifica secventa pe care opereaza • Operatii care modifica secventa pe care opereaza • Sortare • Cautare binara • Interclasare • Ansambluri (heap) • Min/max

  39. Folosite pentru a transmite valori predicatelor la executie Obiectele de tip functie: abstractizare care permite comportamentul de functie Instanta a unei clase care supraincarca operatorul() (operatorul apel de functie) #include <iostream> using namespace std; class gt_n{ int val; public: gt_n(int v):val(v){} bool operator()(int n){return val>n;} }; int main(){ gt_n f(4); cout<<f(3)<<endl;//f.operator()(3); cout<<f(5)<<endl;//f.operator()(5); return 0; } Obiecte de tip functie

  40. Clasificarea obiectelor de tip functie • Pe baza tipului returnat si a numarului de argumente ale operatorului () • Generator – obiect de tip functie care nu ia nici un parametru si returneaza o valoare de tip arbitrar (ex: rand(), <cstdlib>) • Functie unara – functie cu un parametru care returneaza un tip arbitrar(inclusiv void) • Functie binara - functie cu 2 parametri care returneaza un tip arbitrar(inclusiv void) • Predicat unar – functie unara care returneaza bool • Predicat binar – functie binara care returneaza bool • Ordonare stricta – predicat binar care permite o interpretare mai generala a egalitatii ( 2 elemente sunt egale daca nici unul nu e strict mai mic decat altul – nr reale) • LessThanComparable – clasa care are operatorul< • Assignable – clasa care are operatorul = • EqualityComparable – clasa care are operatorul ==

  41. Operatii care nu modifica secventa • for_each • find/find_end/find_first/adjacent_find • equal • count/count_if • mismatch • search/search_n

  42. aplica o functie data ca parametru pe fiecare element al secventei specificate template <class InputIterator, class Function> Function for_each (InputIterator first, InputIterator last, Function f); #include <iostream> #include <algorithm> #include <vector> using namespace std; void myfunction (int i) { cout << " " << i; } int main () { vector<int> myvector; myvector.push_back(10); myvector.push_back(20); myvector.push_back(30); cout << "Vectorul contine:"; for_each (myvector.begin(), myvector.end(), myfunction); return 0; } for_each

  43. template <class InputIterator, class T> InputIterator find ( InputIterator first, InputIterator last, const T& value ); Returneaza un iterator pe primul element egal cu value, sau un iterator pe end(), in cazul in care nu gaseste elementul #include <iostream> #include <algorithm> #include <vector> using namespace std; int main () { int elems[] = { 10, 20, 30 ,40 }; vector<int> myvector(elems,elems+4); vector<int>::iterator it; it = find (myvector.begin(), myvector.end(), 30); ++it; cout << “The element following 30 is " << *it << endl; return 0; } find The element following 30 is 40

  44. template <class InputIterator, class Predicate> InputIterator find_if ( InputIterator first, InputIterator last, Predicate pred ); Predicate – functie care are ca parametru un obiect de tipul template-ului si returneaza o valoare booleana Gaseste un element in domeniul [first, last) care sa respecte conditia specificata de pred si returneaza un iterator pe element, altfel returneaza un iterator pe end() #include <iostream> #include <algorithm> #include <vector> using namespace std; bool positive (int i) { return (i>0);} int main () { vector<int> myvector; vector<int>::iterator it; myvector.push_back(-10); myvector.push_back(-95); myvector.push_back(40); myvector.push_back(-55); it = find_if (myvector.begin(), myvector.end(), positive); cout << "The first positive value" << *it << endl; return 0; } find_if predicat The first positive value 40

  45. Alte variatii find • find_end – gaseste ultima aparitie a unei secvente in alta secventa si returneaza un iterator • find_first_of – gaseste prima aparitie a oricarui element dintr-o secventa in alta secventa • adjacent_find – cauta prima aparitie a doua valori consecutive egale intr-o secventa si returneaza un iterator la ea

  46. Verifica daca elementele din doua domenii sunt egale facand compararea pe perechi de elemente corespunzatoare template <class InputIterator1, class InputIterator2> bool equal ( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2); template <class InputIterator1, class InputIterator2, class BinaryPredicate> bool equal ( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, BinaryPredicate pred); #include <iostream> #include <algorithm> #include <vector> using namespace std; bool mypredicate (int i, int j) { return (i==j);} int main () { int myints[] = {20,40,60,80,100}; vector<int>myvector (myints,myints+5); if (equal (myvector.begin(), myvector.end(), myints)) cout << "The contents of both sequences are equal." << endl; else cout << "The contents of both sequences differ." << endl; myvector[3]=81; if (equal (myvector.begin(), myvector.end(), myints, mypredicate)) cout << "The contents of both sequences are equal." << endl; else cout << "The contents of both sequences differ." << endl; return 0; } equal The contents of both sequences are equal. The contents of both sequences differ.

  47. Returneaza numarul de aparitii ale unui element intr-o secventa sau / numarul elementelor pentru care o conditie este adevarata template <class InputIterator, class T> typename iterator_traits<InputIterator>::difference_type count ( ForwardIterator first, ForwardIterator last, const T& value ); template <class InputIterator, class Predicate> typename iterator_traits<InputIterator>::difference_type count_if ( ForwardIterator first, ForwardIterator last, Predicate pred ); #include <iostream> #include <algorithm> #include <vector> using namespace std; bool positive(int i) { return (i>0); } int main () { vector<int> myvector; myvector.push_back(-10); myvector.push_back(-95); myvector.push_back(40); myvector.push_back(-55); int nrPos =(int) count_if (myvector.begin(), myvector.end(), positive); cout << "The no of positive values is " << nrPos << endl; return 0; } count/count_if -10 -95 40 -55 The no of positive values is 1

  48. mismatch • Compara doua secvente si returneaza pozitia primei diferente #include <iostream> #include <algorithm> #include <vector> using namespace std; bool mypredicate (int i, int j) {return (i==j);} int main () { vector<int> myvector; for (int i=1; i<6; i++) myvector.push_back (i*10); int myints[] = {10,20,80,320,1024}; pair<vector<int>::iterator,int*> mypair; mypair = mismatch (myvector.begin(), myvector.end(), myints); cout << "First mismatching elements: " << *mypair.first; cout << " and " << *mypair.second << endl;; mypair.first++; mypair.second++; mypair = mismatch (mypair.first, myvector.end(), mypair.second, mypredicate); cout << "Second mismatching elements: " << *mypair.first; cout << " and " << *mypair.second << endl;; return 0; } Comparatie implicita (==) Comparatie cu predicat First mismatching elements: 30 and 80 Second mismatching elements: 40 and 320

  49. Cauta prima aparitie a unei secvente in alta secventa si returneaza un iterator pe primul element al secventei (comparatia se face folosind == sau predicat) template <class ForwardIterator1, class ForwardIterator2> ForwardIterator1 search ( ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2 ); template <class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> ForwardIterator1 search ( ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2. BinaryPredicate pred ); #include <iostream> #include <algorithm> #include <vector> using namespace std; bool mypredicate (int i, int j) { return (i==j); } int main () { vector<int> myvector; vector<int>::iterator it; for (int i=1; i<10; i++) myvector.push_back(i*10); // using default comparison: int match1[] = {40,50,60,70}; it = search (myvector.begin(), myvector.end(), match1, match1+4); if (it!=myvector.end()) cout << "match1 found at position " << int(it-myvector.begin()) << endl; else cout << "match1 not found" << endl; // using predicate comparison: int match2[] = {20,30,50}; it = search (myvector.begin(), myvector.end(), match2, match2+3, mypredicate); if (it!=myvector.end()) cout << "match2 found at position " << int(it-myvector.begin()) << endl; else cout << "match2 not found" << endl; return 0; } search 10 20 30 40 50 60 70 80 90 40 50 60 70 20 30 50 match1 found at position 3 match2 not found

More Related