Algorytmy i Struktury Danych. Standard Template Library. Część 1. Bożena Woźna-Szcześniak bwozna@gmail.com Jan Długosz University, Poland Wykład 6 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 1 / 30
Standard Template Library - Literatura Stephen Prata: Język C++, Szkoła Programowania. Robomatic, 2003 lub Helion, 2006. Nicolai M. Josuttis: C++ Biblioteka standardowa. Podręcznik Programisty. Helion, 2003. Scott Meyers: STL w praktyce. 50 sposobów efektywnego wykorzystania. Helion, 2004. http://www.sgi.com/tech/stl/ Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 2 / 30
Standard Template Library - krótka historia 1990 - Alex Stepanov i Meng Lee z laboratoriów Hewlett Packard rozszerzaja C++ o bibliotekę szablonów klas i funkcji, nazywana dziś STL. 1994 - STL zostaje uznany za standard - ANSI/ISO Standard C++. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 3 / 30
Standard Template Library - co to jest? Standard Template Library (STL) to biblioteka szablonów, wśród których znajduja się: Kontenery Iteratory Algorytmy Obiekty funkcyjne - funktory Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 4 / 30
Standard Template Library - co to jest? Kontener to jednostka, która podobnie jak tablica umożliwia przechowywanie wielu wartości. Kontenery udostępniane przez bibliotekę STL sa jednorodne, a zatem moga zawierać wyłacznie wartości tego samego typu. Algorytm jest grupa instrukcji opisujacych sposób wykonania konkretnego zadania, jak np. sortowanie tablicy, czy wyszukanie na liście określonej wartości. Iterator to obiekt pozwalajacy się przemieszczać po elementach kontenera. Iteratory sa uogólnieniem wskaźników. Obiekt funkcyjny (funktor) to obiekt zachowujacy się jak funkcja. Funktory moga być obiektami klas lub wskaźnikami do funkcji. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 5 / 30
Kontenery - rodzaje Sekwencyjne: vector (tablica dynamiczna) i bit_vector == vector < bool > deque (tablica dynamiczna dwukierunkowa; kolejka o dwóch końcach) list (lista dwukierunkowa) i slist (lista jednokierunkowa) tablica i string nie sa kontenerami STL, ale można je przetwarzać za pomoca algorytmów STL Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 6 / 30
Kontenery - rodzaje Sekwencyjne: vector (tablica dynamiczna) i bit_vector == vector < bool > deque (tablica dynamiczna dwukierunkowa; kolejka o dwóch końcach) list (lista dwukierunkowa) i slist (lista jednokierunkowa) tablica i string nie sa kontenerami STL, ale można je przetwarzać za pomoca algorytmów STL Asocjacyjne - implementowane za pomac a drzew typu BST: set (zbiór) i multiset (multi-zbiór) map (mapa) i multimap (multimapa) hash, hash_set, hash_multiset, hash_map, hash_multimap Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 6 / 30
Kontenery - rodzaje Sekwencyjne: vector (tablica dynamiczna) i bit_vector == vector < bool > deque (tablica dynamiczna dwukierunkowa; kolejka o dwóch końcach) list (lista dwukierunkowa) i slist (lista jednokierunkowa) tablica i string nie sa kontenerami STL, ale można je przetwarzać za pomoca algorytmów STL Asocjacyjne - implementowane za pomac a drzew typu BST: set (zbiór) i multiset (multi-zbiór) map (mapa) i multimap (multimapa) hash, hash_set, hash_multiset, hash_map, hash_multimap Adaptery - nie wspieraja iteratorów: stack queue priority_queue Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 6 / 30
Kontener vector #include <vector> Zaimplementowany jako tablica dynamiczna Dynamicznie rozszerzalny szybki dostęp do elementów za pomoc a operatora [] Może zawierać elementy dowolnego typu Metody: Kontener.push_back(element) - dodaje element do kontenera na koniec. Kontener.pop_back() - usuwa ostatni element z kontenera. Kontener.size() - zwraca rozmiar kontenera. Kontener.max_size() - zwraca maksymalny rozmiar kontenera. Kontener.capacity() - zwraca maksymalna liczbę elementów, która może zostać wstawiona do kontenera Kontener bez realokacji. Kontener.empty() - sprawdza czy kontener nie jest pusty. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 7 / 30
Dostęp do elementów kontenera vector Kontener.at(index) - zwraca element wektora z pozycji index. Kontener.v(index) - zwraca element wektora z pozycji index. Kontener.front() - zwraca pierwszy element wektora. Nie sprawdza, czy kontener jest pusty. Kontener.back() - zwraca ostatni element wektora. Nie sprawdza, czy kontener jest pusty. http://www.sgi.com/tech/stl/vector.html Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 8 / 30
Kontener vector - przykład 1 #include <iostream> #include <vector> using namespace std; int main() { vector<int> intvect; // kontener wektorowy dla liczb całkowitych cout << "Podaj ile elementów chcesz mieć w wektorze: " << endl; int n; cin >> n; // n - elementowy kontener wektorowy dla liczb całkowitych vector<int> intvect1(n); for (int i=1; i<=n; ++i){ intvect.push_back(i); //dołącz elementy i na koniec kontenera intvect1[i-1] = i; //dołącz elementy i na i-1 miejsce w kontenerze intvect1.push_back(2*i); //dołącz elementy 2i na koniec kontenera // wyswietl wszystkie elementy rozdzielone spacjami for (int i=0; i < intvect.size(); ++i) //1 2 3 4 5 cout << intvect[i] << ; cout << endl; for (int i=0; i < intvect1.size(); ++i)//1 2 3 4 5 2 4 6 8 10 cout << intvect1[i] << ; return 0; Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 9 / 30
Kontener vector - przykład 2 #include <iostream> #include <vector> using namespace std; int main() { int a[5] = {12, 7, 9, 21, 13 ; vector<int> v(a,a+5); //utwórz kontener v zainicjalizowany tablicą a for (int i=0; i < 5; ++i) cout << a[i] << ; cout << endl; // 12 7 9 21 13 for (int i=0; i < v.size(); ++i) cout << v[i] << ; cout << endl; // 12 7 9 21 13 v.pop_back(); for (int i=0; i < v.size(); ++i) cout << v[i] << ; cout << endl; // 12 7 9 21 v.push_back(15); for (int i=0; i < v.size(); ++i) cout << v[i] << ; cout << endl; // 12 7 9 21 15 return 0; Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 10 / 30
int array[5] = {12, 7, 9, 21, 13 ; vector<int> v(array,array+5); Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 11 / 30
Kontener vector - przykład 3 #include <iostream> #include <string> #include <vector> using namespace std; int main(){ const int NUM = 5; vector<int> ratings(num); vector<string> titles(num); cout << "Postępuj dokładnie według instrukcji. Wpisz\n" << NUM << "tytułów książek oraz ich oceny na skali 0-10.\n"; for (int i = 0; i < NUM; i++) { cout << "Wpisz tytuł numer " << i + 1 << ": "; getline(cin, titles[i]); cout << "Wpisz ocenę na skali 0-10: "; cin >> ratings[i]; cin.get(); cout << "Dziękuję. Twoje dane:\n" << "Ocena\t Książka\n"; for (int i = 0; i < NUM; i++) { cout << ratings[i] << "\t" << titles[i] << endl; return 0; Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 12 / 30
Kontener vector - przykład 4 #include <iostream> #include <vector> using namespace std; int main() { int arr[] = { 12, 3, 17, 8 ; // standardowa tablica C // inicjalizacja v tablicą C vector<int> v(arr, arr+4); while (!v.empty()) // czy wektor jest pusty? { cout << v.back() << " "; //zwraca ostatni element wektora v.pop_back(); // usuwa ostatni element wektora cout << endl;//8 17 3 12 return 0; Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 13 / 30
Kontener vector - Konstruktory vector<t> v; - Deklaracja wektora danych typu T. vector<t> v(size_type n); - Deklaracja wektora danych typu T o rozmiarze n. vector<t> v(size_type n,const T& t); - Deklaracja wektora danych typu T o rozmiarze n zawierajacego wartość t. vector<t> v(begin_iterator, end_iterator); - Kopia wektora danych typu T z zakresu begin_iterator, end_iterator. vector<t> v(vector<t> v1); - Kopia wektora danych typu T o nazwie v1. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 14 / 30
Kontener vector - Konstruktory int arr[] = { 12, 3, 17, 8 ; vector<int> v(arr, arr+4); // 12 3 17 8 vector<int> v1(v); // 12 3 17 8 vector<int> v2(10); // 0 0 0 0 0 0 0 0 0 0 vector<int> v3(10,5); // 5 5 5 5 5 5 5 5 5 5 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 15 / 30
Usuwania elementów z kontenera vector Kontener.erase() - usuwa wszystkie elementy z kontenera. Kontener.erase(iterator) - usuwa element wskazywany przez iterator z kontenera i zwraca iterator do następnego elementu. Kontener.erase(begin_iterator, end_iterator) - usuwa element z zakresu begin_iterator, end_iterator z kontenera i zwraca iterator do następnego elementu. Kontener.clear() - usuwa wszystkie elementy z kontenera. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 16 / 30
Wstawianie elementów do kontenera vector Kontener.insert(iterator, const T& t) - wstawia element t w miejsce wskazywane przez iterator. Kontener.insert(iterator pos, size_type n, const T& x) - wstawia przed pozycje pos n kopii elementu x. Kontener.insert(iterator pos, begin_iterator, end_iterator) - wstawia przed pozycje pos elementy z zakresu od begin_iterator do end_iterator Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 17 / 30
Iteratory i ich typy Iteratory zachowuja się jak zwyczajne wskaźniki..., >, ++,, ==,! =, = (vector, dequeue:, <, >, +, (int) ) kontener::iterator nazwa // zapis i odczyt kontener::const_iterator nazwa // tylko odczyt Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 18 / 30
Iteratory Iterator pozwala na przemieszczanie się po elementach kontenera Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 19 / 30
Iteratory Funkcje składowe begin() i end() zwracaja iterator odpowiednio do pierwszego elementu kontenera i do pierwszego za ostatnim elementem kontenera. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 20 / 30
Iteratory Można mieć wiele iteratorów wskazujacyhc na różne badź identyczne elementy kontenera Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 21 / 30
Iteratorty #include <iostream> #include <vector> using namespace std; int main() { int arr[] = { 12, 3, 17, 8 ; vector<int> v(arr, arr+4); // definicja iteratora dla vector a //i ustawienie go na jego pierwszy element vector<int>::iterator iter = v.begin(); cout << "Pierwszy element v = " << *iter << endl; // 12 iter++; cout << "Drugi element v = " << *iter << endl; // 3 iter = v.end()-1; cout << "Ostatni element v = " << *iter << endl; //8 return 0; Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 22 / 30
Iteratorty #include <iostream> #include <vector> using namespace std; int max(vector<int>::iterator start, vector<int>::iterator end); int main() { int arr[] = { 12, 3, 17, 101, 34, 2, 84; vector<int> v(arr, arr+7); cout << "max of v = " << max(v.begin(),v.end()) << endl; //101 return 0; int max(vector<int>::iterator start, vector<int>::iterator end) { int m = *start; while(start!= end){ if (*start > m) m = *start; ++start; return m; Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 23 / 30
Iteratorty #include <iostream> #include <vector> using namespace std; int main() { int arr[] = { 12, 3, 17, 101, 34, 2, 84; vector<int> v(arr, arr+7); for (vector<int>::iterator i = v.begin(); i!= v.end(); i++) // initialize i with pointer to first element of v // i++ increment iterator, move iterator to next element { cout << *i << " ";// de-referencing iterator returns the // value of the element the iterator points at cout << endl; return 0; Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 24 / 30
Kategorie iteratorów Iteratory dziela się na 5 kategorii, w których kategoria wyższa (bardziej szczegółowa) zawsze zawiera kategorię niższa (bardziej ogólna). Na przykład: Algorytm akceptujacy iterator forward będzie również pracował z iteratorem dwukierunkowym i swobodnego dostępu. Nie każdy iterator może być użyty z każdym kontenerem! Na przykład: klasa list nie ma iteratora swobodnego dostepu. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 25 / 30
Kategorie iteratorów Kategoria iteratora określa osiagalne operacje Iterator forward: iter + + (inkrementacja) iter (dereferencja) == and! = (porównanie) Iterator bidirectional dodatkowo posiada: iter (dekrementacje) iterator swobodnego dostępu (random-access) dodatkowo posiada: iter[n] (operator indeksowania) iter = +n (n-krotna inkrementację) Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 26 / 30
Algorytm For_Each() #include <iostream> #include <vector> #include <algorithm> using namespace std; void show(int n) { cout << n << " "; int main() { int arr[] = { 12, 3, 17, 101, 34, 2, 84; vector<int> v(arr, arr+7); /* Zastosuj funkcję show do każdego elementu wektora v */ for_each (v.begin(), v.end(), show); //12 3 17 101 34 2 84 return 0; Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 27 / 30
Algorytm Find() #include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { int key; int arr[] = { 12, 3, 17, 8, 34, 56, 9 ; vector<int> v(arr, arr+7); vector<int>::iterator iter; cout << "Wpisz wartość :"; cin >> key; iter = find(v.begin(),v.end(),key); if (iter!= v.end()) cout << "Element " << key << " Zanleziony" << endl; else cout << "Elementu " << key << " nie ma w wektorze v" << endl; return 0; Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 28 / 30
Algorytm Find_If() #include <iostream> #include <vector> #include <algorithm> using namespace std; bool mytest(int n) { if ((n>21) && (n<36)) return true; else return false; int main() { int arr[] = { 12, 3, 22, 23, 34, 56, 9 ; vector<int> v(arr, arr+7); vector<int>::iterator iter; // zwraca pierwszy iterator, który spełnia warunek funkcji iter = find_if(v.begin(),v.end(), mytest); if (iter!= v.end()) cout << "Element " << *iter << endl; else cout << "Elementu nie ma w wektorze v" << endl; return 0; Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 29 / 30
Algorytm count_if() #include <iostream> #include <vector> #include <algorithm> using namespace std; bool mytest(int n) { return (n>14) && (n <36); ; int main() { int arr[] = { 12, 3, 17, 8, 34, 56, 9 ; vector<int> v(arr, arr+7); // znajduje liczbe elementów spelniających warunek funkcji int n=count_if(v.begin(),v.end(),mytest); cout << "Zaleziono " << n << " elementów" << endl; return 0; Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 6 30 / 30