Documente Academic
Documente Profesional
Documente Cultură
Curs13 Algoritmi
Curs13 Algoritmi
Curs13 Algoritmi
Algoritmii acoperă un domeniu larg de operaţii generale asupra containerelor precum: traversare, sortare, căutare,
inserare sau ştergere de elemente.
Algoritmii sunt funcţii generice, care se referă la containere prin intermediul iteratorilor. Tipurile iteratorilor folosiţi
de un algoritm sunt date ca parametri ai şablonului.
Algoritmii sunt declaraţi în zona de nume std şi semnăturile lor se află în fişierul antet algorithm.
Cei mai mulţi algoritmi sunt scurţi şi simpli, putând fi definiţi inline.
Algoritmii care produc rezultate pe care le depun într-un container sunt clasificaţi ca algoritmi de copiere şi au
numele terminat cu sufixul _copy.
Algoritmii a căror funcţionare este determinată de satisfacerea unui predicat sunt cunoscuţi ca algoritmi cu predicate.
Lista de parametri a unui asemenea algoritm va conţine un obiect funcţie predicat. Numele acestor algoritmi conţine sufixul
_if.
În prezentarea algoritmilor vom utiliza următoarele abrevieri:
InIt - InputIterator, OutIt – OutputIterator, FwIt – ForwardIterator,
BIt – BidirectionalIterator, RAIt – RandomAccessIterator, Pred – Predicate,
BinPred – BinaryPredicate, OpUnar – UnaryOperator, Func – Function, T – value_type
(tipul elementelor din container)
Algoritmi care nu modifică secvenţa.
Se folosesc pentru a extrage informaţii din secvenţă sau a găsi poziţia unor elemente din secvenţă.
1. for_each() elimină un ciclu explicit, repetând o operaţie f asupra elementelor dintr-un interval de iteratori. Se
foloseşte pentru extragerea de informaţii asupra elementelor secvenţei.
template <class InIt, class Func>
Op for_each(InIt prim, InIt ultim, Func f){
while(prim!=ultim)
f(*prim++);
return f;
}
adjacent_find()găseşte prima pereche de elemente vecine egale / sau care satisfac predicatul binar.
template <class FwIt> FwIt adjacent_find(FwIt prim, FwIt ultim);
template <class FwIt> FwIt adjacent_find(FwIt prim, FwIt ultim, BinPred p);
1
template <class InIt, class T>
size_t count_if(InIt prim, InIt ultim, Pred p);
copy_backward() copiază valorile dintr-un interval de iteratori la o destinaţie, copierea începând de la ultimul
element din interval către primul.
2
template <class BIt1, class BIt2>
BIt2 copy_backward(BIt1 prim, BIt1 ultim, BIt2 rez){
while(prim != ultim)
*--rez = *--ultim;
return rez;
}
copy_if() copiază toate valorile din intervalul de iteratori care satisfac predicatul, la destinaţie.
template <class It1, class It2, class Pred>
It2 copy_if(It1 prim, It1 ultim, It2 rez, Pred p){
while(prim != ultim){
if(p(*prim))
*rez++ = *prim;
prim++;
}
return rez;
}
replace_if() înlocuieşte toate valorile care satisfac o anumită condiţie din intervalul de iteratori cu o valoare
nouă.
template <class FwIt, class T, class Pred>
void replace_if(FwIt prim, FwIt ultim, Pred p, const T& valn);
3
void iter_swap(FwIt1 a, FwIt2 b);
swap_ranges() interschimbă elementele din două intervale de iteratori
template <class FwIt1, class FwIt2>
void swap_ranges(FwIt1 prim1, FwIt1 ultim1, FwIt2 prim2);
5. transform() aplică un operator unar elementelor dintr-un interval de iteratori, depunând elementele transformate
în alt interval de iteratori
template <class InIt, class OutIt, class OpUnar>
OutIt transform(InIt prim, InIt ultim, OutIt rez, OpUnar op);
6. generate() completează elementele din intervalul de iteratori cu valori obţinute de la un functor generator
(predicat fără argumente)
template <class FwIt, class Generator>
void generate(FwIt prim, FwIt ultim, Generator gen);
generate_n() completează cu valori furnizate de generator primele n elemente dintr-un domeniu de iteratori
template <class OutIt, class Size, class Generator>
OutIt generate_n(OutIt prim, Size n, Generator gen);
8. unique() şterge elementele consecutive identice cu un element / sau elementele consecutive elementului, aflate în
relaţie cu acesta.
template <class FwIt>
FwIt unique(FwIt prim, FwIt ultim);
template <class FwIt, class Pred>
FwIt unique(FwIt prim, FwIt ultim, Pred p);
şi variantele _copy:
template <class InIt, class OutIt>
OutIt unique_copy(InIt prim, InIt ultim, OutIt rez);
template <class InIt, class OutIt, class Pred>
OutIt unique_copy(InIt prim, InIt ultim, OutIt rez, Pred p);
10. rotate() deplasează la stânga elemenetele secvenţei; elementele scoase sunt inserate la sfârşitul secvenţei
(deplasare circulară). Iteratorul med indică începutul secvenţei de elemente rotite.
template <class FwIt>
void rotate(FwIt prim, FwIt med, FwIt ultim);
template <class FwIt, class OutIt>
OutIt rotate(FwIt prim, FwIt med, FwIt ultim, OutIt rez);
4
11. partition() împarte secvenţa în două intervale, astfel că elementele care satisfac un predicat vor fi plasate în
primul interval (înaintea celorlalte).
template <class BIt, class Pred>
BIt partition(BIt prim, BIt ultim, Pred p);
stable_partition() realizează în plus faţă de algoritmul precedent, ordonarea relativă a elementelor din fiecare
partiţie
template <class BIt, class Pred>
BIt stable_partition(BIt prim, BIt ultim, Pred p);
12. random_shuffle() amestecă aleatoriu ordinea elementelor din secvenţă. Generatorul de numere aleatoare poate
fi specificat ca argument
template <class RAIt>
void random_shuffle(RAIt prim, RAIt ultim);
template <class RAIt, class RandGen>
void random_shuffle(RAIt prim, RAIt ultim, RandGen& rand);
13. iota() umple un interval de iteratori cu valori crescătoare, pornind cu o valoare dată ca parametru
template <class FwIt, class T>
void iota(FwIt prim, FwIt ultim, T val);
1. sort() realizează sortarea elementelor din intervalul de iteratori. Se pretează folosirii de către containere cu acces
direct (vector şi deque). Pentru containerul list se foloseşte funcţia membră list::sort().
Algoritmul sort() utilizează sortarea rapidă (quicksort), având în medie complexitatea O(N logN) şi O(N2) în
cazul cel mai nefavorabil, cu N=ultim-prim, dar sortarea nu este stabilă, în sensul că elementele cu aceeaşi cheie pot să nu
mai ocupe aceleşi poziţii relative după sortare.
template <class RAIt>
void sort(RAIt prim, RAIt ultim);
template <class RAIt, class Compare>
void sort(RAIt prim, RAIt ultim, Compare cp);
2. stable_sort() algoritmul de sortare stabilă stable_sort() , deşi are în medie un timp de execuţie cu 40%
mai mare, are în toate situaţiile complexitatea O(N logN)
template <class RAIt>
void stable_sort(RAIt prim, RAIt ultim);
template <class RAIt, class Compare>
void stable_sort(RAIt prim, RAIt ultim, Compare cp);
3. partial_sort() sortează primele M elemente din secvenţă, restul rămânând nesortate. Valoarea lui M nu este dată
în mod explicit, ci prin intermediul unui iterator med, astfel că M=med-prim. Complexitatea este O(N log M)
template <class RAIt>
void partial_sort(RAIt prim, RAIt med, RAIt ultim);
template <class RAIt, class Compare>
void partial_sort(RAIt prim, RAIt med, RAIt ultim, Compare cp);
Există şi variante _copy, care au ca parametri suplimentari iteratori la intervalul destinaţie.
template <class InIt, class RAIt>
RAIt partial_sort_copy(InIt prim, InIt ultim, RAIt prim_rez, RAIt ultim_rez);
template <class InIt, class RAIt, class Compare>
RAIt partial_sort(InIt prim,InItIt ultim,RAIt prim_rez,RAIt ultim_rez,Compare cp);
5
4. nth_element() furnizează cel de al n-lea element din secvenţa sortată crescător sau descrescător (fără a sorta
secvenţa).
template <class RAIt>
void nth_element(RAIt prim, RAIt nth, RAIt ultim);
template <class RAIt, class Compare>
void nth_element(RAIt prim, RAIt nth, RAIt ultim, Compare cp);
Valoarea lui n este precizată prin cel de-al doilea parametru n=nth-prim, înainte de apel; după apel *nth conţine
cel de-al n-lea element din secvenţa sortată. Complexitatea în medie este O(N).
5. binary_search() permite localizarea foarte rapidă în O(log n) a unui element într-un container cu acces direct
sortat.
template <class FwIt, class T>
bool binary_search(FwIt prim, FwIt ultim, const T& val);
template <class FwIt, class T, class Compare>
bool binary_search(FwIt prim, FwIt ultim, const T& val, Compare cp);
6. lower_bound() găseşte prima poziţie i dintr-o secvenţă sortată, în care poate fi inserată o valoare val astfel ca
relaţia de ordine să se păstreze, adică *j < val (respectiv comp(*j, val)=true)pentru j [prim, i)
template <class FwIt, class T>
FwIt lower_bound(FwIt prim, FwIt ultim, const T& val);
template <class FwIt, class T, class Compare>
FwIt lower_bound (FwIt prim, FwIt ultim, const T& val, Compare cp);
7. upper_bound() găseşte ultima poziţie i dintr-o secvenţă sortată, în care poate fi inserată o valoare val astfel ca
relaţia de ordine să se păstreze.
template <class FwIt, class T>
FwIt upper_bound(FwIt prim, FwIt ultim, const T& val);
template <class FwIt, class T, class Compare>
FwIt upper_bound (FwIt prim, FwIt ultim, const T& val, Compare cp);
8. equal_range() determină cel mai mare interval dintr-o secvenţă sortată, în care poate fi inserată o valoare val ,
în orice poziţie, astfel ca relaţia de ordine să se păstreze.
template <class FwIt, class T>
pair<FwIt,FwIt> equal_range(FwIt prim, FwIt ultim, const T& val);
template <class FwIt, class T, class Compare>
pair<FwIt,FwIt> equal_range(FwIt prim, FwIt ultim, const T& val, Compare cp);
9. interclasare
merge() combină două secvenţe sortate într-o secvenţă de asemeni sortată. Are complexitate liniară.
template <class InIt1, class InIt2, class OutIt>
OutIt merge(InIt1 prim1, InIt1 ultim1, InIt2 prim2, InIt2 ultim2, OutIt rez);
template <class InIt1, class InIt2, class OutIt, class Compare>
OutIt merge(InIt1 prim1,InIt1 ultim1,InIt2 prim2,InIt2 ultim2,OutIt rez,Compare cp);
inplace_merge() dacă cele două domenii de iteratori sunt contigue([prim, med) şi [med, ultim)), s-ar putea
face interclasare peste ele, dacă s-ar utiliza o zonă tampon de memorie. Rezultatul interclasării va fi plasat în [prim,ultim)
template <class BIt>
BIt inplace_merge(BIt prim, BIt med, BIt ultim);
template <class BIt, class Compare>
BIt inplace_merge(BIt prim, BIt med, BIt ultim, Compare cp);
Algoritmi cu mulţimi.
6
Descriu principalele operaţii cu mulţimi (incluziune, reuniune, intersecţie, diferenţă) pentru mulţimi (containere
sortate). Au complexitate liniară O(N1+N2), unde N1 şi N2 sunt cardinalele celor două mulţimi.
1. includes() determină dacă mulţimea M2 este inclusă în mulţimea M1.
template <class InIt1, class InIt2>
bool includes(InIt1 prim1, InIt1 ultim1, InIt2 prim2, InIt2 ultim2);
template <class InIt1, class InIt2, class OutIt, class Compare>
bool includes (InIt1 prim1, InIt1 ultim1, InIt2 prim2, InIt2 ultim2, Compare cp);
2. set_union() construieşte mulţimea reuniune M1M2 a mulţimilor date prin intervalele de iteratori
template <class InIt1, class InIt2, class OutIt>
OutIt set_union(InIt1 prim1, InIt1 ultim1, InIt2 prim2, InIt2 ultim2, OutIt rez);
template <class InIt1, class InIt2, class OutIt, class Compare>
OutIt set_union(InIt1 prim1, InIt1 ultim1, InIt2 prim2, InIt2 ultim2, OutIt rez,
Compare cp);
4. set_difference() construieşte mulţimea diferenţă M1-M2 a mulţimilor date prin intervalele de iteratori (conţine
elementele din prima mulţime care nu apar în cea de a doua)
template <class InIt1, class InIt2, class OutIt>
OutIt set_difference(InIt1 prim1,InIt1 ultim1,InIt2 prim2,InIt2 ultim2,OutIt rez);
template <class InIt1, class InIt2, class OutIt, class Compare>
OutIt set_difference(InIt1 prim1, InIt1 ultim1, InIt2 prim2, InIt2 ultim2,
OutIt rez, Compare cp);
Algoritmi cu heapuri.
Un heap este un arbore binar complet parţial ordont, folosit pentru implementarea cozii prioritare.
1. pop_heap()rearanjează elementele din intervalul [prim, ultim-1), astfel că dacă se extrage un element din
vârful heapului (din poziţia prim) prin interschimbul cu elementul din poziţia ultim-1 , noul interval [prim,ultim-1) să
reprezinte un heap. Complexitatea operaţiei este O(log(ultim-prim)).
template <class RAIt>
void pop_heap(RAIt prim, RAIt ultim);
template <class RAIt, class Compare>
void pop_heap (RAIt prim, RAIt ultim, Compare cp);
2. push_heap()rearanjează elementele din heap astfel că dacă se adaugă un element în ultima poziţie ultim-1
intervalul [prim, ultim) să reprezinte în continuare un heap. Complexitatea operaţiei este O(log(ultim-prim))
template <class RAIt>
void push_heap(RAIt prim, RAIt ultim);
7
template <class RAIt, class Compare>
void push_heap (RAIt prim, RAIt ultim, Compare cp);
3. make_heap() aranjează elementele din intervalul de iteratori, astfel încât acestea să reprezinte un heap
template <class RAIt>
void make_heap(RAIt prim, RAIt ultim);
template <class RAIt, class Compare>
void make_heap (RAIt prim, RAIt ultim, Compare cp);
4. sort_heap() transformă un heap într-o secvenţă sortată (metoda de sortare heapsort). Complexitatea este O(N
log N) şi sortarea nu este stabilă.
template <class RAIt>
void sort_heap(RAIt prim, RAIt ultim);
template <class RAIt, class Compare>
void sort_heap (RAIt prim, RAIt ultim, Compare cp);
Algoritmi de permutare.
O permutare provine dintr-o secvenţă prin schimbarea între ele a două elemente. Pentru o secvenţă având N elemente,
există N! permutări. Mulţimea celor N! permutări se poate considera ordonată după relaţia < (şi în general comp) între
elemente. Conform acestei relaţii de ordine putem defini permutarea următoare (respectiv permutarea precedentă) în raport cu
permutarea curentă.
prev_permutation(), next_permutation() generează în intervalul de iteratori permutarea precedentă
(următoare). Întoarece true dacă există permutarea precedentă (următoare) şi false în caz contrar.
template <class BIt>
bool prev_permutation(BIt prim, BIt ultim);
template <class Bit, class Compare>
bool prev_permutation(BIt prim, BIt ultim, Compare cp);
template <class BIt>
bool next_permutation(BIt prim, BIt ultim);
template <class Bit, class Compare>
bool next_permutation(BIt prim, BIt ultim, Compare cp);
8
Algoritmi numerici.
Descriu operaţii numerice generale. Accesul la aceştia se obţine prin includerea fişierului antet <numeric>.
1. accumulate() adună la elementele din intervalul de iteratori o valoare iniţială dată ca parametru.
template <class InIt, class T>
T accumulate(InIt prim, InIt ultim, T vinit);
template <class InIt, class T, class BinOp>
T accumulate(InIt prim, InIt ultim, T vinit, BinOp bop);
3. partial_sum() calculează în containerul rezultat valorile acumulate din prima poziţie, primele două, primele trei,
etc.
template <class InIt, class OutIt>
OutIt partial_sum(InIt prim, InIt ultim, OutIt rez);
template <class InIt, class OutIt, class BinOp>
OutIt partial_sum(InIt prim, InIt ultim, OutIt rez, BinOp bop);
4. adjacent_difference() calculează diferenţele între elementele consecutive ale unui container c, adică d0=c0,
di=ci-ci-1, i>0.
template <class InIt, class OutIt>
OutIt adjacent_difference(InIt prim, InIt ultim, OutIt rez);
template <class InIt, class OutIt, class BinOp>
OutIt adjacent_difference (InIt prim, InIt ultim, OutIt rez, BinOp bop);