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 transform
for_each
Algoritam 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
transform
Algoritam 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
count
Algoritam 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;
find
Ovi 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);
search
Algoritam 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).
fill
Ovaj 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);
generate
Ovaj 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
iota
Algoritam 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.
remove
Algoritam 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.
unique
Algoritam
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