STL: algorytmy sortujące. STL: algorytmy sortujące. STL: algorytmy sortujące. STL: algorytmy sortujące. STL: algorytmy sortujące

Podobne dokumenty
STL: algorytmy sortujące. STL: algorytmy sortujące. STL: algorytmy sortujące. STL: algorytmy sortujące. STL: algorytmy sortujące

STL: implementowanie algorytmów C++: STL. STL: implementowanie algorytmów. STL: implementowanie algorytmów. STL: implementowanie algorytmów

STL: kontenery. STL: kontenery. STL: kontenery. Typy kontenerów STL. STL: kontenery. STL: kontenery. multimap. Kontener map: przykład zadanie:

STL: kontenery C++: STL: kontenery. STL: kontenery. STL: kontenery. STL: kontenery. Fabryka obiektów. Fabryka obiektów

Algorytmy w C++ dla opornych!

Algorytmy, iteratory, kolekcje niestandardowe

STL: implementowanie algorytmów. STL: implementowanie algorytmów. STL: implementowanie algorytmów. STL: implementowanie algorytmów

Wstęp do programowania obiektowego. STL - Standard Template Library

Algorytmy i Struktury Danych. Anna Paszyńska

Programowanie i struktury danych

STL: kontenery. Typy kontenerów STL. STL: kontenery. STL: kontenery. STL: kontenery. Typy kontenerów STL. deque (double-ended queue) list

Programowanie współbieżne i rozproszone

Programowanie Komponentowe Zarządzanie obiektami: kontenery

obiekty funkcyjne - funktory

Programowanie Obiektowo Zorientowane w języku C++ Biblioteka STL

STL Standardt Template Library (wprowadzenie)

Wydajność użycia funktorów z biblioteką STL języka C++

Algorytmy sortujące i wyszukujące

Paradygmaty programowania

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

Programowanie w C++ Wykład 7. Katarzyna Grzelak. 23 kwietnia K.Grzelak (Wykład 7) Programowanie w C++ 1 / 40

Programowanie w C++ Wykład 6. Katarzyna Grzelak. 1 kwietnia K.Grzelak (Wykład 6) Programowanie w C++ 1 / 43

Standard C++0x (C++1x?) Marcin Świderski

Podstawowe algorytmy i ich implementacje w C. Wykład 9

Kontenery i iteratory. Wykorzystanie kontenerów w praktyce.

Algorytmy i Struktury Danych, 2. ćwiczenia

Zaawansowane programowanie w C++ (PCP)

funkcje rekurencyjne Wykład 12. Podstawy programowania (język C) Funkcje rekurencyjne (1) Funkcje rekurencyjne (2)

Szablony funkcji i szablony klas

Programowanie w VB Proste algorytmy sortowania

Zaawansowane programowanie w języku C++ Biblioteka standardowa

C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów

STL: Lekcja 1&2. Filozofia STL

STL: kontenery. STL: kontenery. STL: kontenery. STL: kontenery. STL: kontenery. STL: kontenery

2. Klasy cz. 2 - Konstruktor kopiujący. Pola tworzone statycznie i dynamicznie - Funkcje zaprzyjaźnione - Składowe statyczne

Część 4 życie programu

Pojemniki Pojemnik to obiekt, którego zadaniem jest przechowywanie innych obiektów.

Programowanie obiektowe - Przykładowe zadania egzaminacyjne (2005/2006)

Szablony klas, zastosowanie szablonów w programach

Algorytmy i struktury danych

Tablice mgr Tomasz Xięski, Instytut Informatyki, Uniwersytet Śląski Katowice, 2011

Wykład 1_2 Algorytmy sortowania tablic Sortowanie bąbelkowe

Algorytmy i złożoności. Wykład 3. Listy jednokierunkowe

Przeciążenie operatorów

C++ Przeładowanie operatorów i wzorce w klasach

PARADYGMATY PROGRAMOWANIA Wykład 3

Szablony funkcji i klas (templates)

Wykład 5 Wybrane zagadnienia programowania w C++ (c.d.)

Informacje wstępne #include <nazwa> - derektywa procesora umożliwiająca włączenie do programu pliku o podanej nazwie. Typy danych: char, signed char

Projektowanie klas c.d. Projektowanie klas przykład

Podstawy języka C++ Maciej Trzebiński. Instytut Fizyki Jądrowej Polskiej Akademii Nauk. Praktyki studenckie na LHC IVedycja,2016r.

Dla każdej operacji łącznie tworzenia danych i zapisu ich do pliku przeprowadzić pomiar czasu wykonania polecenia. Wyniki przedstawić w tabelce.

I - Microsoft Visual Studio C++

Kiedy potrzebne. Struktura (rekord) Struktura w języku C# Tablice struktur. struktura, kolekcja

Funkcje. Deklaracja funkcji. Definicja funkcji. Wykorzystanie funkcji w programie.

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 5. Karol Tarnowski A-1 p.

Paradygmaty programowania

Język ludzki kod maszynowy

