Documente Academic
Documente Profesional
Documente Cultură
OBS: Modul in care sunt organizate datele poate sa rezolve o buna parte din problema.
Exemplu:
Exista vreo structura de date pe care ati prefera-o pentru rezolvarea Pb 1 si, respectiv, Pb 2?
Daca da - care si de ce?
Notiuni introductive
=> Nu exista stuctura de date care sa fie buna pentru orice scop/ in orice situatie.
Algoritm
= o procedura / o secventa de pasi care rezolva o problema data intr-un mod repetabil si cu
resurse (timp si memorie) finite; primeste un set de date de intrare si returneaza o solutie –
Da.
Chiar daca o serie de aplicatii nu necesita explicit algoritmi (ex: aplicatii simple Web based,
mobile), multe altele se bazeaza pe ei.
Exemple:
1. Considerati o aplicatie de tip serviciu Web care calculeaza rute intre 2 locatii (Google maps).
Implementarea se bazeaza pe cel mai rapid hardware, o interfata grafica, retea si probabil
integreaza concepte POO. Cu toate astea, va avea nevoie de algoritmi pentru anumite operatii:
gasirea rutelor optime(shortest-path algorithm), redarea hartilor, interpolarea adreselor.
In functie de resursele avute la dispozitie si alte restrictii trebuie ales algoritmul potrivit.
Complexitatea algoritmilor
Analiza algoritmilor:
- o problema poate sa aiba mai multe solutii (eg. sortarea elementelor unui vector
poate sa fie facuta in multe feluri).
- cum putem sa aflam care e cel mai eficient algoritm din punct de vedere al duratei si
memoriei consumate?
Analiza la executie (running time analysis) - ne spune cum creste durata cu cresterea
dimensiunii problemei (a datelor de intrare)
Complexitatea algoritmilor
DAR: Numarul exact de pasi este dificil de calculat => se impun o serie de simplificari
=> in calculul complexitatii tinem cont numai de operatiile critice din algoritm
(acele operatii care, prin natura lor, consuma multe resurse sau sunt efectuate de un
numar semnificativ de ori)
Ex: Intr-un algoritm de sortare o operatie critica este compararea elementelor, intrucat
se produce de foarte multe ori.
Complexitatea algoritmilor
Definitii
Complexitata unui algoritm (A) poate fi masurata cu o functie f(n) care da durata de
executie sau/si memoria necesara pentru A in termeni de dimensiune - “n” a datelor
de intrare si forma lor particulara.
OBS: In cele mai multe cazuri, spatiul de stocare e un multiplu de n – iar complexitatea
se refera la durata de executie.
Complexitatea algoritmilor
Cazul cel mai nefavorabil - complexitatea pentru cel mai neprietenos input = max ( f(n) )
Cazul cel mai favorabil - complexitatea pentru cel mai prietenos input = min ( f(n) )
Cazul mediu - e o predictie a duratei medii = la ce complexitate ne putem astepta in cazul
inputurilor aleatoare (dificil de calculat, ar trebui calculata media ponderata a
complexitatilor in functie de distributia statistica a inputurilor si probablilitatea lor de de
aparitie) – valoarea asteptata
Pentru un algoritm putem sa reprezentam cazul cel mai (ne)favorabil, mediu ca functii:
- f(n)= n^2+500, cel mai nefavorabil caz
- f(n) = 100n+500, cel mai favorabil caz
***Notatie: n^m = n la puterea m
1. Notatia O - “Big O”
• Descrie comportamentul unui algoritm in cazul cel mai nefavorabil fara a se face
referire la celelalte situatii.
• Intrucat, in general, e de interes comportamentul algoritmului pentru date arbitrare de
intrare, este suficient sa specificam o margine superioara pentru timpul de executie.
• f(n) ∈ O(g(n)) implica faptul ca f(n) creste asimptotic cel mult la fel de repede ca g(n)
• O(g(n))={f(n)|exista c si no>0 astfel incat 0<=f(n)<=cg(n), orice n>=no}.
• in general, nu ne intereseaza valorile mici
ale lui n; rata de crestere pentru n<no poate
fi diferita.
*O – ordin de complexitate
Complexitatea algoritmilor
O(g(n))={f(n)|exista c si no >0 astfel incat 0<=f(n)<=cg(n), orice n>=no}
2. f(n) = n^2+1
n^2+1<=2n^2 (=cg(n)) = > O(n^2), c=2, no=1
3. f(n)= 410
410<=1*410 (=cg(n)) = > O(1), c=1, no=410
Observatii:
1. O(n^2) include O(1), O(n), O(nlogn)
2. Valorile pentru c si no nu sunt unice!
Complexitatea algoritmilor
1. Bucle – durata de executie a unui structuri repetitive este maxim egala cu durata
instructiunilor executate (incluzand testele) inmultita cu numarul de iteratii
2. Bucle imbricate (nested loops) - se analizeaza din exterior spre interior; timpul total e
produsul dimensiunilor buclelor x durata instructiunilor executate
4. Instructiuni if-then-else - testul + timpul cel mai nefavorabil de pe ramura then sau else
}else{
Rate de crestere
o n! – rata factoriala - permutari
o 2^n – rata exponentiala – turnurile din Hanoi
o n^3 – rata cubica –inmultirea de matrice
o n^2 – rata patratica – calea cea mai scurta intre
2 noduri ale unui graf; adunare matrice
o nlogn – rata liniar logaritmica – sortare cu
metoda merge sort
o n – rata liniara – gasirea unui element intr-un
vector nesortat
o log n – rata logaritmica - gasirea unui element
intr-un vector sortat
o 1 – rata constanta- aflarea valorii unui element
i dintr-un vector; adaugarea unui element la
inceputul unei liste
Complexitatea algoritmilor
Obs: Exista modalitati de organizare a datelor care imbunatatesc procesul de cautare => daca tinem
datele intr-o anumita ordine, gasirea elementului cautat se face usor. Sortarea colectiei in care se
face cautarea e o astfel de tehnica.
Tipuri de cautari
Cautare liniara intr-o multime neordonata ( Unordered Linear Search)
Cautare liniara intr-o multime ordonata ( Sorted/Ordered Linear Search)
Cautare binara ( Binary search)
Tabele de dispersie - C7
Cautare specializata pentru siruri de caractere (tries, arbori de sufixe, etc) – C7
Cautare liniara/secventiala intr-o multime neordonata
Se presupune dat un vector neordonat => trebuie parcurs tot vectorul ca sa vedem daca
elementul se gaseste acolo sau nu.
- cazul cel mai nefavorabil - algoritmul examineaza n numere pentru cautare (fara succes)
- cazul mediu - sunt evaluate aproximativ n/2 numere pentru cautarea cu succes
Se presupune dat un vector ordonat => nu trebuie parcurs tot vectorul ca sa vedem daca
elementul se gaseste acolo sau nu, ne oprim daca am gasit un element mai mare sau egal
cu cel cautat
- cazul cel mai nefavorabil - algoritmul examineaza n numere pentru cautarea fara succes
- cazul mediu - se fac mai putine evaluari comparativ cu cazul precedent , dar
if (v[m]==data) return m;
else if (v[m]>data) return search_bin_rec(v, l, m-1, data);
else return search_bin_rec(v, m+1, r , data);
return -1;
}
Complexitatea spatiala – la fiecare apel recursiv o sa se puna un stack frame pe stiva =>
cazul cel mai favorabil (elementul cautat e gasit la primul apel) O(1) /nefavorabil O(logn)
Algoritmi de sortare
- metode elementare – potrivite unui numar mic de elemente (<1000): bubble, insertion,
selection sort - > O(n^2)
- metode avansate – potrivite pentru cazul cu multe inregistrari: quick sort, merge sort, heap
sort -> ~ O(nlogn)
- alte metode – care se bazeaza pe o reprezentare bine aleasa a datelor - > < O(nlogn)
Sortare in-place / out- of-place – spatiul suplimentar (pe langa cel al containerului ) e mic/mare.
Metode elementare de sortare
aux=v[6]
Metode elementare de sortare
Pas 0: 9 7 6 15 16 5 10 11 -> 5 7 6 15 16 9 10 11
Pas 1: 5 | 7 6 15 16 9 10 11 -> 5 6 7 15 16 9 10 11
Pas 2: 5 6 | 7 15 16 9 10 11 -> 5 6 7 15 16 9 10 11
Pas 3: 5 6 7 | 15 16 9 10 11 -> 5 6 7 9 16 15 10 11
Pas 4: 5 6 7 9 | 16 15 10 11 -> 5 6 7 9 10 15 16 11
original mai mult decat e necesar (eventual vrem sa facem pozitionarea cand stim
vectorul original.
Dupa ce s-a realizat sortarea indirecta – daca se doreste- se pot rearanja inregistrarile.
Metode avansate de sortare
1. Quicksort
cel mai utilizat algoritm de sortare
1960 - C.A.R. Hoare
consuma mai putine resurse decat alte metode
in medie foloseste nlogn operatii pentru a sorta n elemente, dar n^2 pentru
cazul cel mai nefavorabil (exista imbunatatiri si pentru acesta situatie => nlogn).
se foloseste de paradigma divide et impera (problema se imparte in
subprobleme care sunt apoi rezolvate – iar solutiile partiale sunt recombinate
intr-o solutie finala)
Divide: daca v (vectorul de sortat) are cel putin 2 elemente, selecteaza un element
x din v – pivot (de exemplu ultimul element) si imparte elementele din v in 3 parti:
elemente < x (L) elemente = x (E) elemente > x (G)
1. Se alege 50 pivot.
Pozitia finala a pivotului 50 e 4
(*v începe de la 0, si sunt 4 elemente in
multimea L).
2. Se alege 30 pivot.
Pozitia finala a pivotului 30 e 2.
3. Se alege 90 pivot.
Pozitia finala a pivotului 90 e 7.
4. Se alege 15 pivot.
Pozitia finala a pivotului 15 e 0.
5. Pozitia finala a lui 45 e 3.
5. Se alege 59 pivot.
Pozitia finala a pivotului 59 e 5.
6. Pozitia finala pentru 21 este 1.
7. Pozitia finala pentru 80 este 6.
Metode avansate de sortare
daca low <high // pana nu se mai poate imparti (am cel putin 2 elemente)
Complexitatea spatiala- in cel mai bun caz O(logn) – cel mai rau caz O(n) – daca arborele de
recursivitatea e neechilibrat (e de fapt o lista)
Metode avansate de sortare
Observatii:
4 1 10 7 100 11 3 2
4 1 10 7 100 11 3 2
2 1 10 4 100 11 3 7
• Aceasta este o estimare buna pentru valoarea elementului din mijloc si conduce la
2. Mergesort
Foloseste paradigma divide et impera
Avantaje: e potrivit secventelor reprezentate prin liste inlantuite
II. Care dintre metodele de sortare precedente sunt stabile? Dar in-place?
III. Implementati recursiv bubble sort, insertion sort, selection sort. Care e
complexitatea spatiala/temporala pentru aceste implementari?
IV. Implementati 1-6 sub forma de functii (cerinte partial implementate in Tema
recapitulativa) si calculati complexitatea lor:
1. Creati unui vector v - alocat dinamic, de dimensiune n. Vectorul contine
elemente de tip Date. Date e un tip de date definit de voi.