Você está na página 1de 8

Analiza algoritmilor Laborator 2

Determinarea complexitatii unui algoritm Determinarea complexitatii unui algoritm recursiv Metode de rezolvare a recurentelor de complexitate Determinarea complexitatii unui algoritm Cum numaram pasii pe care ii executa un algoritm? recapitulare - masuram complexitatea ca pe o functie de dimensiunea datelor de intrare: : N->R! - pe parcursul acestui laborator" #n$ va reprezenta estimarea numarului de pasi pe care ii face algoritmul atunci cand dimensiunea datelor de intrare este n - de exemplu: pentru sortare" #n$ va estima numarul de pasi necesari sortarii unui vector de n elemente numararea este in general simpla pe algoritmi nerecursivi - ceea ce trebuie sa facem in general este sa identificam operatiile critice si sa vedem de cate ori se executa acestea - cand algoritmul este nerecursiv" pur si simplu il luam de la cap la coada si numaram operatiile critice" inmultim cand ele se afla intr-unul sau mai multe cicluri etc ceva mai dificil este cu algoritmii recursivi - nu este mereu clar sau usor de determinat cate apeluri recursive se executa %xemplu de determinare a complexitatii pe un algoritm nerecursiv &ie un algoritm care sorteaza cele n elemente dintr-un vector prin metoda urmatoare: in fiecare din n-' pasi cauta minimul din vectorul ramas si il intersc(imba cu elementul corespunzator pasului la care am a)uns* +seudocodul ar arata in felul urmator:
for i=1 to n { k=i for j=i+1 to n if a[j]<a[k] then k=j // k a devenit indicele elementului minim de la a[i] la a[n] // interschimbam acest element cu a[i] aux = a[i] a[i] = a[k] a[k] = aux

Cate operatii executa acest algoritm? Avem o bucla exterioara de la ' la n in care se petrec , atribuiri si o bucla interioara al carei numar de ciclari depinde de i-ul curent* -n bucla interioara avem o comparatie si maxim o atribuire* Asadar" pe cazul cel mai defavorabil #cand avem dupa comparatie si atribuire$" vom estima complexitatea ca fiind:
T ( n) = ( 4 +
i =1 n n

j =i +1

2)

T ( n) = ( 4 + 2( n i ))
i =1

T ( n) = 4n + 2( n i )
i =1

T ( n) = 4n + n( n 1) T ( n) = n 2 + 3n

Asadar" complexitatea acestui algoritm este .#n2$" complexitate pe care am fi obtinut-o si daca ignoram o parte din atribuiri si tineam cont numai de operatiile critice" comparatiile de c(ei* -n acest caz obtineam o alta constanta #este vorba de constanta din definitia lui .$* Determinarea complexitatii unui algoritm recursiv Care sunt factorii care influenteaza complexitatea in mod esential? costul recursiv al unui apel - cate noi apeluri recursive lanseaza un anumit apel - dimensiunea parametrilor acestor noi apeluri costul nerecursiv al unui apel - celelalte treburi pe care le mai face un apel in afara de a lansa noi apeluri recursive Cum combinam acesti factori? #n$ / costul0recursiv#n$ ! costul0nerecursiv#n$ 1elatii de recurenta uzuale divide et impera

problema e impartita in b subprobleme de dimensiune n2c b si c difera de la un algoritm la altul" cel mai des b/c/2
n T ( n) = bT ( ) + f ( n) c

- f#n$ reprezinta costul nerecursiv c(ip and con3uer - in fiecare pas" problema este redusa la o subproblema de dimensiune n-c #practic se elimina c posibilitati$" cu a)utorul unor operatii care vor constitui cost nerecursiv #f#n$$ - T ( n ) = T ( n c ) + f ( n) c(ip and be con3uered - b subprobleme de dimensiune n-c - T ( n) = bT (n c) + f ( n) %xemplu de determinare a recurentei de complexitate pentru un algoritm recursiv &ie algoritmul de sortare prin interclasare #mergesort" in engleza$ pe care il vom folosi pentru toate exemplificarile de acum incolo* %fectul lui este sortarea unui vector de n elemente" printr-o strategie divide et impera* - imparte vectorul in 2 )umatati #divide$ - sorteaza fiecare )umatate folosind sortare prin interclasare #impera$ - combina cei 2 vectori sortati intr-un singur vector mare" sortat #combina$ +seudocod
mergesort start! sto"# { if start<sto" then { mijloc= start+sto"#/$ mergesort start! mijloc# // sortea%a "rima jumatate mergesort mijloc+1! sto"# // sortea%a a doua jumatate merge start! mijloc! sto"# // interclasea%a vectorii sortati } } merge start! mijloc! sto"# { for i=start to sto" b[i]=a[i] // co"ia%a jumatatile sortate intr&un vector auxiliar b i=start' j=mijloc+1' k=start' // co"ia%a ina"oi in a "e cel mai mic dintre elementele curente in // cele $ jumatati (hile i<=mijloc# and j<=sto"#

if b[i]<=b[j] then a[k++]=b[i++] else a[k++]=b[j++] // co"ia%a ce a mai ramas din "rima jumatate! daca in ea a mai ramas (hile i<=mijloc a[k++]=b[i++] // similar "t a doua (hile j<=sto" a[k++]=b[j++]

Costul nerecursiv il determinam usor" este efortul efectuat de functia merge* Aici se asaza pe rand n elemente intr-un nou vector sortat* +entru a alege al i-lea element" se realizeaza maxim 4 teste #i5/mi)loc" )5/stop" b6i75/b6)7$ si 4 atribuiri #a687/b6i7" 8!!" i!!$" prin urmare costul nerecursiv este 9#n$* .peratia de copiere care precede interclasarea propriu-zisa este in mod evident si ea 9#n$ si nu afecteaza complexitatea functiei* f#n$ / 9#n$ +entru a determina si costul recursiv ne uitam in functia mergesort" unde se fac 2 apeluri recursive" fiecare de dimensiune n22 #fiecare din ele pe un vector de 2 ori mai mic decat cel din pasul curent$* costul0recursiv#n$ / 2 #n22$ :e obtine recurenta de complexitate: #n$ / 2 #n22$ ! 9#n$ Metode de rezolvare a recurentelor de complexitate Metoda iterativa #si reprezentarea cu arbori de recurenta$ Metoda substitutiei Metoda master Metoda iterativa - presupune pur si simplu sa calculezi suma seriei rezultata din eliminarea recurentei %xemplu: mergesort
n 20 T ( n) = 21T ( 1 ) + 20 ( n) 2 n n n 21T ( 1 ) = 2 2 T ( 2 ) + 21 ( 1 ) 2 2 2 n n n 2 2 T ( 2 ) = 23 T ( 3 ) + 2 2 ( 2 ) 2 2 2 ............. n n n 2 q T ( q ) = 2 q +1T ( q +1 ) + 2 q ( q ) 2 2 2

#n$ / 2 #n22$ ! 9#n$ #'$ / 9 #'$ #vectorul de ' element e de)a sortat$

1ecurenta se termina atunci cand se a)unge la #'$ #pentru care cunoastem complexitatea" 9#'$$" deci cand n223/' /; 3/log#n$* Adunand termenii stangi" respectiv termenii drepti din toate aceste ecuatii si reducand termenii care apar atat in stanga" cat si in dreapta" obtinem:
T ( n) =
log( n ) q =0

2q (

log( n ) n ) = (n) = (n)(1 + log(n)) 2q q =0

1eprezentarea cu arbori de recurenta - un nivel in arbore reprezinta un nivel de recursivitate - un nod reprezinta un apel recursiv - pe fiecare nivel de recursivitate este figurat si nerecursiv platit la acel nivel - la fel este figurat costul nerecursiv in dreptul unui nod

costul

+entru recurenta de la mergesort" rezulta log#n$!' nivele in arbore" pe fiecare executandu-se un efort de 9#n$* Asadar: #n$ / #'!log#n$$9#n$ / 9#n!n log#n$$ / 9#n log#n$$* 1ezultatul este acelasi cu cel obtinut anterior* Demonstratia relatiei 9#n!n log#n$$ / 9#n log#n$$ este lasata ca exercitiu* log(n)+1 nivele (n/2)) (n) T(n) T(n/2 ))) T(n/4 ) (n)

(n/2))