Definicja. Ciąg wejściowy: Funkcja uporządkowująca: Sortowanie polega na: a 1, a 2,, a n-1, a n. f(a 1 ) f(a 2 ) f(a n )

KOLEJKA (QUEUE) (lista fifo first in, first out)

Kurs programowania. Wykład 9. Wojciech Macyna. 28 kwiecień 2016

Języki programowania, wtorek , 12:15-13:45 Zadanie 11 - ostatnie

Zadania do wykonania. Rozwiązując poniższe zadania użyj pętlę for.

Programowanie komputerowe. Zajęcia 1

Programowanie Równoległe wykład 12. Thrust C Maciej Matyka Instytut Fizyki Teoretycznej

C++ - szablony kontenerów. Kontenery i szablony kontenerów. C++ - szablony kontenerów. C++ - szablony kontenerów. C++ - szablony kontenerów

Zestaw 1: Organizacja plików: Oddajemy tylko źródła programów (pliki o rozszerzeniach.adb i.ads)!!! Zad. 1: Zad. 2: 2,2,2 5,5,5,5,5,5 Zad.

Aby uzyskać zaliczenie w pierwszym terminie (do 30 stycznia 2018) rozliczyć trzeba co najmniej 8 projektów, po 4 z każdej z części: C++ oraz Python.

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy WSKAŹNIKI KLASOWE

Definicja szablonu klasy. Korzystanie z szablonu. Specjalizacja metody szablonu.

Instrukcje sterujące. Programowanie Proceduralne 1

Szablon klasy std::vector

wykład II uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C - funkcje, tablice i wskaźniki wykład II dr Jarosław Mederski Spis

Biblioteka standardowa C++

1. Napisz program wypisujący w kolejnych wierszach standardowego wyjścia pojedyncze słowa następującego napisu Bardzo dlugi napis. 2.

Podstawy programowania. Wykład 7 Tablice wielowymiarowe, SOA, AOS, itp. Krzysztof Banaś Podstawy programowania 1

/* dołączenie pliku nagłówkowego zawierającego deklaracje symboli dla wykorzystywanego mikrokontrolera */ #include <aduc834.h>

Zaawansowane programowanie w C++ (PCP)

Programowanie C++ Wykład 2 - podstawy języka C++ dr inż. Jakub Możaryn. Warszawa, Instytut Automatyki i Robotyki

Typy złożone. Struktury, pola bitowe i unie. Programowanie Proceduralne 1

Podstawy programowania w języku C

Programowanie - instrukcje sterujące

