Documente Academic
Documente Profesional
Documente Cultură
Note de laborator
Ioana Pomparau
Versiunea: 12.01.2016
Cuprins
Prefata i
3 Structuri repetitive 7
3.1 Structura repetitiva cu numar necunoscut de pasi si test initial
- WHILE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.2 Structura repetitiva cu numar necunoscut de pasi si test final
- DO ... WHILE . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.3 Structura repetitiva cu numar cunoscut de pasi - FOR . . . . 9
3.4 Tema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
6 Complexitatea algoritmilor 22
6.1 Timpul de executie si ordinul de crestere al unui algoritm . . . 22
6.2 Aplicatii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
6.3 Tema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
7 Sortari simple 27
7.1 Sortarea prin insertie . . . . . . . . . . . . . . . . . . . . . . . 27
7.2 Sortarea prin selectia minimului . . . . . . . . . . . . . . . . . 28
7.3 Tema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
9 Mergesort si Quicksort 37
9.1 Sortare prin interclasare (Mergesort) . . . . . . . . . . . . . . 37
9.2 Sortarea rapida (Quicksort) . . . . . . . . . . . . . . . . . . . 39
2
Prefata
i
Laboratorul 1
Introducere n studiul
algoritmilor
1
Laboratorul 2
Pseudocod. Instructiuni de
intrare-iesire, atribuire si
structura decizionala
Pseudocod Cod C
real a, b
float a , b ;
integer n
int n ;
char c
char c ;
2
2.2 Citirea datelor de intrare de la tastatura
Pentru a descrie instructiunea prin care utilizatorul introduce valori de la
tastatura vom folosi secventa
read var1 , var2 , ...
Pseudocod Cod C
read a, b, n
s c a n f ( "%f %f %d" , &a , &b , &n ) ;
Pseudocod Cod C
write Hello World!
p r i n t f ( " Hello World !" ) ;
Exemplul 2.4. Calculul sumei a doua numere ntregi ale caror valori sunt
citite de la tastatura.
Pseudocod Cod C
integer a, b
int a , b ;
read a, b
s c a n f ( "%d %d" , &a , &b ) ;
write Suma este: , a + b
p r i n t f ( " Suma : %d" , $a + b$ ;
3
2.4 Atribuire de valori variabilelor
Putem atribui unei variabile valoarea unei expresii folosind instructiunea
var expresie
Pseudocod Cod C
integer a, b, aux
i n t a , b , aux ;
read a, b
s c a n f ( "%d %d" , &a , &b ) ;
aux a
aux = a ;
ab
a = b;
b aux
b = aux ;
4
Pseudocod Cod C
integer n
int n ;
read n
s c a n f ( "%d" , &n ) ;
if n%2 == 0 then
i f ( n % 2 == 0 )
write Numarul , n, este par
p r i n t f ( " Nr . %d este par " , n ) ;
else
else
write Numarul , n, este impar
p r i n t f ( " Nr . %d este par " , n ) ;
end if
Pseudocod Cod C
integer a, b
int a , b ;
read a, b
s c a n f ( "%d %d" , &a , &b ) ;
if a >= b then
i f ( a >= b )
write Maximul: , a
p r i n t f ( " Maximul : %d" , a ) ;
else
else
write Maximul: , b
p r i n t f ( " Maximul : %d" , a ) ;
end if
5
Pseudocod Cod C
integer a, b, c, max
i n t a , b , c , max ;
read a, b, c
s c a n f ( "%d %d %d" , &a , &b , &c ) ;
max a
max = a ;
if max < b then
i f ( max < b ) max = b ;
max b
i f ( max < c ) max = c ;
end if
p r i n t f ( " Maximul : %d" , max ) ;
if max < c then
max c
end if
write Maximul: , max
2.6 Tema
Exercitiul 2.1. Cititi de la tastatura un numar ntreg si verificati daca este
divizibil cu 5.
Exercitiul 2.2 . Introduceti o data exprimata prin trei numere ntregi, repre-
zentand anul, luna si ziua. Afisati data corespunzatoare urmatoarei zile.
De exemplu, daca introducem 2014 5 10, se va afisa 2014 5 11. Ce se
ntampla daca introducem 2014 10 31? Dar 2014 12 31?
Exercitiul 2.4 . Data valoarea unui numar natural mai mic sau egal cu 99,
se cere sa se tipareasca n scriere romana.
6
Laboratorul 3
Structuri repetitive
Pseudocod Cod C
integer n, s, i int n , s , i ;
read n s c a n f ( "%d" , &n ) ;
s0 s = 0;
i1 i = 1;
while i <= n do while ( i <= n ) {
ss+i s = s + i;
ii+1 i ++;
end while }
write s p r i n t f ( "%d" , s ) ;
7
Exemplul 3.2. Sa se afiseze suma cifrelor unui numar ntreg n.
Comentariu. Pentru a calcula suma cifrelor unui numar ntreg, va
trebui sa obtinem individual fiecare cifra. Deoarece nu stim cate cifre are
numarul introdus de utilizator, vom extrage pe rand cate o cifra din numar
si o vom adauga la o suma s, initializata cu 0. Vom folosi formula n%10,
care este egala cu ultima cifra a lui n. Dupa adaugarea ultimei cifre la
suma, aceasta poate fi eliminata din numar prin utilizarea formulei n/10,
care, pentru n ntreg, reprezinta numarul n fara ultima cifra.
Pseudocod Cod C
integer n, s
int n , s ;
read n
s c a n f ( "%d" , &n ) ;
s0
s = 0;
while n! = 0 do
while ( n != 0 ) {
s s + n%10
s = s + n % 10 ;
n n/10
n = n / 10 ;
end while
}
write s
p r i n t f ( "%d" , s ) ;
Pseudocod Cod C
integer x
int x ;
read x
s c a n f ( "%d" , &x ) ;
while x! = 0 do
while ( x != 0 ) {
read x
s c a n f ( "%d" , &x ) ;
end while
}
8
Pseudocod Cod C
integer x
int x ;
do
do{
read x
s c a n f ( "%d" , &x ) ;
while x! = 0
}
while ( x != 0 ) ;
Pseudocod Cod C
integer n, s, i
int n , s , i ;
read n
s c a n f ( "%d" , &n ) ;
s0
s = 0;
for i 1, n do
f o r ( i = 1 ; i <= n ; i ++){
ss+i
s = s + i;
end for
}
write s
p r i n t f ( "%d" , s ) ;
9
Exemplul 3.4. Sa se calculeze numarul de cifre ale unui numar ntreg n.
Pseudocod Cod C
integer n, c
int n , c ;
read n
s c a n f ( "%d" , &n ) ;
c0
c = 0;
while n! = 0 do
while ( n != 0 ) {
cc+1
c++;
n n/10
n = n/ 1 0 ;
end while
}
write c
p r i n t f ( "%d" , c ) ;
Pseudocod Cod C
integer n, r
int n , r ;
read n
s c a n f ( "%d" , &n ) ;
r0
r = 0;
while n! = 0 do
while ( n != 0 ) {
r r 10 + n%10
r = r 10 + n % 10 ;
n n/10
n = n/ 1 0 ;
end while
}
write r
p r i n t f ( "%d" , r ) ;
Pseudocod Cod C
integer x, max
read x i n t x , max ;
max x s c a n f ( "%d" , &x ) ;
while x! = 0 do max = x ;
read x while ( x != 0 ) {
if max < x then s c a n f ( "%d" , &x ) ;
max x i f ( max < x ) max = x ;
end if }
end while
Exemplul 3.7. Sa se calculeze cel mai mare divizor comun a doua numere
ntregi a si b.
10
Comentariu. Vom utiliza algoritmul lui Euclid care se bazeaza pe mpar-
tiri succesive astfel: se calculeaza restul martirii lui a la b, iar daca acesta
este nenul, se face o noua martire, de data aceasta a vechiului mpartitor
la rest, obtinandu-se un al doilea rest. Se continua algoritmul pana cand se
ajunge la un rest egal cu 0. Ultimul rest nenul reprezinta cel mai mare divizor
comun al numerelor initiale:
a : b => r0 =6 0
b : r0 => r1 = 6 0
r0 : r1 => r2 6= 0
Pseudocod Cod C
integer a, b, r
int a , b , r ;
read a, b
s c a n f ( "%d %d" , &a , &b ) ;
do
do{
r a%b
r = a % b;
ab
a = b;
br
b = r;
while r! = 0
while ( r != 0 )
write a
p r i n t f ( "%d" , a ) ;
3.4 Tema
Exercitiul 3.1. Sa se verifice daca un numar este palindrom (un numar este
palindrom daca este egal cu rasturnatul sau, de exemplu, 131, 2552, 6, 303
sunt palindroame).
Exercitiul 3.2. Sa se citeasca de la tastatura un numar natural n si o cifra
k. Eliminati din numar cifra k. De exemplu, daca se introduc n = 12147 si
k = 1, trebuie sa se construiasca numarul 247.
Exercitiul 3.3. Sa se afiseze toate numerele impare cuprinse ntre 23 si 50.
11
Exercitiul 3.4. Sa se afiseze toate numerele de forma 1xx1 care sunt diviz-
ibile cu 3.
Exercitiul 3.5. Sa se afiseze toate perechile de numere x si y cu proprietatea
ca x + y = 150, x este divizibil cu 7 si y cu 11.
Exercitiul 3.6. Sa se afiseze toti divizorii naturali ai unui numar natural
n.
Exercitiul 3.7. Sa se verifice daca un numar natural n este prim (un
numar este prim daca are exact doi divizori, pe 1 si pe el nsusi).
Exercitiul 3.8 . Sa afiseze primele n numere prime.
Exercitiul 3.9. Sa se citeasca de la tastatura un numar natural n si un
numar prim k. Sa se calculeze la ce putere apare k n descompunerea n
factori primi a numarului n.
Exercitiul 3.10. Sa se afiseze descompunerea n factori primi a unui numar
natural n.
Exercitiul 3.11 . Sa se citeasca de la tastatura n numere ntregi si sa se
calculeze media arimetica a acestora.
Exercitiul 3.12 . Sa se citeasca de la tastatura n numere ntregi si sa se
calculeze valoarea minima introdusa.
Exercitiul 3.13. Pentru n dat, sa se afiseze la consola urmatoarele n linii,
unde pe ultima linie sunt n caractere .
*
**
***
...
*** . . . *
Exercitiul 3.14. Pentru n dat, sa se afiseze la consola urmatoarele n linii,
unde pe prima linie sunt n caractere .
*** . . . *
...
***
**
*
12
Exercitiul 3.15. Sa se citeasca de la tastatura doua numere ntregi n si
x. Sa se introduca de la tastatura alte n numere ntregi si sa se calculeze de
cate ori apare valoarea lui x n sirul de numere (frecventa de aparitie a unui
numar ntr-un sir).
Exercitiul 3.16 . Sa se citeasca de la tastatura numere ntregi pana la
ntal-nirea lui 0 si sa se calculeze suma acestora.
Exercitiul 3.17 . Sa se citeasca de la tastatura numere ntregi pana la
ntal-nirea lui 0 si sa se calculeze valoarea maxima introdusa.
Exercitiul 3.18 . Sa se simuleze aruncarea unui zar de n ori (vezi Anexa
A), afisandu-se valoarea fetei si sa se afiseze de cate ori aparut valoarea 6.
Exercitiul 3.19 . Se arunca doua zaruri (vezi Anexa A) pana la obtinerea
unei duble. Sa se afiseze suma punctelor.
Exercitiul 3.20. Scrieti un program prin care i permiteti utilizatorului sa
ghiceasca un numar generat aleator astfel: programul va genera aleator un
numar ntreg cuprins ntre 1 si 100 (vezi Anexa A; numarul de ncercari
de care dispune utilizatorul este nelimitat; utilizatorul poate opri jocul prin
apasarea tastei 0. Scenariul va fi urmatorul:
1. utilizatorul introduce un numar
2. cat timp (while) numarul introdus este diferit de cel ghicit sau de 0 se
executa urmatoarele
3. dupa ncheierea buclei while, fie numarul introdus este chiar cel care
trebuia ghicit, caz n care se afiseaza mesajul Ati ghicit din ... ncercari,
fie utilizatorul a introdus 0 pentru a parasi jocul, caz n care afisati
numarul care trebuia ghicit.
Exercitiul 3.21
. Scrieti un program care afiseaza la consola un meniu dupa
urmatorul scenariu:
13
1. la rularea programului, utilizatorului i se va afisa meniul
14
Laboratorul 4
15
#i n c l u d e < s t d i o . h>
#i n c l u d e < s t d l i b . h>
i n t main ( ) {
int v [ 100 ] , n , i , s ;
p r i n t f ( "n = " ) ;
s c a n f ( "%d" , &n ) ;
for ( i = 0 ; i < n ; i ++){
p r i n t f ( "v [% d] = " , i ) ;
s c a n f ( "%d" , &v [ i ] ) ;
}
s = 0;
for ( i = 0 ; i < n ; i ++)
s = s + v[ i ];
p r i n t f ( "S = %d" , s ) ;
s y s t e m ( " pause " ) ;
return 0 ;
}
4.1 Tema
Exercitiul 4.1. Sa se citeasca de la tastatura n numere ntregi, cu 1 < n <
50 si sa se memoreze ntr-un vector. Calculati produsul elementelor aflate pe
pozitii impare in vector.
Exercitiul 4.2. Sa se citeasca de la tastatura n numere ntregi, cu 1 < n <
50 si sa se memoreze ntr-un vector. Calculati numarul de elemente nule din
vector.
Exercitiul 4.3. Sa se citeasca de la tastatura n numere ntregi, cu 1 < n <
50 si sa se memoreze ntr-un vector. Calculati valoarea maxima din vector.
Exercitiul 4.4. Sa se citeasca de la tastatura n numere ntregi, cu 1 <
n < 50 si sa se memoreze ntr-un vector. Afisati pozitiile pe care se gaseste
valoarea minima din vector.
Exercitiul 4.5. Sa se citeasca de la tastatura n numere ntregi, cu 1 < n <
100 si sa se memoreze ntr-un vector. Afisati numerele n ordinea inversa
citirii.
Exercitiul 4.6. Se introduc succesiv numere pana la ntalnirea lui 0, dar nu
mai multe de 1000. Sa se memoreze numerele introduse ntr-un vector si sa
se calculeze media lor aritmetica.
16
Exercitiul 4.7. Se introduc succesiv numere pana la ntalnirea lui 0, dar nu
mai multe de 100. Sa se memoreze numerele introduse ntr-un vector si sa
se calculeze numarul de elemente pare.
Exercitiul 4.9 . Sa se verifice daca cele n elemente ale unui vector formeaza
o progresie aritmetica (n ordinea n care se gasesc n vector).
17
Exercitiul 4.18 . Fiind dat un vector cu n elemente, numere ntregi citite de
la tastatura, mutati primul element pe pozitia pe care ar trebui sa se gaseasca
daca vectorul ar fi sortat crescator. Mutati de asemenea, toate elemente mai
mici n stanga acestuia, nu neaparat n ordine crescatoare, si toate numerele
mai mari n dreapta. Folositi o singura parcurgere a vectorului.
Exercitiul 4.20. Introduceti de la tastatura doua numere mari (de cel putin
15 cifre), cifra cu cifra. Memorati ciferele celor doua numere n cate un
vector. Calculati suma si produsul acestora.
18
Laboratorul 5
Tablouri bidimensionale
(Matrice)
19
Exemplul 5.1. Sa se citeasca de la tastatura doua valori ntregi m si n
(1 m 100 si 1 n 100) si elementele unei matrice de numere reale
cu m linii si n coloane. Calculati suma elementelor matricei.
#i n c l u d e < s t d i o . h>
#i n c l u d e < s t d l i b . h>
i n t main ( ) {
i n t n , m, i , j ;
f l o a t a [ 10 ] [ 10 ] , s = 0 ;
p r i n t f ( "m = " ) ;
s c a n f ( "%d" , &m) ;
p r i n t f ( "n = " ) ;
s c a n f ( "%d" , &n ) ;
for ( i = 0 ; i < m; i ++)
for ( j = 0 ; j < n ; j ++){
p r i n t f ( "a [% d ][% d] = " , i , j ) ;
s c a n f ( "%f" , &a [ i ] [ j ] ) ;
s = s + a[ i ][ j ];
}
p r i n t f ( "s = %f" , s ) ;
s y s t e m ( " pause " ) ;
return 0 ;
}
5.1 Tema
Exercitiul 5.1. Pentru o matrice patratica de ordin n ( 1 n 100) sa se
afiseze elementele de pe diagonala principala.
20
Exercitiul 5.6 . Fiind data o matrice patratica de ordin n ( 1 n 100),
stabiliti daca este un patrat magic. O matrice este patrat magic daca suma
elementelor de pe fiecare linie este egala cu suma elementelor de pe fiecare
coloana si cu suma elementelor de pe diagonale.
21
Laboratorul 6
Complexitatea algoritmilor
22
- Operatia 2 are costul 2 (n + 1), deoarece se constituie din atribuirea
succesiva a valorilor 1, 2, . . . , n + 1, variabilei i si verificarea conditiei
i <= n pentru fiecare din aceste valori.
T(n) = 1 1 + 2 (n + 1) 1 + 1 n = 3 n + 3.
0 f (n) c g(n), n n0 }
6.2 Aplicatii
Sa se calculeze timpul de executie pentru urmatorii algoritmi:
23
Op. Algoritm Cost Nr. rep.
1 for i 0, m 1 do 2*(m + 1) 1
2 for j 0, p 1 do 2*(p + 1) m
3 c[i][j] 0 1 m*p
4 for k 0, n 1 do 2*(n + 1) m*p
5 c[i][j] c[i][j] + a[i][k] 1 m*p*n
b[k][j]
end for
end for
end for
Obtinem T(m, n, p) = 2 (m + 1) + 2 m (p + 1) + m p + 2 m p
(n + 1) + m p n si termenul dominant este m n p.
24
Op. Algoritm Cost Nr. rep.
1 gasit 0 1 1
2 i0 1 1
3 while i < n AND gasit == 0 do 1 1 (n) + 1
4 if x == v[i] then 1 1 (n)
5 gasit 1 1 2 (n)
else
6 ii+1 1 1 (n) 2 (n)
end if
end while
25
Cazul cel mai nefavorabil: elementul nu apartine sirului, atunci, T(n) se
poate scrie ca un sir recursiv astfel
T(1) =1
T(n) =a T(n/2) + b, n > 1,
unde a si b sunt constante reale. Prin urmare, timpul de executie are termenul
dominant log n.
6.3 Tema
Calculati timpul de executie si determinati termenul dominant al acestuia
pentru fiecare din algoritmii de mai jos.
Exercitiul 6.1.
x0
for i 0, n 1 do
for j 0, i 1 do
xx+1
end for
end for
Exercitiul 6.2 .
x0
for i 0, n 1 do
j2
while j <= n do
xx+1
j j2
end while
end for
26
Laboratorul 7
Sortari simple
27
Op. Algoritm Cost Nr. rep.
1 Insertie(v[], n)
for i 1, n 1 do 2*n 1
2 aux v[i] 1 n1
3 j i1 1 n1
4 while aux < v[j] AND j >= 0 do 1 i (n)
5 v[j + 1] v[j] 1 i (n) 1
6 j j1 1 i (n) 1
end while
7 v[j + 1] aux 1 n1
end for
Pn1 Pn1
Pn1 Obtinem T(n) = 2 n + (n 1) + (n 1) P+n1 i=1 i (n) + i=1 i (n) 1 +
i=1 i (n) 1 + (n 1) = 3 n 1 + 3 i=1 i (n).
Cazul cel mai favorabil: elementele sunt n ordine crescatoare, caz n care
conditia de la operatia 4 se evalueaza de fiecare data ca fiind falsa, atunci
i (n) = 1, oricare ar fi i = 1, n 1 si T(n) = 6 n 4.
Cazul cel mai nefavorabil: elementele sunt n ordine strict descrescatoare;
n aceasta situatie i (n) = i + 1, oricare ar fi i = 1, n 1 si T(n) = 3 n
1 + 3 (2 + 3 + + n) = 32 n (n + 1) + 3 n 4.
La adresa http://www.sorting-algorithms.com/insertion-sort este
studiat mecanismul sortarii prin insertie aplicat pe diferite clase de date de
intrare.
Algoritm. Dorim sa sortam crescator cele n elemente v[0], v[1], v[n 1] ale
unui vector v. Pentru fiecare i de la 0 la n 2,
1. Se cauta valoarea minima din sirul v[i], . . . , v[n 1], ramas neordonat.
28
Op. Algoritm Cost Nr. rep.
1 Selectie(v[], n)
for i 0, n 2 do 2*n 1
2 poz min i 1 n1
3 for j i + 1, n 1 do 2*(n - i) 1
4 if v[j] < v[poz min] then 1 ni
5 poz min j 1 1i (n)
end if
end for
6 if poz min! = i then 1 n1
7 v[poz min] v[i] 1 2i (n)
end if
end for
Obtinem T(n) = 4 n 2 + n2
P
i=0 {3 n 3 i + 1i (n) + 3 2i (n)}.
Cazul cel mai favorabil: elementele sunt n ordine crescatoare, caz n care
conditiile de la operatiile 4, respectiv 6, se evalueaza de fiecare data ca fiind
false. Prin urmare, 1i (n) = 0 si 2i (n) = 0, oricare ar fi i = 0, n 2.
Cazul cel mai nefavorabil: elementele sunt n ordine strict descrescatoare;
n aceasta situatie 1i (n) = n i 1 si 2i (n) = 1, oricare ar fi i = 0, [ n2 ];
1i (n) = 0 si 2i (n) = 0, oricare ar fi i = [ n2 ] + 1, n 2
In ambele cazuri T(n) este o functie polinomiala de grad 2.
La adresa http://www.sorting-algorithms.com/selection-sort este
studiat mecanismul sortarii prin selectie aplicat pe diferite clase de date de
intrare.
7.3 Tema
Exercitiul 7.1. Implementati algoritmul de sortare prin selectia maximului.
Exercitiul 7.2. Pentru cei doi algoritmi de mai sus, scrieti variantele care
ordoneaza descrescator sirurile.
29
Idee: se construieste un vector c cu m elemente in care c[i] reprezinta
frecventa de aparitie a lui i n sirul dat, oricare ar fi 0 i < m; se con-
struieste sirul sortat crescator folosind informatia din c. La implementare se
tine cont de timpul de executie astfel ncat complexitatea sa fie O(n + m).
Exercitiul 7.5
. Implementati Heapsort. Vezi documentul Heapsort.pdf.
30
Laboratorul 8
Tehnici de programare.
Recursivitate si Divide et
Impera
8.1 Recursivitate
Un algoritm recursiv este caracterizat de
- apeluri recursive prin care algoritmul se apeleaza pe el nsusi cel putin
o data; valorile parametrilor trebuie sa convearga n urma apelurilor
recursive spre valorile parametrilor dintr-o conditie de oprire
- conditii de oprire care specifica situatiile n care rezultatul poate fi
calculat direct, fara a fi necesar un apel recursiv.
Mai jos este descris un exemplu de algoritm recursiv generic.
alg rec(n)
if n == n0 then
R0
else
alg rec(h(n))
end if
Functia h are proprietatea ca exista k 0 astfel ncat h(k) (n) = h h
h(n) = n0
Exemplul 8.1. Functia de mai jos afiseaza toate numerele mai mici decat
o valoare data n ordine descrescatoare.
31
void p r i n t ( i n t n ) {
i f ( n == 0 ) p r i n t f ( "%d " , n ) ;
else {
p r i n t f ( "%d " , n ) ;
print (n 1 ) ;
}
}
x0 = 1
1
xk = xk1 + , k > 0.
xk1
Vom defini o functie x() recursiva cu proprietatea ca pentru orice k 0,
x(k) returneaza valoarea termenului xk .
float x ( int k ){
i f ( k == 0 ) return 1 ;
e l s e return x ( k 1 ) + 1 / x ( k 1 ) ;
}
32
Pentru a rezolva si alte tipuri de probleme n mod recursiv este necesar
sa se gaseasca relatii de recursivitate ntre pasii algoritmului iterativ.
Exemplul 8.3. Sa se scrie un subprogram recursiv care sa primeasca ca
parametru un numar natural si sa calculeze suma cifrelor acestuia.
Pentru a rezolva aceasta problema vom defini functia suma cif re : N
N. Urmatoarele proprietati ale functiei se deduc usor:
si avem implementarea
int s u m a c i f r e ( int k ){
i f ( k == 0 ) return 0 ;
e l s e return s u m a c i f r e ( k / 1 0 ) + k%1 0 ;
}
cmmdc(a, 0) = a
cmmdc(a, b) = cmmdc(b, a%b).
33
- divide: problema initiala este mpartita n subprobleme; fiecare sub-
problema este rezolvata recursiv n aceeasi maniera; atunci cand di-
mensiunea problemei curente se reduce la o valoare suficient de mica,
atunci aceast este rezolvata direct;
Studiu de caz. Pentru a calcula suma elementelor unui sir format din n
elemente, se poate aplica divide et impera astfel: suma tuturor elementelor
se poate scrie ca suma dintre suma elementelor din prima jumatate si suma
elementelor din a doua jumatate a sirului; fiecare subsir este impartit n
mod recursiv n doua subsiruri; atunci cand un subsir este suficient de mic
(de exemplu, cand este format dintr-un singur element) rezultatul poate fi
calculat direct.
Fie sirul x1 , x2 , x3 , . . . , xn . Se poate construi o functie suma(p, u) =
xp + xp+1 + + xu dupa principiul divide et impera astfel:
int suma ( int x [ ] , int p , int u ) {
i f ( p==u ) return x [ p ] ;
else {
int m = ( p+u ) / 2 ;
return ( suma ( p , m) + suma (m+1 , u ) ) ;
}
}
34
e l s e i f ( x < v [m] ) return cb ( v , x , p , m 1 ) ;
e l s e return cb ( v , x , m + 1 , u ) ;
}
}
8.3 Tema
Exercitiul 8.1. Sa se calculeze al n-lea termen al sirului lui Fibonacci:
f0 = 1
f1 = 1
fk = fk1 + fk2 , k > 1.
Exercitiul 8.3 . Din numarul 4 se poate obtine orice numar natural n prin
aplicarea urmatoare-lor operatii:
35
Pentru o functie f cu proprietatile de mai sus sa se calculeze o aproximatie
a solutiei ecuatiei f (x) = 0 cu o eroare > 0. Functia f si intervalul [a, b]
vor fi alese de catre student. Eroarea va fi introdusa de utilizator (de obicei
mai mica decat 104 ).
Indicatie. Se creeaza o functie care primeste ca parametru un numar
real x si returneaza valoarea reala f (x); la fiecare pas se verifica daca |f (xn )| <
, caz n care xn reprezinta aproximatia solutiei; n caz contrar se calculeaza
urmatorul element din sir si se continua (recursiv).
Exemple de functii care verifica toate conditiile de mai sus
f : [1, 3] R; f (x) = x3 8,
36
Laboratorul 9
Mergesort si Quicksort
- atunci cand unul dintre siruri a fost parcurs complet, elementele ramase
n celalalt sir sunt copiate n c.
37
Se poate scrie urmatoarea functie recursiva.
mergesort(v[], p, u)
if p < u then
m (p + u)/2
mergesort(v, p, m)
mergesort(v, m + 1, u)
interclasare(v, p, m, u)
end if
Functia interclasare() realizeaza interclasarea sirurilor ordonate v[p], v[p +
1], . . . , v[m] si v[m + 1], . . . , v[u] n sirul c[0], c[1], . . . c[u p]. La final, valorile
din vectorul c (sortat) se copiaza napoi n v[p], v[p + 1], . . . v[u].
interclasare(v[], p, m, u)
ip
j m+1
k0
while i <= m AND j <= u do
38
if v[i] <= v[j] then
c[k] v[i]
ii+1
else
c[k] v[j]
j j+1
end if
k k+1
end while
while i <= m do
c[k] v[i]
ii+1
k k+1
end while
while j <= u do
c[k] v[j]
j j+1
k k+1
end while
for i 0, k 1 do
v[i + p] c[i]
end for
39
Pivotare. Daca pivotul este ales ca fiind primul element al sirului curent,
pentru a i gasi pozitia n ordinea finala se procedeaza n felul urmator: se
parcurge simultan sirul de la stanga la dreapta ncepand cu cea de-a doua
pozitie si de la dreapta la stanga (cu prioritate) pana la ntalnire; elementele
mai mici decat pivotul, aflate la dreapta se vor interschimba cu cele mai mari
aflate la stanga. In final se interschimba valorea pivotului cu valorea pe care
s-a oprit parcurgerea.
Exemplul 9.1. Vom considera sirul 47, 34, 91, 75, 5, 65, 1, 23 si vom
exemplifica operatia de pivotare.
- se alege 47 ca pivot si se ncepe parcurgerea simultana: 47, 34, 91 75,
5, 65, 1, 23
- are loc o noua interschimbare, a lui 75 cu 1: 47, 34, 23, 1, 5, 65, 75,
91
- cum 65 > 47, se continua parcurgerea spre stanga: 47, 34, 23, 1, 5,
65, 75, 91.
40
pivot v[p]
sp+1
du
while s <= d do
while v[d] > pivot do
dd1
end while
while v[s] < pivot AND s <= d do
ss+1
end while
if s <= d then
v[s] v[d]
dd1
ss+1
end if
end while
v[p] v[d]
return d
41
Laboratorul 10
42
struct o b i e c t {
float greutate ;
float valoare ;
int i n d e x ;
} ob [ 1 0 0 ] ;
43
10.2 Colorarea unei harti
Se considera o harta cu n tari, numerotate de la 0 la n 1. Pentru oricare
doua tari se nregistreaza relatia de vecinatate. Acest lucru se realizeaza cu
ajutorul unei matrice a, astfel: daca tarile i si j sunt vecine, atunci a[i][j] = 1;
n caz contrar, a[i][j] = 0. Gasiti o modalitate de a colora harta, utilizand
cat mai putine culori, astfel ncat doua tari vecine sa nu aiba aceeasi culoare.
Dispunem de un numar nelimitat de culori c0 , c1 , c2 , . . . .
Aplicand strategia Greedy, vom colora prima tara utilizand culoarea c0 .
La fiecare pas vom ncerca sa coloram urmatoarea tara folosind c0 ; daca
tara are un vecin colorat cu c0 , testam posibilitatea de a folosi culoarea c1 ;
continuam pana cand gasim o culoare valida.
Nod (tara) 0 1 2 3 4 5 6
Culoare c0 c1 c2 c3 c0 c1 c5
Prin urmare s-au folosit 5 culori. Se poate gasi o solutie mai buna (o
modalitate de a colora harta cu mai putin de 5 culori)? (Raspuns: Da)
44
10.3 Tema
Exercitiul 10.1. Gasiti un exemplu pentru problema nefractionara a ruc-
sacului n care tehnica Greedy nu genereaza o solutie optima.
45
Laboratorul 11
Tehnici de programare.
Backtracking
46
backtrack permut(x[], n)
init(x, n)
k0
while k >= 0 do
ok 0
while x[k] < n AND !ok do
x[k] x[k] + 1
if (valid(x, k)) then
ok 1
end if
end while
if (!ok) then
x[k] 0
k k1
else
if (k == n 1) then
print sol(x, n)
else
k k+1
end if
end if
end while
valid(x[], k)
for i 0, k 1 do
if (x[k] == x[i]) then
return 0
end if
end for
return 1
47
print sol(x[], n)
for i 0, n 1 do
write x[i]
end for
11.2 Tema
Exercitiul 11.1. Sa se genereze toate aranjamentele de m elemente din
multimea {1, 2, 3, . . . , n}, unde 0 m n.
48
Exercitiul 11.5 . Intr-o tabara se organizeaza n fiecare seara foc de tabara.
In prima seara toti participantii se aseaza n jurul focului. In cea de-a doua
seara acestia trebuie sa se aseze astfel ncat cei care au fost vecini n prima
seara sa nu mai stea alaturi. Determinati toate posibilitatile de a i aseza pe
cei n participanti n a doua seara.
49
Laboratorul 12
Tehnici de programare.
Programare dinamica
50
Pentru a calcula valoarea valoarea asociata unei solutii optime se foloseste
una dintre strategiile bottom-up (se calculeaza solutiile optime ale subprob-
lemelor si din aceste informatii se obtine solutia optima a problemei initiale)
sau top-down cu memoization (problema initiala este descompusa si, pe
masura ce subproblemele sunt rezolvate, solutiile sunt salvate pentru a putea
fi refolosite).
Exemplul 12.1. Sirul lui Fibonacci este definit astfel
f0 = 1
f1 = 1
fk = fk1 + fk2 , k > 1.
Implementarea acestuia n mod recursiv poate fi realizata cu ajutorul functiei
long f ( i n t k ) {
i f ( k == 0 | | k == 1 ) return 1 ;
e l s e return f ( k 1 ) + f ( k 2 ) ;
}
insa n abordarea de mai sus, se produc aceleasi apeluri de mai multe ori,
prin urmare aceeasi problema este rezolvata n mod repetat. Complexitatea
algoritmului este exponentiala.
Cu o strategie de tip bottom-up, primii n termeni ai sirului lui Fibonacci
pot fi calculati secvential, ncepand cu cel de-al treilea
f [0] = 1; f [1] = 1;
for ( k = 2 ; k < n ; k++)
f [k] = f [k 1] + f [k 2];
Obtinem un algoritm liniar.
51
Acest sir, odata construit, ofera toate informatiile necesare gasirii unui
subsir SCM: valoarea maxima din l reprezinta lungimea unui astfel de sir;
daca valoarea maxima se gaseste pe o pozitie p, atunci, ap reprezinta ul-
timul element al unui subsir SCM; pentru a gasi urmatoarele elemente (de la
dreapta spre stanga) se va parcurge l spre stanga, ncepand cu pozitia p - 1;
doua elemente consecutive dintr-un subsir SCM, aij si aij+1 , au proprietatea
ca aij < aij+1 si lij = lij+1 1.
Pentru exemplul de mai sus, cum valoarea maxima se gaseste pe pozitia
8 n l, rezulta ca un subsir SCM va avea ca ultim element pe a8 = 6. In
continuare, se va cauta n l, ncepand cu pozitia 7, un element cu proprietatea
ca este mai mic cu o unitate ca 5 si ca elementul corespunzator din a este mai
mic ca 6. Primul element care ndeplineste aceste conditii este chiar l7 . Se
continua algoritmul pana cand se construieste un subsir SCM de dimensiune
5.
Pentru a construi sirul l, se va tine cont de faptul ca
l0 = 1
li = 1 + max{lj |0 j i 1 si ai < aj }, i > 0.
Propunem urmatorul algoritm, care calculeaza valorile lui l ntr-o maniera
de tip bottom-up.
calcul l(l[], a[], n)
l[0] 1
for i 1, n 1 do
max 0
for j 0, i 1 do
if (a[i] > a[j] AND l[j] > max) then
max l[j]
end if
end for
l[i] max + 1
end for
52
if (l[i] > l[poz max]) then
poz max i
end if
end for
k l[poz max]
s[k 1] a[poz max]
for i k 2, 0, 1 do
j poz max 1
while (a[j] >= a[poz max] AND l[j]! = l[poz max] 1) do
j j1
end while
s[i] a[j]
poz max j
end for
12.2 Tema
Exercitiul 12.1. Inmultirea unui sir de matrice. Se considera un si
r A0 , A1 , . . . , Ak1 de matrice de dimensiune n0 n1 , n1 n2 , . . . , respectiv,
nk1 nk . Stiind ca n multirea matricelor este asociativa, sa se determine o
modalitate de parantetizare a produsului A0 A1 . . . Ak1 astfel ncat numarul
total de nmultiri elementare sa fie minim.
53
Indicatie: se construieste matricea C de ordin k, cu proprietatea ca
C[i, j] = numarul minim de produse elementare necesare pentru a calcula
produsul Ai , Ai+1 , . . . , Aj , cu 0 i j < k. Elementele acestei matrice
(zona de deasupra diagonalei principale) se pot calcula n mod recursiv ast-
fel:
C[i, i] = 0
C[i, i + 1] = ni ni+1 ni+2
C[i, j] = min{C[i, l] + C[l + 1, j] + ni nl+1 nj+1 |0 i l j < k}.
Exercitiul 12.3
. Cel mai lung subsir comun. Sa se determine cel mai
lung subsir comun a doua siruri de dimensiune n, respectiv m.
54
Anexa A
int main ( ) {
p r i n t f ( "%d %d %d\n" , rand ( ) , rand ( ) , rand ( ) ) ;
De fiecare data se vor afisa aceleasi trei valori. Motivul pentru care se
ntampla acest lucru este pentru ca functia rand() foloseste generatoare de
numere pseudoaleatoare. Generatorul de numere pseudoaleatoare este
un algoritm care construieste un sir de numere cu proprietati asemanatoare
unui sir aleator de numere. Fiecare sir este complet determinat de un seed
(samanta). In mod implicit seed-ul utilizat este 1. Seed-ul poate fi initializat,
nainte de apelurile rand(), folosind functia srand(). O modalitate prin care
la fiecare rulare sa se foloseasca un alt seed este de a utiliza comanda
s r a n d ( time (NULL ) ) ;
55
#i n c l u d e <time . h> / / ! ! ! !
int main ( ) {
s r a n d ( time (NULL ) ) ;
p r i n t f ( "%d %d %d\n" , rand ( ) , rand ( ) , rand ( ) ) ;
56