Krótkie wprowadzenie do STL. XIV LO im. S. Staszica, K06 D

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

Kontenery i iteratory. Wykorzystanie kontenerów w praktyce.

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

Kurs programowania. Wykład 9. Wojciech Macyna

Programowanie i struktury danych

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

STL Standardt Template Library (wprowadzenie)

Kompletna dokumentacja kontenera C++ vector w -

Algorytmy i Struktury Danych. Anna Paszyńska

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

STL: Lekcja 1&2. Filozofia STL

Struktury danych: stos, kolejka, lista, drzewo

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

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

Wykład 4. Klasa List Kolejki Stosy Słowniki

Paradygmaty programowania

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

Struktury Danych i Złożoność Obliczeniowa

Algorytmy w C++ dla opornych!

Java Collections Framework

Język C++ część 9 szablony klas. Jarosław Gramacki Instytut Informatyki i Elektroniki. szablony funkcji

Język C++ wykład VIII

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

Dynamiczny przydział pamięci w języku C. Dynamiczne struktury danych. dr inż. Jarosław Forenc. Metoda 1 (wektor N M-elementowy)

Zaawansowane programowanie w języku C++ Biblioteka standardowa

Technologie programowania Wykład 4. Szablony funkcji Notes. Szablony funkcji Notes. Szablony funkcji Notes. Notes. Przemek Błaśkiewicz.

Algorytmy i struktury danych. Wykład 4 Tablice nieporządkowane i uporządkowane

Stos LIFO Last In First Out

Podstawowe struktury danych

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.

Zajęcia nr 5 Algorytmy i wskaźniki. dr inż. Łukasz Graczykowski mgr inż. Leszek Kosarzewski Wydział Fizyki Politechniki Warszawskiej

Programowanie Komponentowe Zarządzanie obiektami: kontenery

Wykład 3. Złożoność i realizowalność algorytmów Elementarne struktury danych: stosy, kolejki, listy

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

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

Biblioteka standardowa C++

Lista, Stos, Kolejka, Tablica Asocjacyjna

Programowanie w C++ z użyciem kontenerów - parę przykładów programów Opracowanie: dr hab. Mirosław R. Dudek, prof. UZ

Listy i funkcje zaprzyjaźnione w C++

Struktura danych. Sposób uporządkowania informacji w komputerze. Na strukturach danych operują algorytmy. Przykładowe struktury danych:

STL Standard Template Library

Programowanie w języku Java. Kolekcje

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

Algorytmy i Struktury Danych

INFORMATYKA W SZKOLE. Podyplomowe Studia Pedagogiczne. Dr inż. Grażyna KRUPIŃSKA. D-10 pokój 227

java.util.* :Kolekcje Tomasz Borzyszkowski

Algorytmy i. Wykład 3: Stosy, kolejki i listy. Dr inż. Paweł Kasprowski. FIFO First In First Out (kolejka) LIFO Last In First Out (stos)

Zaawansowane programowanie w C++ (PCP)

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

Struktury danych (I): kolejka, stos itp.

Teoretyczne podstawy informatyki

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

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

Functionalization. Funkcje w C. Marcin Makowski. 30 listopada Zak lad Chemii Teoretycznej UJ

Szablon klasy std::vector

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

Programowanie w C++ Wykład 8. Katarzyna Grzelak. 7 maja K.Grzelak (Wykład 8) Programowanie w C++ 1 / 31

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

Jak Windows zarządza pamięcią?

Programowanie w C++ Wykład 6. Katarzyna Grzelak. kwiecień K.Grzelak (Wykład 6) Programowanie w C++ 1 / 40

wykład IV uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C, a C++. wykład IV dr Jarosław Mederski Spis Język C++ - wstęp

Algorytmy i struktury danych

Praktycznie całe zamieszanie dotyczące konwencji wywoływania funkcji kręci się w okół wskaźnika stosu.

Analiza algorytmów zadania podstawowe

Listy, krotki, słowniki, funkcje

1 Podstawy c++ w pigułce.

Zadanie 1 Przygotuj algorytm programu - sortowanie przez wstawianie.

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

Szablony funkcji i szablony klas

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

Algorytmy i Struktury Danych.

Języki i techniki programowania Ćwiczenia 2

Kontenery, algorytmy

Operatory na rzecz typu TString


Szablon klasy std::list