Automatyczne tworzenie operatora = Integer2& operator=(const Integer& prawy) { zdefiniuje. Integer::operator=(ri);

Podstawy języka C++ Maciej Trzebiński. Praktyki studenckie na LHC IFJ PAN. Instytut Fizyki Jądrowej Polskiej Akademii Nauk. M. Trzebiński C++ 1/16

Języki programowania C i C++ Wykład: Typy zmiennych c.d. Operatory Funkcje. dr Artur Bartoszewski - Języki C i C++, sem.

C++ wprowadzanie zmiennych

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

utworz tworzącą w pamięci dynamicznej tablicę dwuwymiarową liczb rzeczywistych, a następnie zerującą jej wszystkie elementy,

Rekurencja (rekursja)

Podstawy programowania skrót z wykładów:

PROGRAMOWANIE GENERYCZNE W JĘZYKU C++

Kurs programowania. Wykład 1. Wojciech Macyna. 3 marca 2016

Język C++ wykład VIII

Strona główna. Strona tytułowa. Programowanie. Spis treści. Sobera Jolanta Strona 1 z 26. Powrót. Full Screen. Zamknij.

Języki Programowania. Prowadząca: dr inż. Hanna Zbroszczyk. tel: Konsultacje: piątek:

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Podstawy Programowania 1 Sortowanie tablic jednowymiarowych. Plan. Sortowanie. Sortowanie Rodzaje sortowania. Notatki. Notatki. Notatki.

Język C zajęcia nr 11. Funkcje

8. Wektory. Przykłady Napisz program, który pobierze od użytkownika 10 liczb, a następnie wypisze je w kolejności odwrotnej niż podana.

Przeciążanie operatorów

Transkrypt:

1. partition 2. stable_partition 3. sort 4. stable_sort 5. partial_sort 6. partial_sort_copy 7. nth_element 8. lower_bound 9. upper_bound 10.equal_range 11.binary_search 12.merge 13.inplace_merge 14.includes 15.set_union 16.set_intersection 17.set_difference 18.set_symmetric_difference 19.lexicographical_compare 20.next_permutation template<class BidirectionalIterator, class Predicate> BidirectionalIterator partition( BidirectionalIterator _First, BidirectionalIterator _Last, BinaryPredicate _Comp ); porządkuje na nowo sekwencję elementów tak, że w pierwszej kolejności w sekwencji znajdują się elementy spełniające warunek podany w predykacie, a następnie pozostałe, niespełniające warunku. Zwracany iterator wskazuje element graniczny, tj. pierwszy element niespełniający warunku z predykatu. 90 91 #include <algorithm> // std::partition bool Nieparzyste (int i) { return (i%2)==1; std::vector<int> V; for (int i=1; i<10; ++i) V.push_back(i); // 1 2 3 4 5 6 7 8 9 std::vector<int>::iterator bound; bound = std::partition (V.begin(), V.end(), Nieparzyste); std::cout << nieparzyste elementy:"; for (std::vector<int>::iterator it=v.begin(); it!=bound; ++it) std::cout << parzyste elementy:"; for (std::vector<int>::iterator it=bound; it!=v.end(); ++it) 92 template<class BidirectionalIterator, class Predicate> BidirectionalIterator stable_partition( BidirectionalIterator _First, BidirectionalIterator _Last, Predicate _Pred ); porządkuje na nowo sekwencję elementów tak, że w pierwszej kolejności w sekwencji znajdują się elementy spełniające warunek podany w predykacie, a następnie pozostałe, niespełniające warunku. Zwracany iterator wskazuje element graniczny, tj. pierwszy element niespełniający warunku z predykatu porządkowanie jest stabilne. Co to znaczy, że jest stabilne? 93 Szereg algorytmów porządkujących występuje w wersjach stabilnych i niestabilnych. Wersje stabilne zachowują wzajemne uporządkowanie elementów traktowanych jako identyczne z punktu widzenia funkcji porządkującej, np. sekwencja: C 1,B 1,C 2,A 1,B 2,A 2 po posortowaniu pod względem dużej litery algorytmem stabilnym będzie miała postać: A 1,A 2,B 1,B 2,C 1,C 2 natomiast po posortowaniu algorytmem niestabilnym może mieć np. postać: A 2,A 1,B 1,B 2,C 2,C 1 Np. implementacja algorytmu sort w STL jest oparta na quicksort, a więc jest niestabilna. Istnieje jednak również wersja stable_sort, która zachowuje wzajemne uporządkowanie elementów identycznych. template<class RandomAccessIterator> void sort( RandomAccessIterator _First, RandomAccessIterator _Last ); template<class BidirectionalIterator> void stable_sort( BidirectionalIterator _First, BidirectionalIterator _Last ); porządkuje elementy w sekwencji określanej przez parę iteratorów [_First,_Last) w porządku nierosnącym, 94 95 1

#include <algorithm> // std::stable_sort bool porownajint (double i,double j) { return (int(i)<int(j)); ; double mydoubles[] = {3.14, 1.41, 2.72, 4.67, 1.73, 1.32, 1.62, 2.58; std::vector<double> V; V.assign(mydoubles,mydoubles+8); std::cout << "sortowanie porownajint:"; std::stable_sort (V.begin(), V.end(), porownajint); for (std::vector<double>::iterator it=v.begin(); it!=v.end(); ++it) template<class RandomAccessIterator> void partial_sort( RandomAccessIterator _First, RandomAccessIterator _SortEnd, RandomAccessIterator _Last ); sortuje ograniczoną liczbę elementów z sekwencji określanej przez parę iteratorów [_First,_Last) w porządku nierosnącym, którą da się zmieścić w zakresie [_First,_SortEnd). Reszta elementów trafia do [_SortEnd,_Last) w nieokreślonej kolejności, 96 97 #include <algorithm> // std::partial_sort bool porownaj (int i,int j) { return (i<j); int myints[] = {9,8,7,6,5,4,3,2,1; std::vector<int> V (myints, myints+9); std::partial_sort (V.begin(), V.begin()+5, V.end(), porownaj); std::cout << "V zawiera:"; for (std::vector<int>::iterator it=v.begin(); it!=v.end(); ++it) template<class InputIterator, class RandomAccessIterator> RandomAccessIterator partial_sort_copy( InputIterator _First1, InputIterator _Last1, RandomAccessIterator _First2, RandomAccessIterator _Last2 ); Sortuje liczbę elementów z sekwencji określanej przez parę iteratorów [_First1,_Last1) w porządku nierosnącym, którą da się umieścić w zakresie [_First2,_Last2) i kopiuje posortowane elementy do sekwencji [_First2,_Last2), Jeżeli [_First1,_Last1) jest mniejszy od [_First2,_Last2), kopiowana jest mniejsza liczba elementów, 98 99 #include <algorithm> // std::partial_sort_copy bool porownaj (int i,int j) { return (i<j); ; int myints[] = {9,8,7,6,5,4,3,2,1; std::vector<int> V (5); std::partial_sort_copy (myints, myints+9, V.begin(), V.end(), porownaj); std::cout << "V zawiera:"; for (std::vector<int>::iterator it=v.begin(); it!=v.end(); ++it) template<class RandomAccessIterator> void nth_element( RandomAccessIterator _First, RandomAccessIterator _Nth, RandomAccessIterator _Last ); częściowo sortuje sekwencję określaną przez parę iteratorów [_First,_Last) w porządku nierosnącym. To znaczy, że: po posortowaniu elementy mniejsze od elementu wskazywane przez _Nth umieszczane są w lewej części sekwencji, tj. [_First, _Nth), natomiast większe w prawej [_Nth,_Last). Jednak żadna z podsekwencji nie musi być posortowana, 100 101 2

#include <algorithm> // std::nth_element, std::random_shuffle bool porownaj (int i,int j) { return (i>j); std::vector<int> V; for (int i=1; i<10; i++) V.push_back(i); // 1 2 3 4 5 6 7 8 9 std::random_shuffle (V.begin(), V.end()); std::nth_element (V.begin(), V.begin()+5, V.end(), porownaj); std::cout << "V contains:"; for (std::vector<int>::iterator it=v.begin(); it!=v.end(); ++it) template<class ForwardIterator, class Type> ForwardIterator lower_bound( ForwardIterator _First, ForwardIterator _Last, const Type& _Val ); zwraca iterator na pierwsze wystąpienie w posortowanej sekwencji [_First,_Last) elementu o wartości _Val, jeżeli w sekwencji brak takiego elementu, zwracany jest iterator do miejsca, w którym element ten powinien się znajdować, tj. do pierwszego elementu większego od poszukiwanej wartości, 102 103 template<class ForwardIterator, class Type> ForwardIterator upper_bound( ForwardIterator _First, ForwardIterator _Last, const Type& _Val ); zwraca iterator na pierwszy element za ostatnim elementem o wartości _Val w posortowanej sekwencji [_First,_Last), jeżeli w sekwencji brak takiego elementu, zwracany jest iterator do miejsca, w którym element ten powinien się znajdować, tj. do pierwszego elementu większego od poszukiwanej wartości, 104 #include <iostream> #include <algorithm> #include <vector> // std::cout // std::lower_bound, std::upper_bound, std::sort // std::vector int myints[] = {10,20,30,30,20,10,10,20; std::vector<int> v(myints,myints+8); // 10 20 30 30 20 10 10 20 std::sort (v.begin(), v.end()); // 10 10 10 20 20 20 30 30 std::vector<int>::iterator low,up; low=std::lower_bound (v.begin(), v.end(), 20); // up= std::upper_bound (v.begin(), v.end(), 20); // std::cout << "lower_bound at position " << (low- v.begin()) << '\n'; std::cout << "upper_bound at position " << (up - v.begin()) << '\n'; ^ ^ 105 template<class ForwardIterator, class Type> pair<forwarditerator, ForwardIterator> equal_range( ForwardIterator _First, ForwardIterator _Last, const Type& _Val ); zwraca parę iteratorów ograniczających w sekwencji [_First,_Last) podsekwencję elementów o wartości _Val, jeżeli w sekwencji brak takiego elementu, iteratory wskazują na miejsce, w którym element ten powinien się znajdować, tj. do pierwszego elementu większego od poszukiwanej wartości, szablonu reprezentującym obiekt funkcyjny/funkcję służący do porównań, Uwaga: elementy powinny być posortowane względem operatora < (elementy są uważane za równe, jeżeli: (!(a<b) &&!(b<a))) lub podanego obiektu funkcyjnego/funkcji służącej do porównań. 106 #include <algorithm> // std::equal_range, std::sort bool mygreater (int i,int j) { return (i>j); int myints[] = {10,20,30,30,20,10,10,20; std::vector<int> V(myints,myints+8); // 10 20 30 30 20 10 10 20 std::pair<std::vector<int>::iterator,std::vector<int>::iterator> bounds; std::sort (v.begin(), v.end(), mygreater); // 30 30 20 20 20 10 10 10 bounds=std::equal_range ( v.begin(), v.end(), 20, mygreater); // ^ ^ std::cout << "bounds at positions " << (bounds.first - v.begin()); std::cout << " and " << (bounds.second - v.begin()) << '\n'; 107 3

template <class ForwardIterator, class T> bool binary_search ( ForwardIterator _First, ForwardIterator _Last, const T& _Val); zwraca wartość logiczną true, jeżeli w posortowanej sekwencji [_First,_Last) znajduje się element o wartości _Val (dwa elementy a i b są uważane za równe, jeżeli: (!(a<b) &&!(b<a))), optymalizuje liczbę porównań poprzez dokonywanie porównań między niesąsiadującymi elementami z posortowanego zakresu, template<class InputIterator1, class InputIterator2, class OutputIterator> OutputIterator merge( InputIterator2 _First2, InputIterator2 _Last2, łączy dwa identycznie posortowane zakresy elementów [_First1,_Last1) i [_First2,_Last2) w jeden posortowany zakres docelowy, którego początek jest wskazywany przez _Result, 108 109 #include <iostream> #include <algorithm> #include <vector> // std::cout // std::merge, std::sort // std::vector int first[] = {5,10,15,20,25; int second[] = {50,40,30,20,10; std::vector<int> v(10); std::sort (first,first+5); std::sort (second,second+5); std::merge (first,first+5,second,second+5,v.begin()); std::cout << "Wynikowy wektor zawiera:"; // 5 10 10 15 20 20 25 30 40 50 for (std::vector<int>::iterator it=v.begin(); it!=v.end(); ++it) 110 template<class BidirectionalIterator> void inplace_merge( BidirectionalIterator _First, BidirectionalIterator _Middle, BidirectionalIterator _Last ); łączy dwa posortowane zakresy elementów [_First,_Middle) i [_Middle,_Last) w jeden sumaryczny zakres docelowy [_First,_Last). Alokuje pomocniczy bufor na dane, aby zwiększyć efektywność, a jeżeli jest to niemożliwe, używa mniej efektywnego algorytmu. Różnice merge vs. inplace_merge: merge: liczba porównań co najwyżej distance(first1, last1) + distance(first2, last2) 1 inplace_merge: dokładnie N-1 porównań, jeżeli dostępny jest wystarczający obszar pamięci, w przeciwnym razie: N log(n) gdzie N = distance(first, last). 111 Różnice merge vs. inplace_merge: std::inplace_merge(a.begin(), a.begin() + n, a.end()); nie jest równoważny: std::merge(a.begin(), a.begin() + n, a.begin() + n, a.end(), a.begin()); ponieważ merge nie może skierować wyniku swojego działania do a (tj. do tego samego kontenera, z którego pochodziły dane wejściowe). Gdybyśmy się jednak upierali, to w takim przypadku należałoby napisać np.: decltype(a) b; std::merge(a.begin(), a.begin() + n, a.begin() + n, a.end(), std::back_inserter(b)); back_inserter konstruuje iterator, który umieszcza nowe elementy na końcu zawartości kontenera podanego w argumencie (kontener musi mieć metodę push_back). Przypisane wartości do tego iteratora są dodawane na końcu. 112 #include <algorithm> // std::inplace_merge, std::sort, std::copy int first[] = {5,10,15,20,25; int second[] = {50,40,30,20,10; std::vector<int> v(10); std::vector<int>::iterator it; std::sort (first,first+5); std::sort (second,second+5); it=std::copy (first, first+5, v.begin()); std::copy (second,second+5,it); std::inplace_merge (v.begin(),v.begin()+5,v.end()); std::cout << " Wynikowy wektor zawiera :"; // 5 10 10 15 20 20 25 30 40 50 for (it=v.begin(); it!=v.end(); ++it) UKSW, WMP. SNS, Warszawa 113 4

template<class InputIterator1, class InputIterator2> bool includes( InputIterator2 _First2, InputIterator2 _Last2); sprawdza, czy wszystkie wartości z jednego posortowanego zakresu [_First1,_Last1) są zawarte w drugim (_First2,_Last2) (tj. czy pierwszy jest podzbiorem drugiego dwa elementy a i b są uważane za równe, jeżeli: (!(a<b) &&!(b<a))), #include <algorithm> // std::includes, std::sort bool porownaj (int i, int j) { return i<j; int C1[] = {5,10,15,20,25,30,35,40,45,50; int C2[] = {40,30,20,10; std::sort (C1,C1+10); std::sort (C2,C2+4); if ( std::includes(c1,c1+10,c2,c2+4, porownaj) ) std::cout << "C1 zawiera C2!\n"; 114 115 template<class InputIterator1, class InputIterator2, class OutputIterator> OutputIterator set_union( InputIterator2 _First2, InputIterator2 _Last2, Łączy wszystkie elementy znajdujące się w przynajmniej jednym z dwóch posortowanych zakresów tworząc jeden wspólny posortowany zakres wynikowy (suma zbiorów) dwa elementy a i b są uważane za równe, jeżeli: (!(a<b) &&!(b<a)), 116 #include <algorithm> // std::set_union, std::sort int first[] = {5,10,15,20,25; int second[] = {50,40,30,20,10; std::vector<int> v(10); // 0 0 0 0 0 0 0 0 0 0 std::vector<int>::iterator it; std::sort (first,first+5); // 5 10 15 20 25 std::sort (second,second+5); // 10 20 30 40 50 it=std::set_union (first, first+5, second, second+5, v.begin()); // 5 10 15 20 25 30 40 50 0 0 v.resize(it-v.begin()); // 5 10 15 20 25 30 40 50 std::cout << "Suma ma " << (v.size()) << " elementów:\n"; for (it=v.begin(); it!=v.end(); ++it) UKSW, WMP. SNS, Warszawa 117 template<class InputIterator1, class InputIterator2, class OutputIterator> OutputIterator set_intersection( InputIterator2 _First2, InputIterator2 _Last2, łączy wszystkie elementy, które należą do obydwu posortowanych przedziałów w jeden wspólny posortowany przedział wynikowy (przecięcie zbiorów) dwa elementy a i b są uważane za równe, jeżeli: (!(a<b) &&!(b<a)), 118 #include <algorithm> // std::set_intersection, std::sort int first[] = {5,10,15,20,25; int second[] = {50,40,30,20,10; std::vector<int> v(10); // 0 0 0 0 0 0 0 0 0 0 std::vector<int>::iterator it; std::sort (first,first+5); // 5 10 15 20 25 std::sort (second,second+5); // 10 20 30 40 50 it=std::set_intersection (first, first+5, second, second+5, v.begin()); // 10 20 0 0 0 0 0 0 0 0 v.resize(it-v.begin()); // 10 20 std::cout << "Czesc wspolna ma " << (v.size()) << " elementów:\n"; for (it=v.begin(); it!=v.end(); ++it) UKSW, WMP. SNS, Warszawa 119 5

template<class InputIterator1, class InputIterator2, class OutputIterator> OutputIterator set_difference( InputIterator2 _First2, InputIterator2 _Last2, łączy wszystkie elementy, które należą do pierwszego, ale nie do drugiego z przedziałów (obydwa muszą być posortowane) w jeden posortowany przedział wynikowy (różnica zbiorów) dwa elementy a i b są uważane za równe, jeżeli: (!(a<b) &&!(b<a)), 120 #include <algorithm> // std::set_difference, std::sort int first[] = {5,10,15,20,25; int second[] = {50,40,30,20,10; std::vector<int> v(10); // 0 0 0 0 0 0 0 0 0 0 std::vector<int>::iterator it; std::sort (first,first+5); // 5 10 15 20 25 std::sort (second,second+5); // 10 20 30 40 50 it=std::set_difference (first, first+5, second, second+5, v.begin()); // 5 15 25 0 0 0 0 0 0 0 v.resize(it-v.begin()); // 5 15 25 std::cout << "Roznica ma " << (v.size()) << " elementów:\n"; for (it=v.begin(); it!=v.end(); ++it) UKSW, WMP. SNS, Warszawa 121 template<class InputIterator1, class InputIterator2, class OutputIterator> OutputIterator set_symmetric_difference( InputIterator2 _First2, InputIterator2 _Last2, łączy wszystkie elementy, które należą albo do jednego, albo do drugiego z przedziałów (obydwa muszą być posortowane) w jeden posortowany przedział wynikowy (różnica symetryczna zbiorów) dwa elementy a i b są uważane za równe, jeżeli: (!(a<b) &&!(b<a)), 122 #include <algorithm> // std::set_symmetric_difference, std::sort int first[] = {5,10,15,20,25; int second[] = {50,40,30,20,10; std::vector<int> v(10); // 0 0 0 0 0 0 0 0 0 0 std::vector<int>::iterator it; std::sort (first,first+5); // 5 10 15 20 25 std::sort (second,second+5); // 10 20 30 40 50 it=std::set_symmetric_difference(first,first+5,second,second+5,v.begin()); // 5 15 25 30 40 50 0 0 0 0 v.resize(it-v.begin()); // 5 15 25 30 40 50 std::cout << "Roznica symetr. ma " << (v.size()) << " elementów:\n"; for (it=v.begin(); it!=v.end(); ++it) UKSW, WMP. SNS, Warszawa 123 template<class InputIterator1, class InputIterator2> bool lexicographical_compare( InputIterator2 _First2, InputIterator2 _Last2 ); porównuje dwa przedziały element po elemencie aby wskazać ten mniejszy. Zwraca true, jeżeli pierwszy jest leksykograficznie mniejszy, lub false wpp, 124, std::boolalpha #include <algorithm> // std::lexicographical_compare #include <cctype> // std::tolower bool porownaj(char c1, char c2) { return std::tolower(c1)<std::tolower(c2); ; char V1[]="Apple"; char V2[]="apartment"; std::cout << std::boolalpha; std::cout << "Porownuje V1 i V2 leksykograficznie (V1<V2):\n"; std::cout << "Operator domyślny (<): "; std::cout << std::lexicographical_compare(v1,v1+5,v2,v2+9); std::cout << "Operator porownaj: "; std::cout << std::lexicographical_compare(v1,v1+5,v2,v2+9,porownaj); 125 6

template <class BidirectionalIterator> bool next_permutation (BidirectionalIterator first, BidirectionalIterator last); zmienia porządek elementów w sekwencji [first, last) na następną, leksykograficznie większą permutację, Za pierwszą permutację przyjmujemy sekwencję posortowaną rosnąco. Za ostatnią malejąco. Zwraca true, jeżeli istnieje możliwość dokonania kolejnej permutacji i wykonuje ją. W przeciwnym przypadku, tj. kiedy osiągnięto już ostatnią permutację, zmienia prządek na pierwszą permutację i zwraca false. #include <iostream> #include <algorithm> int myints[] = {1,2,3; std::sort (myints,myints+3); // std::cout // std::next_permutation, std::sort // ustawiamy początkową permutację std::cout << "The 3! possible permutations with 3 elements:\n"; do { std::cout << myints[0] << ' ' << myints[1] << ' ' << myints[2] << '\n'; while ( std::next_permutation(myints,myints+3) ); std::cout << "After loop: " << myints[0] << ' ' << myints[1] << ' ' << myints[2] << '\n'; 126 127 Podsumowanie 1. partition 2. stable_partition 3. sort 4. stable_sort 5. partial_sort 6. partial_sort_copy 7. nth_element 8. lower_bound 9. upper_bound 10.equal_range 11.binary_search 12.merge 13.inplace_merge 14.includes 15.set_union 16.set_intersection 17.set_difference 18.set_symmetric_difference 19.lexicographical_compare 20.next_permutation 128 1. accumulate 2. partial_sum 3. inner_product 4. adjacent_difference 129 template<class InputIterator, class Type> Type accumulate( InputIterator _First, InputIterator _Last, Type _Val ); sumuje wartości zawarte w sekwencji [_First,_Last) do wartości początkowej sumy zawartej w _Val. Zwraca wynik sumowania. chociaż domyślną operacją jest sumowanie, istnieje wersja z dodatkowym, ostatnim argumentem szablonu reprezentującym funkcję lub obiekt funkcyjny służący do wykonywania dowolnych innych operacji. #include <functional> // std::minus #include <numeric> // std::accumulate int init = 100; int numbers[] = {10,20,30; std::cout << "Domyślna suma: "; std::cout << std::accumulate(numbers,numbers+3,init); // Domyślna suma: 160 std::cout << "Minus z biblioteki <functional>: "; std::cout << std::accumulate (numbers, numbers+3, init, std::minus<int>()); // Minus z biblioteki <functional>: 40 130 131 7

#include <functional> // std::minus #include <numeric> // std::accumulate int MojaFun (int x, int y) {return x+2*y; struct MojaKlasa { int operator()(int x, int y) {return x+3*y; MObj; int init = 100; int numbers[] = {10,20,30; std::cout << "MojaFun: "; std::cout << std::accumulate (numbers, numbers+3, init, MojaFun); // MojaFun: 220 std::cout << "MObj : "; std::cout << std::accumulate (numbers, numbers+3, init, MObj); // Mobj: 280 132 template<class InputIterator, class OutIt> OutputIterator partial_sum( InputIterator _First, InputIterator _Last, oblicza uogólnioną sumę częściową zbioru elementów z sekwencji [_First,_Last). Polega to na utworzeniu sekwencji wynikowej, której pierwszy element jest wskazywany przez _Result, zawierającej wartości będące sumą elementów poprzedzających każdą z tych wartości w sekwencji wejściowej. np. dla sekwencji wejściowej 1,2,3,4,5 sumy w sekwencji wynikowej będą miały wartości: 1, 1+2, 1+2+3, 1+2+3+4, 1+2+3+4+5 chociaż domyślną operacją jest sumowanie istnieje wersja z dodatkowym, ostatnim argumentem szablonu reprezentującym funkcję lub obiekt funkcyjny służący do wykonywania dowolnych innych operacji. 133 #include <functional> // std::multiplies #include <numeric> // std::partial_sum int myop (int x, int y) {return x+y+1; int val[] = {1,2,3,4,5; int result[5]; std::partial_sum (val, val+5, result, std::multiplies<int>()); std::cout << "using functional operation multiplies: "; for (int i=0; i<5; i++) std::cout << result[i] << ' '; std::partial_sum (val, val+5, result, myop); std::cout << "using custom function: "; for (int i=0; i<5; i++) std::cout << result[i] << ' '; template<class InputIterator1, class InputIterator2, class Type> Type inner_product( InputIterator2 _First2, Type _Val ); oblicza iloczyn stanowiący odpowiednik iloczynu skalarnego dwóch wektorów reprezentowanych sekwencjami [_First1,_Last1) i _First2. Wartością takiej operacji jest suma iloczynów odpowiadających sobie elementów sekwencji powiększona o wartość bazową _Val: _Val + (*_First1) * (*_First2) +.. Dwie domyślne operacje mnożenia oraz dodawania wyniku wszystkich par do wartości bazowej można zastąpić dwoma funkcjami lub obiektami funkcyjnymi, odpowiednio op2 i op1. 134 135 #include <functional> // std::minus, std::divides #include <numeric> // std::inner_product int myaccumulator (int x, int y) {return x-y; int myproduct (int x, int y) {return x+y; int init = 100; int series1[] = {10,20,30; int series2[] = {1,2,3; std::cout << "using functional operations: "; std::cout << std::inner_product(series1,series1+3,series2,init, std::minus<int>(),std::divides<int>()); std::cout << "using custom functions: "; std::cout << std::inner_product(series1,series1+3,series2,init, myaccumulator,myproduct); 136 template<class InputIterator, class OutIterator> OutputIterator adjacent_difference( InputIterator _First, InputIterator _Last, oblicza różnicę sąsiadujących elementów sekwencji źródłowej. Np. dla sekwencji 1,2,3,4,5 sekwencja wynikowa reprezentuje wartości: 1, 2-1, 3-2, 4-3, 5-4, domyśla operacja odejmowania można zastąpić funkcją lub obiektem funkcyjnym. 137 8

#include <functional> // std::multiplies #include <numeric> // std::adjacent_difference int myop (int x, int y) {return x+y; int val[] = {1,2,3,5,9,11,12; int result[7]; std::adjacent_difference (val, val+7, result, std::multiplies<int>()); std::cout << "using functional operation multiplies: "; for (int i=0; i<7; i++) std::cout << result[i] << ' '; std::adjacent_difference (val, val+7, result, myop); std::cout << "using custom function: "; for (int i=0; i<7; i++) std::cout << result[i] << ' '; Ogólna konwencja dotycząca parametrów algorytmów: alg(beg, end, other args); alg(beg, end, dest, other args); alg(beg, end, beg2, other args); alg(beg, end, beg2, end2, other args); beg, end zakres pierwszego zbioru przechowującego dane wejściowe, na których działa algorytm alg dest iterator wskazujący miejsce, gdzie ma być zapisany wynik działania algorytmu alg. Algorytm zakłada, że miejsce to jest bezpieczne, tj. np. dostatecznie duże (nie wykonuje kroku weryfikacji). beg2, end2 zakres drugiego zbioru przechowującego dane wejściowe; algorytmy, korzystające tylko z beg2 zakładają, że liczba elementów drugiej sekwencji jest co najmniej tak duża jak zakres beg, end. 138 139 Ogólna konwencja dotycząca parametrów algorytmów: Algorytmy używające predykatów występują w dwóch wersjach, np.: 1. unique(beg, end); // używa == do porównywania 2. unique(beg, end, comp); // używa comp do porównywania Pierwsza używa przeciążonego operatora logicznego < lub == zdefiniowanego dla typu danych przechowywanych w kontenerze. Druga używa obiektu funkcyjnego, tj. predykatu comp Ogólna konwencja dotycząca parametrów algorytmów: Algorytmy mające w nazwie if występują w dwóch wersjach, np.: 1. find(beg, end, val); // znajduje pierwsze wystąpienie val 2. find_if(beg, end, pred); // znajduje pierwszą wartość, // gdzie pred==true Algorytmy mające w nazwie _copy występują w dwóch wersjach, np.: 1. reverse(beg, end); // odwraca porządek elementów 2. reverse_copy(beg, end, dest); // kopiuje w odwrotnym // porządku do dest 140 141 Algorytmy kontenera list: W przeciwieństwie do innych kontenerów, kontener list definiuje kilka algorytmów jako swoje własne metody. Np. dla obiektu lst można wywołać: lst.merge(lst2); // używa operatora < lst.merge(lst2, comp); // używa comp lst.remove(val); // używa operatora == lst.remove_if(pred); // używa pred lst.reverse(); lst.sort(); // używa operatora < lst.sort(comp); // używa comp lst.unique(); // używa operatora == lst.unique(pred); // używa pred 142 Algorytmy kontenera list: Algorytm splice może wystąpić z różnymi listami argumentów, np. dla lst.splice : 1. (p, lst2), gdzie p iterator na element w lst. Przenosi elementy z kontenera lst2 do lst tuż przed p usuwając je z lst2 (lst i lst2 nie mogą być tym samym kontenerem i muszą być tego samego typu), 2. (p, lst2, p2), gdzie p iterator na element w lst, a p iterator na element w lst2. Przenosi element p2 do lst w miejsce tuż przed p. (lst i lst2 mogą być tym samym kontenerem), 3. (p, lst2, b, e), gdzie p iterator na element w lst, a b i e określają przedział w kontenerze lst2. Przenosi elementy z przedziału do lst w miejsce tuż przed p. (lst i lst2 mogą być tym samym kontenerem, ale p nie może należeć do przedziału b,e). 143 9

Algorytmy kontenera list: Algorytmy zadeklarowane jako metody są szybsze od algorytmów generycznych: algorytmy generyczne zamieniają przechowywane wartości, algorytmy zadeklarowane jako metody działają na wskaźnikach reprezentujących linki między elementami kontenera. C++: STL Implementowanie własnych algorytmów 144 STL: implementowanie algorytmów Algorytm przeszukiwania w głąb Przeszukiwanie grafu odwiedzenie wszystkich jego wierzchołków w kolejności jak na rysunku obok: Reprezentacja grafu w programie Wierzchołki są identyfikowane przez liczby całkowite. Dla każdego z wierzchołków przechowujemy listy numerów wierzchołków, z którymi jest połączony krawędzią: vector< vector<int> > 146 STL: implementowanie algorytmów Algorytm przeszukiwania w głąb typedef vector<int> vi; typedef vector<vi> vvi; int N; // liczba wierzchołków vvi W; // graf vi V; // V zawiera flagi określające, czy wierzchołek został odwiedzony void dfs(int i) { if(!v[i]) { V[i] = true; // zaznaczamy węzeł jako odwiedzony for_each(w[i].begin(), W[i].end(), dfs); // rekurencyjne wywołanie bool check_graph_connected_dfs() { int start_vertex = 0; V = vi(n, false); dfs(start_vertex); return (find(v.begin(), V.end(), 0) == V.end()); 147 10