Documente Academic
Documente Profesional
Documente Cultură
𝑻(𝒏) = 𝜣(𝒏𝟐 )
Pornim cu un sir gol de numere. Luăm câte un număr din
șirul inițial și il plasăm in sirul sortat la poziția
corespunzătoare. Plasarea numărului in șir la poziția
corespunzătoare se face prin comparare succesivă de la
stânga la dreapta sau invers.
Pasi:
1-Divide: sirul de n elemente se imparte in doua subsiruri
de n/2 elemente.
2-Conquer: se sorteaza recursiv cele 2 siruri.
3-Combine: se combina prin interclasare cele doua siruri
sortate obtinute la pasul Conquer.
Heapsort
𝑻(𝒏) = 𝜣(𝒏𝒍𝒐𝒈𝟐 𝒏)
Un heap este un sir de obiecte care pot fi văzute ca și un
arbore binar aproape complet – ultimul rand al arborelui
se completează de la stânga la dreapta.
MEMOIZED-CUT-ROD(p,n)
1. Fie un sir auxiliar r[0..n]
2. for i=0 to n
3. 𝑟[𝑖] = −∞
4. return MEMOIZED-CUT-ROD-AUX(p,n,r)
MEMOIZED-CUT-ROD-AUX(p,n,r)
1. if 𝑟[𝑛] ≥ 0
2. return r[n]
3. if n==0
4. q=0
5. else 𝑞 = −∞
6. for i=1 to n
7. q=max(q, p[i]+MEMOIZED-CUT-
ROD-AUX(p,n-i,r))
8. r[n]=q PRINT-OPTIMAL-PARENS(s, i, j)
9. return q 1. If i == j
2. Print "𝐴"𝑖
3. Else print “(”
4. PRINT-OPTIMAL-PARENS(s, i, s[i, j])
5. PRINT-OPTIMAL-PARENS(s, s[i, j] + 1, j)
Greedy 𝑻(𝒏) = 𝜣(𝒏)
6. Print “)”
Metoda greedy este o metoda generala de proiectare
a algoritmilor care consta in construirea solutiei
global optimale printr-un sir de solutii cu character
de optim local atunci cand este posibila exprimarea
“optimului global”. Algoritmii greedy sunt in general
simpli si sunt folositi la problem de optimizare cum ar
fi: sa se gaseasca cea mai buna ordine de executare a
unor lucrari, sa se gaseasca cel mai scut drum intr-un
graf. Aceasta metoda se aplica problemelor in care se
da o multime A cu n elemente si se cere sa se
determine o submultime B care sa indeplineasca
anumite conditii pentru a fi acceptata. Este posibil sa
existe mai multe multimi acceptabile, de aceea se
cere sa se determine o solutie posibila care fie sa
maximizeze, fie sa minimieze o functie obiectiv dat.
Aceasta solutie posibila se numeste solutie-optima.
Metoda greedy intotdeauna face o alegere care sa
fie cea mai buna in acel moment. Folosind metoda Pasi :
greedy vom obtine cu siguranta o solutie posibila Determinam structura optimala a problemei,
maximal dar nu avem garantia ca elementul adaugat Dezvoltam o solutie recursive pe baza solutiei
este acel element maximal pentru care functia optimale,
obiectiv este maximizata/minimizata. Greedy Aratam ca daca se efectueaza o alegere greedy,
intotdeauna face alegerea care pare cea mai bună în ramane doar o subproblema,
fiecare moment, in speranța că această alegere va Aratam ca alegerea greedy este sigura,
conduce la soluția optimă. Greedy nu conduce la Dezvoltam un algoritm recursive pentru
alegerea optimală. Pentru o problemă de rezolvarea problemei greedy.
optimizare, in primul rând trebuie să cautăm soluția
prin programare dinamică si abia apoi soluția
greedy.
Backtracking O(exponentiala) 1. k = 1, si 𝑆 = ∅
2. While k>0
Conceptual, tehnica backtracking cauta 3. If k>n
sistematic solutia, intr-un spatiu al solutiilor 4. Print S // afisează soluția s
organizat sub forma unui arbore. Fiecare nod 5. k = k -1
din arbore defineste o stare a problemei. Toate 6. Else
drumurile de la radacina la Frunze formeaza 7. If (există 𝑣 ∈ 𝑆𝑘 neconsiderată până in acest moment)
spatiul starilor. O solutie a problemei 8. 𝑆 = {𝑣1 , … , 𝑣𝑘−1 , 𝑣}
reprezinta acele stari pentru care exista drum 9. If 𝛷(𝑆) adevărate // testarea conditiilor de continuare
de la radacina la un nod etichetat cu un n-uplu. 10. k = k +1
Pot exista arbori statici si arbori dinamici. 11. else k = k-1 // pasul de backtracking
Metoda de generare a tuturor solutiilor DAME(n)
posibile si apoi de determinare a solutiilor 1. k=1, 𝑆 = {𝑥1 , 𝑥2 , … 𝑥𝑛 } = {0, … ,0}
rezultate prin verificarea indeplinirii conditiilor 2. While k>0
interne necesita foarte mult timp. In cadrul 3. If (k > n) printeaza solutia S
tehnici backtracking nu se genereaza toate 4. k = k-1
solutiile posibile, ci numai acelea care 5. Else 𝑥 𝑖 = 𝑥𝑖 + 1
Stiva
Last-in, first-out
INSERT -> PUSH, DELETE -> POP
STACK-EMPTY(S) PUSH(S,x) POP(S)
1. If S.top == 0 1. S.top = S.top + 1 1. If STACK-EMPTY(S)
2. Return true 2. S[S.top] = x 2. eroare
3. Else return false 3. Else S.top = S.top – 1
4. Return S[S.top + 1]
Functia de dispersie
CHAINED-HASH-INSERT(T, x) CHAINED-HASH-SEARCH(T, k) CHAINED-HASH-DELETE(T, x)
1. Insert x la varful listei T[h(x.key)] 1. Se caută un element cu cheia k 1. Se sterge x din lista T[h(x.key)]
în lista T[h(k)]
HASH-INSERT(T, k) HASH-SEARCH(T, k)
1. i = 0 1. i = 0
2. Repeat 2. Repeat
3. j = h(k,i) 3. j = h(k,i)
4. If T[j] == NIL 4. If T[j] == k
5. T[j] = k 5. Return j
6. Return j 6. i =i+1
7. Else i = i + 1 7. Until T[j] == NIL or i == m
8. Until i == m 9. Return NIL
9. Return “hash table overflow”
Reprezintă un sir Adj de |V| liste, cate o listă pentru Presupunem că nodurile sunt numerotate cu 1, 2, ...,
fiecare nod din graf. Pentru fiecare 𝑢∈𝑉, 𝐴𝑑𝑗[𝑢] |V|
conține toate nodurile v din graf astfel incat există Folosim o matrice de dimensiune |𝑉|×|𝑉|, 𝐴=(𝑎_𝑖𝑗)
un arc (𝑢,𝑣)∈𝐸. Notatia 𝐺.𝐴𝑑𝑗[𝑢] pentru a ne referi astfel încât 𝑎_𝑖𝑗={1, 𝑑𝑎𝑐ă (𝑖,𝑗)∈𝐸 sau 0, î𝑛 𝑐𝑎𝑧
la lista de adiacență a nodului u. Dacă G graf 𝑐𝑜𝑛𝑡𝑟𝑎𝑟)}. Matricea de adiacență necesită spațiu de
orientat, atunci un arc (u,v) este reprezentat prin memorie Θ(𝑉^2), indiferent de numărul de noduri
𝑣∈𝐴𝑑𝑗[𝑢]. Dacă G graf neorientat, atunci u apare in Pentru un graf neorientat, matricea este simetrică:
Adj[v] și v apare in Adj[u]. Spațiul de memorie 𝐴=𝐴t. Dacă graful este ponderat, atunci in matrice
necesar: Θ(𝑉+𝐸). Dacă graful este ponderat cu se salvează ponderile w(u,v).
ponderile 𝑤:𝐸→𝑅, atunci ponderea w(u,v) se
BFS(G,s)
Parcurgerea in latime (breadth-first) O(V+E) 1. For fiecare nod 𝑢 ∈ 𝐺. 𝑉 − {𝑠}
Dacă se dă ca și start un nod s din graf, parcurgerea 2. u.color = WHITE
in latime explorează in mod sistematic arcele din G 3. u.d = ∞
4. u.π = Nil // predecesorul lui u
pentru a descoperi fiecare nod care poate fi
5. s.color = GRAY
identificat pornind de la s.
6. s.d = 0
Calculează distanța de la s la fiecare nod din graf
7. s. π = Nil
care este conectat la s.
8. Q = ∅ //se initializează coada Q la multimea vidă
Algoritmul explorează frontiera dintre nodurile 9. ENQUEUE(Q, s)
descoperite si cele nedescoperite în lațime, adică 10. While 𝑄 ≠ ∅
descoperă toate nodurile la distanță k, apoi cele la 11. u = DEQUEUE(Q)
distanță k+1, etc. 12. For fiecare nod 𝑣 ∈ 𝐺. 𝐴𝑑𝑗[𝑢]
Se presupune ca initial toate nodurile din graf sunt 13. If v.color == WHITE
colorate alb (nedescoperite). 14. v.color = GRAY
Dacă (𝑢,𝑣)∈𝐸 și u este nod negru, atunci v va fi sau 15. v.d = u.d + 1
negru sau gri: toate nodurile adiacente unui nod 16. v. π = u
negru au fost descoperite. 17. ENQUEUE(Q,v)
Nodurile gri pot avea noduri albe adiacente: acestea 18 u.color = BLACK
reprezintă frontiera dintre nodurile descoperite. PRINT-PATH(G, s, v)
Parcurgerea in latime calculează un arbore de 1. If v == s Print s
parcurgere in latime cu radacina in s. 2. Elseif v.π == Nil
De fiecare data cand se descoperă un nod v alb la 3. Print „nu exista cale de la s la v”
scanarea listei de adiacență a nodului u, arcul (u,v) 4. Else PRINT-PATH(G, s, v.π)
se salvează in arborele de parcurgere. 5. Print v
Parcurgerea in adancime O(V+E) DFS-VISIT(G, u) DFS(G)
1. Time = time + 1 1. For fiecare nod 𝑢 ∈ 𝐺. 𝑉
Presupune o căutare in graf cat de adânc
2. u.d = time 2. u.color = WHITE
posibil. Se parcurge pe arcele nodului cel mai
3. u.color = GRAY 3. u.π = Nil
recent descoperit. 4. Time = 0
4. For fiecare 𝑣 ∈ 𝐺. 𝐴𝑑𝑗[𝑢]
Dacă toate arcele unui nod v au fost explorate, 5. If v.color == WHITE 5. For fiecare nod 𝑢 ∈ 𝐺. 𝑉
atunci algoritmul face back-tracking la 6. v.π = u 6. If u.color == WHITE
următorul nod care trebuie explorat după v. 7. DFS-VISIT(G, v) 7. DFS-VISIT(G, u)
Folosim aceasi convenție de colorare: WHITE, 8. u.color = BLACK
GRAY si BLACK. Pentru fiecare nod folosim 2 9. Time = time+1
stampile de timp: -v.d momentul in care 10. u.f = time
nodul a fost descoperit (cand este marcat
GRAY).
-v.f momentul in care parcurgerea termină lista de
adiacență a lui v (cand nodul este marcat BLACK).
MST-PRIM(G, w, r) BELLMAN-FORD(G, w, s)
1. For fiecare 𝑢 ∈ G. 𝑉 1. INITIALIZE-SINGLE-SOURCE(G, s)
2. u.key = ∞ 2. For i = 1 to |G.V| - 1
3. u.π = Nil 3. For fiecare arc (u,v)
4. r.key = 0 4. RELAX(u, v, w)
5. Q = V 5. For fiecare arc (u,v)
6. While Q != ∅ 6. If v.d > u.d + w(u,v)
7. u = EXTRACT-MIN(Q) 7. Return FALSE
8. For fiecare 𝑣 ∈ 𝐺. 𝐴𝑑𝑗[𝑢] 8. Return TRUE
9. If 𝑣 ∈ 𝑄 and w(u,v) < v.key INITIALIZE-SINGLE-SOURCE(G, s)
10 v.π = u 1. For fiecare nod v din graful G
11. v.key = w(u,v) 2. v.d = ∞
3. 𝑣. 𝜋 = Nil
4. s.d = 0
Cai minime in grafuri aciclice (DAG) O(V+E) RELAX(u, v, w)
1. If v.d > u.d + w(u,v)
DAG-SHORTEST-PATH(G, w, s) 2. v.d = u.d + w(u,v)
1. TOPOLOGICAL-SORT(G) 3. 𝑣. 𝜋 = u
2. INITIALIZE-SINGLE-SOURCE(G, s)
3. For fiecare 𝑢 ∈ G. 𝑉 //in ordinea topologica
4. For fiecare nod v ∈ G.Adj[u] Algoritmul lui Dijkstra
5. RELAX(u, v, w) Rezolvă problema căii minime dacă 𝑤(𝑢,𝑣)≥0
DIJKSTRA(G, w, s)
1. INITIALIZE-SINGLE-SOURCE(G, s)
2. 𝑆=∅
3. Q = G.V // coadă min-priority
4. While Q=∅
5. u = EXTRACT-MIN(Q)
6. 𝑆=𝑆∪{𝑢}
7. For fiecare nod 𝑣∈𝐺.𝐴𝑑𝑗[𝑢]
8. RELAX(u, v, w)