T(n/2 ) T(n/4 )

(n) (n)

(n/4)

T(n/4 )

T(n/4 )

(1)

(n) T(1) T(1) T(1) T(1)

T(1)

n frunze

Metoda substitutiei - mai intai trebuie sa ai intuitie si sa g(icesti o solutie &#n$ pentru recurenta de complexitate - apoi iti confirmi intuitia prin inductie dupa n - pentru recurenta #n$ / f# #g#n$$$ #neaparat g#n$5n$" cu #n<$/c pe cazul elementar" si pentru =g(iceala> &#n$" sc(ema metodei substitutiei este urmatoarea:
caz de aza : F (n0 ) = c pas de inductie : ipoteza inductiva : T ( g (n)) = F ( g ( n)) T ( n) = F ( n )

n n0 (n ! N n = g (n ! )) T (n) = F ( n)

:c(ema in cuvinte - identificam n<" c" g#n$ si alegem & pentru recurenta de care ne ocupam - verificam cazul de baza - demonstram ca #g#n$$/&#g#n$$ /; #n$/&#n$ %xemplu: mergesort # #n$ / 2 #n22$ ! 9#n$" #'$ / 9#'$$ -dentificare parametri: n</'" c/9#'$" g#n$/n22 Alegere solutie: &#n$/9#n!n log#n$$ Caz de baza: #n<$ / &#n<$ 5/; #'$/&#'$/9#'$ #adevarat$ +as de inductie: -poteza inductiva: #n22$ / &#n22$ / 9#n22!n22 log#n22$$ rebuie aratat ca #n$ / &#n$*
T (n) = 2T ( n / 2) + ( n) T ( n ) = 2 F ( n / 2) + ( n ) T (n) = 2 ( n / 2 + ( n / 2) log(n / 2)) + ( n) T (n) = ( n + n log(n / 2)) + ( n) T (n) = ( n + n (log(n) 1)) + ( n) T (n) = ( n + n log(n)) = F ( n)

#3*e*d*$

Am completat sc(ema de inductie si ne-am confirmat asadar ipoteza" 9#n!n log#n$$ este intr-adevar o solutie pentru recurenta de complexitate a algoritmului mergesort* Metoda master - reprezinta un set de criterii pentru a determina in general comportamentul algoritmilor divide et impera - valabila pentru algoritmi care au recurenta de complexitate de forma #n$ / b #n2c$ ! f#n$ si in plus respecta anumite restrictii :c(ita de )ustificare a teoremei master +entru recurenta de mai sus" arborele de recurenta va contine pe al doilea nivel b noduri #fiecare nod reprezentand o problema de dimensiune n2c$" pe urmatorul b2" apoi tot asa pana la ultimul nivel pe care se vor gasi binaltimea0arborelui frunze*
log(b )

nr " frunze = b logc ( n ) = n log c (b ) = n log( c ) = n E (notatie)

Considerand doar varful si baza arborelui de recurenta: - la varf" costul semnificativ este costul nerecursiv f#n$ - la baza" fiecare frunza rezolva o problema elementara" iar costul nivelului ultim din arbore e influentat nu atat de ce face fiecare frunza" cat de numarul de frunze" n%" care determina de cate ori se face acel efort =elementar> - intrebarea devine care dintre costul de la varf si cel de la baza este dominant? daca este unul dominant" atunci el va dicta complexitatea algoritmului Cele 4 cazuri din teorema master se bazeaza pe relatia dintre aceste 2 costuri" in felul urmator: Cazul ' #n% dominant$ - valabil daca @;< a*i* f#n$ .#n%-@$ #n$/ 9#n%$ Cazul 2 #costuri similare pentru n% si f#n$$ - valabil daca f#n$ 9#n%$ - in acest caz" efortul e distribuit uniform intre nivelele din arbore si va fi de ordinul f#n$Anumarul0de0nivele #n$/ 9#f#n$ log#n$$ Cazul ' #f#n$ dominant$

valabil daca @;< a*i* f#n$ B#n%!@$ si" in plus" constantele <5a5'" n<" a*i* pt orice nCn<" b f#n2c$ D a f#n$ #n$/ 9#f#n$$ daca nu s-ar indeplini conditia suplimentara b f#n2c$ D a f#n$" costul nerecursiv ar creste foarte mult in )osul arborelui" iar f#n$ nu ar mai fi dominant

Você também pode gostar