Wstęp do programowania

Wstęp do programowania

W przypadku STL w specyfikacji nazwy pliku nagłówkowego brak rozszerzenia tj. <string> <string.h> zamiast

Wstęp do programowania

Programowanie obiektowe

Algorytmy i struktury danych

Algorytmy i Struktury Danych. Co dziś? Drzewo decyzyjne. Wykład IV Sortowania cd. Elementarne struktury danych

Język ludzki kod maszynowy

operacje porównania, a jeśli jest to konieczne ze względu na złe uporządkowanie porównywanych liczb zmieniamy ich kolejność, czyli przestawiamy je.

dr inż. Jarosław Forenc

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

Tablice. Monika Wrzosek (IM UG) Podstawy Programowania 96 / 119

Paradygmaty programowania

prowadzący dr ADRIAN HORZYK /~horzyk tel.: Konsultacje paw. D-13/325

Programowanie komputerowe. Zajęcia 4

Drzewa poszukiwań binarnych

10.1 Szablony Szablony funkcji Szablony klas Szablony jako wstęp do biblioteki STL... 10

Realizacja ekstensji klasy. Paulina Strzelecka, Tomasz Roszkowski

Program 14. #include <iostream> #include <ctime> using namespace std;

Zaawansowane programowanie w C++ (PCP)

E S - uniwersum struktury stosu

Sortowanie. Kolejki priorytetowe i algorytm Heapsort Dynamiczny problem sortowania:

Algorytmy i struktury danych. Wykład 6 Tablice rozproszone cz. 2

Transkrypt:

Krótkie wprowadzenie do STL XIV LO im. S. Staszica, K06 D Arkadiusz Betkier Wojciech Sirko 30 marca 2010

Spis treści 1 Wstęp 2 2 Podstawowe struktury danych 4 2.1 pair................................ 4 2.2 stack................................ 5 2.3 queue............................... 5 2.4 list................................. 6 2.5 vector............................... 8 2.6 deque............................... 8 2.7 priority queue........................... 9 2.8 set................................. 10 2.9 map................................ 11 3 Podstawowe algorytmy 13 3.1 swap................................ 13 3.2 min................................. 13 3.3 max................................ 13 3.4 sort................................. 14 3.5 stable sort............................. 15 3.6 nth element............................ 15 3.7 reverse............................... 15 3.8 next permutation......................... 16 3.9 random shuffle........................... 17 1

