it = copy(srcBeg, srcEnd, destBeg)
it = copy_if(srcBeg, srcEnd, destBeg, op)
it = copy_n (srcBeg, num, destBeg)
it = copy_backward (srcBeg, srcEnd, destEnd)
Algoritmi djeluju na spremnike kroz iteratore.
<algorithm> osim nekoliko numeričkih koji su
definirani u zaglavlju <numeric> te algoritama u <memory> zaglavlju.
_if. Ova verzija uzima predikat dok osnovna verzija uzima vrijednost. Na primjer, find() i find_if().
_copy. Ova verzija kopira ulazni niz, dok osnovna radi na njemu. Na primjer, reverse() i reverse_copy() .
_n. Ova verzija umjesto end iteratora uzima broj elemenata s kojima treba raditi.
Algoritmi su podijeljeni u nekoliko grupa:
Osnovna literatura za algoritme je https://en.cppreference.com
Definirani su u zaglavlju <algorithm>.
all_of, any_of, none_of provjera predikata
for_each, for_each_n (C++17) primjena funkcije na elemente
count, count_if broj elemenata koji zadovoljavaju kriterij
mismatch prvo mjesto razlikovanja
find, find_if, find_if_not nalaženje elementa
find_end nalaženje posljednjeg niza elemenata
find_first_of nalaženje bilo koje elementa iz skupa
adjacent_find nalaženje prva dva jednaka elementa
search, search_n potraga za nizom elemenata
Definirani su u zaglavlju <algorithm>.
copy, copy_if, copy_n, copy_backward kopiranje elemenata
move, move_backward micanje elemenata
fill, fill_n kopiranje zadane vrijednosti
transform primjeni funkciju na kolekciju
generate, generate_n sukcesivni funkcijski pozivi
remove, remove_if, remove_copy, remove_copy_if uklanjanje elemenata
replace, replace_if, replace_copy , replace_copy_if zamjena elemenata
swap, swap_ranges, iter_swap međusobna zamjena elemenata
reverse, reverse_copy inverzija kolekcije
rotate, rotate_copy rotacija elemenata kolekcije
shift_left, shift_right (C++20) pomak elemenata
shuffle slučajno preuređivanje
sample (C++17) slučajni izbor elemenata
unique, unique_copy ukloni konsekutivne duplikate
Definirani su u zaglavlju <algorithm>.
is_partitioned ispitivanja particioniranosti
partition, partition_copy, stable_partition particioniranje
partition_point lociranje razdijelne točke
is_sorted provjera sortiranosti
is_sorted_until najveći sortirani raspon
sort, stable_sort sortiranje
partial_sort, partial_sort_copy, nth_element parcijalno sortiranje
lower_bound prvi element koji nije manji od zadanog
upper_bound prvi element veći od zadanog
binary_search binarno pretraživanje
equal_range raspon ekvivalentnih elemenata
merge, inplace_merge spajanje sortiranih kolekcija
Definirani su u zaglavlju <algorithm>.
includes inkluzija
set_difference skupovna razlika
set_intersection presjek
set_symmetric_difference simetrična razliak
set_union unija
is_heap je li max hrpa
is_heap_until najveći raspon koji je max hrpa
make_heap učini max hrpom
push_heap dodaj element u max hrpu
pop_heap ukloni element iz max hrpe
sort_heap pretvorimax hrpu u rastući niz
max , max_element maksimum
min , min_element minimum
minmax , minmax_element minimum i maksimum
clamp (C++17) odsjecanje između dva praga
equal jednakost
lexicographical_compare leksikografsko uspoređivanje
compare_3way, lexicographical_compare_3way (C++20) trostruko uspoređivanje
is_permutation je li permutacija nečega
next_permutation sljedeća permutacija
prev_permutation prethodna permutacija
Definirani su u zaglavlju <numeric>.
iota ispuni suksesivnim inkrementima
accumulate, reduce (C++17) sumiraj
inner_product skalarni produkt
adjacent_difference diferencije elemenata
partial_sum, exclusive_scan (C++17), inclusive_scan (C++17) parcijalne sume
transform_reduce (C++17) primjena funkcije i zatim redukcija
transform_exclusive_scan (C++17) primjena funkcije i exclusive_scan
transform_inclusive_scan (C++17) primjena funkcije i inclusive_scan
Definirani su u zaglavlju <memory>.
uninitialized_copy , uninitialized_copy_n kopiranje
uninitialized_fill , uninitialized_fill_n ispunjavanje
uninitialized_move (C++17), uninitialized_move_n (C++17) premještanje
uninitialized_default_construct (C++17), uninitialized_default_construct_n (C++17) defaultna konstrukcija
uninitialized_value_construct (C++17), uninitialized_value_construct_n (C++17) vrijednosna inicijalizacija
destroy_at (C++17), destroy (C++17), destroy_n (C++17) destrukcija
Ovi algoritmi kopiraju ulazni niz u izlazni niz. Ulazni niz je dan kao raspon elemenata, a izlazni niz je dan samo iteratorom koji pokazuje na prvi element niza.
it = copy(srcBeg, srcEnd, destBeg)
it = copy_if(srcBeg, srcEnd, destBeg, op)
it = copy_n (srcBeg, num, destBeg)
it = copy_backward (srcBeg, srcEnd, destEnd)
copy i copy_if uzimaju raspon elemenata koje kopiraju [srcBeg,srcEnd) i kopiraju ih u spremnik
čiji je početni iterator destBeg.
copy_n uzima iterator na prvi element ulaznog niza i broj elemenata koje treba kopirati.
copy, copy_if i copy_n iteriraju u pozitivnom smjeru pri kopiranju (od srcBeg prema srcEnd)
dok algoritam copy_backward iterira u negativnom smjeru (od srcEnd prema srcBeg). Stoga copy_backward uzima
end-iterator izlaznog niza.
copy_if kopira element samo ako predikat op vrati true.
list<int> lst{1,2,3,4,5};
vector<int> vec(5);
copy(lst.begin(), lst.end(), vec.begin()); // Kopiraj listu u vektor
fill(vec.begin(), vec.end(), 0);
// Kopiraj samo neparne brojeve iz liste u vektor
copy_if(lst.begin(), lst.end(), vec.begin(),
[](int x){ return x % 2; });
// Pisanje preko istog spremnika.
vector<int> vec1{1,2,3,4,5,6,7,8,9};
copy_n(next(vec1.begin(),4),4,vec1.begin()); // 5,6,7,8,5,6,7,8,9,
vector<char> vec2(10,'.');
vec2.push_back('a');
vec2.push_back('b');
vec2.push_back('c');
print(vec2);
// Insertiraj točkice s ulaza na kraj spremnika
vec2.insert(vec2.end(), 10, '.'); // ..........abc..........
// Za kopiranje na kraj istog spremnika koristimo copy_backward
copy_backward(vec2.begin()+10, vec2.begin()+13, vec2.end());
// ..........abc.......abc
for_each i transformfor_eachAlgoritam for_each djeluje na kolekciji zadanoj sa dva iteratora i na svakom elementu kolekcije
poziva funkciju koja je treći argument algoritma. Signatura algoritma je sljedeća:
UnaryProc for_each (InputIterator beg, InputIterator end, UnaryProc op)
gdje je UnaryProc tip funkcije (funkcijskog objekta, lambda izraza) koji se poziva na svakom elementu kolekcije.
Povratna vrijednost je kopija objekta op. Povratna vrijednost od op se ignorira.
Algoritam for_each može mijenjati elemente spremnika ako op uzima argument poreferenci. Ako op
ima unutarnje stanje, to stanje će biti dohvatljivo kroz povratnu vrijednost algoritma.
void f(int& n) { n = n*n; }
// ...
std::vector<int> vek{0,1,2,3,4,5,6,7,8,9};
std::for_each(vek.begin(), vek.end(), f);
// sada je vek = {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}
int noParni = 0;
std::for_each(vek.begin(), vek.end(), [&noParni](int x){
if(!(x % 2))
noParni++;
});
std::cout << noParni << std::endl; // 5
transformAlgoritam transform prolazi kroz ulaznu kolekciju, na svakom elementu kolekcije poziva funkciju op i rezultat
ispisuje u izlaznu kolekciju. Vraća iterator koji pokazuje iza zadnjeg transformiranog elementa u izlaznoj kolekciji.
Signatura algoritma je sljedeća:
OutputIterator transform(InputIterator srcBeg, InputIterator srcEnd, OutputIterator destBeg, UnaryFunc op)
Na primjer,
int f(int n) { return n*n; }
// ...
std::vector<int> vek{0,1,2,3,4,5,6,7,8,9};
std::transform(vek.begin(), vek.end(), vek.begin(), f);
// vek = 0 1 4 9 16 25 36 49 64 81
Algoritam ima verziju koja uzima dva ulazna niza i funkciju sa dva argumenta koja ulazne nizove transformira u izlazni. Na primjer,
int f2(int n, int m) { return n-m; }
// ...
std::random_device rd; // zaglavlje <random>
std::mt19937 g(rd());
std::vector<int> vek1 = vek, vek2(vek.size());
std::shuffle(vek1.begin(), vek1.end(), g); // slučajna permutacija
std::transform(vek.begin(), vek.end(), vek1.begin(), vek2.begin(), f2);
// vek2 = vek - vek1
countAlgoritam count() vraća broj pojavljivanja vrijednosti u nizu: count_if vraća broj elemenata na kojima je
predikat istinit.
n = count(beg, end, value)
n = count_if(beg, end, op)
Na primjer,
int A[] = { 2, 0, 4, 6, 0, 3, 1, -7 };
const int N = sizeof(A) / sizeof(int);
std::cout << "Broj nula: "
<< std::count(A, A + N, 0) << std::endl;
std::cout << "Broj brojeva > 2: "
<< std::count_if(A, A + N, [](int x){ return x>2; }) << std::endl;
findOvi algoritmi vraćaju iterator na prvi nađeni element ili end iterator. Osnovna verzija traži vrijednost,
a druge dvije traže prvi element na kojem je predikat istinit (find_if) ili neistinit (find_if_not).
it = find (beg, end, value)
it = find_if(beg, end, op)
it = find_if_not(beg, end, op)
Na primjer,
std::vector<int> vec{1,4,1,9,4,5,5,7,4};
auto it = find(vec.begin(), vec.end(), 4);
assert(*it == 4);
assert(std::distance(vec.begin(), it) == 1);
it = find_if_not(vec.begin(), vec.end(), [](int x){ return x<7;});
assert(*it == 9);
assert(std::distance(vec.begin(), it) == 3);
searchAlgoritam search traži niz elemenata u kolekciji. Kolekcija koja se pretražuje je dana s prvim parom
iteratora (beg i end), a niz elemenata koji tražimo je zadan s drugim parom iteratora (beg1 i end1).
Za uspoređivanje elemenata se u prvoj verziji algoritma koristi operator ==, a u drugoj binarni predikat
op: op(elem,searchElem) vraća "istinu" ako su elementi isti, a u suprotnom laž.
it = search(beg, end, beg1, end1)
it = search(beg, end, beg1, end1, op)
std::list<int> li{1,2,3,4,5,1,2,3,4,5};
std::array<int,3> niz{3,4,5};
auto it1 = std::search(li.begin(), li.end(), niz.begin(), niz.end());
if(it1 != li.end()){
it1++; // Nađi drugu grupu "niz"
auto it2 = std::search(it1, li.end(), niz.begin(), niz.end());
assert(*it2 == 3);
assert(std::distance(li.begin(),it2) == 7);
}
Algoritam search traži prvi podniz u nizu i vraća iterator na prvu poziciju nađenog podniza ili end iterator.
Algoritam koji traži zadnji podniz u nizu naziva se find_end (umjesto search_end, što bi bilo konzistentno).
fillOvaj algoritam inicijalizira svaki element kolekcije sa zadanom vrijednošću. Ne vraća ništa.
#include <cmath>
std::vector<double> vec(10);
std::fill(vec.begin(), vec.end(), M_PI);
generateOvaj algoritam inicijalizira svaki element kolekcije pozivom funkcije op() koja ne uzima argumente.
#include <cstdlib> // za rand
std::vector<int> vec(5);
std::generate(vec.begin(), vec.end(), rand); // 1804289383,846930886,1681692777,1714636915,1957747793
iotaAlgoritam iota generira niz sikcesivnih vrijednosti (svaka sljedeća je veća za 1)
polazeći od dane vrijednosti.
#include <numeric> // za iota
std::vector<float> vec(5);
std::iota(vec.begin(), vec.end(), 15);// 15,16,17,18,19
Algoritam replace svako pojavljivanje stare vrijednsti zamijenjuje s novom.
Verzija replace_if zamijenjuje svaki element na kojem unarni predikat op vrati istinu s
novom vrijednošću. Verzija _copy ovog algoritma kombinira copy i replace i smješta transformirane
elemente u izlaznu kolekciju.
replace(beg, end, oldValue, newValue)
replace_if(beg, end, op, newValue)
replace_copy(beg, end, destBeg, oldValue, newValue)
replace_copy_if(beg, end, destBeg, op, newValue)
Na primjer,
std::vector<char> vec{'a','b','c','d','e','f'};
std::replace(vec.begin(), vec.end(), 'a', 'x'); // x,b,c,d,e,f
std::vector<char> vec1;
std::replace_copy(vec.begin(), vec.end(), std::back_inserter(vec1), 'e', 'x');
// x,b,c,d,x,f
Algoritmi ne mogu brisati elemente spremnika te stoga samo
prebacuje elemente određene za brisanje na kraj spremnika i
vraća novi end iterator spremnika (iterator koji pokazuje na prvi eliminirani element).
Pri tome algoritam ne garantira da će elementi određeni za brisanje biti prebačeni na
kraj spremnika. U većini implementacija oni će biti jednostavno prebrisani.
removeAlgoritam remove briše sve sve elemente jednake zadanom iz kolekcije. Na primjer,
Nakon prolaza remove algoritma potrebno je zvati funkciju spremnika erase kako bi se
izvršilo stvarno brisanje elemenata.
std::vector<int> ivecc{1,2,3,4,5,6,7,8,9,0};
auto newend = std::remove(ivecc.begin(), ivecc.end(), 1); // samo premještanje elemenata
ivecc.erase(newend, ivecc.end()); // stvarno brisanje elemenata
Verzija remove_if briše one elemente na kojima predikat vrati istinu.
Verzija remove_copy kombinira copy i remove. Ulazni niz ostaje isti, a na izlazni se kopiraju
samo oni elementi koji nisu izbrisani. Na primjer,
std::vector<char> vec{'a','b','c','a','d','e','f'};
std::remove_copy(vec.begin(), vec.end(), std::ostream_iterator<char>(std::cout, " "), 'a'); // b,c,d,e,f
remove algoritam se ne koristi sa listom koja ima (efikasniju)
remove metodu. S listom se ne koristi niti sort algoritam jer ona ima sort metodu koja je efikasnija.
remove algoritam se ne koristi sa asocijativnim spremnicima koji imaju
verziju erase metode koja radi istu operaciju.
Asocijativni spremnici map, set, multimap i multiset se ne sortiraju jer
su u njima po konstrukciji elementi sortirani.
uniqueAlgoritam
unique
eliminira sve kosekutivne duplikate u spremiku (otkrivene operatorom
==).
Metoda std::sort služi
sortiranju spremika (pomoću operatora <) i pozivamo ju prije
std::unique() kako bismo osigurali da su duplikati konsekutivni:
// Izbacivanje duplikata
std::vector<std::string> lista_imena;
// Ubacimo neka imena
lista_imena.push_back("Ante");
lista_imena.push_back("Lovre");
lista_imena.push_back("Karmela");
lista_imena.push_back("Ante");
lista_imena.push_back("Lovre");
// Sortirajmo listu kako bi se ista imena našla jedna do drugih
std::sort(lista_imena.begin(), lista_imena.end());
// "brisanje" duplikata
auto it_unique = std::unique(lista_imena.begin(), lista_imena.end());
// stvarno brisanje
lista_imena.erase(it_unique, lista_imena.end()); // Ante Karmela Lovre
Kao i kod remove algoritma, postoje i unique_if i unique_copy algoritmi.
Na spremnicima čiji su elementi sortirani za pretraživanja možemo koristiti algoritme:
Asocijativni spremnici map, multimap, set i multiset imaju
implementirane metode lower_bound, upper_bound i equal_range.
Nesortirani asocijativni spremnici unordered_map, itd. imaju
implementiranu metodu equal_range.
lower_bound,
a drugi je onaj koji vraća upper_bound. Ako su vraćeni iteratori
jednaki onda element nije nađen. Ako je vraćeni raspon neprazan, onda on
sadrži sve elemente ekvivalentne traženom elementu.
Primjer:
std::default_random_engine r_engine;
r_engine.seed( std::time(nullptr) );
std::uniform_int_distribution<unsigned int> dist(0, 7);
std::vector<unsigned int> vec(20);
std::generate(vec.begin(), vec.end(), [&dist, &r_engine]() { return dist(r_engine); } );
// npr. 3,7,3,4,7,4,1,6,2,6,6,7,4,0,2,5,1,6,2,2
std::sort(vec.begin(), vec.end());
// 0,1,1,2,2,2,2,3,3,4,4,4,5,6,6,6,6,7,7,7
auto its = std::equal_range(vec.begin(), vec.end(), 4);
for(auto it = its.first; it != its.second; ++it)
std::cout << "vec[" << std::distance(vec.begin(), it) << "]=" << *it << ",";
std::cout << std::endl; // vec[9]=4,vec[10]=4,vec[11]=4