1 Wstęp STL (Standard Template Library) jest biblioteką języka C++ zawierającą implementacje pewnych przydatnych algorytmów i struktur danych. Niniejszy dokument stanowi jedynie, poddane pewnym uproszczeniom i przemilczeniom, wprowadzenie dokumentacja STL znajduje się na stronie SGI (http://www.sgi.com/tech/stl/) i jest znacznie obszerniejsza. STL zawdzięcza swoją użyteczność m.in. zastosowaniu szablonów. Są one uogólnieniem klas lub funkcji, których właściwy kod powstaje w czasie kompilacji, po podaniu przez programistę pewnych parametrów (parametry te mogą być typami danych, klasami, czy stałymi liczbowymi). Szablony pozwalają programiście zaoszczędzić czas, gdyż umożliwiają wykorzystanie pewnej ogólnej implementacji do konkretnego zastosowania bez konieczności kopiowania kodu, by np. zmienić użyty typ danych. Mimo licznych zalet STL a, nadużywanie go może prowadzić do niepożądanych skutków, takich jak niepotrzebnie skomplikowane czy niewydajne rozwiązania. Zaleca się więc umiar i rozwagę. 2

// Tak moga wygladac s z a b l o n y. // S z a b l o n k l a s y AB. template < c l a s s T> c l a s s AB { public : AB(T a, T b) : a(a), b(b) {} T sum () { return a+b; } private : T a, b; }; // S z a b l o n f u n k c j i abs. template < c l a s s T> T abs (T a) { i f (x < 0) return -x; e l s e return x; } // W przypadku szablonow k l a s n a l e z y w y r a z n i e // podac parametry s z a b l o n u w nawiasach o s t r y c h. AB < int > abi (1, 3); abi. sum (); // z w r o c i 4 AB < f l o a t > abf (1.4f, 2.5 f); abf. sum (); // z w r o c i 3. 9 f // W przypadku szablonow f u n k c j i parametry sa // rozpoznawane na p o d s t a w i e podanych // argumentow f u n k c j i. abs ( -4); // z w r o c i 4 abs ( -3.9 f) // z w r o c i 3. 9 f 3

2 Podstawowe struktury danych Poniższe opisy struktur składają się z tekstu, tabelek z kluczowymi (nie wszystkimi) operacjami i przykładowych kodów. Tabelki zawierają nazwy operacji, skrótowe opisy i złożoność obliczeniową. Typu wartości operacji nietrudno się domyślić, natomiast w kwestii argumentów przyjęta jest taka konwencja: v oznacza wartość typu takiego, jaki jest trzymany w strukturze, k oznacza indeks można przyjąć, że jest to int, natomiast i oznacza iterator więcej o tym przy listach. Pomijając pair przypadek zdegenerowany, wszystkie wymienione poniżej struktury udostępniają dodatkowo operację clear(), która działa w czasie liniowym i odpowiada za usunięcie wszystkich elementów ze struktury oraz operację empty(), która określa (w czasie stałym), czy struktura jest pusta. Oczywiście wszystkie złożoności obliczeniowe są podane względem liczby elementów w strukturze. Ku przejrzystości przykładowego kodu (i aby nakłonić czytelnika do niestosowania metody copy-paste bez pełnego zrozumienia) nie będą się w nim pojawiać instrukcje wypisywania na wyjście. Zamiast tego pojawiać się będą wyrażenia zakończone średnikiem i opatrzone komentarzami określającymi ich wartości. Liczy się przy tym na domyślność czytelnika. Ponadto zakłada się, że przed miejscem użycia kodu wpisano using namespace std, w przeciwnym przypadku trzeba podopisywać std:: w odpowiednie miejsca. 2.1 pair Obiekt pair przechowuje dwa elementy first i second (dostępne wprost). Funkcja make pair tworzy odpowiednią parę. Oczywiście można też skorzystać ze standardowego konstruktora. #include <utility > pair < f l o a t, int > para (0.1f, 9); para. first ; // > 0. 1 f para. second ; // > 9 para. first = 0.5 f; para. second = 3; // pow to p r o c e d u r a od potegowania // t r z e b a d o p i s a c #i n c l u d e <cmath> pow ( para. first, para. second ); // > 0. 1 2 5 f para = make_pair (2.0f, 10) ; pow ( para. first, para. second ); // > 1 0 2 4. 0 f 4

2.2 stack Struktura stack to STL owy stos. Stos, jaki jest, każdy widzi można dokładać na wierzch, oglądać wierzch i z niego zdejmować, ale żeby nagle dostać się gdzieś do środka, trzeba się na ogół nieźle napracować. size() rozmiar stosu O(1) push(v) dodawanie na wierzch O(1) pop() zrzucanie z wierzchu O(1) top() element na wierzchu O(1) #include <stack > // typ i n t j e s t po to, aby p r z y k l a d u p r o s c i c // moznaby z a m i a s t t e g o np. utoworzyc s t o s // s t a c k < p a i r < s t a c k <f l o a t >, i n t > > // s z a b l o n y mozna w i e c bez problemu s k l a d a c stack < int > stos ; stos. push (123) ; stos. push (456) ; stos. push (789) ; stos. size (); // > 3 while (! stos. empty ()) { stos. top (); // > { 789, 456, 123 } stos. pop (); } 2.3 queue Struktura queue odpowiada kolejce (takiej typowej, jak w sklepiku po pączki). Można więc wstawić element na koniec, zrzucić z początku i obejrzeć ten na początku i ten na końcu. Jednak, tak jak poprzednio, nie tak łatwo dostać się do środka. size() rozmiar kolejki O(1) push(v) dodawanie na koniec O(1) pop() zrzucanie z początku O(1) front() element na początku O(1) back() element na końcu O(1) 5

#include <queue > queue < int > kolejka ; kolejka. push (123) ; kolejka. push (456) ; kolejka. push (789) ; kolejka. size (); // > 3 while (! kolejka. empty ()) { kolejka. front (); // > { 123, 456, 789 } kolejka. pop (); } 2.4 list Więcej operacji udostępnia list lista dwukierunkowa. Można wstawiać, oglądać i usuwać elementy z końców. Ponadto można listę przeglądać, zarówno od początku do końca jak i przeciwnie. Co więcej (i to jest kluczowa własność listy), można usunąć element z dowolnego miejsca, jak również wstawić element w dowolne miejsce, pod warunkiem posiadania pod ręką odpowiedniego wskaźnika. Taki wskaźnik w STL u nazywa się iteratorem i jest dodatkowo wyposażony w instrukcję zwiększania (zmniejszania) odpowiednią dla konkretnej struktury danych. W przypadku listy zwiększenie oznacza przeskok do następnego elementu na liście. Iterator na pierwszy element uzyskuje się wywołując na liście begin(), a na za-ostani-element wywołując end() będzie to widać w przykładzie. size() rozmiar listy O(?) a push back(v) dodawanie na koniec O(1) pop back() zrzucanie z końca O(1) back() element na końcu O(1) push front(v) dodawanie na początek O(1) pop front() zrzucanie z początku O(1) front() element na początku O(1) erase(i) usuwanie wskazanego elementu O(1) insert(i, v) wstawianie przed wskazany element O(1) a Nie ma gwarancji, że jest to O(1) równie dobrze może być O(n). Zależy to od konkretnej implementacji STL, dlatego lepiej nie używać size w tym przypadku. 6

#include <list > list < int > lista ; // na poczatku p u s t a l i s t a list < int >:: iterator it; // to s i e j e s z c z e przyda list < int >:: iterator cit ; // to t e z // wpierw zwykle dodawanie na konce for ( int x = 0; x < 5; x ++) { lista. push_back (x + 5); lista. push_front (-x * 2); } // po t e j o p e r a c j i l i s t a wyglada tak : // { 8, 6, 4, 2, 0, 5, 6, 7, 8, 9 } lista. size (); // > 10 for (it = lista. begin (); it!= lista. end (); it ++) *it; // > { 8, 6, 4, 2, 0, 5, 6, 7, 8, 9 } // usuwanie z b r z e g u... lista. pop_front (); lista. pop_back (); lista. front (); // > 6 lista. back (); // > 8 // znajdzmy c o s... for (it = lista. begin (); it!= lista. end (); it ++) i f (* it % 2 == 1) cit = it, break; // t e r a z c i t w s k a z u j e na p i e r w s z y n i e p a r z y s t y // e l e m e n t na l i s c i e ( 5 ) // ( na s z c z e s c i e t a k i i s t n i e j e, // i n a c z e j z r o b i l i b y s m y tu powazny b l a d ) // ponadto c i t == i t lista. erase (++ it); // zobaczmy, co s i e s t a l o z l i s t a u s u n e l i s m y // n a s t e p n i k p i e r w s z e g o n i e p a r z y s t e g o elementu for (it = lista. begin (); it!= lista. end (); it ++) *it; // > { 6, 4, 2, 0, 5, 7, 8 } // t e r a z wstawimy 6 z powrotem, a l e tym razem // p r z e d 5 ( c i t n a d a l w s k a z u j e na 5) lista. insert (cit, 6); for (it = lista. begin (); it!= lista. end (); it ++) *it; // > { 6, 4, 2, 0, 6, 5, 7, 8 } 7

2.5 vector Twór o nazwie vector łączy zalety stosu i tablicy. Odpowiada stack w sensie dodawania i usuwania elementów, ale pozwala na bezpośrednie odwoływanie się do każdego z nich tak, jak w zwykłej tablicy. Idea kryjąca się w implementacji tego tworu jest dość prosta stwórz tablicę, a gdy miejsce się w niej skończy, stwórz dwa razy większą tablicę i przekopiuj elementy ze starej do nowej, itd... size() rozmiar O(1) push back(v) dodawanie na koniec O(1) pop back() zrzucanie z końca O(1) back() element na końcu O(1) [k] referencja na k-ty element O(1) #include <vector > vector < int > vec ; vec. push_back (123) ; vec. push_back (456) ; vec. push_back (789) ; for ( int i = 0; i < vec. size (); i ++) vec [i]; // > { 123, 456, 789 } vec [1] = 666; while (! vec. empty ()) { vec. back (); // > { 789, 666, 123 } vec. pop_back (); } 2.6 deque Bardziej wyrafinowaną strukturą jest deque, która z zewnątrz zachowuje się podobnie jak vector, ale pozwala wstawiać i usuwać z obu stron z końca i z początku. Innymi słowy, jest to kolejka dwustronna, która dodatkowo umożliwia bezpośrednie odwoływanie się do każdego elementu. 8

size() rozmiar O(1) push back(v) dodawanie na koniec O(1) pop back() zrzucanie z końca O(1) back() element na końcu O(1) push front(v) dodawanie na początek O(1) pop front() zrzucanie z początku O(1) front() element na początku O(1) [k] referencja na k-ty element O(1) #include <deque > deque < int > deq ; deq. push_back (123) ; deq. push_back (456) ; deq. pop_front (); deq. push_front (789) ; deq. push_back (111) ; for ( int i = 0; i < deq. size (); i ++) deq [i]; // > { 789, 456, 111 } deq [1] = 666; while (! deq. empty ()) { deq. back (); // > { 111, 666, 789 } deq. pop_back (); } 2.7 priority queue Czasem przydaje się też priority queue kolejka priorytetowa. Wstawia się do niej elementy, a ona zawsze daje szybki dostęp do elementu największego i umożliwia jego usunięcie. Niektórzy chcieliby, aby zamiast zwykłej największości można tu było umieścić bardziej wyrafinowane kryterium porównywania. Jest to możliwe, podobnie jak przy sortowaniu (patrz: 3.4), przy czym trzeba to jeszcze sprytnie zapakować w strukturę. Szczegóły w dokumentacji STL. size() rozmiar kolejki O(1) push(v) dodawanie O(log n) pop() zrzucanie największego O(log n) top() element największy O(1) 9

#include <queue > priority_queue < int > pq. push (5) ; pq.top (); // > 5 pq. push (8) ; pq.top (); // > 8 pq. push (3) ; pq.top (); // > 8 pq.pop (); pq.top (); // > 5 pq.pop (); pq.top (); // > 3 pq; 2.8 set Struktura set służy do reprezentacji zbioru (powtórzenia elementów redukują się). Elementy można dodawać, usuwać i wyszukiwać. Ponadto można wyszukać pierwszy element o wartości niemniejszej (większej) od podanej. Można też przeglądać set w kolejności od najmniejszej wartości do największej 1. Dla bardziej dociekliwych set jest zaimplementowany przy użyciu drzew czerwono-czarnych, a w komentarzach w kodzie pojawiają się odwołania do Cormena. size() rozmiar O(1) insert(v) dodawanie O(log n) find(v) wyszukiwanie a O(log n) erase(v) usuwanie po wartości O(log n) erase(i) usuwanie po iteratorze b O(log n) lower bound(v) pierwszy element niemniejszy O(log n) upper bound(v) pierwszy element większy O(log n) a Jeżeli element nie występuje w zbiorze, zwrócony zostanie iterator s.end(), gdzie s to nazwa tego zbioru. W przeciwnym przypadku będzie to iterator na znaleziony element. b Usuwanie po iteratorze jest w rzeczywistości nieco szybsze niż po wartości, niemniej złożoność jest taka sama. 1 W kwestii przeglądania i iteratorów, patrz: list. 10

#include <set > set < int > s; set < int >:: iterator it; s. insert (123) ; s. insert (456) ; s. insert (789) ; s. insert (111) ; s. insert (999) ; s. erase (456) ; for (it = s. begin (); it!= s. end (); it ++) *it; // > { 111, 123, 789, 999 } it = s. lower_bound (500) ; *it; // > 789 s. erase (it); for (it = s. begin (); it!= s. end (); it ++) *it; // > { 111, 123, 999 } *s. begin (); // > 111 // t e s t na o b e c n o s c wynik : n i e o b e c n y it = s. find (1000) ; (it!= s. end ()); // > f a l s e // a t u wynik pozytywny it = s. find (111) ; (it!= s. end ()); // > t r u e 2.9 map Struktura map służy do reprezentacji przyporządkowania. Działa prawie jak set< pair<x,y> > z tą różnicą, że elementy są porównywane tylko względem pierwszej wartości (klucza) z pary. Dodatkowo elementy można wstawiać i odwoływać się do nich przy użyciu operatora [ ]. Tu wyjątkowo k oznacza klucz, a v wartość przyporządkowaną. 11

size() rozmiar O(1) [k] = v dodawanie / zmiana wartości O(log n) [k] odwołanie do wartości pod kluczem a O(log n) find(k) wyszukiwanie po kluczu O(log n) erase(k) usuwanie po kluczu O(log n) erase(i) usuwanie po iteratorze O(log n) lower bound(k) pierwszy element niemniejszy b O(log n) upper bound(k) pierwszy element większy c O(log n) a Odwołanie jest przez referencję wartość można dowolnie modyfikować. b Względem klucza, nie zaś wartości. c Względem klucza. #include <map > map < int, f l o a t > m; map < int, f l o a t >:: iterator it; m [0] = 1.0 f; m [256] = 3.14 f; m [42] = 4.2 f; m [ 1000* 1000* 1000] = 1. 618 f; m [0] = 1.1 f; m. size (); // > 4 m [256]; // > 3. 1 4 f // t e r a z i t e r a t o r w s k a z u j e na p are // ( k l u c z, w a r t o s c ) // k o l e j n o s c p r z e g l a d a n i a j e s t r o s n a c a po k l u c z u for (it = m. begin (); it!= m. end (); it ++) (* it). first ; // > { 0, 42, 256, 1000000000 } for (it = m. begin (); it!= m. end (); it ++) (* it). second ; // > { 1. 1 f, 4. 2 f, 3. 1 4 f, 1. 6 1 8 f } m. erase (256) ; m. size (); // > 3 // s p r a w d z a n i e o b e c n o s c i k l u c z a it = m. find (256) ; (it!= m. end ()); // > f a l s e it = m. find (42) ; (it!= m. end ()); // > t r u e m. erase (it); m. size (); // > 2 m [0] += 1.1 f; m [0]; // > 2. 2 f 12

3 Podstawowe algorytmy Przez ciąg będziemy tu rozumieć strukturę danych umożliwiającą bezpośrednie odwoływanie się do elementów (np.: tablica, vector). Litera n w złożoności odpowiada oczywiście długości danego ciągu. 3.1 swap Złożoność obliczeniowa: O(1) Funkcja swap powoduje, iż dwie zmienne wymieniają się wartościami. #include <algorithm > int a = 123, b = 321; swap (a, b); a; // > 321 b; // > 123 3.2 min Złożoność obliczeniowa: O(1) Funkcja min zwraca mniejszą (dokładniej niewiększą) z dwóch wartości. Konkretniej zwraca referencję do wartości, co bywa bardzo wygodne. #include <algorithm > int a = 26, b = 12; min (a, b); // > 12 min (a, b) ++; a; // > 26 b; // > 13 3.3 max Złożoność obliczeniowa: O(1) Funkcja max zwraca większą (dokładniej niemniejszą) z dwóch wartości. Reszta analogicznie do min. 13

3.4 sort Złożoność obliczeniowa: O(n log n) Funkcja sort sortuje ciąg. Zamiast sortować ciąg standardowo, można podać własną funkcję porównującą, względem której odbędzie się sortowanie 2. #include <algorithm > #include <vector > // Ta f u n k c j a odpowiada porzadkowi, w ktorym // w s z y s t k i e l i c z b y n i e p a r z y s t e sa m n i e j s z e // od k a z d e j p a r z y s t e j, // a l i c z b y o j e d n a k o w e j p a r z y s t o s c i // sa uporzadkowane standardowo. bool cmp_parz ( const int & a, const int & b) { i f (a % 2 == b % 2) return a <= b; e l s e return (a % 2 == 1); } int liczby [] = { 5, 8, 3, 6, 1, 2, 7 }; // s o r t u j e m y n a s z a f u n k c j a porownujaca sort ( liczby, liczby + 7, cmp_parz ); for ( int i = 0; i < 7; i ++) liczby [i]; // > { 1, 3, 5, 7, 2, 6, 8 } // s o r t u j e m y standardowa f u n k c j a porownujaca <= sort ( liczby, liczby + 7); for ( int i = 0; i < 7; i ++) liczby [i]; // > { 1, 2, 3, 5, 6, 7, 8 } vector < int > vec ; for ( int i = 0; i < 7; i ++) vec. push_back (7 - i); // vec : { 7, 6, 5, 4, 3, 2, 1 } sort ( vec. begin (), vec. end ()); for ( int i = 0; i < vec. size (); i ++) vec [i]; // > { 1, 2, 3, 4, 5, 6, 7 } 2 Taka funkcja porównująca musi mieć dwa argumentu typu const referencja do wyrazu ciągu i zwracać bool. Funkcja ta nie może być zupełnie dowolna musi odpowiadać pewnemu porządkowi liniowemu. Ciąg posortowany ma wówczas tę własność, że dla każdych dwóch kolejnych wyrazów ciągu wartość funkcji porównującej na tych wyrazach wynosi true. 14

3.5 stable sort Złożoność obliczeniowa: O(n log n) Do sortowania stabilnego przydaje się stable sort. Używa się tak samo, jak sort, dlatego przykładu nie będzie. 3.6 nth element Złożoność obliczeniowa: O(n) Funkcja nth element przestawia wyrazy danego ciągu w taki sposób, że na n-tej pozycji stoi taki wyraz jaki stałby w ciągu posortowanym, a dodatkowo każdy wyraz stojący na prawo od n-tego jest niemniejszy od każdego stojącego na lewo od n-tego. Argumentem funkcji wyznaczającym n-tą pozycję nie jest jednak liczba n, a iterator (wskaźnik) wskazujący na n-tą pozycję. #include <algorithm > // Chcemy z n a l e z c mediane t a k i e g o c i a g u : int liczby [] = { 10, 1, 2, 7, 2, 5, 9 }; int n = 7; // r o z m i a r n a s z e g o c i a g u ( n i e p a r z y s t y! ) // po p o s o r t o w a n i u c i a g wygladalby tak : // { 1, 2, 2, 5, 7, 9, 10 } // mediana j e s t na srodku na poz. ( n 1) / 2 // w tym wypadku mediana t o 5 ( na poz. 3) nth_element ( liczby, liczby + (n - 1) / 2, liczby + n ); liczby [(n - 1) / 2]; // > 5 3.7 reverse Złożoność obliczeniowa: O(n) Funkcja reverse odwraca ciąg. #include <algorithm > #include <vector > vector < int > vec ; for ( int i = 0; i < 7; i ++) vec. push_back (i); // wyglada tak : { 0, 1, 2, 3, 4, 5, 6 } reverse ( vec. begin (), vec. end ()); // a t e r a z tak : { 6, 5, 4, 3, 2, 1, 0 } 15

3.8 next permutation Złożoność obliczeniowa: O(n) Funkcja next permutation przekształca ciąg w jego kolejną leksykograficznie permutację 3. Wartością funkcji jest true, jeżeli taka permutacja istnieje. W przeciwnym przypadku jest to false, co oznacza osiągnięcie największej leksykograficznie permutacji ciągu posortowanego nierosnąco. Nasuwa się więc wniosek, że aby przejrzeć wszystkie permutacje musimy zacząć od ciągu posortowanego niemalejąco. #include <algorithm > vector < int > vec ; vec. push_back (3) ; vec. push_back (5) ; vec. push_back (7) ; do { for ( int i = 0; i < vec. size (); i ++) vec [i]; // > ( p a t r z n i z e j ) } while ( next_permutation ( vec. begin (),vec. end ())); // w y n i k i beda t a k i e : // > { 3, 5, 7 } // > { 3, 7, 5 } // > { 5, 3, 7 } // > { 5, 7, 3 } // > { 7, 3, 5 } // > { 7, 5, 3 } 3 Porządek leksykograficzny dla dwóch różnych ciągów tej samej długości wyznacza się w ten sposób, że porównuje się ich kolejne wyrazy aż do pierwszej napotkanej (ostrej) nierówności ona zaś określa nierówność między ciągami. 16

3.9 random shuffle Złożoność obliczeniowa: O(n) Funkcja random shuffle ustawia wyrazy ciągu w losowej kolejności. #include <algorithm > int liczby [] = { 1, 2, 3, 4, 5, 6, 7 }; // t u t a j, na k o n i e c i jako, ze j e s t malo kodu : // standardowy t r i k na o k r e s l e n i e // r o z m i a r u s t a t y c z n i e s t w o r z o n e j t a b l i c y // uwaga : to d z i a l a poprawnie t y l k o wtedy, // gdy d e k l a r a c j a t a b l i c y j e s t widoczna int n = s i z e o f ( liczby )/ s i z e o f (* liczby ); n; // > 7 // a t e r a z do r z e c z y random_shuffle ( array, array + n); // trudno p r z e w i d z e c e f e k t // moze byc np. t a k i : // { 5, 3, 2, 4, 6, 1, 7 } 17