You are on page 1of 179

ALGORITMIC

A
Lector Dr. Paul Iacob
Asistent Drd. Lucian Sasu
Universitatea Transilvania din Brasov
Facultatea de Matematic a si Informatic a
Catedra de Informatic a
Octombrie 2003
2
Cuprins
1 Introducere 7
1.1 Scopul cursului . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2 Generalit at i . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2 Limbajul pseudocod 11
2.1 Obiective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.2 Limbajul pseudocod . . . . . . . . . . . . . . . . . . . . . . . 11
2.3 Rezumat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3 Analiza algoritmilor 17
3.1 Obiective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.2 Analiza algoritmilor . . . . . . . . . . . . . . . . . . . . . . . . 17
3.3 Algoritmi parametrizat i (subalgoritmi) . . . . . . . . . . . . . 21
3.4 Notat ia asimptotic a . . . . . . . . . . . . . . . . . . . . . . . . 24
3.5 Rezumat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3.6 Exercit ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
4 Structuri elementare de date 27
4.1 Obiective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
4.2 Structuri liniare . . . . . . . . . . . . . . . . . . . . . . . . . . 27
4.3 Stiva . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
4.3.1 Alocarea secvent ial a a stivei . . . . . . . . . . . . . . . 29
4.3.2 Alocarea nl ant uit a a stivei . . . . . . . . . . . . . . . . 29
4.4 Coada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
4.4.1 Alocarea secvent ial a a cozii . . . . . . . . . . . . . . . 31
4.4.2 Alocarea nl ant uit a a cozii . . . . . . . . . . . . . . . . 32
4.5 Arbori binari . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.5.1 Alocarea secvent ial a a unui arbore binar . . . . . . . . 34
4.5.2 Alocarea nl ant uit a a unui arbore binar . . . . . . . . . 34
4.5.3 Alocarea mixt a a unui arbore binar . . . . . . . . . . . 35
4.6 Rezumat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
3
4.7 Exercit ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
5 Recursivitate 39
5.1 Obiective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
5.2 Prezentare general a . . . . . . . . . . . . . . . . . . . . . . . . 39
5.3 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
5.3.1 Calcularea lui n! . . . . . . . . . . . . . . . . . . . . . 45
5.3.2 Sirul lui Fibonacci . . . . . . . . . . . . . . . . . . . . 45
5.4 Rezumat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
5.5 Exercit ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
6 Metoda Backtracking 49
6.1 Obiective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
6.2 Prezentare general a . . . . . . . . . . . . . . . . . . . . . . . . 49
6.3 Exemplu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
6.4 Rezumat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
6.5 Exercit ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
7 Generarea submult imilor 55
7.1 Obiective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
7.2 Schema general a de lucru . . . . . . . . . . . . . . . . . . . . . 55
7.3 Generarea elementelor unui produs cartezian . . . . . . . . . . 57
7.4 Generarea tuturor submult imilor unei mult imi . . . . . . . . . 58
7.5 Generarea mult imii combin arilor . . . . . . . . . . . . . . . . . 59
7.6 Generarea mult imii permut arilor . . . . . . . . . . . . . . . . . 62
7.7 Generarea mult imii aranjamentelor . . . . . . . . . . . . . . . 65
7.8 Submult imi de sum a dat a . . . . . . . . . . . . . . . . . . . . 67
7.9 Rezumat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
7.10 Exercit ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
8 Metoda Divide et Impera 71
8.1 Obiective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
8.2 Prezentare general a . . . . . . . . . . . . . . . . . . . . . . . . 71
8.3 Problema turnurilor din Hanoi . . . . . . . . . . . . . . . . . . 72
8.3.1 Metoda I . . . . . . . . . . . . . . . . . . . . . . . . . . 74
8.3.2 Metoda a IIa . . . . . . . . . . . . . . . . . . . . . . . 75
8.3.3 Metoda a IIIa . . . . . . . . . . . . . . . . . . . . . . 76
8.4 Algoritmul de sortare QuickSort . . . . . . . . . . . . . . . . . 77
8.5 Rezumat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
8.6 Exercit ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
4
9 Sortare si statistici de ordine 83
9.1 Obiective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
9.2 Exemplic ari, generalit at i . . . . . . . . . . . . . . . . . . . . 83
9.3 Determinarea simultan a a minimului si a maximului . . . . . . 84
9.4 G asirea celor mai mici dou a elemente dintrun sir . . . . . . . 85
9.5 Problema select iei . . . . . . . . . . . . . . . . . . . . . . . . . 87
9.5.1 Select ie n timp mediu liniar . . . . . . . . . . . . . . . 87
9.5.2 Select ia n timp liniar n cazul cel mai defavorabil . . . 88
9.6 Heapsort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
9.7 Algoritmi de sortare n timp liniar . . . . . . . . . . . . . . . . 92
9.7.1 Algoritmul sort arii prin num arare (CountSort) . . . . . 92
9.7.2 Sortare pe baza cifrelor . . . . . . . . . . . . . . . . . . 94
9.7.3 Sortare pe grupe . . . . . . . . . . . . . . . . . . . . . 95
9.8 Rezumat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
9.9 Exercit ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
10 Metoda Greedy 99
10.1 Obiective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
10.2 Prezentare general a . . . . . . . . . . . . . . . . . . . . . . . . 99
10.3 Submult imi de sum a maxim a . . . . . . . . . . . . . . . . . . 100
10.4 Arborele Human . . . . . . . . . . . . . . . . . . . . . . . . . 102
10.5 Interclasare optimal a . . . . . . . . . . . . . . . . . . . . . . . 106
10.6 Rezumat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
10.7 Exercit ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
11 Programare dinamic a 111
11.1 Obiective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
11.2 Prezentare general a . . . . . . . . . . . . . . . . . . . . . . . . 111
11.3

Inmult irea unui sir de matrici . . . . . . . . . . . . . . . . . . 112
11.4 Cel mai lung subsir cresc ator . . . . . . . . . . . . . . . . . . . 117
11.5 Rezumat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
11.6 Exercit ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
12 Teste de autoevaluare 121
A Metode utile n calculul complexitat ii 127
A.1 Sume des nt alnite . . . . . . . . . . . . . . . . . . . . . . . . 127
A.2 Delimitarea sumelor . . . . . . . . . . . . . . . . . . . . . . . 128
A.2.1 Induct ia matematic a . . . . . . . . . . . . . . . . . . . 128
A.2.2 Aproximarea prin integrale . . . . . . . . . . . . . . . . 129
A.3 Analiza algoritmilor recursivi . . . . . . . . . . . . . . . . . . 130
5
A.3.1 Metoda iterat iei . . . . . . . . . . . . . . . . . . . . . . 130
A.3.2 Recurent e liniare omogene . . . . . . . . . . . . . . . . 131
A.3.3 Recurent e liniare neomogene . . . . . . . . . . . . . . . 132
B Rezolvari 135
B.1 Rezolv ari pentru capitolul 3 . . . . . . . . . . . . . . . . . . . 135
B.2 Rezolv ari pentru capitolul 4 . . . . . . . . . . . . . . . . . . . 145
B.3 Rezolv ari pentru capitolul 5 . . . . . . . . . . . . . . . . . . . 150
B.4 Rezolv ari pentru capitolul 6 . . . . . . . . . . . . . . . . . . . 153
B.5 Rezolv ari pentru capitolul 7 . . . . . . . . . . . . . . . . . . . 160
B.6 Rezolv ari pentru capitolul 8 . . . . . . . . . . . . . . . . . . . 162
B.7 Rezolv ari pentru capitolul 9 . . . . . . . . . . . . . . . . . . . 165
B.8 Rezolv ari pentru capitolul 10 . . . . . . . . . . . . . . . . . . 168
B.9 Rezolv ari pentru capitolul 11 . . . . . . . . . . . . . . . . . . 174
6
Capitolul 1
Introducere
1.1 Scopul cursului
Lucrarea de fat a si propune s a e un nurs introductiv n teoria algorit-
milor. Se vor introduce not iunile de algoritm, subalgoritm, complexitatea
algoritmilor, diferite metode de programare, probleme clasice. Cursul este
detinat student ilor din anul nt ai, at at de la zi c at si de la forme alternative
(nv at am ant la distanc u a, cursuri postuniversitare).
1.2 Generalitat i
Pentru rezolvarea unei probleme pe calculator, se parcurg urm atorii pasi:
1. se detecteaz a problema;
2. se adaug a restrict iile impuse de domeniul care a creat problema;
3. se creeaz a un model matematic;
4. se concepe un algoritm (un mod) de rezolvare a problemei;
5. se scrie un program;
6. se interpreatez a rezultatele de la calculator n termeni specici dome-
niului problemei.
Pasii 1, 2, 3 sunt n general reunit i sub numele de analiz a. Pasii 4, 5
constituie programarea. Pasul 6 face parte din implementare.
Deci algoritmul reprezint a un pas intermediar ntre modelul matematic
si programul realizat ntr-un program conceput pentru calculator. Originea
7
cuv antului algoritm este legat a de numele Abu Jafar Mohammed Ibn M us a
al Khow arizm, autor arab al unei c art i de matematic a. Not iunea de algoritm
este fundamental a, deci nu se poate deni; n general, ea este explicat a ca o
succesiune nit a de pasi computat ionali care transform a date de intrare n
date de iesire.
Propriet at ile pe care trebuie s a le aibe un algoritm sunt:
1. Fiecare pas trebuie s a cont in a o operat ie bine denit a (de exemplu
urm atoarele operat ii nu sunt bine denite: 4/0 sau scade 10 sau 20
din 30);
2. Pasul care urmeaz a ec arui pas trebuie s a e unic denit;
3. Fiecare pas trebuie s a e efectuabil, adic a s a poat a executat cu cre-
ionul pe h artie: operat ii cu numere ntregi - da, dar operat ii cu numere
reale n general - nu.
4. Trebuie s a se termine n timp nit. Se poate spune c a timpul trebuie
s a e rezonabil de scurt si totusi vor considerat i algoritmi care pe
masinile actuale necesit a zeci de ani pentru c a se presupune c a viitoarele
masini vor mult mai rapide.
Ce vom studia n leg atur a cu algoritmii?
1. Cum s a concepem un algoritm? Crearea unui algoritm nu va nicio-
dat a pe deplin automatizat a, va r am ane o problem a a omului n primul
r and si abia apoi a masinii.

In aceast a ordine de idei vom studia n
acest curs metode de elaborare a algoritmilor.
2. Exprimarea noastr a va restr ans a, din necesitatea de a scrie usor pro-
grame corecte, la algoritmi structurat i, adic a algoritmi care folosesc
anumite structuri specice care vor expuse la nceputul cursului.
3. Vom nv at a s a veric am corectitudinea algoritmilor conceput i. Un al-
goritm corect trebuie s a rezolve problema propus a pentru orice date
de intrare. Nu se pune problema veric arii cu anumite date (acest lu-
cru t ine de vericarea programului), ci problema unei demonstrat ii a
corectitudinii programului (n general ca o teorem a).
4. Nu ajunge s a construim algoritmi corect i! Trebuie s a cunoastem si
performant ele algoritmilor creat i. Pot exista mai mult i algoritmi care
s a rezolve aceeasi problem a, unii mai greu sau mai usor de nteles (de
urm arit), unii mai lungi n num arul de pasi descrisi, dar cu performant a
urm arit a prin analiz a (num arul de pasi elementari executat i, n leg atur a
8
cu dimensiunea intr arii). O alt a problem a este cea legat a de dimensiu-
nea memoriei necesare execut iei programului realizat dup a un anumit
algoritm.
9
10
Capitolul 2
Limbajul psedocod si structuri
fundamentale
2.1 Obiective

In acest capitol se va prezenta lexicul limbajului pseudocod, care va


folosit n restul lucr arii pentru reprezentarea algoritmilor. Se introduc
instruct iunile de atribuire, decizie, ciclare, citire, scriere. Not iunile prezen-
tate sunt nsot ite de exemple simple care s a ajute la nsusirea temeinic a a
elementelor.
2.2 Limbajul pseudocod
Limbajul n care este descris algoritmul trebuie s a e un intermediar ntre
limbajul matematic si cel de programare.
Limbajul schemei logice are avantaje de explicat ie grac a, dar si dezavan-
taje legate de structurare si translatare, asa c a vom folosi pseudocodul. Acest
limbaj foloseste cuvinte cheie (subliniate), cuvinte care denesc variabile si
constante si text explicativ (ntre acolade).
Putem distinge urm atoarea structur a general a:
Start Numele programului
citeste( date de intrare )
prelucreaz a datele
scrie( rezultate )
Stop
Putem specica:
11
Liste de date (a, b, x)
Vectori (a(i), i = 1, n)
Matrici ((x(i, j), j = 1, n), i = 1, m)
Constante (Viteza=, v)
Operat ia cea mai des folosit a este atribuirea.
a = 1
1 a
copiere
Figura 2.1: Atribuirea a = 1.

In acest mod, numele a este legat de o zon a de memorie n care se intro-


duce valoarea 1. Pentru
a = b +c
efectul este dat n gura 2.2:
b c
zona intermediara
+
calcul
copiere
a
Figura 2.2: Atribuirea a = b +c.
Se calculeaz a rezultatul operat iei de adunare b + c, acesta depun andu-
se ntr-o zon a intermediar a. Rezultatul adun arii se copiaz a apoi n zona de
memorie alocat a variabilei a. Chiar si pentru o atribuire de genul:
a = a + 1
rezultatul adun arii lui a cu 1 se depune ntr-o zon a intermediar a, dup a care
se copiaz a n locat ia lui a, precum n gura 2.3.
Atunci c and pasul urm ator depinde de o anumit a situat ie cucerit a p an a
atunci, el este rezultatul unei decizii care va scris astfel:
dac a condit ie logic a atunci
(grup de pasi 1)
altfel
(grup de pasi 2)
12
a 1
zona intermediara
+
calcul
copiere
a
Figura 2.3: Atribuirea a = a + 1.
sf arsit dac a
Exemplul 1.
Start Algoritm 1
citeste( i, a )
dac a i 1 atunci
a = a +i
altfel
a = a i
sf arsit dac a
scrie( a=, a )
Stop
Acest program scrie a = 10 dac a intrarea este 0, 10, iar pentru intrarea 2, 10
scrie a = 8.
Exemplul 2. Urm atorul algoritm g aseste cel mai mare dintre trei nu-
mere:
Start Algoritm 2
citeste( a, b, c )
max = a
dac a max < b atunci
max = b
sf arsit dac a
dac a max < c atunci
max = c
sf arsit dac a
scrie( Maximul este , max )
Stop
Urm arit i algoritmul pentru valorile de intrare (10, 1, 3), (2, 2, 5), (1, 12, 2).
Exist a grupuri de instruct iuni care se execut a n mod repetat. Aceste
structuri se numesc cicluri si apar des n elaborarea algoritmilor.
Prima form a de ciclare se numeste ciclu cu num arator si se foloseste atunci
13
c and se stie de c ate ori se execut a un grup de instruct iuni. Are forma:
pentru ind = vi, vf, pas
grup de pasi
sf arsit pentru
Dac a pas = 1, atunci el se poate omite. Grupul de pasi din interiorul ciclului
poate s a nu se execute niciodat a, dac a se stie c a plec and de la valoarea
init ial a, modic and ind cu pasul specicat, nu se trece de valoarea nal a vf.
De exemplu, ciclul de mai jos nu se execut a dac a n < 1:
pentru ind = 1, n
grup de pasi
sf arsit pentru
Exemplul 3. Algoritmul de mai jos calculeaz a suma componentelor unui
vector a(i), i = 1, n:
Start Algoritm 3
citeste( n, (a(i), i = 1, n) )
s = 00 este element neutru pentru adunare
pentru i = 1, n, 1
s = s +a(i)
sf arsit pentru
scrie( suma este , s )
Stop
Exemplul 4. Pentru a num ara componentele pozitive (np), negative (nn)
si cele nule (nz) ale unui vector vom avea urm atorul algoritm:
Start Algoritm 4
citeste( n, (a(i), i = 1, n) )
np = 0
nn = 0
nz = 0
pentru i = 1, n
dac a a(i) > 0 atunci
np = np + 1
altfel
dac a a(i) < 0 atunci
nn = nn + 1
altfel
nz = nz + 1
sf arsit dac a
14
sf arsit dac a
sf arsit pentru
scrie( Pozitive= , np, Negative= , np, Nule= , nz )
Stop
Acest tip de cicluri se numesc cicluri cu num ar ator. Mai avem si cicluri cu
condit ie, care poate nainte sau dup a corpul ciclului (grupul de pasi ce se
execut a de ecare dat a).
Ciclul cu test anterior are forma:
c at timp (condit ie logic a)
grup de pasi
sf arsit c at timp
Corpul ciclului poate s a nu se execute niciodat a, dac a codit ia logic a este de
la nceput fals a.
Exemplul 5. Algoritmul urm ator (algoritmul lui Euclid) serveste la deter-
minarea celui mai mare divizor comun a dou a numere:
Start Euclid
citeste( a, b )
m = a
n = b
c at timp n ,= 0
r = rest(m/n)
m=n
n=r
sf arsit c at timp
scrie( CMMDC dintre , a, si , b, este , m )
Stop
Ciclul cu test posterior are forma:
repet a
grup de pasi
p an a c and condit ie logic a
Urm arit i algoritmul pentru intr arile (10, 3) si (258, 12).
Grupul de pasi se execut a cel put in o dat a.
Exemplul 6. Se cere listarea combin arilor din 1, 2, 3, 4, 5 luate c ate
3:
Start Combin ari
pentru i = 1, 3
j = i
15
repet a
j = j + 1
k = j
repet a
k = k + 1
scrie( i,-,j,-,k )aseaz a o combinat ie
p an a c and k = 5
p an a c and j = 4
sf arsit pentru
Stop
2.3 Rezumat
Un algoritm are o structur a bine denit a. Instruct iunile prezentate, m-
preun a cu not iunea de subalgoritm din capitolul 3 formeaz a un vocabular
sucient pentru scrierea algoritmilor. Sau prezentat: forma general a a
unui algoritm, citirea si scrierea datelor, atribuirea, instruct iunea de deci-
zie, cele trei forme de ciclare.
16
Capitolul 3
Analiza algoritmilor.
Subalgoritmi. Notat ia
asimptotica
3.1 Obiective
Acest capitol prezint a modalitatea de comparare a performant ei algorit-
milor, folosind not iunea de complexitate. Se introduc cele trei notat ii asimp-
totice mpreun a cu relat iile dintre ele, formule de calucl general, propriet at i.
Exemplicarea se face prin compararea a doi algoritmi care rezolv a aceeasi
problem a: sortarea unui vector de numere (problem a de larg interes, care nu
are o rezolvare trivial a).
Se introduce de asemenea not iunea de subalgoritm, absolut necesar a n
scrierea algoritmilor recursivi sau ca form a de abstractizare. Capitolul se
ncheie cu o suit a de probleme propuse spre rezolvare, a c aror solut ionare
este dat a la sf arsitul lucr arii.
3.2 Analiza algoritmilor
Putem usor s a ne d am seama c a pentru a rezolva o anumit a problem a
pot exista mai mult i algoritmi. De exemplu, se stie deja c a pentru aarea
celui mai mare divizor comun a dou a numere se poate folosi e algoritmul
lui Euclid, e un algoritm bazat pe descompunerea numerelelor n produse
de factori primi.
Se pune ntrebarea: care din acesti algoritmi este mai bun? si n general:
cum putem compara doi algoritmi care rezolv a aceeasi problem a?
Cu r aspunsul la aceast a ntrebare se ocup a analiza algoritmilor.
17
A analiza un algoritmnseamn a a preciza ce resurse (de memorie si timp)
o s a aib a nevoie atunci c and va translatat n program care rezolv a pe
calculator problema respectiv a.
Vom parcurge treptele spre not iunile de baz a ale analizei algoritmilor
studiind doi algoritmi de sortare. Primul de care ne ocup am este sortarea
prin insert ie.
Pentru problema sort arii avem: la intrare un sir de n valori numerice
(a
1
, a
2
, . . . , a
n
) si vrem la iesire un sir (a

1
, a

2
, . . . , a

n
), obt inut prin permu-
tarea valorilor init iale, astfel nc at a

1
a

2
a

n
. Ideile algoritmului
descris mai jos (sortare prin interclasare) pot nt elese dac a ne g andim la
aranjarea c art ilor de joc: avem pe mas a, cu fat a n jos, o serie de c art i pe
care le putem lua una c ate una n m an a, deplas andu-le p an a la locul pe care
trebuie s a l ocupe.
Exemplu: Fie sirul A = 3 1 5 2 7 4 .Acest sir va parcurs de un
cursor i (se ia c ate o carte) si mutat n cadrul sirului cu ajutorul unui cursor
j care parcurge pe A

p an a la locul potrivit:
pentru i = 1:
A

= 3
pentru i = 2, elementul A(2) = 1 este mai mic dec at 3, deci trebuie
pus n fat a lui:
A

= 1 3
pentru i = 3:
A

= 1 3 5
pentru i = 4:
A

= 1 2 3 5
pentru i = 5:
A

= 1 2 3 5 7
pentru i = 6:
A

= 1 2 3 4 5 7
S a observ am c a nu avem nevoie de un spat iu suplimentar pentru rezultat si
putem face ceea ce se numeste sortare in place (pe loc) (i.e. n afara sirului
nu se t in dec at cel mult un num ar constant de elemente ale sirului).

In pseudocod algoritmul poate scris astfel:


Start Sortins
1 citeste( n, (A(i), i = 1, n) )
18
2 pentru i = 2, n
3 k = A(i)
insereaz a A(i) n sirul sortat A(1), . . . , A(i 1)
4 j = i 1
5 c at timp j > 0 si A(j) > k
6 A(j + 1) = A(j)
7 j = j 1
sf arsit c at timp
8 A(j + 1) = k
sf arsit pentru
9 scrie( A(i), i = 1, n )
Stop
Dintre resursele consumate ne va interesa n primul r and timpul de rulare.
Timpul de rulare al unui algoritm pentru o anumit a intrare (instant a) este
exprimat prin num arul de pasi elementari executat i.
Pentru nceput vom considera ca pas elementar ecare linie parcurs a din
algoritmul n pseudocod si timpul pentru un astfel de pas o constant a diferit a
pentru ecare linie (desi este evident c a unele din aceste constante sunt egale).

Incepem prin a prezenta algoritmul Sortins cu timpul ec arei instruc-


t iuni si num arul de execut ii ale liniei respective. Vom nota cu t
i
num arul
de execut ii ale ciclului de la linia 5 (evident c a el este diferit pentru ecare
valoare a lui i).
Urm arind tabelul de mai jos, putem calcula timpul total de execut ie:
Num ar linie Instruct iune Timp Numar de operat ii
Start Sortins
1 citeste ( n, (A(i), i = 1, n) ) c
1
n + 1
2 pentru i = 2, n c
2
n 1
3 k = A(i) c
3
n 1
4 j = i 1 c
4
n 1
5 c at timp j > 0 si A(j) > k c
5
n

i=2
t
i
6 A(j + 1) = A(j) c
6
n

i=2
(t
i
1)
7 j = j 1 c
7
n

i=2
(t
i
1)
sf arsit c at timp
8 A(j + 1) = k c
8
n 1
sf arsit pentru
9 scrie ( A(i), i = 1, n ) c
9
n
Stop
19
T(n) = c
1
(n + 1) +c
2
(n 1) +c
3
(n 1) +c
4
(n 1) +
+ c
5

i=2
t
i
+ (c
6
+c
7
)
n

i=2
(t
i
1) + (c
6
+c
7
)
n

i=2
(t
i
1) +
+ c
8
(n 1) +c
9
n
Cum putem s a-l a am pe t
i
? O se ne punem, de fapt, problema intervalu-
lui n care se plimb a, studiind cele dou a cazuri care corespund limitelor
intervalului.
Cel mai rapid caz se obt ine c and sirul este gata sortat si deci n linia 5 vom
avea A(j) k pentru orice j = 2, . . . , n deci n acest caz t
i
= 1, iar
T(n) = a n +b, unde a, b constante, deci T funct ie liniar a de n.
Cel mai r au caz se obt ine c and sirul dat este sortat descresc ator, ceea ce
nseamn a c a pe linia 5 vom avea A(j) > k pentru orice j de la i 1 la 1, deci
t
i
= i 1 ; atunci
n

i=2
(i 1) =
n(n1)
2
si
n

i=2
(i 2) =
(n2)(n1)
2
, deci
T(n) = a n
2
+b n +c, funct ie p atratic a de n.
Analiza se face, n general, pentru cel mai r au caz .
S a vedem acum dac a sortarea se poate face altfel, eventual mai repede.
Pentru aceasta vom adopta o alt a metod a, divide et impera. Aceast a
metod a porneste de la ideea c a problema pus a pentru o intrare mare (num ar
mare de date) este mai greu de rezolvat dec at o problem a cu un num ar redus
de date, de exemplu un sir format dintr-un singur element. Principiul divide
et impera funct ioneaz a astfel:
- se mparte problema n mai multe subprobleme
- se rezolv a ecare din subprobleme (n general recursiv)
- se combin a solut iile pat iale ntr-o solut ie nal a
Vom reveni cu am anunte despre aceast a metod a n capitolul 8.
Algoritmul sort arii prin interclasare (mergesort) se bazeaz a pe metoda
divide et impera. S a vedem ce nseamn a interclasarea: din dou a siruri
sortate cresc ator s a se creeze sirul sortat tot cresc ator care cont ine toate
elementele celor dou a siruri init iale.
Aceasta d a urm atorul algoritm:
Start Interclasare
20
citeste( n, (A(i), i = 1, n) )
citeste( m, (B(j), j = 1, m) )
k = 0
i = 1
j = 1
repet a
k = k + 1
dac a A(i) < B(j) atunci
C(k) = A(i)
i = i + 1
altfel
C(k) = B(j)
j = j + 1
sf arsit dac a
p an a c and i > n sau j > m
Ciclul de mai jos poate s a nu se execute nici o dat a
pentru il = i, n
k = k + 1
C(k) = A(il)
sf arsit pentru
Ciclul de mai jos poate s a nu se execute nici o dat a
pentru jl = j, m
k = k + 1
C(k) = B(jl)
sf arsit pentru
Din cele dou a cicluri pentru anterioare, se execut a exact unul singur
scrie( C(kl), kl = 1, m+n )
Stop
Se observ a c a timpul total de execut ie pentru algoritmul de interclasare
este T(n, m) = c (n + m) unde c este timpul maxim necesar execut iei
instruct iunilor din interiorul ciclurilor repet a si pentru (c nu depinde de m, n).
Pentru algoritmul de sortare prin interclasare prezent am not iunea de su-
balgoritm.
3.3 Algoritmi parametrizat i (subalgoritmi)
Rareori un algoritm, ca aceia prezentat i p an a acum, constituie probleme
independente; n general, algoritmii pentru rezolvarea unor probleme com-
plexe au p art i care se combin a ntre ele.
Pentru punerea n evident a a unei astfel de structuri modulare vom folosi
21
algoritmi parametrizat i numit i si subalgoritmi.
Parametrii vor variabile ale c aror valori vin din algoritmul care cheam a
si se ntorc napoi n acesta, deci efectele produse asupra parametrilor de
intrare vor exista si dup a ce subalgoritmul se termin a
1
.
Algoritmul Interclas parametrizat ar : Interclas(A, n, B, m, C) ceea ce
nseamn a: interclaseaz a A (av and n componente) cu B (av and m compo-
nente) si obt ine C.

Intr-un algoritm parametrizat nu mai au ce c auta instruct iunile de intrare


si nici instruct iunea Stop; n locul acesteia din urm a vom folosi Return care
nseamn a ntoarce-te n (sub)algoritmul chem ator.
Exemplu: Interclas(A

, n

, B

, m

, C

).
Corespondent a dintre parametrii de chemare si cei din subalgoritm se face
pozit ional.
Pentru usurarea exprim arii, vom considera si subalgoritmi de tip funct ie
care returneaz a o valoare.

In acest caz, valoarea care se determin a de c atre
subalgoritm este atribuit a numelui funct iei.
Exemplu:
ArieCerc(r)
ArieCerc = r r
Return
Apelul unui astfel de subalgoritm se face la fel ca mai nainte.

In plus, va-
loarea returnat a poate folosit a ntro expresie sauntro atribuire:
STotal = ArieCerc(10) 5

In continuare vom folosi o variant a special a a interclas arii numit a Merge(A,


p, q, r). Acest algoritm interclaseaz a elementele A(p), . . . , A(q) cu elementele
A(q + 1), . . . , A(r) si pune rezultatul n locul A(p), . . . , A(r).
Asa cum am precizat la nceputul acestui capitol algoritmul sort arii prin
interclasare Mergesort se bazeaz a pe metoda divide et impera, ai c arei pasi
au fost deja prezentat i. Evident iem n continuare pasii acestui algoritm:
1.

Imparte sirul init ial n dou a siruri
2. Rezolv a (recursiv) ecare din cele dou a subprobleme
3. Combin a (interclaseaz a) cele dou a subsiruri sortate pentru a obt ine
sirul sortat
Exemplu: e sirul: 2 1 5 3
1. mp art ire: 2 1 5 3
1
Relativ la limbaje de programare: transmiterea parametrilor se face prin adres a.
22
2. sortare (recursiv)
(a) mp at ire: 2 1
(b) Sortarea este evident a, ecare parte av and c ate un element
(c) interclasare 1 2
(a) mp at ire: 5 3
(b) Sortarea este evident a, ecare parte av and c ate un element
(c) interclasare 3 5
3. interclasare: 1 2 3 5
Algoritmul va :
Mergesort(A, p, r)
dac a p < r atunci
q =
_
p+r
2

partea ntreag a
q este indicele elementului de la jum atatea sirului
cheam a Mergesort(A, p, q)
cheam a Mergesort(A, q + 1, r)
cheam a Merge(A, p, q, r)
sf arsit dac a
Return
Acest algoritm poate folosit de exemplu astfel:
Start Sortare
citeste( n, (A(i), i = 1, n) )
cheam a Mergesort(A, 1, n)
scrie( Sirul sortat este: , (A(i), i = 1, n) )
Stop
Observat ii:
1. Sortarea const a de fapt din interclasarea perechilor de siruri de un
element, de dou a elemente, . . . , p an a c and interclas am o pereche de
siruri de
n
2
elemente, obt in and sirul sortat.
2. Dac a la un moment dat un sir are un num ar impar de elemente, atunci
se va mp art i n dou a subsiruri de dimeniuni care difer a printr-o unitate
(subsirurile sunt c at mai echilibrate ca num ar de elemente).
Vericat i execut ia algoritmului pentru sirul 3 2 5 6 4 1 0 7
23
3.4 Notat ia asimptotica
Pentru a vedea cum se comport a timpul de execut ie al unui algoritm
pentru intr ari mari vom deni funct iile , , O.
Spunem c a T(n) = (f(n)) dac a N, c
1
, c
2
> 0 astfel nc at:
0 < c
1
f(n) < T(n) < c
2
f(n), n > N (3.1)
Spunem c a T(n) = (f(n)) dac a N, c
1
> 0 astfel nc at:
0 < c
1
f(n) < T(n), n > N (3.2)
Spunem c a T(n) = O(f(n)) dac a N, c
1
> 0 astfel nc at:
T(n) < c
1
f(n), n > N (3.3)
L as am n seama cititorului s a demonstreze propriet at ile de mai jos.
Fie F , , O. Atunci:
1. Tranzitivitate:
T(n) = F(f(n)) si f(n) = F(g(n)) T(n) = F(g(n))
2. Reexivitate:
T(n) = F(T(n))
3. Simetrie:
f(n) = (g(n)) g(n) = (f(n))
4. Bisimetrie:
f(n) = O(g(n)) g(n) = (f(n))
f(n) = (g(n)) g(n) = O(f(n))
5. Dac a
M astfel nc at g(n) > f(n), n > M
atunci
(f(n) +g(n)) = (g(n))
6. T(n) = (f(n)) T(n) = O(f(n)) si T(n) = (f(n))
7. (cf(n)) = (f(n)), c constant a > 0
Aplic and propriet at ile 1-7 se demonstreaz a imediat urm atoarele:
24
1. T(n) = a n
2
+b n +c T(n) = (n
2
)
2. T(n) = c
1
n log n +c
2
n +c
3
T(n) = (n log n)
Din cele de mai sus, precum si analiza f acut a la algoritmul de sortare prin
insert ie rezulta c a complexitatea acestuia este T(n) = (n
2
).
Calculul complexit at ii algoritmului de sortare prin interclasare se efectu-
eaz a mai jos.
C and un algoritm cont ine o apelare a lui nsusi se numeste recursiv.

In
acest caz timpul de execut ie se descrie printr-o ecuat ie recursiv a. Pentru
rezolvarea unei asemenea ecuat ii vom folosi metode matematice care vor
descrise n capitolul dedicat metodei Divide et impera.
Ne vom limita acum la a scrie recurent a pentru sortare prin interclasare.
Dac a timpul pentru un sir cu n elemente este T(n), atunci timpul pentru
sirul cu
n
2
elemente va T
_
n
2
_
, deci:
T(n) =
_
a , dac a n = 1
2 T
_
n
2
_
+c n , dac a n > 1

In capitolul 8 vom demonstra c a T(n) = (nlog


2
n). Deci complexitatea
algoritmului Mergesort este (nlog
2
n).

In nal, deducem c a complexitatea algoritmului de sortare prin insert ie


((n
2
)) este mai mare dec at cea a algoritmului Mergesort ((nlog
2
n)), altfel
spus Mergesort este mai performant dec at sortarea prin insert ie.
3.5 Rezumat
Pentru compararea a doi algoritmi, cel mai utilizat criteriu este cel al
timpului de execut ie relativ la dimensiunea datelor de intrare. Calculul com-
plexit at ii unui algoritm este o etap a obligatorie a solut iei acestuia. Pentru
exprimarea complexit at ii se folosesc notat iile O(), (), () care sunt legate
de viteza de variat ie a timpului cerut pentru rezolvarea unei instant e, n
funct ie de dimensiunea intr arii.
Subalgoritmii sunt o modalitate de a concepe blocuri de cod parametri-
zate, apelabile prin intermediul unei interfet e (liste de parametri de apel).
Ele efectueaz a prelucr ari asupra datelor transmise, rezultatul returnat ind
folosit mai apoi de algoritmul apelant. De asemenea, reprezint a o form a de
abstractizare, utilizat a n toate paradigmele de programare.
3.6 Exercit ii (rezolvarile la pagina 135)
1. Determinat i complexitatea algoritmilor din capitolul 2.
25
2. Se deneste produsul scalar a doi vectori A si B, de aceeasi dimensiune
n cu formula PS =
n

i=1
A(i) B(i). S a se scrie algoritmul pentru calculul
produsului scalar.
3. Se d a n, vectorul A(i), i = 1, n si un num ar x. S a se scrie un algoritm
care g aseste indicele j pentru care A(j) = x (problema c aut arii).
4. Cum se modic a algoritmul de mai sus dac a stim c a vectorul este sortat
cresc ator?
5. Se dau n si vectorul A(i), i = 1, n. S a se g aseasc a cel mai mic element.
6. Reluat i problema anterioar a n situat ia n care trebuie s a aat i c ate
elemente minime sunt.

Incercat i s a rezolvat i problema folosind o singur a


parcurgere a sirului.
7. Se dau n si vectorul A(i), i = 1, n. Ce num ar apare cel mai des si de
c ate ori?
8. Cum se modic a algoritmul de mai sus dac a vectorul este sortat cresc ator?
9. Se dau n, ((A(i, j), j = 1, n), i = 1, n) (A este o matrice p atratic a, cu
n linii si n coloane). S a se calculeze produsul elementelor diferite de 0:
(a) din toat a matricea;
(b) de pe diagonala principal a;
(c) de sub diagonala principal a.
26
Capitolul 4
Structuri elementare de date
4.1 Obiective
Am folosit, p an a acum, structuri de date foarte simple cum ar :
variabile simple (dintre care unele aveau domeniul de valori format doar
din dou a valori)
vectori cu componente sortate sau nesortate (asa cum sunt folosit i n
matematic a)
matrici considerate ca vectori de vectori sau ca masive biortogonale
Vom studia acum alte structuri de date necesare n algoritmii ulteriori: lista,
stiva, coada, arborii binari, mpreun a cu diferite forme de reprezentare a
acestora.
4.2 Structuri liniare
O structur a liniar a este o mult ime de n 0 componente x(1), x(2), . . . x(n)
cu propriet at ile:
1. c and n = 0 spunem c a structura este vid a;
2. dac a n > 0 atunci x(1) este primul element iar x(n) este ultimul ele-
ment;
3. oricare ar x(k) unde k 2, . . . , n1 exist a un predecesor x(k 1)
si un succesor x(k + 1).
Ne va interesa s a execut am cu aceste structuri urm atoarele operat ii:
27
- ad augarea unui element;
- extragerea unui element;
- accesarea unui element x(k) din structur a;
- combinarea a dou a sau mai multe structuri n una singur a;
- ruperea unei structuri n mai multe structuri;
- sortarea elementelor unei structuri;
- c autarea unui element al structurii care are anumite propriet at i;
- operat ii specice
4.3 Stiva
Una din cele mai cunoscute structuri liniare este stiva. O stiv a este ca-
racterizat a prin disciplina de intrare si de iesire. S a consider am o mult ime
de c art i puse una peste alta; exist a o prim a carte care se poate lua foarte
usor (TOP) si o carte carte care se poate lua numai dac a se nl atur a toate
celelate c art i (BOTTOM).
Disciplina unei stive este ultimul intrat, primul iesit (disciplina care nu
v-ar place s a e respectat a c and stat i la r and la lapte!), prescurtat LIFO
(Last In, First Out).
Diferent ele fat a de un vector sunt:
- un vector are o lungime x a, nonzero, cunoscut a aprioric;
- o stiv a poate vid a;
- stiva are un num ar variabil de elemente n timpul execut iei unui algo-
ritm
Se pune problema reprezent arii concrete a unei stive n memoria unui calcu-
lator. Putem aloca o stiv a n dou a moduri:
1. Secvent ial
2.

Inl ant uit
28
4.3.1 Alocarea secvent iala a stivei
Folosim vectorul ca ind structura cea mai apropiat a de structura real a
a memoriei.

In vectorul (x(i), i = 1, n) consider am:
x(1) x(2) x(3) . . . x(k) . . . x(n)

BOTTOM TOP
adic a din cele n componente ale unui vector doar primele k elemente fac parte
din stiv a.
Algoritmul de intrare n stiv a este:
a Stiva
dac a k = n atunci
Dep asire
altfel
k = k + 1
x(k) = a
sf arsit dac a
Return
Algoritmul de iesire (scoatere) din stiv a este:
a Stiva
dac a k = 0 atunci
Stiva vid a
altfel
a = x(k)
k = k 1
sf arsit dac a
Return
4.3.2 Alocarea nlant uita a stivei

In alocarea nl ant uit a ecare element al structurii este nsot it de adresa


de memorie la care se a a precedentul element. Vom folosi semnul * cu sensul
nici o adres a de memorie. Vom avea v arful stivei pus n evident a (ancorat)
n INC si elementul de la baza stivei va avea cont ine n c ampul LEG *, ca
n gur a:
INFO LEG
INC X(k) X(k 1) . . . X(2) X(1) *
29
(ordinea 1, 2, . . . k este ordinea intr arii n stiv a).

In acest caz intrarea n stiv a va folosi stiva de locuri libere


1
(aceast a stiv a
se numeste LIBERE), pentru a obt ine noi locuri la introducerea n stiv a.
Vom prezenta n continuare algoritmii de intrare/iesire dintr-o stiv a n
cazul n care alocarea ei a fost nl ant uit a.
Algoritmul de intrare n stiv a este:
a Stiva
a este informat ia introdus a n stivc a
y LIBEREalocare de memorie pentru elementul nou
INFO(y) = a
LEG(y) = INC
INC = y
Return
La nceput, INC =*, stiva necont in and nici un element.
Algoritmul de iesire din stiv a este:
a Stiva
a este informat ia extras a din v arful stivei nevide
dac a INC =* atunci
Stiva este vid a
altfel
a = INFO(INC)
aux = INC
INC = LEG(INC)
aux LIBEREEliberarea spat iului de memorie
sf arsit dac a
Return
4.4 Coada
O alt a structur a de date folosit a n concept ia algoritmilor este coada. O
coad a este caracterizat a si ea de o disciplin a de intrare/iesire, binent eles
diferit a de cea a stivei. De data aceasta putet i s a v a g andit i la coada la
lapte: primul care s-a asezat al coad a va primul servit, adic a primul care
iese din coad a.
Disciplina unei cozi este deci primul venit, primul plecat (rst in, rst
out - FIFO).
1
Cunoscut a n cadrul limbajelor de programare drept heap; obt inerea de memorie se
face prin alocare dinamic a, eliberarea ei prin dealocare.
30
O coad a poate vid a si are si ea un num ar variabil de elemente n timpul
execut iei unui algoritm.
4.4.1 Alocarea secvent iala a cozii
Coada alocat a secvent ial si va g asi locul tot ntr-un vector (X(i), i =
1, n):
x(1) x(2) . . . x(F) . . . x(S) . . . x(n)

FAT

A SF

ARSIT
Din cele n componente ale vectorului, doar componentele x(F), . . . , x(S)
fac parte din coad a.
Algoritmul de intrare n coad a este:
a Coada
dac a S = n atunci
Dep asire
altfel
S = S + 1
x(S) = a
sf arsit dac a
Return
Algoritmul de iesire din coad a este:
a Coada
dac a F > S atunci
Coada este vid a
altfel
a = x(F)
F = F + 1
sf arsit dac a
Return
Se poate imagina usor c a proced and n acest mod (scot and din fat a si in-
troduc and la sf arsit), coada migreaz a spre dreapta si poate s a ajung a n
situat ia de dep asire c and de fapt mai exist a mult loc gol (n vectorul x) pe
primele pozit ii. Apare astfel ideea de a folosi elementele vectorului ca si cum
ar dispuse circular, precum n gura 4.1, pagina 32.
L as am n seama cititorului s a scrie algoritmii de intrare/iesire din coada
circular a.
31
X(1)
X(2)
X(n)
X(F)
X(S) Sfarsit
Fata
Figura 4.1: Coada circular a
4.4.2 Alocarea nlant uita a cozii
Alocareanl ant uit a se face similar cu alocareanl ant uit a a stivei n noduri
de tipul:
INFO LEG
x(F) . . . x(S) *

FAT

A SF

ARSIT
Algoritmul de intrare n coad a este:
a Coada
y LIBERE
INFO(y) = a
LEG(y) =
dac a FAT

A=* atunci
Coada este vid a
FATA=y
altfel
LEG(SF

ARSIT)=y
sf arsit dac a
SF

ARSIT=y
Return
Init ial, coada este vid a, i.e. FAT

A=SF

ARSIT=*.
Algoritmul de iesire din coad a este:
32
a Coada
dac a FATA=* atunci
Coada este vid a
altfel
a = INFO(FATA)
aux =FATA
FATALEG(FATA)
aux LIBERE
sf arsit dac a
Return
4.5 Arbori binari
Un arbore n care orice v arf (nod) are 0, 1 sau 2 descendent i se numeste
arbore binar. Un arbore binar care are v arfuri cu 0 sau 2 descendent i se
numeste arbore binar strict. Un astfel de arbore se poate folosi, de exemplu,
la reprezentarea n memorie a unei expresii aritmetice.
Exemplu: expresia
(a +b) c
2
c
3
se va reprezenta astfel:
Figura 4.2: Arborele binar atasat expresiei aritmetice (a+b) c
2
c
3
. Semnul
este reprezentare pentru operatorul de ridicare la putere.
Frunzele acestui arbore (nodurile f ar a descendent i) cont in operanzii, iar
celelalte noduri cont in operatorii. Deoarece nu toate operat iile sunt comu-
tative, este foarte important dac a un nod este descendent pe st anga sau pe
dreapta. R ad acina unui arbore este nodul care nu este descendentul nim anui.
33
Alocarea unui arbore binar se poate face:
- secvent ial
- nl ant uit
- mixt
4.5.1 Alocarea secvent iala a unui arbore binar

In vectorul (x(i), i = 1, n) vom avea urm atoarele reguli:


- r ad acina este n x(1);
- pentru ecare nod x(i), descendentul s a din st anga este x(2 i) iar cel
din dreapta este x(2 i + 1);
- dac a nu exist a descendent, se pune *.
Reprezentarea secvent ial a a arborelui din gura 4.2 este:
- / + c 2 a b * * * * c 3 * * . . . *
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 . . . 31
Observat ie: Pozit iile x(10), . . . x(13), x(16), . . . x(31) cont in *.
Vom volosi aceast a alocare n capitolul destinat sort arii pentru a construi
o structur a de date asem an atoare, numit a HEAP
2
.
4.5.2 Alocarea nlant uita a unui arbore binar

In acest caz se folosesc noduri de forma INFO LS LD , unde LS


si LD cont in adresele de memorie ale nodurilor descendent st ang, respectiv
descendent drept. Reprezentarea nl ant uit a a arborelui din gura 4.2 este
dat a n gura 4.3.
2
A nu se confunda cu heapul pomenit n nota de subsol de la pagina 30
34
Figura 4.3: Alocarea nl ant uit a pentru arborele din gura 4.2.
4.5.3 Alocarea mixta a unui arbore binar
La acest tip de alocare se folosesc trei vectori INFO, LS, LD unde LS(i)
si LD(i) cont in indicii unde se a a memorat i descendentul st ang, respectiv
descendentul drept ai nodului i.
Reprezentarea mixt a a arborelui din gura 4.2 este:
INFO LS LD
1 - 2 3
2 4 5
3 / 6 7
4 + 8 9
5 c * *
6 2 * *
7 10 11
8 a * *
9 b * *
10 c * *
11 3 * *
La arborii binari ne intereseaz a problema parcurgerii lor. T inem cont de
faptul c a:
- arborele binar se deneste recursiv ca: r ad acin a, subarbore st ang, su-
barbore drept (ecare subarbore este la r andul lui un arbore binar,
posibil vid);
- la parcurgere mai nt ai va subarborele st ang naintea celui drept.
Dup a pozit ia r ad acinii (R) relativ la subarborele st ang (S) si subarborele
drept (D), avem urm atoarele trei tipuri de parcurgeri ale unui arbore binar:
35
1. postordine (SRD);
2. preordine (RSD)
3. inordine (SRD)
Exemple de parcurgeri:
1. Parcurgerea arborelui din gura 4.2 n preordine:
- + a b c / 2 c 3
Acest a scriere se numeste scriere polonez a prexat a a unei expresii arit-
metice.
2. Parcurgerea arborelui din gura 4.2 n inordine:
a + b c - 2 / c 3
3. Parcurgerea arborelui din gura 4.2 n postordine:
a b + c 2 c 3 / -
Acest a scriere se numeste scriere polonez a postxat a a unei expresii
aritmetice.
D am n continuare algoritmul iterativ pentru parcurgerea n preordine a
unui arbore binar. Vom avea nevoie de o STIV

A care va cont ine nodurile


succesive parcurse pe st anga care urmeaz a s a e parcurse si pe dreapta;
r adacina arborelui se a a n rad.
Preordine iterativ(rad)
STIV A = STIVA este vid a
nodCurent = rad
maiAmNoduri = adevarat
repet a
parcurgPeStanga = adevarat
repet a
dac a nodCurent ,= atunci
scrie( INFO(nodCurent) )
parcurgere pe st anga
nodCurent STIV A
nodCurent = LS(nodcurent)
altfel
36
parcurgPeStanga = fals
sf arsit dac a
p an a c and parcurgPeStanga = fals
parcurgere pe dreapta
dac a STIV A = atunci
maiAmNoduri = fals
altfel
nodCurent STIV A
nodCurent = LD(nodCurent)
sf arsit dac a
p an a c and maiAmNoduri = adevarat
Return
Se pot da algoritmi iterativi si pentru celelalte dou a parcurgeri (vezi pro-
blema 2 de la exercit ii). De asemenea se pot da algoritmi recursivi pentru
parcurgeri, mai usor de nt eles, dar ceva mai inecient i (a se vedea capitolul
5, problema 6).
4.6 Rezumat
Pentru prelucrarea datelor se folosesc diferite structuri adecvate: liste,
stive, cozi, arbori (sunt cele mai des utilizate, dar mai multe vor studiate
ntrun curs dedicat de structuri de date). Exist a diferite tipuri de repre-
zent ari ale acestor structuri: pe baz a de tablouri, folosind alocarea dinamic a,
sau o variant a mixt a (la arbori). Stiva si coada au politici specice de acces,
iar arborele poate parcurs n moduri diferite pentru procesarea datelor.
4.7 Exercit ii (rezolvarile la pagina 27)
1. Scriet i algoritmii de intrare/iesire din coada circular a.
2. Scriet i algoritmii iterativi pentru parcurgerea arborilor binari n inor-
dine si postordine.
3. Se d a o stiv a alocat a nl ant uit si o valoare x. S a se extrag a din stiv a,
dac a exist a, elementul cu INFO = x.
4. Se d a o stiv a si o valoare x. S a se introduc a n stiv a dup a elementul cu
INFO = x un element cu INFO = y.
5. S a se implementeze o coad a folosind dou a stive. S a se analizeze com-
plexitatea.
37
6. S a se implementeze o stiv a prin dou a cozi. S a se analizeze complexita-
tea.
38
Capitolul 5
Recursivitate
5.1 Obiective
Capitolul detaliaz a modul de lucru al unui subalgoritm recursiv. Este
dat un exemplu simplu de algoritm recursiv, pentru care se descriu toate
informat iile care se depun pe stiv a la execut ia lui. Explicat iile date sunt
aplicabile pentru orice caz de recursivitate.
5.2 Prezentare generala
Recursivitatea reprezint a un mod de elaborare a algoritmilor, caracterizat
prin faptul c a un subalgoritm se apeleaz a pe el nsusi (direct sau indirect).
Ea a ap arut din necesit at i practice, permit and implementarea unei funct ii
matematice recursive. Nu reprezint a o modalitate mai puternic a sau mai
slab a din punct de vedere al rezultatelor ce se pot obt ine comparativ cu
metodele iterative; sa demonstrat c a aceste dou a abord ari sunt egale ca si
putere de calcul. Algoritmii recursivi nu sunt mai rapizi dec at algoritmii
iterativi echivalent i, dar uneori sunt mai expresivi si mai usor de ntret inut
(modicat).
Pentru nt elegerea algoritmilor recursivi, este esent ial a nt elegerea lucru-
lui cu stiva.

Inainte de a se efectua un apel de subalgoritm (recursiv sau nu),
se salveaz a pe stiv a adresa de memorie a instruct iunii de la care se va conti-
nua execut ia dup a ntoarcerea din apel. La intrarea ntrun subalgoritm se
rezerv a spat iu pe stiv a pentru parametrii transmisi si pentru variabilele care
au fost declarate n subalgoritm (variabile locale). La iesirea din apel, stiva
se elibereaz a de informat ia depus a la intrarea n apel, iar adresa urm atoarei
instruct iuni ce se va executa se preia de pe v arful stivei (si de asemenea
aceast a informat ie va scoas a de pe stiv a).
39
Exemplu: urm atorul program nu are o utilitate zdrobitoare, dar ilustreaz a
cele spuse mai nainte. Pentru a simplica expunerea, vom considera c a
transmiterea parametrilor se face prin valoare (pe stiv a se copiaz a valorile
parametrilor) si nu prin adres a (c and pe stiv a se copiaz a adresa de memorie
a parametrilor efectivi) - a se vedea convent ia de la pagina 22.

In cazul
exemplului de mai jos, ntruc at n corpul subalgoritmului nu se modic a
valoarea lui n, rezultatul ar acelasi indiferent de convent ia de apel.
Start Exemplu
citeste( n )
Recursiv(n)
scrie( Sf arsit )10
Stop
Recursiv(n)
i = 2 ni este variabil a local a, alocat a n subalgoritmul Recursiv
dac a n = 0 atunci
Return
altfel
Recursiv(n 1)
i = i + 1100
scrie( i )
sf arsit dac a
Return
Ca si comentarii sunt trecute niste adrese la care se presupune a se aa
instruct iunile corespunz atoare. S a presupunem c a se va citi n = 2. Evolut ia
stivei programului este:
La intrarea n algoritmul Exemplu, se rezerv a spat iu pe stiv a pentru
variabila n, n care dup a citire se depune valoarea 2:
n = 2


Inainte de apelul Recursiv(2) din algoritmul Exemplu se scrie pe stiv a
adresa de memorie a instruct iunii care se va executa dup a ce se va
reveni din acest apel (n cazul nostru instruct iunea de scriere cu adresa
10):
adr = 10
n = 2
Se apeleaz a Recursiv(2); se scrie pe stiv a valoara parametrului n = 2,
se rezerv a spat iu de memorie pentru i (pentru care nu se atribuie o
valoare anume la nceput):
40
i
n = 2
adr = 10
n = 2
Se calculeaz a i = 2 n = 4, valoare care se depune n locul rezervat
pentru i la acest apel (n cazul nostru, n v arful stivei):
i = 4
n = 2
adr = 10
n = 2
Se face testarea n = 0; deoarece este condit ia nu este ndeplinit a, se
intr a pe ramura altfel.
Avem din nou apel: nainte de acesta se salveaz a adresa de memorie
a instruct iunii de la care se va continua execut ia (incrementarea de la
adresa 100):
adr = 100
i = 4
n = 2
adr = 10
n = 2
Se intr a n Recursiv(1); se salveaz a pe stiv a valoarea parametrului n =
1, se rezerv a spat iu de memorie pentru i (pentru care nu se atribuie o
valoare anume la nceput):
i
n = 1
adr = 100
i = 4
n = 2
adr = 10
n = 2
Se calculeaz a i = 2 n = 2, valoare care se depune n locul rezervat
pentru i la acest apel (n cazul nostru, n v arful stivei):
41
i = 2
n = 1
adr = 100
i = 4
n = 2
adr = 10
n = 2
Se face testarea n = 0; deoarece este condit ia nu este ndeplinit a, se
intr a pe ramura altfel.
Avem din nou apel: nainte de acesta se salveaz a adresa de memorie
a instruct iunii de la care se va continua execut ia (incrementarea de la
adresa 100):
adr = 100
i = 2
n = 1
adr = 100
i = 4
n = 2
adr = 10
n = 2
Se intr a n apelul Recursiv(0); se salveaz a pe stiv a n = 0, se rezerv a
spat iu de memorie pentru i (pentru care nu se atribuie o valoare anume
la nceput):
i
n = 0
adr = 100
i = 2
n = 1
adr = 100
i = 4
n = 2
adr = 10
n = 2
Se calculeaz a i = 2 n = 0, valoare care se depune n locul rezervat
pentru i la acest apel (n cazul nostru, n v arful stivei):
42
i = 0
n = 0
adr = 100
i = 2
n = 1
adr = 100
i = 4
n = 2
adr = 10
n = 2
Se face testarea n = 0; deoarece este condit ia ndeplinit a, se intr a pe
ramura atunci, care reprezint a ntoarcere la metoda Recursiv(1).
La ntoarcerea din Recursiv(0) n Recursiv(1), se scoate de pe stiv a
informat ia care a fost depus a datorit a apelului Recursiv(0), revenindu
se la forma de dinainte de efectuarea acestui apel:
i = 2
n = 1
adr = 100
i = 4
n = 2
adr = 10
n = 2
Instruct iunea de la care se va continua execut ia este de la adresa 100,
care a fost scoas a de pe stiv a.
Suntem n Recursiv(1). Execut ia se continu a de la instruct iunea cu
adresa 100 (conform punctului precedent), deci i ia valoarea 2 +1 (va-
loareal 2 din sum a ind datorat a informat iei i = 2 de pe stiv a), care se
aseaz a.
Datorit a instruct iunii de retur nale din subalgoritmul Recursiv, avem o
ntoarcere de la Recursiv(1) la Recursiv(2). Se cur at a stiva de informat iile
i = 2, n = 1, adr = 100 si se continu a execut ia de la instruct iunea cu
adresa 100:
i = 4
n = 2
adr = 10
n = 2
43
Suntem n Recursiv(2). Execut ia se continu a de la instruct iunea cu
adresa 100, deci i ia valoarea 4 +1 (valoarea 4 din sum a ind datorat a
informat iei i = 4 de pe stiv a), care se aseaz a.
Datorit a instruct iunii de retur nale din subalgoritmul Recursiv, avem o
ntoarcere de la Recursiv(2) la Exemplu. Se cur at a stiva de informat iile
i = 4, n = 2, adr = 10 si se continuarea execut iei se va face de la
instruct iunea cu adresa 10. Stiva va :
n = 2
Se execut a instruct iunea cu adresa 10: Scrie(Sfarsit).
Se termin a programul (algoritmul Exemplu), iar stiva devine vid a.

In
cazul unei implement ari, controlul ar preluat de c atre sistemul de
operare.
Algoritmul a asat valorile 3, 5. Evident, acest lucru se putea face mult mai
simplu printro iterat ie; dar exemplul de fat a a dorit s a ilustreze funct ionarea
unui apel recursiv. Datorit a operat iilor de cur at are a stivei (care se efectueaz a
printro simpl a incrementare sau decrementare a valorii dintrun registru al
microprocesorului), precum si datorit a informat iilor repetate care se salveaz a
pe stiv a (n, i, adr), timpul si spat iul de memorie necesar sunt mai mari dec at
pentru variantele iterative. Totusi, n destul de multe cazuri implement arile
recursive sunt mult mai usor de urm arit si de nt eles dec at cele recursive.
O observat ie important a: programatorul este singurul r aspunz ator de
faptul c a programul lui se termin a. Altfel spus, trebuie mare atent ie la
impunerea unei condit ii de terminare a recursivit at ii (n cazul nostru, testarea
pentru n = 0).

In caz contrar, un astfel de algoritm implementat va epuiza
spat iul disponibil pentru stiv a si se va opri f ar a a rezolva problema (apel
recursiv la innit).
Dac a revenim la convent ia ca transferul parametrilor s a se fac a prin
adres a, atunci pe stiv a, n cadul ec arui subalgoritm apelat, n loc de va-
loarea lui n sar depus adresa de memorie rezervat a n cadrul algoritmului
(la noi: adresa bazei stivei).

In acest fel, orice modicare care sar face asu-
pra parametrului n din subalgoritmul Recursiv s-ar face de fapt (via aceast a
adres a pus a pe stiv a) asupra valorii lui n din algoritmul Exemplu. Majo-
ritatea limbajelor (Pascal, C/C++, C#, PL/SQL) au mecanisme prin care
se poate stabili dac a pe stiv a se depune o valoare (copia valorii parametru-
lui efectiv) sau o adres a de memorie (adresa la care este stocat parametrul
efectiv).
44
5.3 Exemple
5.3.1 Calcularea lui n!
Pentru un n natural, denim valoarea n! n mod recursiv astfel:
n! =
_
1, pentru n = 0
n (n 1)!, pentru n > 0
(5.1)
Algoritmul recursiv este urm atoarea:
Start FactRec
citeste( n )
scrie( Fact(n) )
Stop
unde subalgoritmul Fact are forma:
Fact(n)
dac a n = 0 atunci
Fact = 1
altfel
Fact = n Fact(n 1)
sf arsit dac a
Return
Complexitatea algoritmului este dat a de ecuat ia recursivu a T(n) = T(n
1) + c, c ind o constant a datorat a apelului recursiv (operat iei cu stiva) si
nmult irii, pentru care solut ia este T(n) = (n) (pentru rezolvarea recurent ei
anterioare, a se vedea A). Varianta iterativ a este de aceeasi complexitate
teoretic a, dar mai rapid a n practic a.
5.3.2 Sirul lui Fibonacci
Sirul lui Fibonacci se deneste astfel:
f(n) =
_
_
_
0, n = 0
1, n = 1
f(n 1) +f(n 2), n 2
(5.2)
Vom implementa recursiv acest algoritm:
Start FiboRec
citeste( n )
scrie( Fibo(n) )
Stop
unde algoritmul recursiv Fibo este:
45
Fibo(n)
dac a n = 0 sau n = 1 atunci
Fibo = n
altfel
Fibo = Fibo(n 1) +Fibo(n 2)
sf arsit dac a
Return
Complexitatea teoretic a este dat a de ecuat ia recursiv a T(n) = T(n 1) +
T(n 2) + c, care duce la T(n) = (
n
), unde =
1+

5
2
(t aietura de
aur)(a se vedea Anexa A) . Complexitatea exponent ial a mare este datorat a
faptului c a se calculeaz a de mai multe ori aceleasi valori: de exemplu, n
f(n) = f(n 1) + f(n 2), f(n 2) este apelat at at pentru calculul lui
f(n 1), c at si pentru cel de al doilea membru al p art ii drepte a ecuat iei
anterioare. Redundant a de calcul devine tot mai accentuat a pentru valori
mici ale argumentului.
S a vedem o implementare iterativ a:
Start FiboIter
citeste( n )
f(0) = 0
f(1) = 1
pentru i = 2, n
f(i) = f(i 1) +f(i 2)
sf arsit pentru
scrie( f(n) )
Stop
Complexitatea algoritmului anterior este evident (n). Acest fapt se dato-
reaz a memor arii valorilor lui f si evit arii calculului repetat (ca n algoritmul
precedent).
5.4 Rezumat
Rezolvarea recursiv a a problemelor este deseori mai usoar a dec at cea ite-
rativ a.

In esent a, orice apel de subalgoritm (recursiv sau nu) determin a
depunerea unor informat ii pe o stiv a gestionat a automat. Codul rezultat
este mai scurt si mai usor de depanat; ns a o implementare recursiv a poate
duce la o complexitate crescut a, datorit a rezolv arii n mod repetat a ace-
lorasi probleme, deci este necesar a de ecare dat a o analiz a pertinent a a
complexit at ii (un exemplu relevant este dat n cele dou a implement ari pen-
tru calculul sirului lui Fibonacci de mai sus).
46
5.5 Exercit ii (rezolvarile la pagina 39)
1. S a se calculeze recursiv maximul unui sir.
2. S a se calculeze recursiv suma elementelor dintrun sir.
3. S a se calculeze puterea a na a unui num ar real a, cu o complexitate
mai bun a dec at (n).
4. S a se dea un contraexemplu pentru care algoritmul de la 3 nu d a
num arul optim de nmult iri.
5. S a se scrie un algoritm care calculeaz a termenul fibo(n) al sirului Fi-
bonacci n timp mai bun de (n) (a se veda si problema 3).
6. S a se dea algoritmi recursivi pentru parcurgerea n preordine, postor-
dine, inordine a unui arbore binar.
47
48
Capitolul 6
Metoda Backtracking
6.1 Obiective
Acest capitol introduce una din cele mai generale modalit at i de rezolvare
a problemelor: metoda Backtracking. Ea duce la scrierea unor algoritmi care
evit a generarea tuturor combinat iilor posibile si apoi la validarea rezultatelor.
Este prezentat a schema general a de algoritm backtracking si probleme clasice
pentru a c aror rezolvare se foloseste aceast a abordare.
6.2 Prezentare generala
Metoda Backtracking se poate aplica algoritmilor care trebuie s a constru-
iasc a o solut ie de forma
x = (x(1), x(2), . . . , x(n)) (6.1)
unde pentru orice i 1, 2, . . . , n, x(i) A
i
, A
i
ind o mult ime dat a ca
informat ie de intrare si unde, n plus, componentele lui x trebuie s a mai
satisfac a niste condit ii interne.
Exemplu: s a consider am:
A
1
= A, B, E
A
2
= A, C
A
3
= U, S, E, C
Cerint e:
1. S a se construiasc a cuvintele care au prima liter a din A
1
, a doua liter a
din A
2
, a treia liter a din A
3
;% si care respect a condit iile interne de la
2;
49
2.

In plus, se cere respectarea urm atoarelor condit ii interne:
(a) Nu sunt dou a litere consecutive egale;
(b) Nu sunt formate numai din consoane sau numai din vocale.
Dac a lu am n considerare numai cerint a de la 1, obt inem solut iile admisi-
bile ale problemei, de exemplu (AAU), (ACS), (EAU), (BAU), (BCC), . . . .
Dar (AAU), (BCC) nu respect a condit iile interne 2a, iar (EAU) nu respect a
condit ia 2b.
O metod a de rezolvare a acestei probleme ar s a construim mai nt ai
toate solut iile admisibile si apoi s a veric am care dintre ele respect a condit iile
interne. Acest mod de a aborda problema duce, n exemplul nostru, la 324 =
24 de solut ii din care evident cele carencep cu AA, de exemplu, nu sunt bune.
Dac a mult imile A
1
, A
2
, . . . , A
n
au respectiv k
1
, k
2
, . . . , k
n
elemente, atunci
am avea n total k
1
k
2
. . . k
n
solut ii admisibile. Pentru k
1
= k
2
= = k
n
=
m avem m
n
solut ii admisibile, deci un algoritm de tip brute force care ia n
considerare toate posibilit at ile ar avea o complexitate exponent ial a.
Algoritmul de tip backtracking urm areste micsorarea num arului de ope-
rat ii, dar trebuie s a spunem c a r am ane de complexitate exponent ial a. Acest
algoritm urm areste s a genereze c ate o component a x(k) A
k
c at timp mai
are o component a netestat a din A
k
; dac a nu mai are componente netestate,
se revine la alegerea elementului de pe pozit ia anterioar a x(k 1), altfel se
merge la componenta x(k + 1). In felul acesta s-ar genera toat a mult imea
solut iilor admisibile; dar dac a dup a ce am g asit o component a x(k) test am
dac a bucata de vector (x(1), x(2), . . . , x(k)) generat a p an a atunci satisface
condit iile de continuare derivate din condit iile interne, atunci vom putea s a
nu permitem generarea inutil a a unor solut ii care oricum nu ar bune (n
exemplul nostru (AA )).
Trebuie s a mai subliniem c a simplul fapt c a bucata (x(1), x(2), . . . x(k))
din vectorul x satisface condit iile de continuare nu nseamn a c a o s a g asim,
obligatoriu, o solut ie a problemei (exist a, totusi, o metod a care g aseste solut ia
pas cu pas, f ar a revenire, numit a Greedy; ea va prezentat a mai t arziu).
Schema algoritmului general va :
Backtracking(A, n)
k = 1
c at timp k > 0
dac a k = n + 1 atunci
scrie( (x(i)), i = 1, n )s-a generat o solut ie
k = k 1
altfel
dac a mai exist a valori netestate a A
k
atunci
50
x(k) = a
dac a (x(1), x(2), . . . , x(k)) satisface condit iile de continuare atunci
k = k + 1
sf arsit dac a
altfel
k = k 1
sf arsit dac a
sf arsit dac a
sf arsit c at timp
Return
6.3 Exemplu
Vom utiliza acest algoritm prin problema asez arii damelor pe tabla de
sah astfel nc at oricare dou a dame s a nu se atace (2 dame se atac a dac a sunt
pe aceesi linie, coloan a, diagonal a).
Vom considera mult imile (A
i
)
i=1,n
ca ind pozit iile (de la 1 la n) pe care
le poate ocupa o dam a pe linia i. Evident c a de data aceasta toate mult imile
A
i
sunt egale.
Deci o congurat ie pe o tabl a de n = 5 precum mai jos va simbolizat a
de vectorul solut ie x = (1, 3, 5, 2, 4) si se poate vedea c a n acest caz condit iile
interne sunt respectate (oricare dou a dame nu se bat).


Algoritmul pentru n > 4 este:
Dame(n)
pentru i = 1, n
x(i) = 0init ial pe nici o linie nu avem pozit ionat a nici o regin a
sf arsit pentru
k = 1
c at timp k > 0
dac a k = n + 1 atunci
scrie( (x(i)), i = 1, n )
k = k 1
altfel
x(k) = x(k) + 1
51
dac a x(k) n atunci
dac a DispunereCorecta(x, k)=adevarat atunci
k = k + 1
sf arsit dac a
altfel
x(k) = 0 Nu avem nici o regin a pe aceast a linie
k = k 1 Ne ntoarcem la regina de pe pozit ia anterioar a
sf arsit dac ax(k) n
sf arsit dac a k = n + 1
sf arsit c at timp
Return
DipunereCorecta(x, k) testeaz a dac a condit iile de continuare pentru bucata
x(1), . . . , x(k) sunt ndeplinite; returnaz a adev arat dac a nu avem regine care
se atac a, fals n caz contrar.
DispunereCorecta(x, k)
corect = adevarat presupunem init ial c a nu avem nici un atacntre regina
k si cele dispuse anterior
pentru i = 1, k 1
dac a x(k) = x(i) sau [x(k) x(i)[ = k i atunci
sunt pe aceeasi coloan a sau pe aceeasi diagonal a
corect = fals
sf arsit dac a
sf arsit pentru
DispunereCorecta = corect
Return
6.4 Rezumat
Multe probleme cer generarea uneia/mai multora/tuturor solut iilor care
respect a anumit a cerint e. O abordare de tipul genereaz a toate combinat iile,
apoi ret inele pe cele valide (bruteforce) este posibil a, dar si cea mai ine-
cient a. Metoda backtracking urm areste depistarea c at mai devreme cu
putint a a solut iilor care sunt invalide (pe m asur a ce componentele lor se ge-
nereaz a). Desi algoritmii rezultatt i sunt de complexitate exponent ial a, multe
solut ii admisibile, dar invalide sunt evitate.
52
6.5 Exercit ii (Rezolvarile la pagina 153)
1. Scriet i un algoritm pentru parcurgerea tablei de sah cu un cal (calul
sare pe diagonal a unui dreptunghi cu laturile de un p atrat si dou a
patrate). Fiecare p atrat al tablei trebui s a e vizitat exact o singur a
dat a.
2. Av and 4 culori si o hart a cu n t ari (dat a print-o matrice de adiacent a:
a
ij
= 1 dac a t ara i este vecin a cu t ara j, 0 altfel), s a se coloreze
harta astfel ca dou a t ari vecine s a nu aibe aceeasi culoare (dou a t ari se
consider a a vecine dac a au o frontier a comun a).
3. O organizat ie are n component a sa n b arbat i si m femei. S a se scrie
un algoritm care listeaz a toate modalit at ile n care se poate alc atui o
delegat ie care s a cont in a cel put in k femei, k < m.
4. Cum poate pl atit a o sum a de x lei, n bancnote de valoare v(i),
i = 1, n din care avem c ate b(i) buc at i? S a se dea toate solut iile posibile.
53
54
Capitolul 7
Generarea submult imilor
7.1 Obiective
De multe ori solut iile care se cer pentru rezolvarea unei (sub)probleme
sunt de o form a particular a: produse carteziene, familia submult imilor, a
combinat iilor, aranjamentelor, permut arilor, submult imilor de sum a dat a.
Acest capitol cont ine rezolv ari clasice pentru aceste probleme, n mai multe
variante.
7.2 Schema generala de lucru
O aplicat ie imediat a a metodei Backtracking este generarea submult imilor.
Vom considera sumbult imi ale mult imii A = a(1), a(2), . . . , a(n) cu n ele-
mente. Evident c a avem biject ie ntre mult imea indicilor 1, 2, . . . , n si
elementele mult imii A. Exemplu:
1, 3, 4, 5 a(1), a(3), a(4), a(5)
Ca atare, vom presupune pentru simplicarea algoritmilor c a a(i) = i, i
1, . . . , n.
Avem la dispozit ie urm atoarele modalit at i de reprezentare a unei submult imi
X cu i elemente ale lui A:
1. Printrun vector x cu i componente care cont ine elementele submult imii,
preciz anduse valoarea lui i sau complet and componentele lui x cu o
valoare neutilizat a (de exemplu 0);
2. Analog cu metoda 1, dar plas and elemetele submult imii la sf arsitul
vectorului x;
55
3. Prin vectorul caracteristic al submult imii: un vector c cu n componente
unde c(i) = 1 arat a c a a(i) apart ine submult imii, iar c(i) = 0 arat a c a
a(i) nu apart ine submult imii.
Exemplu: pentru A = 1, 2, 3, 4, 5, 6, 7, submult imea X = 1, 3, 4, 5 poate
reprezentat a astfel:
1. x = (1, 3, 4, 5, 0, 0, 0): elementele din submult imea X la nceput, restul
p an a la n pozit ii ind completate cu o valoare care nu se g aseste n A,
de exemplu 0 (care nu este indice valid);
2. x = (0, 0, 0, 1, 3, 4, 5): elementele din submult imea X la sf arsit, primele
pozit ii ind completate cu o valoare care nu se g aseste n A;
3. c = (1, 0, 1, 1, 1, 0, 0): c este vectorul caracteristic:
c(i) =
_
1, dac a i X
0, dac a i , X
Toate gener arile prezentaten continuare au un caracter iterativ ecare
nou element (i.e. submult ime) al mult imii ind g asit pe baza elementului
anterior.
Algoritmul general pe care l vom prezenta n continuare foloseste, pe
l ang a un vector de dimensiune n (n care apar succesiv elementele submult imii)
si un indicator de generare. Acest indicator de generare are init ial valoarea
0; apoi are valoarea 1 c at timp se mai poate genera o submult ime X si din
nou valoarea 0 c and s-a terminat generarea.
Generare(x, n, ig)
dac a ig = 0 atunci
x = valoarea (submult imea) init ial a
ig = 1
Returniese n (sub)algoritmul apelant
sf arsit dac a
dac a exist a un succesor al lui x atunci
x =succesorul lui xig r am ane 1
altfel
ig = 0nu s-a mai putut genera submult imea X
sf arsit dac a
Return
Un mod de utilizare a acestui algoritm pentru gener ari este urm atorul:
ig = 0
56
repet a
cheam a Generare(x, n, ig)
dac a ig = 0 atunci
exitIesi din ciclare
altfel
cheam a Prelucrare(x, n)prelucreaz a elementul proasp at obt inut al
submult imii
sf arsit dac a
p an a c and fals

In majoritatea algoritmilor pe carei vom prezenta, vectorii vor generat i


n ordine lexicograc a
1
, ceea ce corespunde strategiei generale Backtracking.
7.3 Generarea elementelor unui produs car-
tezian
Fiind date mult imile A
1
, A
2
, . . . A
m
, unde A
i
= 1, 2, . . . , n(i), dorim s a
gener am elementele produsului cartezian A
1
A
2
A
m
. Vom avea n
total
m

i=1
n(i) elemente.

In algoritmul urm ator elementele produsului cartezian vor generate suc-


cesivn vectorul x cu melemente, unde o congurat ie x = (x(1), x(2), . . . , x(m))
va desemna elementul (A
1
(x(1)), A
2
(x(2)), . . . , A
m
(x(m))) al produsului car-
tezian.
Vom porni deci cu un element init ial x = (1, 1, . . . , 1) care nseamn a c a
din ecare mult ime A
i
lu am primul element.

In continuare vom determina
cel mai mare indice i cu proprietatea c a x(i) < n(i) si vom alege ca succesor
al lui x = (x(1), x(2), . . . , x(m)) elementul x = (x(1), x(2), . . . , x(i1), x(i)+
1, 1, . . . , 1).
Dac a pentru ecare i 1, . . . , m avem x(i) = n(i) nseamn a c a aceasta
a fost ultima component a a produsului cartezian si generarea s-a terminat.
Algoritmul pentru generarea produsului cartezian este:
ProdusCartezian(x, m, n, ig)
1
Dou a siruri x = (x(1), . . . , x(n)) si y = (y(1), . . . , y(n)) sunt n ordine lexicograc a
strict cresc atoare dac a exist a k 1, k < n astfel nc at x(i) = y(i) pentru orice i k si
x(k +1) < y(k +1). Exemplu: (1, 1, 2) < (1, 2, 1) n sens lexicograc. Pentru cazul n care
x si y au forma general a x = (x(1), . . . , x(m)) si y = (y(1), . . . , y(n)), dac a exist a k m, n
astfel nc at (x(1), . . . , x(k)) < (y(1), . . . , y(k)) atunci x este mai mic (lexicograc) dec at y.
Dac a un astfel de k nu exist a (adic a x(1) = y(1), . . . , x(p) = y(p) unde p este min(m, n)),
atunci cel mai scurt dintre vectori este considerat cel mai mic. Exemplu: (1, 2) < (1, 3, 4),
(1, 2) < (1, 2, 3).
57
dac a ig = 0 atunci
pentru i = 1, m
x(i) = 1
sf arsit pentru
ig = 1
Return
sf arsit dac a
pentru i = m, 1, 1
dac a x(i) < n(i) atunci
x(i) = x(i) + 1
Return
altfel
x(i) = 1
sf arsit dac a
sf arsit pentru
ig = 0
Return
7.4 Generarea tuturor submult imilor unei mul-
t imi
O prim a metod a ar s a gener am elementele produsului cartezian al
mult imilor A
1
= A
2
= = A
n
= 0, 1. Vectorul x care se obt ine, interpre-
tat ca vector caracteristic, va element al mult imii p art ilor lui 1, 2, . . . , n
O a doua metod a ve genera submult imile unei mult imi n ordinea cresc atoare
a num arului de elemente utliz and metoda (2) de reprezentare a mult imilor.
Specic am c a vectorii x vor generat i si de aceast a dat a n ordine lexicogra-
c a strict cresc atoare.
Fie x = (x(1), x(2), . . . , x(n)); atunci succesorul lui se va determina n
modul urm ator: se va determina indicele i cu proprietatea c a x(i) < i si
pentru n j > i avem x(j) = j. Este evident c a urm atorul element x

n
ordine lexicograc a este cel n care x

(i) = x(i) + 1 iar celelalte componente


cresc cu c ate 1, adic a: x

(i + 1) = x(i) + 2, . . . , x

(n) = x(i) +n i + 1.
Se ncepe cu x = (0, 0, . . . , 0) care reprezint a mult imea vid a, iar atunci
c and x = (1, 2, . . . , n) nseamn a c a am generat ultimul element.
Algoritmul pentru generarea submult imilor unei mult imi este:
Submultimi(x, m, ig)
dac a ig = 0 atunci
pentru i = 1, n
58
x(i) = 0
sf arsit pentru
ig = 1
Return
sf arsit dac a
pentru i = n, 1, 1
dac a x(i) < i atunci
x(i) = x(i) + 1
pentru j = i + 1, n
x(j) = x(j 1) + 1
sf arsit pentru
Return
sf arsit dac ax(i) < i
sf arsit pentru
ig = 0
Return
7.5 Generarea mult imii combinarilor
Fie A = 1, 2, . . . n si m n. Vom construi n continuare algoritmi de
generare a tuturor celor C
m
n
combin ari din mult imea A cu proprietatea c a
oricare dou a elemente difer a ntre ele prin natura lor, nu si prin ordine.
O prim a metod a se bazeaz a pe metoda de reprezentare 1. Si de aceast a
dat a vectorii vor generat i n ordine lexicograc ancep and cu x = (1, 2, . . . , m)
2
.
Fiind dat x = (x(1), x(2), . . . , x(m)), urm atorul element x

va determinat
astfel:
1. se determin a indicele i cu proprietatea: x(i) < n m + i, x(i + 1) =
n m+i + 1, . . . , x(m) = n
2. se trece la x

prin:
- x

(j) = x(j) dac a j < i


- x

(i) = x(i) + 1
- x

(j) = x(j 1) + 1 pentru j de la i + 1 la m


3. c and nu g asim i cu proprietatea de mai sus nseamn a c a x = (n m+
1, n m + 2, . . . , n) si deci s-a generat ultimul element.
2
Restul componentelor vectorului x ind permanent 0, nu vor mai reprezentate, deci
vom lucra efectiv doar cu m componente n loc de n.
59
Algoritmul va urm atorul:
Combin1(x, n, m, ig)
dac a ig = 0 atunci
pentru i = 1, m
x(i) = i
sf arsit pentru
ig = 1
Return
sf arsit dac a
pentru i = m, 1, 1
dac a x(i) < n m +i atunci
x(i) = x(i) + 1
pentru j = i + 1, m
x(j) = x(j 1) + 1
sf arsit pentru
Return
sf arsit dac a
sf arsit pentru
ig = 0
Return
A doua metod a foloseste reprezentarea elementelor prin vectorul carac-
teristic, generat n ordine lexicograc a cresc atoare. Primul element va :
x = (0, 0, . . . , 0, 1, 1, . . . , 1) vectorul cu ultimele m pozit ii egale cu 1 si 0 n
rest.
Fie acum vectorul x c aruia vrem s a i determin am succesorul x

; pentru
aceasta vom pune n evident a ultima secvent a de cifre 1:
X =(. . . , 0, 1, . . . 1, 0, . . . , 0)
a b
unde a este indicele unde ncepe aceast a secvent a iar b indicele ultimului
element egal cu 1.
Trecerea la x

depinde de faptul c a ultima secvent a cont ine un singur


element (a = b) sau mai multe elemente (a < b).
Dac a a = b atunci x

(a 1) = 1, x

(a) = 0 si n rest x

(i) = x(i) va
determina congurat ia urm atoare.
Dac a a < b atunci rezult a c a x(a 1) = 0. S a not am cu l
1
lungimea
secvent ei de elemente 1, deci l
1
= b a + 1 si cu l
0
lungimea secvent ei de
zerouri de la sf arsitul lui x, deci l
0
= n b. Rezult a c a l
1
2 si l
0
0.
Trecerea de la x la x

se poate vedea usor n urm atoarea schem a:


60
l
1
l
0
x = (. . . , 0, 1, . . . , 1, 0, . . . , 0)
a b
l
1
1
x = (. . . , 1, 0, . . . , 1, . . . , 1)
a n l
1
+ 2
Deci x

(a 1) va deveni 1, urmeaz a apoi un sir de l


0
+ 1 zerouri, urmat,
n nal de un sir de l
1
1 elemente egale cu 1. Algoritmul pentru generarea
combin arilor este urm atorul:
Combinari2(x, n, m, ig, a, b)
dac a ig = 0 atunci
pentru i = 1, n m
x(i) = 0
sf arsit pentru
pentru i = n m + 1, n
x(i) = 1
sf arsit pentru
ig = 1
a = n m+ 1
b = n
Return
sf arsit dac a
dac a a = 1 atunci
ig = 0
Return
sf arsit dac a
dac a a < b atunci
l
1
= b a + 1
x(a 1) = 1
pentru i = a, n l
1
+ 1
x(i) = 0
sf arsit pentru
pentru i = n l
1
+ 2, n
x(i) = 1
sf arsit pentru
a = n l
1
+ 2
b = n
Return
altfel
61
x(a 1) = 1
x(a) = 0
b = a 1
pentru i = a 1, 1, 1
dac a x(i) = 0 atunci
a = i + 1
Return
sf arsit dac a
a = 1
sf arsit pentru
sf arsit dac aa < b
Return
7.6 Generarea mult imii permutarilor
Complexitatea oric arui algoritm care rezolv a aceast a problem a este de
(n!), deoarece trebuie generat i n! vectori. Vectorul p cu n elemente va
cont ine permutarea mult imii A = 1, 2, . . . , n. Exist a mult i algoritmi pen-
tru rezolvarea acestei probleme, dar noi prezent am aici numai doi dintre ei.
Pentru mai multe detalii, a se consulta lucrarea [3].
Prima metod a este: urm areste generarea vectorului xn ordine lexicogra-
c a cresc atoare. Pentru construct ia lui p

succesorul lui p vom pune n


evident a ultima secvent a descresc atoare:
p(i) < p(i + 1) > p(i + 2) > > p(n) (7.1)
si n consecint a componenta care trebuie modicat a este p(i).

In locul lui
p(i) trebuie pus a o component a p(j) cu j > i, cu condit ia ca p(j) > p(i), dar
pentru c a p

este succesorul lui p, trebuie ales j astfel nc at p(j) s a e cel mai


mic cu proprietatea p(j) > p(i); e acest indice k; atunci prin interschimbarea
lui p(i) cu p(k) se ajunge la:
(p(1), . . . , p(i 1), p(k), p(i + 1), . . . , p(k 1), p(i), p(k + 1), . . . , p(n))
unde p(i +1) > p(i +2) > > p(k 1) din ecuat ia (7.1). Dac a p(i) nu ar
mai mare dec at p(k+1), atunci am avea (datorit a inegalit at ii p(k) > p(k+1))
c a p(k) nu ar cel mai mic din secvent a p(i +1), . . . , p(n) care este mai mare
dec at p(i), contradict ie cu alegerea lui k; deci avem c a p(i) > p(k + 1),
deci p(i) > p(k + 1) > > p(n). Usor se demonstreaz a c a p(k 1) > p(i).
Rezult a c a secvent a de la p(i+1) la p(n) este descresc atoare si pentru a obt ine
p

nu avem dec at s a invers am aceast a secvent a, interschimb and termenii de la


nceput cu cei de la sf arsit p an a la mijlocul secvent ei. Algoritmul este:
62
Perm1p, n, ig
dac a ig = 0 atunci
pentru i = 1, n
p(i) = i
sf arsit pentru
ig = 1
Return
sf arsit dac a
i = n 1
c at timp p(i) > p(i + 1)
i = i 1
dac a i = 0 atunci
ig = 0
Return
sf arsit dac a
sf arsit c at timp
k = n c autarea lui k
c at timp p(i) > p(k)
k = k 1
sf arsit c at timp
schimb a p(i) cu p(k)
p(i) p(k)
3
calculeaz a mijlocul secvent ei
m =
_
ni
2

[x] este partea ntreag a a lui x


pentru j = 1, m
p(i +j) p(n + 1 j)
sf arsit pentru
Return
Metoda pe care o prezent am n continuare se bazeaz a pe generarea recursiv a
a permut arilor. Dac a avem S
k
mult imea permut arilor de k elemente de forma
p = (p(1), . . . , p(k)) S
k
, atunci S
k+1
va cont ine pe baza ec arei permut ari p
c ate k+1 permut ari P

: (p(1), . . . , p(k), k+1), (p(1), . . . , p(k1), k+1, p(k)),


. . . , (p(1), k + 1, p(2), . . . , p(k)), (k + 1, p(1), . . . , p(k)). Deci permut arile S
n
vor frunzele unui arbore construit astfel:
- r ad acina cont ine 1;
- descendent ii unei permut ari p = (p(1), . . . , p(k)) sunt cele k + 1 per-
mut ari descrise mai sus
3
Notat ia a b nseamn a interschimb a valoarea lui a cu valoarea lui b, care se
efectueaz a prin urm atoarea secvent a: aux = a, a = b, b = aux.
63
Putem atasa acestui arbore unul n care toate permut arile sunt de n ele-
mente, prin completarea permut arii de k elemente cu componentele (k +
1, k + 2, . . . , n).
Exemplu: pentru n = 3 se obt ine arborele din Figura 7.1 si arborele
atasat din Figura 7.2.
(1,2) (2,1)
(1,3,2) (1,2,3) (3,1,2) (3,2,1) (2,1,3) (2,3,1)
(1)
Figura 7.1: Arborele atasat unei permut ari de 3 elemente
(1,3,2) (1,2,3) (3,1,2) (3,2,1) (2,1,3) (2,3,1)
(1,2,3) (2,1,3)
(1,2,3)
Figura 7.2: Arbore cu noduri completate p an a la n
Arborele atasat are, evident, aceleasi v arfuri terminale. Trecerea de la o
permutare p la urm atoarea permutare p

nseamn a o parcurgere a frunzelor


acestui arbore.
Fie p = (p(1), . . . , p(n)); atunci p

se construieste astfel:
Dac a n apare pe o pozit ie m > 1, atunci se face interschimbarea p(m)
p(m 1) si s-a obt inut noua permutare. Dac a p(1) = n, atunci se per-
mut a circular spre st anga cele n elemente, obt in anduse tat al permut arii p.

In continuare, dac a n 1 apare pe o pozit ie m ,= 1, atunci se efectueaz a


interschimbarea p(m) p(m 1) si sa obt inut noua permutare; n caz
contrar, se permut a circular ultimele n 1 pozit ii si se ncearc a deplasarea
spre st anga a lui n 2, etc. Algoritmul este:
Perm2(p, n, ig)
dac a ig = 0 atunci
64
pentru i = 1, n
p(i) = i
sf arsit pentru
ig = 1
Return
sf arsit dac a
pentru i = n, 2, 1
m = 1
c at timp p(m) ,= i
m = m + 1
sf arsit c at timp
dac a m ,= 1 atunci
p(m1) p(m)
Return
sf arsit dac a
cheam a PermCircStanga(p, n, i) se permut a circular primele i compo-
nente ale lui P
Return
sf arsit pentru
ig = 0
Return
unde PermCircStanga(p, n, i) este urm atorul algoritm:
PermCirc(p, n, i)
x = p(1)
pentru j = 1, i 1
p(j) = p(j + 1)
sf arsit pentru
p(i) = x
Return
7.7 Generarea mult imii aranjamentelor
O prim a metod a const a n generarea tuturor combin arilor de n luate c ate
m si pentru ecare din acestea realizarea tuturor permut arilor. Aceast a idee
duce la urm atorul algoritm:
Aranj1(x, n, m, ig, c, p, ig1)
dac a ig = 0 atunci
pentru i = 1, m
x(i) = i
c(i) = i
65
p(i) = i
sf arsit pentru
ig = 1
ig1 = 1
Return
sf arsit dac a
cheam a Perm(p, m, ig1)
dac a ig1 ,= 0 atunci
pentru i = 1, m
x(i) = c(p(i))
sf arsit pentru
altfel
cheam a Combin(c, m, ig)
dac a ig = 1 atunci
pentru i = 1, m
p(i) = i
x(i) = c(i)
sf arsit pentru
ig1 = 1
Return
sf arsit dac a
sf arsit dac a
Return
S a observ am c a metoda nu genereaz a aranjamentele n ordine lexicogra-
c a cresc atoare. Urm atoarea metod a urm areste s a p astreze aceast a ordine,
conform strategiei generale Backtracking.
Fie x = (x(1), . . . , x(m)) un aranjament oarecare. Pentru determinarea
lui x

, aranjamentul succesor, n ordine lexicograc a, vom determina mai nt ai


indicele i, cel mai mare indice care poate m arit. Un x(i) nu poate m arit
dac a valorile x(i)+1, x(i)+2, . . . , n nu sunt disponibile. Vom folosi un vector
disp cu n componente care sunt 0 sau 1. disp(k) = 0 arat a c a valoarea k este
disponibil a iar disp(k) = 1 arat a c a valoarea x(k) nu este disponibil a (este
deja folosit a n x). C and se g aseste valoarea x cu proprietatea ment ionat a,
x(i), x(i + 1), . . . , x(m) vor primi cele mai mici valori disponibile, n ordine
cresc atoare. Rezult a de aici c a p an a la g asirea lui i toate valorile cercetate
regresiv vor f acute disponibile.
Obt inem n acest fel urm atorul algoritm:
Aranj2(x, n, m, ig, disp)
dac a ig = 0 atunci
pentru i = 1, m
66
x(i) = i
disp(i) = 1
sf arsit pentru
pentru i = m + 1, n
disp(i) = 0
sf arsit pentru
ig = 1
Return
sf arsit dac a
pentru i = m, 1, 1
disp(x(i)) = 0
pentru j = x(i) + 1, n
dac a disp(j) = 0 atunci
x(i) = j
disp(j) = 1
k = 0
pentru l = i + 1, m
repet a
k = k + 1
p an a c and disp(k) = 0
x(l) = k;
disp(k) = 1
sf arsit pentru
Return
sf arsit dac a
sf arsit pentru
sf arsit pentru
ig = 0
Return
7.8 Generarea submult imilor de suma data
Fie A = (a(1), . . . , a(n)) un vector cu componente strict pozitive si M > 0
un num ar pozitiv dat. Se cer submult imile B = i
1
, i
2
, . . . , i
l
1, 2, . . . , n
astfel nc at

iB
a(i) = M (7.2)
67
Vom folosi pentru reprezentarea mult imilor B metoda 3, deci dac a x este
vectorul caracteristic al lui B atunci (7.2) se rescrie ca:
n

i=1
x(i) a(i) = M (7.3)
Componentele lui x vor generate succesiv dup a metoda general a bac-
ktracking: dac a am stabilit deja n x componentele x(1), x(2), . . . , x(k 1),

k1
i=1
x(i) a(i) M, atunci componenta x(k) trebuie s a satisfac a condit iile:
k

i=1
x(i) a(i) M (7.4)
si
k

i=1
x(i) a(i) +
n

i=k+1
a(i) M (7.5)
Vom considera
S =
k

i=1
x(i) a(i) (7.6)
si
R =
n

i=k+1
a(i) (7.7)
Vom presupune c a elementele mult imii A sunt sortate cresc ator (se face
o sortare n prealabil). Algoritmul va :
SumbultimiSuma(a, x, n, M, k, S, R, ig)
dac a ig = 0 atunci
pentru i = 0, n
x(i) = 1
k = 1
S = 0
R =
n

i=1
a(i)
sf arsit pentru
altfel
S = S x(k) a(k)
R = R +a(k)
x(k) = 1
k = k 1
sf arsit dac a
68
c at timp k > 0
dac a x(k) < 1 atunci
x(k) = x(k) + 1
S = S +x(k) a(k)
dac a S = M atunci
ig = 1
Return
sf arsit dac a
dac a S < M si S +R M atunci
R = R x(k)
k = k + 1
sf arsit dac a
dac a S +R < M atunci
S = S +x(k) a(k)
R = R +a(k)
x(k) = 1
k = k 1
sf arsit dac a
altfel
S = S a(k)
R = R +a(k)
x(k) = 1
k = k 1
sf arsit dac a
sf arsit c at timp
ig = 0
Varianta recursiv a, mult mai usor de urm arit este dat a mai jos. Variabila
ramas este egala cu M S din algoritmul precedent.
SubmultimiRecursiv(a, x, n, k, ramas)
dac a ramas = 0 atunci
cheam a Prelucrare(a, x, k 1)
Return
sf arsit dac a
dac a k > n sau ramas < 0 atunci
Return
sf arsit dac a
pentru x[k] = 0, 1
cheam a SubmultimiRecursiv(a, x, n, k + 1, ramas x[k] a[k])
sf arsit pentru
Return
69
7.9 Rezumat
Pentru determinarea unor submult imi (de o natur a particular a) a unei
mult imi exist a algoritmi specializat i. Se pot da, evident, mai mult i algoritmi
pentru generarea unei solut ii. Aceste tipuri de probleme se nt alnesc adeseori
sub o form a mascat a n enunt ul altor probleme, sau ca etap a intermediar a
ntrun caz mai mare.
7.10 Exercit ii (rezolvarile la pagina 160)
1. S a se scrie algoritmi recursivi pentru generarea tipurilor de submult imi
din acest capitol.
70
Capitolul 8
Metoda Divide et Impera
8.1 Obiective
Capitolul prezint a metoda Divide et Impera, ce se poate utiliza atunci
c and rezolvarea unei probleme se face prin spargerea ei n cazuri de dimen-
siune mai mic a (dar de aceeasi natur a cu problema init ial a), iar apoi prin
recombinarea solut iilor obt inute. Determinarea complexit at ii se reduce la
rezolvarea unei recurent e, pentru care o unealt a util a este Teorema central a.
Este dat cel mai ecient algoritm de sortare (Quicksort) si se demonstreaz a
o limit a inferioar a pentru algoritmiide sortate bazat i pe comparat ii.
8.2 Prezentare generala
Aceast a metod a nu este ceva nou pentru cursul nostru. Am rezolvat cu ea
problema sort arii prin interclasare n capitolul 3, pagina 20. Metoda const a
n urm atoarele etape:
1. Partit ionarea problemei init iale n mai multe probleme mai mici;
2. Rezolvarea (de obicei recursiv a) a ec arei subprobleme; dac a o subpro-
blem a este de dimensiune sucient de mic a, atunci ea se poate rezolva
printro metod a ad-hoc, care poate mai put in performant a pentru
cazuri de dimensiune mare;
3. Combinarea rezultatelor part iale pentru a obt ine rezultatul problemei
init iale.
Dac a o problem a a fost divizat a n a subprobleme care au dimensiunea
n
b
si sunt rezolvate recursiv, atunci complexitatea este dat a de formula:
T(n) = aT
_
n
b
_
+f(n) (8.1)
71
unde f(n) este costul combin arii solut iilor subproblemelor.
Aarea formei lui T(n) este o problem a de algebr a care se poate aborda
prin induct ie sau folosind rezultatele teoremei principale din [2]:
Teorema 1. (Teorema central a.) Fie a 1 si b > 1 constante, e f(n) o
funct ie si T(n) denit a pe ntregii nenegativi prin recurent a:
T(n) = aT
_
n
b
_
+f(n) (8.2)
unde interpret am pe
n
b
e ca pe
_
n
b
_
, e ca pe
_
n
b
_
. Atunci T(n) poate
delimitat a asimptotic dup a cum urmeaz a:
1. Dac a f(n) = O(n
log
b
a
) pentru o anumit a constant a > 0, atunci
T(n) = (n
log
b
a
)
2. Dac a f(n) = (n
log
b
a
) atunci T(n) = (n
log
b
a
log n)
3. Dac a f(n) = (n
log
b
a+
) pentru o anumit a constant a > 0 si dac a
af
_
n
b
_
cf(n) pentru o anumit a constant a c < 1 si tot i n sucient i
de mari, atunci T(n) = (f(n)).
Demonstrat ia se poate g asi n [2].
Am folosit divide et impera la sortarea unui sir (sortarea prin interclasare,
algoritmul Mergesort); se vede c a se ajunge la complexitatea:
T(n) = (nlog
2
n)
(care se deduce din cazul 2 al Teoremei centrale), complexitate mai bun a
dec at cea de la sortarea prin insert ie, care era
T(n) = (n
2
)
8.3 Problema turnurilor din Hanoi
Prima problem a pe care o prezent am este Problema turnurilor din Ha-
noi, problem a care nu are nici o leg atur a cu Hanoi-ul, ci este un joc logic
inventat n secolul trecut de matematicianul francez Eduard Lucas. El a
fost cel care a v andut pentru prima oar a aceast a problem a drept joc, cu opt
discuri si trei baghete.
Dup a o str aveche legend a hindus a, zeul Brahma ar xat pe masa tem-
plului s au din Benares trei bastonase verticale de diamant si ar nsirat pe
acesta 64 de discuri de m arimi descresc atoare (de la baz a la v arf), form and
72
astfel un trunchi de con. A dispus apoi ca discurile s a e mutate pe un al
doilea, folosind si al treilea bastonas; zi si noapte trebuia mutat c ate unul
din discurile aate n v arful unuia din bastonase n v arful altui bastonas, res-
pect and n ecare moment ordinea descresc atoare a m arimii discurilor aate
pe ecare bastonas. Legenda spune c a, d and aceast a porunc a, Brahma a
sust inut c a atunci c and se va termina asezarea celor 64 de dicuri pe cel de-al
doilea bastonas, atunci se va sf arsi si viat a pe P am ant. O versiune destul
de optimist a deoarece presupun and c a mutarea unui disc ar dura o secund a,
cele 64 de discuri vor ajunge pe al doilea bastonas n circa 584.942.416.729
de ani.
Enunt ul formalizat al problemei este: e trei tije si n discuri perforate
de diametre diferite. Discurile sunt asezate init ial pe tija 1 n ordinea des-
cresc atoare a diametrelor acestora consider and sensul de la baz a la v arf. Pro-
blema const a n a muta turnul de n discuri de pe tija 1 pe tija 2 ntr-un
num ar minim de mut ari, t in and cont de urm atoarele reguli:
1. La ecare mutare se mut a un singur disc
2.

In permanet a, pe ecare tij a, deasupra unui disc pot mutate numai
discuri de diametre mai mici.
Calcularea num arului minim de pasi: observ am c a pentru 2, 3, 4 si 5 discuri,
problema se rezolv a efectu and un num ar de mut ari egal cu 3, 7, 15 si respectiv
31, de unde putem formula ipoteza c a pentru problema cu n discuri vom
efectua 2
n
1 mut ari.
S a demonstr am valabilitatea acestui rezultat prin induct ie matematic a
complet a dup a n. Am ar atat c a armat ia este adev arat a pentru n = 2, 3, 4, 5
discuri. Presupunem c a ea este adev arat a pentru n discuri, deci sunt necesare
2
n
1 mut ari. Vom demonstra c a pentru n+1 discuri sunt necesare 2
n+1
1
mut ari.
Putem rezolva problema mut arii celor n + 1 discuri n trei etape:
1. Mut am primele n discuri pe tija a treia
2. Mut am al n + 1-lea disc pe a doua tij a
3. Mut am cele n discuri de pe a treia tij a pe cea de-a dou a tij a.
Folosind acest procedeu, sunt necesare:
1. 2
n
1 mut ari pentru realizarea primei etape
2. o mutare pentru realizarea celei de a doua etape
73
3. 2
n
1 mut ari pentru realizarea celei de a treia etape

In total sunt suciente 2


n+1
1 mut ari

In continuare vom prezenta mai mult i
algoritmi, ecare baz anduse pe c ate o observat ie important a.
8.3.1 Metoda I
O mutare poate scris a ca o pereche (i, j) cu i 1, 2, 3 si i ,= j,
semnic and c a se mut a discul cel mai mic de pe tija i pe tija j. Mai not am
cu H(m, i, j) sirul mut arilor necesare pentru a muta primele m discuri (cele
mai de sus) de pe tija i pe tija j.

In aceste ipoteze, problema se reduce la a
determina sirul de mut ari H(m, i, j). Observ am c a putem scrie:
H(m, i, j) =
_
(i,j), pentru m = 1
H(m-1, i, k),(i,j),H(m-1, k, j) pentru m ,= 1
(8.3)
unde k = 6 i j este tija diferit a de tijele i si j.
Cu aceasta reducem rezolvarea problemei cu n discuri la rezolvarea a
dou a probleme cu n 1 discuri. Algoritmul se bazeaz a pe ideea c a n loc
de H(m, i, j) putem scrie H(i, j), memor and valoarea lui m separat. Se
mai poate observa c a H(i, j) se transform a n H(i, k), (i, j), H(k, j) cu
k = 6 i j. Av and n mijloc tot perechea (i, j), rezult a c a imediat ce
o pereche este generat a, ea poate nscris a direct pe locul ei. Algoritmul
obt ine cele 2
n
1 mut ari folosind n acest scop o matrice M cu 2 linii si
2
n
1 coloane, ecare coloan a memor and o mutare.

Incepem prin a nscrie
perechea (1,2) pe coloana 2
n1
. Perechile ce vor lua nastere din ea vor
nscrise pe coloanele 2
n2
si 2
n1
+ 2
n2
. Se observ a c a acest algoritm face
parte din clasa algoritmilor Divide et Impera.
Mai general, pentru ecare valoare a lui m n, n 1, . . . , 2 se expan-
deaz a perechile din coloanele c de forma c = /2
m
+ 2
m11
, perechile care
rezult a din cea din coloana c ind nscrise pe coloanele c 2
m2
, c + 2
m2
.
Hanoi1(M, n, N)N = 2
n
1
k1 = N + 1
k2 = k1/2
k3 = k2/2
M(1, k2) = 1
M(2, k2) = 2
pentru m = n, 2, 1
pentru l = k2, N, k1
i = M(1, l)
1
Mp este notat ie pentru multiplu de p.
74
j = M(2, l)
k = 6 i j
M(1, l k3) = i
M(2, l k3) = k
M(1, l +k3) = k
M(2, l +k3) = j
sf arsit pentru
k1 = k2
k2 = k3
k3 = k3/2
sf arsit pentru
8.3.2 Metoda a IIa
Varianta recursiv a este bazat a tot pe metoda Divide et Impera. Aceast a
metod a este elegant a din punct de vedere al redact arii, dar inecient a din
cauza spat iului ocupat n stiv a si ant arzierilor datorate apelurilor n cascad a
a procedurii.
Hanoi2(n, i, j)
dac a n = 1 atunci
mut a discul superior de pe tija i pe tija j
altfel
cheam a Hanoi2(n 1, i, 6 i j)
mut a discul superior de pe tija i pe tija j
cheam a Hanoi2(n 1, 6 i j, j)
sf arsit dac a
Return
(3,1,3) (3,3,2)
(4,1,2)
(2,1,2) (2,1,2)
(1,1,3) (1,1,3)
(2,2,3)
(1,2,1) (1,1,3) (1,3,2)
(2,3,1)
(1,3,2) (1,2,1) (1,3,2)
Figura 8.1: Arborele apelurilor recursive pentru Hanoi2(4, 1, 2)
75
8.3.3 Metoda a IIIa
Vom porni de la algoritmul precedent, pe care l vom transforma ntr
unul iterativ. Apelul Hanoi2(4,1,2) va duce la arborele de apeluri recursive
din gura 8.1, unde n ecare nod este memorat un triplet de forma (n, i, j).
Prin parcurgerea n inordine a acestui arbore binar si asarea pentru e-
care nod a ultimelor dou a numere memorate n el, se ajunge la determinarea
solut iei cerute. Pentru parcurgere se va folosi o stiv a S n care se vor memora
triplete de forma (a, b, c). Arborele nu este construit n mod explicit.
Hanoi3(n)
i = 1
j = 2
gata = fals
niv = 1pornim de la r ad acin a, care se a a pe nivelul 1
S = S este stiv a
con = 0
repet a
c at timp niv < n 1
niv = niv + 1
(i, j, niv) S
j = 6 i j
sf arsit c at timp
scrie( i, 6 i j )
scrie( i, j )
scrie( 6 i j, j )
dac a S = atunci
gata = adevarat
altfel
(i, j, niv) S
scrie( i, j )
i = 6 i j
sf arsit dac a
p an a c and gata = adevarat
Return
Observat ie: Pentru implementarea stivei se poate folosi o matrice cu n 2
linii si 3 coloane.
76
8.4 Algoritmul de sortare QuickSort
Fie sirul x = (x(1), x(2), . . . , x(n)). Dorim s a sort am acest sir, adic a i
1, . . . , n 1, x(i) x(i +1). Dup a cum stim, algoritmii sunt caracterizat i
de timpul de execut ie si spat iul de memorie ocupat.
Sortarea unui sir cu metoda bulelor sau cea a insert iei s-a f acut cu algo-
ritmi in place (n afara sirului sau ment inut cel mult un num ar constant
de elemente din sir), iar prin metoda interclas arii se ocup a un alt sir (nu este
un algoritm in place) si n plus timpul de execut ie ascunde o constant a
multiplicativ a mare.
Ne dorim s a realiz am un algoritm de sortare prin metoda Divide et Im-
pera, f ar a a folosi un sir intermediar, deci in place. Profesorul C.A.R.
Hoare de la Universitatea Oxford a propus mp at irea sirului n p art i nu
neap arat egale av and proprietatea c a toate elemetele primei p art i s a e mai
mici sau egale dec at un x(k) xat (determinat de algoritmul de partitionare
care va prezentat mai jos), iar componentele celei de a doua p art i s a e
mai mari dec at x(k). Faza de combinare lipseste (este o metod a Divide et
Impera schioap a).
Algoritmul QuickSort (sortare rapid a) este:
QuickSort(x, p, r)
dac a p < r atunci
cheam a Part(x, p, r, k)
cheam a QuickSort(x, p, k)
cheam a QuickSort(x, k + 1, r)
sf arsit dac a
Return
Algoritmul care realizeaz a partit ionarea este:
Part(x, p, r, k)
pivot = x(p)
i = p 1
j = r + 1
terminat = fals
repet a
repet a
j = j 1
p an a c and x(j) pivot
repet a
i = i + 1
p an a c and x(i) pivot
dac a i < j atunci
77
x(i) x(j)
altfel
k = j
terminat = adevarat
sf arsit dac a
p an a c and terminat = adevarat
Return
Exemplu: e sirul:
5 3 2 6 4 1 3 7
i j
Avem: pivot = 5, p = 1, r = 8. Primul element al sirului mai mic sau egal
dec at pivotul 5 este 3 (n c autarea de la dreapta la st anga) si primul element
al sirului mai mare sau egal dec at pivorul 5 este 5 (c autare de la st anga spre
dreapta). Dup a g asirea lor le interschimb am, ajung and la congurat ia:
3 3 2 6 4 1 5 7
i j
Apoi, succesiv:
3 3 2 1 4 6 5 7
i j
3 3 2 1 4 6 5 7
j i
Deoarece j a devenit mai mic dec at i, se iese din procedura de partit ionare
cu valoarea lui k = 5.

In acest moment sa terminat partit ionarea dup a
pivot = 5.

In continuare se face partit ionarea sirului din partea st ang a
pentru pivot = 3:
3 3 2 1 4
i j
1 3 2 3 4
i j
1 2 3 3 4
i j
1 2 3 3 4
j i
78
Deoarece avem j i, procedura se termin a valoarea lui k = 2. Analog se
procedeaz a pentru ecare subcaz, p an a c and se ajunge la vectori de lungime
1, care sunt (evident) sortat i.
Observat ie: C and sirul este deja ordonat cresc ator, se face partit ionare
dup a ecare element.
Complexitatea partit ion arii este dat a de T
P
(n) = c n, c constant a. Com-
plexitatea QuickSort n cazul sirului init ial sortat este:
T
Q
(n) = T
Q
(1) +T
Q
(n 1) +T
P
(n) =
= T
Q
(n 1) +T
P
(n) +c =
= T
Q
(1) +T
Q
(n 2) +T
P
(n 1) +T
P
(n) +c =
= T
Q
(n 2) +T
P
(n 1) +T
P
(n) + 2c =
= =
= T
Q
(2) +
n

k=3
T
P
(k) + (n 2)c =
= T
Q
(1) +T
Q
(1) +
n

k=2
T
P
(k) + (n 2)c =
=
n

k=2
T
P
(k) +cn =
n

k=2
c k +c n = (n
2
)
unde am considerat n mod convenabil c a T
Q
(1) este m arginit de acceasi
constant a c care apare n expresia lui T
P
(n).

In cel mai bun caz, c and sirul semparten jum atate, T


Q
(n) = 2T
Q
(n/2)+
(n) = (nlog n) (conform teoremei centrale). Se poate demonstra c a tim-
pul mediu al QuickSortului este (nlog n).

In practic a se dovedeste c a
QuickSort este cel mai rapid algoritm de sortare!!
Ne punem ntrebarea dac a exist a algoritmi de sortare cu complexitatea
mai mic a dec at nlog n? Se poate demonstra c a dac a algoritmul se ba-
zeaz a doar pe comparat ii ntre elemente, nu se poate cobor sub bariera
de (nlog n). Pentru a demonstra, alegem a
1
, a
2
, a
3
elemente pe care le
compar am (Figura 8.2). Se obt ine un arbore binar care are drept frunze
permut arile indicilor elementelor init iale, adic a 3! frunze.

In cazul a n valori, obt inem un arbore binar cu n! frunze. Prin n at imea


unui arbore nt elegem lungimea drumului maxim de la r ad acin a la orice
frunz a si se noteaz a cu h. h reprezint a num arul de comparat ii n cazul cel
mai defavorabil. Este evident c a num arul maxim de frunze pentru un arbore
binar de ad ancime h este 2
h
. Deci n cazul nostru pentru compararea a n
elemente vom avea un arbore cu o ad ancime h astfel nc at n! 2
h
. Rezult a
79
a
1
: a
2
a
2
: a
3
(1,2,3) a
3
a
1
:
(1,3,2) (3,1,2) (2,3,1)
(3,2,1)
a
2
: a
3
(2,1,3)
a
3
a
1
:
<
>=
<
<
<
<
>=
>=
>=
>=
Figura 8.2: Arborele de decizie pentru 3 elemente
c a h log
2
(n!) si folosind aproximat ia lui Stirling:
n!

2n
_
n
e
_
n
2
obt inem c a:
h log
2
n! > nlog
2
n nlog
2
e = (nlog
2
n)
Se obt ine c a T(n) = (nlog
2
n). Am demonstrat deci c a pentru algorit-
mii care se bazeaz a doar pe comparat ii complexitatea nu poate s a scad a
sub nlog
2
n. Pentru cazuri speciale ale sirului ce trebuie sorart, a se vedea
capitolul 9.
8.5 Rezumat
Metoda Divide et Impera se foloseste atunci c and rezolvarea unei pro-
bleme se poate face prin descompunerea ei n cazuri de dimensiune mai mic a,
rezolvarea acestora dupa acelasi principiu, apoi combinarea rezultatelor lor.
Deseori algoritmii de acest tip se scriu ca recursiv (datorit a naturii lor), iar
determinarea complexit at ii se face prin rezolvarea unei ecuat ii recursive, a
c arei solut ii se poate da de multe ori pe baza Teoremei centrale.
Un exemplu important de algoritm de tip divide et Impera este Quicksort.
Problemele de la sf arsitul capitolului dau si alte exemple ale utilit at ii metodei.
2
Se poate ar ata c a:

2n
n+
1
2
e
n
e
(12n+1)
1
< n! <

2n
n+
1
2
e
n
e
(12n)
1
80
8.6 Exercit ii (rezolvarile la pagina 162)
1. Baz anduv a pe observat ia c a mutarea din mijloc se stie, scriet i un
algoritm iterativ pentru problema turnurilor din Hanoi, pun and mereu
mijloacele intervalelor obt inute prinnjum at at irentr-un sir cu num arul
cunoscut de mut ari.
2. Av and la intrare un sir ordonat cresc ator, s a se scrie un algoritm de
tip Divide et Impera pentru g asirea pozit iei unui element de valoare
dat a x, dac a el exist a. Se va folosi metodanjum at at irii intervalului dat
de num arul de elemente al sirului. Care este complexitatea c aut arii?
3. Rezolvat i aceeasi problem a prin c autare secvent ial a (testarea pe r and
a elementelor). Care este n acest caz complexitatea?
4. Demonstrat i c a timpul de execut ie al algoritmului QuickSort, n cazul
unui vector cu toate elementele egale, este (nlog n).
5. Complexitatea algoritmului QuickSort este mare din cauz a c a n cazuri
defavorabile, partit ionarea se face cu un singur element ntr-una din
partit ii. Rescriet i algoritmul de partit ionare, lu and ca element de se-
parare nu primul element, ci valoarea din mijloc ntre primul element,
ultimul si cel aat pe pozit ia din mijloc.
81
82
Capitolul 9
Sortare si statistici de ordine
9.1 Obiective

In acest capitol ne propunem s a rezolv am urm atoarele probleme, relative


la un sir cu n elemente:
1. s a se g aseasc a a i-a component a n ordine statistic a a sirului
2. s a se g aseasc a mediana (componenta din mijloc) unui sir
3. s a se g aseasc a cele mai mici dou a elemente dintrun sir
4. determinarea simultan a a minimului si maximului
Observat ie: Vom considera c a sirul este cu elemente distincten rezolvarea
tuturor problemelor enunt ate, urm and apoi s a extindem rezultatele obt inute
si pentru situat ia n care elementele se repet a.
Vor considerat i mai mult i algoritmi care rezolv a aceast a problem a. Ca-
pitolul cont ine si prezent ari ale altor algoritmi de sortare (heapsort, cu care
ocazie se introduce si structura de date numit a heap, sort ari n timp liniar).
9.2 Exemplicari, generalitat i
Exemple: Fie x = (5, 4, 2, 8, 9, 1, 7). Ce se nt elege prin a i-a component a
n ordine statistic a? Avem n = 7 si n mod evident 1 i 7. Dac a l
consider pe i = 3, vom nt elege prin a i-a component a n ordine statistic a a
sirului x elementul al treilea din sirul x sortat n ordine cresc atoare.
x = (1, 2, 4, 5, 7, 8, 9), x(3) = 4
83
Mediana depinde de paritatea num arului de elemente din sirul dat. Dac a
n este impar atunci mediana este unic a si se g aseste n sirul sortat pe pozit ia
i = (n + 1)/2. Altfel avem dea face cu dou a mediane, una dintre ele pe
pozit ia i = n/2, cealalt a pe pozit ia i = n/2 + 1.

In general, pentru un sir
de lungime n vom considera median a elementul de pe pozit ia
_
n+1
2

din sirul
sortat.

In cazul nostru mediana este 5.
Ce reprezint a minimul si maximul din perspectiva statisticilor de ordine?
Minimul este prima component a n ordine statistic a a unui sir. Maximul este
a n-a component a n ordine statistic a.
9.3 Determinarea simultana a minimului si a
maximului
MinMax(x, n)
dac a n mod 2 = 0 atunci
dac a x(1) < x(2) atunci
min = x(1)
max = x(2)
altfel
min = x(2)
max = x(1)
sf arsit dac a
k = 3
altfel
min = x(1)
max = x(1)
k=2
sf arsit dac a
pentru i = k, n 1, 2
dac a x(i) < x(i + 1) atunci
mic = x(i)
mare = x(i + 1)
altfel
mic = x(i + 1)
mare = x(i)
sf arsit dac a
dac a mic < min atunci
min = mic
sf arsit dac a
84
dac a mare > max atunci
max = mare
sf arsit dac a
sf arsit pentru
scrie( minimul este , min )
scrie( maximul este , max )
Return
Num arul de comparat ii ntre elemente necesare n determinarea indepen-
dent a a min si max este 2(n1) (prin dou a parcurgeri ale sirului), n schimb
pentru determinarea simultan a a min si max avem nevoie de 3 n/2| 2
comparat ii (demonstrat i acest lucru). Suger am cititorului s a execute algo-
ritmul pentru intrarea x = (1, 2, 3, 4, 5, 6, 85, 2).
9.4 Gasirea celor mai mici doua elemente dintr
un sir
Ideea algoritmului prezentat mai jos este urm atoarea: se compar a ele-
mentele 1 cu 2, 3 cu 4, etc; pentru ecare pereche comparat a se determin a
cel mai mic. Aceste elemente c astig atoare se vor compara la r andul lor pe
perechi adiacente, ca mai sus. C and r am ane un singur element, acesta este
minimul sirului. Atas am acestor operat ii un arbore binar (posibil nestrict)
echilibrat, construit n felul urm ator: exist a n noduri terminale (frunze), e-
care cont in and drept informat ie c ate un element din sir; un nod neterminal
are drept valoare minimul din cei doi i (gura 9.4).
4
4
6
7 6 4 5
1
1
2 1
3 2 1
(a) Arborele de comparat ii pentru
vectorul (7, 6, 4, 5, 2, 3, 1)
4
4
6
7 6 4 5
1
1
2 1
1 2 3
(b) Arborele de comparat ii pentru
vectorul (7, 6, 4, 5, 2, 1, 3)
Figura 9.1: Exemple de arbori construit i conform strategiei de mai sus.
85
Evident c a pentru ecare nod neterminal, informat ia sa coincide cu a unui
descendent al s au.

In cadrul acestui algoritm vom folosi termenul nvins
n exprimarea x este nvins de y dac a x > y (deoarece se caut a mini-
mul). Pentru determinarea celui de al doilea minim trebuie s a determin am
cel mai mic element din vectorul init ial nvins de minim: n exemplele
date este 2, nvins de 1. Pentru aceasta vom considera informat ia din
cei doi descendent i ai r ad acinii, n ambele exemple date ind 4 si 1. 4 este
cel mai mic element din jum atatea st ang a a sirului (este descendent st ang
al r ad acinii) si va trebui s a c aut am n jum atatea dreapt a a sirului cel mai
mic num ar, nvins de r ad acin a; acest lucru se face (n exemplele date) co-
bor and n subarborele drept spre frunze. Se compar a toate elementele pe
care informat ia din r ad acin a lea dep asit cu minimul din jum atatea st ang a
(n cazul nostru 4); cobor area se termin a atunci c and e se ajunge la frunze
(cazul 9.1(b)), e este evident c a nu mai are sens cobor area (cazul 9.1(a)).

In algoritmul de mai jos nu se va construi explicit arborele. Se vor folosi


niste cozi pentru ment inerea pentru ecare element din sir a elementelor
nvinse de acesta.
MinMin(x, n, min1, min2)
pentru i = 1, n
C(i) = C(i) este coad a
sf arsit pentru
c at timp n > 1
pozitie = 1pozitie este indicele din vector unde se vor pune elementele
nving atoare
pentru i = 1, n 1, 2
dac a a(i) < a(i + 1) atunci
imin = i
imax = i + 1
altfel
imin = i + 1
imax = i
sf arsit dac a
a(pozitie) = a(imin)
C(pozitie) = C(imin) a(imax)
pozitie = pozitie + 1
dac a n mod 2 ,= 0 atunci
a r amas un element care nu are cu cine se compara
a(pozitie) = a(n)
C(pozitie) = C(n)
pozitie = pozitie + 1
86
sf arsit dac a
n = pozitie 1
sf arsit pentru
sf arsit c at timp
min1 = a(1)
min2 C(1)
c at timp C(1) ,=
y C(1)
dac a y < min2 atunci
min2 = y
sf arsit dac a
sf arsit c at timp
Return
Prin C(i) = C(j) nt elegem trecerea elementelor din coada C(j) n coada
C(i) (dac a cozile sunt implementate folosind liste nl ant uite, atunci aceast a
operat ie se poate face n timp (1)), iar prin C(i) = C(j) x se nt elege
x C(j) urmat de C(i) = C(j).
Num arul de comparat ii se determin a dup a cum urmeaz a: n 1 pentru
determinarea minimului (terminarea ciclului c at timp), dup a care num arul de
comparat ii pentru determinarea minimului din coada C(1). Cum n aceast a
coad a exist a cel mult log
2
n| elemente (n alt imea arborelui de comparat ii -
demonstrat ia o l as am cititorului), avem c a se execut a cel mult log
2
n| 1
comparat ii pentru determinarea celui de al doilea minim. Deci n total avem
n +log
2
n| 2 comparat ii n cazul cel mai defavorabil.
9.5 Problema select iei
9.5.1 Select ie n timp mediu liniar

In general determinarea celei de a ia componente este o problem a av and


ca date de intrare un sir a cu n elemente distincte si un num ar i cu propri-
etatea 1 i n, iar ca dat a de iesire un element rez al sirului a care are
proprietatea c a exist a exact i 1 elemente ale sirului mai mici dec at rez.
Sel(A, p, r, i, rez)
dac a p = r atunci
rez = a(p)
Return
sf arsit dac a
Part(A, p, r, k)Part este algoritmul de partit ionare din QuickSort
dac a i k atunci
87
Sel(a, p, k, i, rez)
altfel
Sel(a, k + 1, r, i k, rez)
sf arsit dac a
Return
Algoritmul Sel aplicat unui sir deja sortat are (cel mai r au caz) comple-
xitatea O(n
2
). Se poate ar ata (vezi lucr arile [3], [2]) c a pentru cazul mediu
complexitatea este de O(n).
9.5.2 Select ian timp liniar n cazul cel mai defavorabil
Ideea algoritmului urm ator este de a obt ine o part itionare mai bun a dec at
versiunea precedent a a algoritmului. Vom folosi algoritmul Part modicat
astfel nc at s a preia ca parametru de intrare elementul n jurul c aruia este
efectuat a partajarea.
Algoritmul Selectie modicat determin a al ilea cel mai mic element al
unui tablou de intrare de n elemente, efectu and urm atorii pasi (oprirea algo-
ritmului se face atunci c and subsirul pe care se face c autarea are un element,
caz n care se returneaaz a aceast a unic a valoare).
1. Se mpart cele n elemente ale tabloului de intrare n
n
5
| grupe de c ate
5 elemente ecare si cel mult un grup s a cont in a restul de n mod 5
elemente.
2. Se determin a mediana ec areia din cele
n
5
| grupe cu sortarea prin
insert ie, ordon and elementele ec arui grup (cu cel mult 5 elemente),
apoi se aleg medianele din listele sortate, corespunz atoare grupelor.
Dac a n ultimul grup avem num ar par de elemente, se va considera cel
mai mare din cele dou a mediane.
3. Se utilizeaz a recursiv Selectie pentru a g asi mediana x din cele
n
5
|
mediane g asite la pasul precedent.
4. Se partit ioneaz a tabloul n jurul medianei medianelor x, utiliz and o
versiune modicat a a algoritmului Partitie. Fie k elemente din prima
parte a partit ion arii.
5. Se utilizeaz a recursiv select ie pentru a g asi al ilea cel mai mic element
din partea inferioar a (dac a i k), sau al (ik)lea cel mai mic element
din partea a doua a partit iei (pentru i > k).

In [2] se arat a c a se ajunge la o complexitate T(n) = O(n).


88
9.6 Heapsort
Fie vectorul:
v = 16 14 10 8 7 9 3 2 4 1
1 2 3 4 5 6 7 8 9 10
Arborele atasat este cel din Figura 9.2 (a se revedea sect iunea 4.5.2, pa-
gina 34). Acest arbore are ad ancimea de log
2
n|.
14 10
8
2 4
9 3
16
7
1
Figura 9.2: Arborele atasat vectorului v
O structur a c areia i se poate pune n corespondent a un arbore binar
echilibrat se numeste HeapMax, dac a oricare nod are o valoare mai mare
dec at oricare din ii s ai. Dac a orice nod are valoarea mai mic a dec at oricare
dintre i, atunci structura se numeste HeapMin.
Algoritmul de heapicare a unui vector cu n elemente ncep and de la a
i-a component a este:
Heapify(a, n, i)
imax = i
repet a
i = imax
l = 2 i
r = l + 1
dac a l n si a(l) > a(i) atunci
imax = l
sf arsit dac a
dac a r n si a(r) > a(imax) atunci
imax = r
sf arsit dac a
dac a i ,= imax atunci
a(i) a(imax)
89
sf arsit dac a
p an a c and i = imax
Return
Algoritmul pentru costruct ia unui heap este urm atorul:
ConstruiesteHeap(a, n)
pentru i = [n/2], 1, 1
Heapify(a, n, i)
sf arsit pentru
Return
Fie sirul:
a = 4 1 3 2 16 9 10 14 8 7
1 2 3 4 5 6 7 8 9 10
Evolut ia arborelui la apelul ConstruiesteHeap(a, 10) este ar atat a n Figura
9.6
Complexitatea: pentru un nod de n alt ime h, complexitatea algoritmu-
lui Heapify este de (h). Se poate ar ata c a pentru un heap cu n noduri
exist a cel mult
n
2
h+1
| noduri de n alt ime h. Deci timpul de execut ie pentru
ConstruiesteHeap este:
T(n) =
log
2
n

h=0
_
n
2
h+1
_
O(h) = O
_
_
n
log
2
n

h=0
h
2
h
_
_
Dar
log
2
n

h=0
h
2
h

h=0
h
2
h
=
1/2
(1 1/2)
2
= 2
Deci timpul de execut ie pentru algoritmul ConstruiesteHeap este O(n).
Folosim cei doi algoritmi de mai sus pentru sortare n modul urm ator:
HeapSort(a, n)
ConstruiesteHeap(a, n)
pentru i = n, 2, 1
a(1) a(i)
Heapify(a, i 1, 1)
sf arsit pentru
Return
Sortarea cu HeapSort se face cu complexitatea O(n) + nO(log
2
n) =
O(nlog
2
n). Deoarece sortatea folosind comparat ii are complexitatea infe-
rioar a (nlog
2
n) (sect iunea 8.4), rezult a c a algoritmul Heapsort are com-
plexitatea (nlog n).
90
2
14 8 7
3
4
1
16 10 9 i
(a) i = 5
2
14 8 7
3
4
1
16 10 9
i
(b) i = 4
2 7
3
4
1
16 10 9 14
8
i
(c) i = 3
2 7
10
4
1
16 3 9 14
8
i
(d) i = 2
2 1
3
4
16
7 10 9 14
8
i
(e) i = 1
1
3
16
14
7 10 9 8
4 2
(f) Heap-ul dup a terminarea algorit-
mului
Figura 9.3: Obt inerea unui maxheap din sirul (4, 1, 3, 2, 16, 9, 10, 14, 8, 7).
91
Exemplu: e sirul: a = (4, 1, 3, 2, 10, 7, 8, 9, 6, 5). Dupa apelul procedurii
ConstruiesteHeap(a, 10) se obt ine heap-ul din Figura 9.5(a). Pentru apelurile
Heapify(a, i 1, 1) (i = n, n 1, . . . , 2) evolut ia este dat a n Figurile 9.5(b)-
9.5(j) (sau pus n evident a prin detasare elementele care nu vor mai face
parte din heap).
Rezultatul sort arii sirului a este: a = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10).
Heapsort este un excelent algoritm de sortare, dar o implementare bun a
a QuickSortului duce la sort ari mai rapide. Heapul este ns a foarte util n
t inerea n evident a dinamic a a cozilor de priorit at i unde o complexitate de
n care sar putea obt ine printrun algoritm cu insert ie este nlocuit a cu o
complexitate de log n p astr and coada ntrun heap.
9.7 Algoritmi de sortare n timp liniar
Exist a algoritmi de sortare a c aror complexitate este mai mic a dec at cea
teoretic a de (nlog
2
n), dar pentru situat ii speciale ale sirului. Astfel, dac a
sirul este constituit din numere ntregi pozitive (sau m acar ntregi), sau dac a
ele sunt numere distribuite uniformntrun interval, sau lund n considerare
cifrele numerelor din sir se pot da diferit i algoritmi de complexitate liniar a
pentru sortare.
9.7.1 Algoritmul sortarii prin numarare (CountSort)
Un astfel de algoritm este algoritmul de sortare prin num arare numit
CountSort. Fie (x(i))
i=1,n
un sir de numere naturale strict pozitive si k
maximul acestui sir. Sortarea prin num arare const an g asirea a c ate elemente
sunt mai mici dec at x(i) (pentru ecare i); n acest fel vom sti pe ce pozit ie
trebuie s a se ae x(i) n sirul sortat (dac a sunt m elemente mai mici dec at
x(i), atunci el ar trebui s a se ae pe pozit ia m + 1 n sirul sortat).
Consider am sirul init ial x = (x(1), x(2), . . . , x(n)); y = (y(1), y(2), . . . , y(n))
va sirul sortat, iar c = (c(1), c(2), . . . c(k)) este un sir ajut ator.
CountSort(x, n, y, k)
pentru i = 1, k
c(i) = 0
sf arsit pentru
pentru j = 1, n
c(x(j)) = c(x(j)) + 1
sf arsit pentru
pentru i = 2, k
c(i) = c(i) +c(i 1)
92
6
2 4 1
8 9
5 3 7
10
(a) Dup a apelul proce-
durii Heapify
4
2 1 10
8 6
5 3 7
9
(b) i = 10
4
2 9 10
7 6
5 3 1
8
(c) i = 9
4
8 9 10
3 6
5 2 1
7
(d) i = 8
4
8 9 10
3 5
2 7 1
6
(e) i = 7
1
8 9 10
3 4
2 7 6
5
(f) i = 6
1
8 9 10
3 2
5 7 6
4
(g) i = 5
4
8 9 10
1 2
5 7 6
3
(h) i = 4
4
8 9 10
3 1
5 7 6
2
(i) i = 3
4
8 9 10
3 2
5 7 6
1
(j) i = 2
Figura 9.5: Evolut ia sirului si a heapului n subalgoritmul Heapsort.
93
sf arsit pentru
pentru j = n, 1, 1
y(c(x(j))) = x(j)
c(x(j)) = c(x(j)) 1
sf arsit pentru
Return
Exemplu: x = (3, 6, 4, 1, 3, 4, 1, 4), k = 6.
- elementele lui c sunt init ializate cu 0:
c = (0, 0, 0, 0, 0, 0)
- pentru i de la 1 la k, pe pozit ia i din c obt inem num arul de elemente
egale cu i n sirul x:
c = (2, 0, 2, 3, 0, 1)
- pentru i = 2, k, pe pozit ia i a sirului c se obt ine c ate elemente mai mici
sau egale cu i sunt n sirul x:
c = (2, 2, 4, 7, 7, 8)
- pentru j = n, 1, cu pasul -1, se a a componentele sirului y sortat:
y = (1, 1, 3, 3, 4, 4, 4, 4, 6)
Complexitatea algoritmului CountSort este (n+k). Dac a k = O(n) (adic a
exist a o constant a c astfel nc at pentru orice n sucient de mare, s a avem
k < cn), atunci complexitatea algoritmului de sortare prin num arare este
(n).
9.7.2 Sortare pe baza cifrelor
S a presupunem c a avem un sir de numere naturale, av and toate acelasi
num ar d de cifre (dac a nu, atunci un num ar se poate completa cu zerouri
nesemnicative p an a c and atinge num arul maxim de cifre din sir). Se poate
face ordonarea sirului de numere n felul urm ator: se porneste de la cifra cea
mai put in semnicativ a (ultima cifr a) si se sorteaz a elementele pe baza aces-
tei informat ii, obt in anduse o alt a ordine (un alt sir). Se porneste de al acest
ultim sir generat si se sorteaz a elementele dup a urm atoarea cifr a mai put in
semnicativ a (penultima cifr a), pentru care se face sortarea elementelor; si
asa mai departe, n nal f ac anduse sortarea dup a cea mai semnicativ a cifr a
(prima cifr a). Esent ial este ca dac a sortarea se face dup a cifra i (numerotarea
94
cifrelor o consider am de la st anga spre dreapta, de la cifra cea mai semni-
cativ a la cea cea mai put in semnicativ a), atunci se pleac a de la ordinea
obt inut a anterior pentru cifra i +1 (1 i < d); n al doilea r and, algoritmul
care este folosit pentru sortarea cifrelor trebuie s a aibe urm atoarea proprie-
tate: dac a ntrun sir x = (x(1), . . . , x(n)) avem c a x(i) = x(j) si i < j, prin
sortare se ajunge ca x(i) s a e repartizat pe pozit ia i

, x(j) s a e repartizat
pe pozit ia j

, iar i

< j

(spunem c a algoritmul de sortare este stabil ).

In pseudocod, algoritmul este:


OrdonarePeBazaCifrelor(a, d)
pentru i = d, 1, 1
sorteaz a stabil tabloul a dup a cifra i
sf arsit pentru
Return
Analiza algoritmului depinde n mod evident de complexitatea algoritmului
prin care se face sortarea pe baza unei cifre. De exemplu, dac a numerele sunt
n baza b, se poate folosi sortarea prin num arare din sect iunea precedent a
(care este stabil). Pentru ecare cifr a dup a care se face sortarea avem timpul
(n + b), iar pentru sortarea complet a (ciclul pentru) complexitatea este
(d(n + b)). Dac a d este constant si b = O(n), atunci complexitatea este
liniar a.
9.7.3 Sortare pe grupe
Pentru algoritmul prezentat aici, n ipoteza n care numerele sunt uniform
distribuite (dac a consider am intervalul dat de minimul si maximul din sir si
dac a mp art im acest interval n k subintervale de lungime egal a, atunci sansa
ca un num ar oarecare din sir s a se g aseasc a n oricare din cele k subintervale
este aceeasi; altfel spus, nu exsite zone n care numerele s a se concentreze n
num ar mult mai mare dec at n alte regiuni de aceeasi dimensiune), se poate
da un algoritm care n medie are complexitatea (n).
Vom considera f ar a a restr ange generalitatea c a numerele sunt n inter-
valul [0, 1) (dac a nu sunt, atunci putem proceda astfel: determin am min =
min x(i), i = 1, n si max = max x(i), i = 1, n; se efectueaz a x(i) = x(i)min,
pentru i = 1, n - n acest fel se aduc numerele n intervalul [0, max min];
apoi se face mp art irea x(i) = x(i)/(max min + 1), prin care se aduc nu-
merele la intervalul [0, 1); dup a sortare se fac operat iile inverse, n ordinea
nmult ire, adunare). principiul algoritmului const a n a mp art i intervalul
[0, 1] n n intervale egale si s a introducem cele n numere n cele n grupe.
Dac a numerele sunt uniform distribuite, nu ar trebui s a apar a diferent e mari
ntre grupe, din punct de vedere a c ate numere cont in. Se sorteaz a numerele
95
din ecare grup a, dup a care se trece prin ecare grup a si se obt ine ordinea
cresc atoare.
Algoritmul de mai jos consider a c a ecare grup a este implementat a ca o
list a nl ant uit a. Pentru subintervalul (k
1
n
, (k + 1)
1
n
), 0 k < n vom avea
lista nl ant uit a b(k).
SortarePeGrupe(a, n)
pentru i = 1, n
insereaz a a(i) n lista b (n a(i)|)
sf arsit pentru
pentru i = 0, n 1
Sorteaz a lista b(i) folosind sortarea prin insert ie
sf arsit pentru
Concateneaz a listele b(0), b(1), . . . , b(n)
Return
Plec and de la proprietatea c a numerele sunt uniform distribuite, se arat a n
[2] c a timpul mediu pentru sortarea pe grupe este O(n).
9.8 Rezumat
Not iunea de statistic a de ordine generalizeaz a pe cele de minim, maxim,
median a. Selectarea celei de a i-a statistici de ordine se pate realiza n timp
liniar. Pentru cazuri particulare ale vectorilor care se sorteaz a, se pot folosi
algoritmi liniari (se dep aseste deci bariera de (nlog n) demonstrat a pentru
algoritmi care lucreaz a exclusiv pe baza comparat iilor).
9.9 Exercit ii (rezolvarile la pagina 83)
1. Descriet i un algoritm care, ind dat a o mult ime S de n numere ntregi
si distincte si un ntreg pozitiv k n, determin a cele k numere care
sunt cele mai apropiate de mediana lui S.
2. Fie a[1 . . . n], b[1 . . . n] dou a siruri sortate. Scriet i un algoritm perfor-
mant care g aseste mediana celor 2n numere.
3. Fiind dat a o mult ime de n numere, dorim s a g asim cele mai mari i
numere n ordinea sortat a, folosind un algoritm bazat pe comparat ii.
S a se scrie mai multe variante si s a se compare din punct de vedere al
complexit at ii.
96
4. S a se modice algoritmul CountSort astfel nc at s a sorteze si siruri
cont in and numere ntregi negative.
97
98
Capitolul 10
Metoda Greedy
10.1 Obiective
Capitolul va introduce o nou a metod a de rezolvare a problemelor. Ea va
ar ata cum se abordeaz a problemele pentru care solut ia sse poate construi
prin alegeri ale componentelor, alegeri asupra c arora nu se revine. Se doreste
a se exemplica demonstrarea corectitudinii algoritmilor (f ar a de care acesta
ar doar o euristic a). Probleme clasice, ale c aror rezultate se pot folosi
n cazuri mai generale sunt enunt ate si rezolvate (sau sunt f acute trimiteri
bibliograce).
10.2 Prezentare generala
Metoda Greedy este o metod a de elaborare a algoritmilor ce determin a
x

X ce veric a o condit ie dat a C. Exemplul semnicativ este cel al proble-


melor de optimizare n care se determin a x

ce minimizeaz a sau maximizeaz a


o funct ie obiectiv. S a presupunem c a solut ia x

are mai multe componente si


c a spat iul solut iilor X este cunoscut. De asemenea presupunem c a C ofer a un
criteriu de select ie prin care se pot alege valori pentru componentele solut iei.
Modul de rezolvare al problemelor dat de strategia Greedy este acela de
construct ie a solut iei component a cu component a. Se pleac a de la solut ia
vid a si la ecare pas al algoritmului se selecteaz a o valoare pentru o com-
ponent a; dac a aceast a valoare convine, atunci aceasta este pus a n solut ie
pe componenta respectiv a.

Intrun cuv ant, se ia tot ce este bun pentru
construct ia solut iei. Aceast a select ie se face n funct ie de C, valoarea aleas a
asigur and la pasul respectiv cea mai bun a continuare n spiritul lui C.
Strategia descris a anterior are un posibil inconvenient dat de modul de
select ie. Dac a la ecare pas alegem cea mai bun a valoare n spiritul lui C,
99
nu este necesar ca n nal s a obt inem solut ia optim a c autat a. Este ceea ce
se nt ampl a n problemele de optimizare: o succesiune de cresteri poate s a
duc a la un optim local si nu la cel global c autat. Dac a se reuseste s a se
demonstreze c a solut ia g asit a veric a condit ia C atunci am obt inut o solut ie
pentru problem a.

In caz contrar, dac a solut ia g asit a este sucient de aproape
de solut ia optim a spunem c a avem o solut ie Greedy eurisitc a.
Cele prezentate anterior pot descrise de procedura Greedy de mai
jos:
Greedy(x)
x =
c at timp solut ia nu este complet a
selecteaz a o valoare a
dac a valoarea a convine atunci
x = x a
sf arsit dac a
sf arsit c at timp
Return

In concluzie o problem a se rezolv a prim metoda Greedy respect and eta-


pele:
1.

In funct ie de condit ia C se g aseste un criteriu de select ie a valorilor
2. Se elaboreaz a algoritmul respect and schema anterioar a
3. Se demonstreaz a corectitudinea alegerii f acute ar at and c a solut ia x

respect a C.

In caz contrar se ncearc a s a se determine c at de departe
este solut ia g asit a de algoritm fat a de solut ia c autat a.
Complexitate solut iei Greedy este dat a de complexitatea select iei valorii
la ecare pas si de num arul de select ii f acut de c atre algoritm.

In general,
metodele de tip Greedy sunt metode de complexitate polinomial a mic a, ceea
ce este o justicare pentru utilitatea metodei.
Exemplifc am metoda anterioar a prin c ateva probleme clasice.
10.3 Submult imi de suma maxima
Enunt ul problemei: Dac a x = (x(i), i = 1, n) reprezint a o mult ime de
elemente atunci s a se determine submult imea y = (y(i), i = 1, k) de sum a
maxim a.
Date de intrare: n - dimensiunea vectorului; x = (x(i), i = 1, n), mult imea
de elemente;
100
Date de iesire: k - num arul de elemente al submult imii y = (y(i), i = 1, k)
- submult imea de elemente.
Problema anterioar a este o problem a clasic a de optimizare care se rezolv a
prin Greedy. Submult imea c autat a este o solut ie a problemei de optimizare
max
_

yY
y[ ,= Y X
_
Simplitatea problemei de optimizare ofer a un criteriu de selet ie foarte simplu
bazat pe observat iile:
1. dac an mult imea x sunt numere pozitive, ad augarea unuia la submult imea
y conduce la cresterea sumei; g asim astfel submult imea y format a din
toate elementele pozitive;
2. n cazul n care toate elementele sunt negative, submult imea y este
format a cu cel mai mare element.
Ca atare, la ecare pas alegem n y elementele pozitive. Dac a nu sunt,
atunci alegem n y elementul maximal.
SumaMax(n, x, k, y)
k = 0
pentru i = 1, n
dac a x(i) 0 atunci
k = k + 1
y(k) = x(i)
sf arsit dac a
sf arsit pentru
dac a k = 0 atunci
max = x(1)
pentru i = 2, n
dac a x(i) > max atunci
max = x(i)
sf arsit dac a
sf arsit pentru
k = 1
y(k) = max
sf arsit dac a
Return
Se observ a c a ecare din cele n select ii are complexitate (1), g asind n nal
o complexitate pentru algoritm de (n).
101
Teorema 2 (Corectitudine). Submult imea y determinat a de c atre algoritm
are suma elementelor maxim a fat a de toate submult imile lui x.
Demonstrat ie. Not am sum(x) suma elementelor din x. Fie z submult imea
de sum a maxim a. Vom ar ata c a y = z trat and cele dou a cazuri.
1.

In x nu sunt elemente pozitive. Atunci sum(z) z(1) max x(i), i = 1, n =
sum(y); din proprietatea lui z rezult a sum(z) = sum(y) si deci y este
submult ime de sum a maxim a.
2.

In x sunt elemente pozitive. Atunci urm atoarele armat ii conduc la
egalitatea y = z:
(a) z nu cont ine elemente negative. Dac a z cont ine elementul a ne-
gativ, atunci sum(z) = sum(z a) + a < sum(z a) fals,
pentru c a z este de sum a maximal a;
(b) z cont ine toate elementele pozitive. Dac a z nu cont ine elementul
strict pozitiv a atunci sum(z) < sum(z +a) fals.
R am ane c a z nu cont ine elemente negative si cont ine toate pozitivele,
deci y = z
10.4 Arborele Human
Enunt ul problemei: dac a S = s
1
, s
2
, . . . , s
n
este o mult ime de semnale
si p = (p(i), i = 1, n) este vectorul de probabilitate asociat lui S, atunci s a se
determine codul de lugime optim a asociat lui S.
Date de intrare: n - num arul de semnale, p = (p(i), i = 1, n) - vectorul de
probabilit at i.
Date de iesire: codul optim reprezentat sub form a arborescent a.
Un exemplu de cod care simuleaz a optimalitatea este alfabetul Morse.
O caracteristic a a acestui cod este aceea c a simbolurile cele mai probabile
sunt codicate cu mai put ine caractere, astfel nc at costul transmisiei s a e
c at mai mic.

Inainte de a da rezolvarea problemei, este bine s a facem o
prezentare a c atorva not iuni de teoria codurilor.
Un cod binar este o aplicat ie injectiv a : S 0, 1
+
. Lungimea me-
die a codului n funct ie de sistemul de probabilit at i este denit a de L() =

n
i=1
[(s
i
)[p(i) ([a[ este num arul de caractere a lui a). Un cod este op-
tim dac a minimizeaz a lungimea medie. Dac a : S 0, 1
+
este un cod
instantaneu, atunci arborele m-ar asociat se noteaz a cu T

si veric a:
102
- are at atea frunze c ate semnale are S;
- drumul n arbore de la r ad acin a la frunz a s S d a codicarea (s)
prin concatenarea marcajelor muchiilor.
Lungimea medie a unui cod poate transportat a ntro lungime medie a
arborelui asociat, dat a de L() =

n
i=1
[(s
i
)[p(i) =

n
i=1
niv
T

(s
i
)p(i) =
L(T

).
Numim arbore Human asociat sistemului de numere reale p = (p(i), i =
1, n) arborele ce minimizeaz a L(T) =

n
i=1
niv
T
(s
i
)p(i).
Vom lucra cu structuri arborescente reprezentate nl ant uit n care n
c ampul de informat ie avem probabilitatea sau frecvent a simbolului.
P an a n acest moment nu am spus nimic despre modul de aplicare al
stretegiei Greedy. R am ane armat ia f acut a init ial c a semnalele cele mai
probabile sunt codicate cu c at mai put ine caractere.
Algoritmul lui Human construieste codul optim prelucr and o p adure
dup a regulile:
- init ial p adurea este format a din v arfuri izolate reprezent and semnalele.
- se repet a o execut ie dat a de:
1. se selecteaz a arborii p adurii av and informat ia cea mai mic a;
2. se conecteaz a cei doi arbori alesi ntrunul singur printro r ad acin a
comun a av and informat ia suma informat iilor din arbori
Proceura Human determin a arbore minim.
Human(n, s, p, rad)
pentru i = 1, n
s(i) LIBERELIBERE este zona din care se fac aloc ari de memorie
LS(s(i)) =
LD(s(i)) =
INFO(s(i)) = p(i)
sf arsit pentru
Sort(n, s)
pentru i = n, 2, 1
x LIBERE
LS(x) = s(i)
LD(x) = s(i 1)
INFO(x) = p(i) +p(i 1)
j = i 1
pentru j > 0 si INFO(x) > INFO(s(j))
103
s(j + 1) = s(j)
j = j 1
sf arsit pentru
s(j + 1) = x
sf arsit pentru
rad = s(1)
Return

In algoritmul precedent procedura Sort determin a o sortare a semnalelor


s(i), i = 1, n descresc ator dup a p(i).
Teorema 3 (Complexitate). Algoritmul Human are complexitatea (n
2
).
Demonstrat ie. Complexitatea algoritmului este dat a de complexitatea sort arii
si de complexitatea selet iilor repetate. Complexitatea sort ariiu este (nlog n).
Select iile repetate ce se fac utilizeaz a principiul inser arii directe. Pentru a in-
sera semnalul pn structura (s(j), j = 1, i1) facem cel mult i1 comparat ii,
g asind n nal un num ar de

n
i=1
i 1 = n(n 1)/2 = (n
2
) comparat ii.
Rezult a complexitatea din enunt .
Teorema 4 (Corectitudine). Algoritmul Human genereaz a un cod optim
n raport cu probabilit at ile p = (p(i), i = 1, n).
Demonstrat ie. Vom folosi n demonstrat ie urm atoarele notat ii:
H = H(p
1
, . . . , p
n
) - arborele dat de algoritmul lui Human
T = T(p
1
, . . . , p
n
) - arborele optim, unde p(i) = p
i
, i = 1, n.
Despre arborele optim se poate ar ata:
p
i
< p
j
rezult a niv
T
(s
i
) > niv
T
(s
j
)
exist a un arbore optim n care cele mai put in probabile semnale sunt
frat i.
S a presupunem c a s
i
si s
j
sunt semnalele cu probbabilitatea cea mai mic a si
c a prin unirea celor dou a semnale se creeaz a un nou semnal notat s
i,j
.
Algoritmul Human construieste arborele binar dup a regula recursiv a
dat a de gura 10.1. Avem urm atorul calcul de lungime:
L(H) =
n

i=1
niv(s
i
) =
n2

i=1
niv(s
i
)p(i) +niv(s
n1
)p(n 1) +niv(s
n
)p(n)
104
s
n1
s
1
s
n
H( ,..., ) s
1
s
n1,n
H( ,..., )
s
n
=>
Figura 10.1: Crearea unui nod pe baza semnalelor cele mai put in probabile
si deoarece niv(s
n1
) = niv(s
n
) rezult a c a:
L(H) =
n2

i=1
niv(s
i
)p(i) + (p(n 1) +p(n))niv(s
n1
) 1 +
+ p(n 1) +p(n) =
=
n2

i=1
niv(s
i
))p(i) +p(n 1, n)niv(s
n,n1
) +p(n 1) +p(n)
g asindn nal L(H(p(1), . . . , p(n))) = L(H(p(1), . . . , p(n1)+p(n)))+p(n
1) +p(n)
Printrun calcul analog se arat a c a si arborele optim ce are pe s
n=1
si s
n
veric a:
L(T(p(1), . . . , p(n))) = L(T(p(1), . . . , p(n 1) +p(n))) +p(n 1) +p(n).
Demonstrat ia optimalit at ii se va face prin induct ie dup a n.
Pentru n = 2 algoritmul ne ofer a H(p(1), p(2)) care codic a pe s
1
cu 0 si
pe s
2
cu 1, ceea ce nseamn a c a este un cod optim.
S a presupunem c a avem proprietatea adev arat a pentru n semnale si anume
codul Human asociat semnalelor s
1
, . . . , s
n
este optim.
Fie p = (p(i), i = 1, n+1) un sistem cu n+1 probabilit at i n care p(n1)
si p(n 2) sunt cele mai mici dou a numere din sirul p. Aplic and formulele
g asite anterior obt inem:
L(H(p(1), . . . , p(n), p(n + 1))) = L(H(p(1), . . . , p(n) +p(n + 1)) +p(n) +p(n + 1))
L(T(p(1), . . . , p(n), p(n + 1))) = L(T(p(1), . . . , p(n) +p(n + 1)) +p(n) +p(n + 1))
Pentru c a arborele Human codic a n semnale optim vom g asi:
L(T(p(1), . . . , p(n) +p(n + 1))) L(H(p(1), . . . , p(n) +p(n + 1)))
105
Din relat iile de mai sus vom g asi:
L(T(p(1), . . . , p(n) +p(n + 1))) +p(n) +p(n + 1) L(H(p(1), . . . , p(n)
+p(n + 1))) +p(n) +p(n + 1)
si deci L(T(p(1), . . . , p(n), p(n + 1))) L(H(p(1), . . . , p(n), p(n + 1))) Din
optimalitatea lui T vom g asi:
L(T(p(1), . . . , p(n), p(n + 1))) = L(H(p(1), . . . , p(n), p(n + 1)))
deci H este un arbore optim.
10.5 Interclasare optimala
Enunt ul problemei: D anduse o mult ime de vectori sortat i cresc ator s a
se elaboreze un algoritm care determin a interclasarea acestora cu num arul
minim de comparat ii.
Date de intrare: n - num arul de vectori, nr = (nr(i), i = 1, n) - num arul
de elemente din ecare vector, x(i) = (x(i, j), j = 1, nr(i)) sirul de vectori.
Date de iesire: y = (y(i), i = 1, nr(1) + +nr(n)), vectorul interclasat.
S a presupunem c a interclasarea a doi vectori se face prin algoritmul de
interclasare direct a. Dac a dimensiunile vectorilor sunt m, respectiv n atunci
num arul de comparat ii este cel mult m + n 1.

In general aceast a inter-
clasare nu este una optim a dar facem presupunerea c a orice doi vectori se
interclaseaz a folosind interclasarea direct a.

In funct ie de modul de intercla-
sare al vectorilor de interclasare se obt in diferite solut ii cu num ar distinct de
comparat ii. Este deci esent ial s a g asim o ordine care conduce c atre num arul
minim de comparat ii.
Vom nota x+y vectorul obt inut prin interclasarea lui x cu y. Dac a avem
4 vectori x, y, z, t cu respectiv 10, 20, 30 si 40 de elemente atunci:
interclasarea ((x+y)+z)+t se face cu (10+20-1)+(30+30-1)+(60+40-
1)=187 comparat ii
inteclasarea ((z +t) +y) +x se face cu (30+40-1)+(70+20-1)+(90+10-
1)=257 comparat ii
deci prima strategie este mai bun a dec at a doua (de fapt, este chiar cea
optim a). Din acest exemplu se observ a c a maxim a 40 se reg aseste n toate
interclas arile ce se efectueaz a conduc and al un num ar mare de comparat ii.
Idea ar ca vectorii cu dimensiuni mici s a se se interclaseze prima dat a astfel
106
nc at aceste valori mici s a apar a n sumele de interclasare. Deci la ecare pas
vom selecta pentru interclasare vectorii de dimensiune minim a.
Pentru ca select ia s a se fac a c at mai usor psstr am vectorii n matricea x
astfel nc at vectorul nr s a e sortat descresc ator.

In acest caz se selecteaz a
ultimii 2 vectori din matricea x. Dup a realizarea interclas arii noul vector se
insereaz a nmatricea x folosind diferite tehnici: insert ia direct a sau insert ia
binar a. Se repet a procesul p an a c and r am ane un singur vector.
InterOpt(n, nr, x, z)
Sortare(n, nr, x)
pentru i = n 1, 1, 1
Inter(nr(i + 1), x(i + 1), nr(i), x(i), y)
n1 = nr(i)
n2 = nr(i + 1)
j = i 1
c at timp j > 0 si n(j) > n1 +n2
pentru k = 1, nr(j)
x(j + 1, k) = x(j, k)
sf arsit pentru
nr(j + 1) = nr(j)
j = j 1
sf arsit c at timp
pentru k = 1, n1 +n2
x(j + 1, k) = y(k)
sf arsit pentru
nr(j + 1) = n1 +n2
sf arsit pentru
Return

In procedura anterioar a procedura Sortare determin a rearanjarea elemente-


lor (liniilor) matricii x descresc ator n funct ie de vectorul nr iar Inter face
interclasare direct a a doi vectori.
Pentru a analiza corectitudinea algoritmului denim printro formul a re-
cursiv a arborele asociat unei strategii de interclasare:
1. Arborele asociat unui vector este format dintrun nod ce are ca informat ie
num arul de elemente ale vectorului;
2. arborele asociat interclas arii a doi vectori x(1) si x(2) este reprezentat
grac n gura 10.2;
3. Dac a T
1
este arborele asociat sirului de vectori x(i
1
), . . . , x(i
k
) iar T
2
este arborele asociat sirului de vectori x(i
k+1
), . . . , x(i
n
) atunci T din -
gura 10.3 este arborele asociat prin strategie sirului de vectori x(i
1
), . . . , x(i
n
).
107
nr(1) nr(2)
nr(1)+nr(2)
T=
Figura 10.2: Arbore construit pe baza a doi vectori
T
1
T
2
T=
Figura 10.3: Arbore construit pe baza a dou a subsecvent e de vectori.
Arborele asociat unui sir de vectori veric a:
- are at atea frunze c at i vectori sunt n sirul de vectori;
- informat ia atasat a unui nod este suma dimensiunilor vectorilor din su-
barborii st ang si drept i ai nodului;
- dac a un vector apare pe nivelul p atunci termenii sirului apar n exact
p interclas ari;
- num arul total de comparat ii dat de strategie este L(T) =

n
i=1
nr(i)
niv(i) n + 1 unde niv(i) este nivelul n T al vectorului x(i)
Teorema 5 (Corectitudine). Algoritmul InterOpt determin a interclasarea
vectorilor x(i), i = 1, n cu num ar minim de comparat ii realizate din inter-
clas arile directe.
Demonstrat ie. Se observ a c a arborele asociat unei strategii de interclasare ete
arborele Human asociat numerelor nr(1), . . . , , nr(n). Algoritmul anterior
repet a modul de construct ie al arborelui Human deci suma

n
i=1
nr(i)
niv(i) este minim a si implicit L(T) este minim. Rezult a c a strategia de
interclasare este optim a.
108
Teorema 6 (Complexitate). Dac a L este num arul de comparat ii rezultat
din interclas arile directe, atunci algoritmul InterOpt are complexitatea (L+
n
2
).
Demonstrat ie. Complexitatea algoritmului este dat a de num arul de comparat ii
f acut de interclas arile directe si de num arul de comparat ii dat de p astrarea
structurii x.

In primul caz num arul este n. Pentru cel de al doilea caz se
observ a c a inserarea direct a foloseste cel mult i 1 comparat ii pentru ou-
nerea sirului y n structura x. G asim un num ar total de
n

i=2
(i 1) = (n
2
)
comparat ii.
Dac a se utilizeaz a o inserare binar a n structura x atunci complexitatea
algoritmului devine (L +nlog n).
10.6 Rezumat
Metoda Greedy nseamn a construirea pas cu pas a solut iei, prin alegerea
componentelor pe baza unei strategii deduse din enunt ul problemei. Spre de-
osebire de metoda Backtracking, nu se revine asupra unei decizii. Ea poate
folosit a si pentru elaborarea unor algoritmi euristici (care nu determin a op-
timul, sau pentru care o demonstrat ie de corectitudine nu este dat a). Pentru
ecare rezolvare greedy trebuie s a se ncerce justicarea prin metode mate-
matice a optimalit at ii solut iei.
10.7 Exercit ii (rezolvarile la pagina 99)
1. Dac a x = (x(i), i = 1, m), y = (y(i), i = 1, n) reprezint a dou a mult imi
de elemente, atunci s a se determine mult imea intersect ie z = (z(i), i =
1, k).
2. D anduse n obiecte de cost c = (c(i), i = 1, n) cu greutatea g =
(g(i), i = 1, n) si un rucsac de capacitate maxim a G, s a se elaboreze un
algoritm de umplere a rucsacului de cost maxim. Un obiect poate pus
n rucsac ntrun anumit procent (problema continu a a rucsacului).
3.

Intro sal a, ntro zi trebuie planicate n spectacole. Pentru ecare
spectacol se cunoaste intervalul n care se desf asoar a: [st, sf). Se cere
s a se planice un num ar maxim de spectacole astfel nc at s a nu se
suprapun a..
109
4. Se dau n numere ntregi nenule b
1
, . . . , b
n
si m numere ntregi nenule
a
1
, . . . a
m
, n m. S a se determine o submult ime a mult imii B =
b
1
, . . . , b
n
care s a maximizeze valoarea expresiei:
E = a
1
x
1
+a
2
x
2
+ +a
m
x
m
unde x
i
B..
5. O stat ie de servire trebuie s a satisfac a cererile a n client i. Timpul de
servire pentru ecare client este cunoscut: pentru clientul i timpul este
t
i
. S a se minimizeze timpul total de asteptare
T =
n

i=1
(timpul de asteptare pentru clientul i)
110
Capitolul 11
Programare dinamic a
11.1 Obiective

In acest capitol se prezint a metoda program arii dinamice. Dup a parcur-


gerea materialului, cititorul al trebui s a e familiarizat cu tr as aturile generale
ale unei probleme pentru care se apeleaz a la programare dinamic a si s a si
nsuseasc a strategia general a de rezolvare a unei probleme folosind aceast a
metod a.
11.2 Prezentare generala
Programarea dinamic a, asemenea metodelor Divide et Impera, rezolv a
problemele combin and solut iile unor subprobleme. Programarea n acest
context se refer a la o metod a tabelar a si nu la scrierea unui cod pentru cal-
culator. Am v azut, n capitolul referitor la divide et impera, c a algoritmii
construit i cu aceast a metod a partit ioneaz a problema n subprobleme indepe-
nedente pe care le rezolv a n general recursiv, dup a care combin a solut iile lor
pentru a obt ine solut ia problemei init iale. Spre deosebire de aceast a abor-
dare, programarea dinamic a este aplicabil a atunci c and aceste subprobleme
nu sunt independente, adic a au n comun subprobleme
1
.

In general, programarea dinamic a se aplic a problemelor de optimizare.


Fiecare solut ie are o valoare si se doreste determinarea solut iei optime (minim
sau maxim). O asemenea solut ie numeste solut ie optim a a problemei, prin
contrast cu valoarea optim a, deoarece pot exista mai multe solut ii care s a
realizeze valoarea optim a.
1
Termenul dinamic a n acest conext nu are nimic n comun cu alocarea dinamic a,
pomenit a n capitolul 4.
111
Dezvoltarea unui algoritm bazat pe metoda program arii dinamice poate
mp art it a ntro secvent a de patru pasi:
1. Caracterizarea structurii unei solut ii optime
2. Denirea recursiv a a valorii unei solut ii optime
3. Calculul valorii unei solut ii optimentro manier a bottomup (plec and
de la subprobleme de dimensiune mic a si ajung and la unele de dimen-
siuni din ce n ce mai mari)
4. Construirea unei solut ii optime din informat ia calculat a.
Pasii 13 sunt baza unei abord ari de tip programare dinamic a. Pasul 4 poate
omis dac a se doreste doar calculul valorii optime.

In vederea realiz arii
pasului 4, deseori se p astreaz a informat ie suplimentar a de la execut ia pasului
3, pentru a usura construct ia unei solut ii optimale.
11.3

Inmult irea unui sir de matrici
Primul nostru exemplu de programare dinamic a este un algoritm care
rezolv a problema nmult irii unui sir de matrici. Se d a un sir A
1
, A
2
, . . . , A
n
de n matrice care trebuie nmult ite. Acest produs se poate evalua folosind
algoritmul clasic de nmult ire a unei perechi de matrici ca subalgoritm, o
dat a ce produsul A
1
A
n
este parantezat (aceast a restrict ie este impus a
de faptul c a nmult ire matricilor este operat ie binar a). Un produs de matrici
este complet parantezat dac a este format dintro sigur a matrice sau dac a
este format din factori complet i parantezat i.
Exemplu: produsul A
1
A
2
A
3
A
4
poate complet parantezat n 5 moduri
distincte, astfel:
(A
1
(A
2
(A
3
A
4
)))
(A
1
((A
2
A
3
) A
4
))
((A
1
A
2
) (A
3
A
4
))
((A
1
(A
2
A
3
)) A
4
)
(((A
1
A
2
) A
3
) A
4
)
Modul n care parantez am un sir de matrici poate avea un impact drama-
tic asupra costului evalu arii produsului. S a consider am mai nt ai costul
nmult irii a dou a matrici. Algoritmul standard este dat de urm atoarea pro-
cedur a, descris a n pseudocod. Prin linii si coloane n

telegem num arul de


linii si coloane ale matricilor implicate.
Inmultire(A, n, m, B, p, q, C)
112
dac a m ,= p atunci
scrie( dimensiuni incompatibile! )
altfel
pentru i = 1, n
pentru j = 1, q
C(i, j) = 0
pentru k = 1, m
C(i, j) = C(i, j) +A(i, k) B(k, j)
sf arsit pentru
sf arsit pentru
sf arsit pentru
sf arsit dac a
Return
Dou a matrici se pot nmult i numai dac a num arul de coloane ale primei ma-
trici este egal cu num arul de linii ale celei de a doua matrici, adic a dac a avem
A(n, m) si B(m, q); n acest caz C = AB va avea n linii si q coloane. Timpul
necesar pentru calculul matricei C este dat de num arul de nmult iri scalare,
n m q.
Pentru a ilustra modul n care apar costuri diferite la parantez ari diferite
ale produsului de matrici, s a consider am problema sirului A
1
, A
2
, A
3
. S a
presupunem c a dimensiunile matricilor sunt 10 100, 100 5, 5 50. Dac a
efectu amnmult irile pentru ((A
1
A
2
)A
3
), atunci vom avea 101005 = 5000
nmult iri scalare pentru a efectua (A
1
A
2
), care va o matrice de dimensiune
105, plus alte 10550 = 2500nmult iri pentru a efectua (A
1
A
2
)A
3
, deci
n total rezult a 7500 nmult iri scalare. Pentru parantezarea (A
1
(A
2
A
3
))
vom avea 100 5 50 = 25000 nmult iri scalare pentru a efectua A
2
A
3
,
care va o matrice de dimensiune 100 50, plus alte 10 100 50 = 50000
nmult iri scalare pentru a efectua A
1
(A
2
A
3
). Deci rezult a un num ar de
75000 nmult iri scalare.
Enunt ul formalizat al problemei este: d anduse un sir A
1
, A
2
, . . . , A
n
de
n matrici, unde pentru i = 1, n matricea A
i
are dimensiunle p
i1
p
i
, s a
parantezeze complet produsul A
1
A
2
A
n
astfel nc at s a se minimizeze
num arul de nmult iri scalare.

Inainte de a rezolva problema nmult irii sirului de matrici prin progra-


mare dinamic a, trebuie s a ne asigur am c a vericarea complet a a tuturor
parantez arilor nu duce la un algoritm ecient. Fie P(n) num arul de paran-
tez ari distincte ale unei secvent e de n matrice. O secvent a de n matrice o
putem diviza ntre matricele k si k+1 pentru orice k = 1, . . . , n1si apoi pu-
tem descompune n paranteze, n mod independent, ecare dintre secvent e.
113

In acest fel vom obt ine urm atoarea recurent a:


P(n) =
_
_
_
1 dac a n = 1
n1

k=1
P(k)P(n k) dac a n 2
(11.1)
Numerele dente de (11.1) se numesc numerele lui Catalan si se arat a c a
P(n) =
1
n
C
n1
2n2
, de unde P(n) = (
4
n
n
2
). Num arul de solut ii este exponent ial,
deci ar o strategie slab a.
Primul pasn schema general a a metodei program arii dinamice este dat de
caracterizarea unei solut ii optimale. Pentru problema noastr a descrierea este
f acut a n continuare. Vom face urm atoarea convent ie de notare: matricea
obt inut a n urma procesului de evaluare a produsului A
i
A
i+1
. . . A
j
se va
nota cu A
i...j
. O parantezare optim a a produsului A
1
. . .A
n
mparte produsul
ntre A
k
si A
k+1
pentru un anumit k din intervalul 1 . . . n. Aceasta nseamn a
c a pentru o valoare a lui k, mai nt ai calcul am matricele A
1...k
si A
k+1...n
si apoi
le nmult im pentru a obt ine rezultatul nal A
1...n
. Costul acestei parantez ari
optime este dat de suma costurilor calculului pentru matricele A
1...k
, A
k+1...n
si A
1...n
. Observat ia care trebuie f acut a este c a: parantezarea subsirului
prex A
1
. . . A
k
n cadrul parantez arii optime a produslui A
1
. . . A
n
este o
parantezare optim a pentru A
1
. . . A
k
, pentru c a altfel, dac a am presupune
c a mai exist a o metod a de parantezare mai put in costisitoare a lui A
1
. . . A
k
ar contrazice faptul c a parantezarea pentru A
1
. . . A
n
este optim a. Aceast a
observat ie este valabil a si pentru parantezara lui A
k+1
. . . A
n
. Prin urmare, o
solut ie optim a a unei instant e a unei probleme cont ine solut ii optime pentru
instant e ale subproblemelor.
Al doilea pas n aplicarea metodei program arii dinamice este dat de de-
nirea valorii unei solut ii optime n mod recursiv, n funct ie de solut iile optime
ale subproblemelor.

In cazul problemei nmult irii sirului de matrice, o sub-
problem a const a n determinarea costului minim al unei parantez ari a sirului
A
i
A
i+1
A
j
, pentru 1 i j n. Fie m(i, j) num arul minim denmult iri
scalare necesare pentru a calcula matricea A
i...j
; costul modalit at ilor optime
de calcul al lui A
1...n
va m(1, n). Denit ia recursiv a a lui m(i, j) este dat a
de formula (11.2)
m(i, j) =
_
0 dac a i = j
min
ik<j
m(i, k) +m(k + 1, j) +p
i1
p
k
p
j
dac a i < j
(11.2)
Valorile m(i, j) exprim a costul solut iilor optime ale subproblemelor. Pen-
tru a putea urm ari modul de construct ie a slout iei optime, s a denim s(i, j)
care va cont ine valoarea k pentru care mp art irea produsului A
i
. . . A
j
pro-
duce o parantezare optim a. Aceasta nseamn a c a s(i, j) este egal cu valoarea
lui k pentru care m(i, j) = m(i, k) +m(k + 1, j) +p
i1
p
k
p
j
.
114

In acest moment este usor s a scriem un algoritm recursiv dat de recurent a


(11.2) care s a calculeze costul minim m(1, n) pentru produsul A
1
. . . A
n
. Dar
acest algoritm necesit a timp exponent ial - nu mai bun dec at c autarea com-
plet a a parantez arilor. Observat ia care se impune n acest moment se refer a
la faptul c a avem relativ put ine subprobleme: o problem a pentru ecare ale-
gere a lui i si j ce satisfac 1 i j n, adic a un total de C
2
n
+n = (n
2
).
Un algoritm recursiv poate nt alni ecare subproblem a de mai multe ori pe
ramuri diferite ale arborelui s au de recurent a. Aceast a proprietate de supra-
punere a subproblemelor este a doua caracteristic a a program arii dinamice.

In loc s a calcul am recursiv solut ia recurent ei (11.2), vom aplica pasul al


treilea din schema program arii dinamice si vom calcula costul optimal cu
o abordare bottomup. Algoritmul urm ator presupune c a matricele A
i
au dimensiunile p
i1
p
i
pentru orice i = 1, . . . , n. Intrarea este secvent a
(p
0
, . . . , p
n
) de n+1 elemente. Procedura foloseste un tablou auxiliar m(1 . . . n, 1 . . . n)
pentru costurile m(i, j) si un tablou auxiliar s(1 . . . n, 1 . . . n) carenregistreaz a
acea valoare a lui k pentru care sa obt inut costul optimn calculul lui m(i, j),
conform (11.2).
InmultireMatrici(p, m, s, n)
pentru i = 1, n
m(i, i) = 0
sf arsit pentru
pentru l = 2, n
pentru i = 1, n l
j = i +l 1
m(i, j) =
pentru k = i, j 1
q = m(i, k) +m(k + 1, j) +p
i1
p
k
p
j
dac a q < m(i, j) atunci
m(i, j) = q
s(i, j) = k
sf arsit dac a
sf arsit pentru
sf arsit pentru
sf arsit pentru
Return
Algoritmul completeaz a tabloul mntrun mod ce corespunde rezolv arii pro-
blemei parantez arii unor siruri de matrici din ce n ce mai mari. Relat ia
(11.2) arat a c a m(i, j), costul de calcul al sirului de j i +1 matrici depinde
doar de costurile calcul arii produselor sirurilor de mai put in de j i + 1
matrici. Aceasta nsemna a c a, pentru k = i, i + 1, . . . , j 1, matricea A
i...k
115
este un produs de k i + 1 < j i + 1 matrice, iar matricea A
k+1...j
este un
produs de j k < j i + 1 matrici.

In ciclul pentru i = 1, n algoritmul init ializeaz a m(i, i) = 0 (costul minim


al sirurilor de lungime 1). La prima execut ie a ciclului pentru l = 2.n se
calculeaz a, cu formula (11.2), m(i, i + 1) pentru i = 1, 2, . . . , n 1 (costul
minim al sirurilor de lungime 2). La a doua trecere prin ciclul pentru l = 2, n
se calculeaz a m(i, i + 2), pentru i = 1, 2 . . . , n 2 (costul minim al sirurilor
de lungime 3), etc. La ecare pas, costul m(i, j) calculat in ciclul pentru
k = i, j 1 depinde doar de intr arile m(i, k) si m(k +1, j) ale tabloului, deja
calculate.

In tabelul 11.2 de mai jos este descris a funct ionarea algoritmului pentru
un sir de n = 6 matrici av and dimensiunile date n tabelul 11.1.
Matrice Dimensiune
A
1
30 35
A
2
35 15
A
3
15 5
A
4
5 10
A
5
10 20
A
6
20 25
Tabelul 11.1: Dimensiunile matricelor care se nmult esc
1 2 3 4 5 6 1 2 3 4 5 6
0 15750 7875 9375 11875 15125 0 1 1 3 3 3
0 0 2625 4375 7125 10500 0 0 2 3 3 3
0 0 0 750 2500 5375 0 0 0 3 3 3
0 0 0 0 1000 3500 0 0 0 0 4 5
0 0 0 0 0 5000 0 0 0 0 0 5
0 0 0 0 0 0 0 0 0 0 0 0
Tabelul 11.2: Evolut ia algoritmului pentru matricile din tabelul 11.1.

In
partea st ang a apare matricea m, n partea dreapt a matricea s.

In tablourile m, s sunt utilizate doar elementele de desupra diagonalei


principale. Num arul minim de nmult iri scalare necesare nmult irii acestor
sase matrici este m(1, 6) = 15125. Pentru a calcula cu formula q = m(i, k) +
116
m(k + 1, j) +p
i1
p
k
p
j
pe m(2, 5), proced am ca mai jos:
m(2, 5) =
_
_
_
m(2, 2) +m(3, 5) +p
1
p
2
p
5
= 13000
m(2, 3) +m(4, 5) +p
1
p
3
p
5
= 7125
m(2, 4) +m(5, 5) +p
1
p
4
p
5
= 11375
_
_
_
= 7125
O simpl a examinare a algoritmului conduce la constatarea c a timpul de
execut ie este (n
3
). Desi acest algoritm determin a num arul optim denmult iri
scalare necesare pentru calculul produsului sirului de matrici, acesta nu pre-
zint a n mod direct modul n care se face nmult irea. Pasul 4 al schemei
generale a metodei program arii dinamice urm areste construirea unei solut ii
optime din informat ia disponibil a.

In acest caz particular, vom folosi tabloul s pentru a determina modul


optim de nmult ire a matricilor. Fiecare element s(i, j) cont ine valoarea lui
k pentru care parantezarea optim a a produsului A
i
. . . A
j
mparte produ-
sul ntre A
k
si A
k+1
. Atunci stim c a n produsul nal de calcul al matricel
A
1...n
optimul este A
1...s(1,n)
A
s(1,n)+1...n
.

Inmult irile anterioare pot deter-
minate recursiv, deoarece s(1, s(1, n)) determin a ultima nmult ire matriceal a
din calculul lui A
1...s(1,n)
; analog, s(s(1, n) +1, n) determin a ultima nmult ire
din produsul A
s(1,n)+1,n
.
11.4 Cel mai lung subsir crescator
Problema se enunt an felul urm ator: se d a un sir de numere a = (a(i), i =
1, n). S a se determine cel mai lung subsir cresc ator. Prin subsir se nt elege
un sir a(i
1
), a(i
2
), . . . , a(i
k
), unde 1 i
1
< i
2
< <
k
n (elementele
subsirului nu sunt neap arat adiacente n sirul init ial).
Dac a am considera toate subsirurile de elemente, atunci acestea ar n
num ar de 2
n
1. Chiar si dac a am genera prin backatracking subsirurile
cresc atoare ale lui a, tot la complexitate exponent ial a sar ajunge.
Ideea este de a calcula, pentru ecare element al sirului a cel mai lung
subsir cresc ator care ncepe cu elementul respectiv.

In nal, se alege cel
mai mare subsir cresc ator din cele determinate pentru ecare element. S a
presupunem c a cel mai lung subsir cresc ator care cont ine elementul a(p) este
a(i
1
), . . . , a(p), . . . , a(i
k
) (1). Facem armat ia c a subsirul a(p), . . . , a(i
k
) este
cel mai lung subsir cresc ator care se formeaz a ncep and cu a(p). Dac a prin
absurd nu ar asa, atunci ar nsemna c a am avea un alt subsir cresc ator
care s a nceap a cu a(p): a(p), . . . a(i
k
)(2). Ori, dac a am considera subsirul
a(i
1
), . . . , a(p), . . . a(i
k
) (partea nal a a lui (1) este nlocuit a cu subsirul (2)),
atunci am avea un subsir cresc ator care s al cont in a pe a(p) mai lung dec at n
cazul (1), ceea ce contrazice faptul c a am presupus (1) maximal. Deci optimul
117
total implic a optimul local, o caracteristic a a problemelor de programare
dinamic a. Armat iile de mai sus reprezint a suportul pentru strategia de
rezolvare aleas a.
Vom considera un sir auxiliar L = (L(i), i = 1, n), care va avea pe pozit ia i
lungimea celui mai lung subsir cresc ator care ncepe cu valoarea a(i). Relat ia
pe care o respect a elementele acestui sir este:
L(i) =
_
1, dac a i = n
1 + maxL(j)[j > i, a(j) a(i), dac a i < n
(11.3)
unde pentru cazul mult imii vide de la a doua variant a maximul se ia 0.
Valorile lui L se vor calcula iterativ (implementarea recursiv a ar extrem de
inecient a, datorit a calculului repetat care sar face pentru aceleasi valori),
n ordinea L(n), L(n1), . . . , L(1). Pentru a determina mai usor subsirul de
lungime maxim a, se construieste un sir sol = (sol(i), i = 1, n) care va cont ine
pentru valoarea i acel j care d a minimul pentru 11.3, sau chiar valoarea i
dac a un asemenea j nu exist a. Determinarea lungimii maxime a unui subsir
se face apoi calcul and max
i=1,n
(L(i)), iar determinarea efectiv a a acestui sir se
face pe baza informat iei din sol.
Exemplu: a = (3, 2, 8, 6, 9, 7), n = 6. Atunci:
L(6) = 1, sol(6) = 6
L(5) = 1 + max = 1, sol(5) = 5
L(4) = 1 + maxL(5), L(6) = 2, sol(4) = 5
L(3) = 1 + maxL(5) = 2, sol(3) = 5
L(2) = 1 + maxL(3), L(4), L(5), L(6) = 3, sol(2) = 3
L(1) = 1 + maxL(3), L(4), L(5), L(6) = 3, sol(1) = 3
Valoarea maxim a din vectorul L este 3, obt inut a pentru L(1) (si altele). Pe
baza vectorului sol obt inem si sirul cresc ator maximal: 2, urmat de elementul
de indice sol(1) = 3, adic a a(3) = 8, care este urmat de elementul de indice
sol(3) = 5, adic a a(5) = 9, pentru care avem sol(5) = 5, adic a nu are
succesor.
Start SubsirCrescator
citeste( n, (a(i), i = 1, n) )
pentru i = n, 1, 1
L(i) = 1
sol(i) = i
118
pentru j = i + 1, n
Acest ciclu nu se execut a niciodat a pentru i = n
dac a a(j) a(i) si 1 +L(j) > L(i) atunci
L(i) = 1 +L(j)
sol(i) = j
sf arsit dac a
sf arsit pentru
sf arsit pentru
LMax = L(1)
pozLMax = 1
pentru i = 2, n
dac a L(i) > LMax atunci
LMax = L(i)
pozLMax = i
sf arsit dac a
sf arsit pentru
scrie( Lungimea maxim a a unui subsir cresc ator este:, LMax )
scrie( a(LMax) )
i = pozLMax
c at timp sol(i) ,= i
i = sol(i)
scrie( a(i) )
sf arsit c at timp
Stop
Complexitatea acestui algoritm este (n
2
), datorit a celor dou a cicluri pentru
imbricate. Ment in am c a nu este absolut necesar vectorul sol, dar determina-
rea solut iei se face mai usor pe baza lui.
11.5 Rezumat
Programarea dinamic a este o metod a care se folosesste n cazurile n care
optimul general implic a optimul part ial; n astfel de cazuri, demonstrat ia se
face de cele mai multe ori prin reducere la absurd. Pentru evitarea calcul arii
acelorasi rezultate, se apeleaz a la tabelare rezultatele pentru cazurile luate
n considerare sunt memorate ntro structur a de tip matricial. Pe baza
acestor informat ii, se poate determina solut ia (solut iile, chiar) pentru care se
atinge optimul.
119
11.6 Exercit ii (rezolvarile la pagina 174)
1. G asit i o parantezare optim a a produsului unui sir de matrice al c arui
sir de dimensiuni este (5, 10, 3, 12, 5, 50, 6) (adic a 5 10, 10 3, etc).
2. Ar atat i c a o parantezare complet a a unei expresii cu n elemente are
exact n 1 perechi de paranteze.
3. Fie R(i, j) num arul de acces ari ale elementului m(i, j) din tabloul m, de
c atre algoritmul InmultireMatrici, pentru calcularea elementelor tablo-
ului. Ar atat i c a:
n

i=1
n

j=i
R(i, j) =
n
3
n
3
. (Indicat ie:
n

i=1
i
2
=
n(n+1)(2n+1)
6
).
4. Se d a o matrice subdiagonal a. Se consider a toate sumele n care se
adun a elementele de pe ecare linie aate sub elementul adunat anterior
sau sub-si-la-dreapta. Se cere un algoritm care g aseste suma maxim a.
Exemplu:
5
2 3
8 1 2
5 9 3 4
Suma maxim a este S = 5 + 2 + 8 + 9.
5. Folosind rezultatele lui InmultireMatrici s a se descrie un algoritm care
realizeaz a nmult irea matricilor n ordine optim a.
120
Capitolul 12
Teste de autoevaluare
1. Algoritmi de sortare prin metoda Divide et impera.
2. Folosind un subalgoritm pentru nmult irea matricilor s a se scrie algo-
ritmul care ridic a la puterea k o matrice p atratic a de ordinul n.
3. D andu-se parcurgerile n preordine A, B, C, D, E, F, G si n inordine
C, B, E, D, A, G, F s a se deseneze arborele binar corespunz ator.
Solut ii
1. (Din ociu: 1p)
Metoda presupune parcurgerea a trei pasi:
a) mp art irea datelor n mai multe p art i;
b) rezolvarea (de obicei recursiv a) a problemei pe ecare bucat a
de date;
c) combinarea rezultatelor part iale n rezultatul nal.
(1p)
Sortarea prin interclasare presupune:
a) mp art irea sirului init ial n dou a p art i;
b) sortarea ec arei jum at at i;
c) interclasarea buc at ilor sortate.
MergeSort(a, p, q)
dac a p q atunci
Return
sf arsit dac a
121
r =
_
p+q
2

MERGESORT(a, p, r)
MERGESORT(a, r + 1, q)
Interclasare(a, p, r, q)
Return
(1p)
Interclasare(a, p, r, q)
i = p
j = r + 1
k = 0
repet a
k = k + 1
dac a a(i) < a(j) atunci
b(k) = a(i)
i = i + 1
altfel
b(k) = a(j)
j = j + 1
sf arsit dac a
p an a c and i > r sau j > q
pentru il = i, r
k = k + 1
b(k) = a(il)
sf arsit pentru
pentru jl = j, q
k = k + 1
b(k) = a(jl)
sf arsit pentru
k = 0
pentru i = p, q
k = k + 1
a(i) = b(k)
sf arsit pentru
Return
(2p)
Apelarea se face:
Start Sortare1
citeste( n, (a(i), i = 1, n) )
MERGESORT(a, 1, n)
122
scrie( (a(i), i = 1, n) )
Stop
Complexitatea rezult a din:
T(n) = 2T
_
n
2
_
+a n
unde a este o constant a. Din teorema central a (pagina 72) onbt inem
T(n) = (nlog n). (1p)
Alt a metod a este Quicksort (n practic a, cel mai bun algoritm de sor-
tare):
Quicksort(a, p, q)
dac a p < q atunci
Partitionare(a, p, q, r)
Quicksort(a, p, r)
Quicksort(a, r + 1, q)
sf arsit dac a
Return
(1p)
unde
Partitionare(a, p, q, r)
el = a(p)
i = p 1
j = q + 1
repet a
repet a
i = i + 1
p an a c and a(i) el
repet a
j = j 1
p an a c and a(j) el
dac a i < j atunci
a(i) a(j)
altfel
r = j
sf arsit dac a
p an a c and i j
Return
(2p)
123
Se apeleaz a ca si cel alalt.
Complexitatea este (n
2
), dar n cazul (frecvent) al mp art irii propor-
t ionale a sirului avem (nlog n). Se pot face mbun at at iri prin alegerea
aleatoare al lui el (elementul pivot). (1p)
2. Vom scrie doi subalgoritmi: unul pentru inmult irea a dou a matrice
p atratice si altul pentru ridicarea la putere a unei matrici.
Din ociu (1p).
InmultireMatrici(a, b, c, n)
pentru i = 1, n
pentru j = 1, n
c(i, j) = 0
pentru k = 1, n
c(i, j) = c(i, j) +a(i, k) b(k, j)
sf arsit pentru
sf arsit pentru
sf arsit pentru
Return
(3p)
PutereMatrice(a, n, k, c)
pentru i = 1, n
pentru j = 1, n
b(i, j) = a(i, j)
sf arsit pentru
sf arsit pentru
pentru p = 2, k
InmultireMatrici(a, n, b, c)
pentru i = 1, n
pentru j = 1, n
b(i, j) = c(i, j)
sf arsit pentru
sf arsit pentru
sf arsit pentru
Return
(4p)
Subalgoritmul PutereMatrice se apeleaz a n felul urm ator:
Start RidicareLaPutere
citeste( k, n, ((a(i, j), j = 1, n), i = 1, n) )
PutereMatrice(a, n, k, c)
124
scrie( ((c(i, j), j = 1, n), i = 1, n) )
Stop
(1p)
Complexitatea este (n
3
k). (1p)
Observat ie: Prin algoritmul ridic arii la putere prezentat n capitolul
5, problema 3, se poate scrie un algoritm de complexitate (n
3
log k).
Utiliz and un subalgoritm care s a efectueze nmult irea a dou a matrce n
timp (n
log
2
7
) (algoritmul lui Strassen, vezi [1]), se ajunge la un algo-
ritm de complexitate
_
n
log
2
7
log k
_
(sau chiar (n
2.376
log k), conform
aceleiasi surse bibliograce).
3. Din ociu (1p). Arborele este dat n gura 12.1. Rat ionamentul prin
care se construieste arborele se poate face dup a o strategie de tip di-
vide et impera: A ind primul nod care apare n parcurgerea n pre-
ordine, rezult a c a el este r ad acina arborelui. Ceea ce se a a la st anga
lui A n sirul dat n parcurgerea n inordine este subarborele st ang al
r ad acinii (la noi: parcurgerea n inordine a subarborelui st ang al lui
A este C, B, E, D, iar la parcurgerea n preordine aceleasi 4 simboluri
apar n ordinea B, C, D, E; analog, pentru partea dreapt a inordine:
G, F, preordine: F, G). La ecare pas se detecteaz a la fel ca mai sus
r ad acina ec arui subarbore, dup a care descendent ii s ai st ang si drept.
C and se ajunge la o secvent a format a dintrun singur nod, nu mai avem
ce s a determin am: arborele este complet construit.
A
C D
B F
G
E
Figura 12.1: Arborele care corespunde celor dou a secvent e: preordine
A, B, C, D, E, F, G si inordine C, B, E, D, A, G, F
Explicat ii: 4 puncte
Pasii efectuat i p an a la sf arsit: 3p
Reprezentare arbore: 1p
125
Este posibil ca s a se determine prin alt a metod a un arbore care respect a
doar una din secvent ele date. De exemplu, arborele din gura 12.2
produce doar parcurgerea n preordine conform secvent ei date, dar nu
si inordinea. (4p).
A
C
B F
E D
G
Figura 12.2: Arbore care produce la parcurgere n preordine
A, B, C, D, E, F, G, dar nu d a rezultat corect pentru inordine:
C, B, E, D, A, G, F, pe c and la noi se obt ine: D, C, E, B, A, F, G.
126
Anexa A
Metode utile n calculul
complexitat ii
A.1 Sume des ntalnite
1. Progresia aritmetic a:
a
k
= a
k1
+r, k = 2, a
1
si r dat i (A.1)
S =
n

k=1
a
k
=
(a
1
+a
n
)n
2
(A.2)
2. Sume particulare:
n

k=1
k =
n(n + 1)
2
= (n
2
) (A.3)
n

k=1
k
2
=
n(n + 1)(2n + 1)
6
= (n
3
) (A.4)
n

k=1
k
3
=
_
n(n + 1)
2
_
2
= (n
4
) (A.5)
si n general:
n

k=1
k
p
= (n
p+1
) (A.6)
3. Progresii geometrice:
127
a
k
= a
k1
r, k = 1, a
1
, r ,= 1 dat i
S =
n

k=1
a
k
=
n

k=1
a
1
r
k
= a
1
r
n1

k=0
r
k
= a
1
r
r
n
1
r 1
(A.7)
Dac a r < 1, atunci
S =
n

k=1
a
k

k=1
a
k
= a
1

1
1 r
(A.8)
A.2 Delimitarea sumelor
De multe ori, sumele nu se reg asesc n formele simple date mai sus. Exist a
diferite tehnici de determinare a unei major ari si minor ari a acestora. Pre-
zent am c ateva din ele mai jos.
A.2.1 Induct ia matematica
Una din modalit at ile usor de abordat pentru delimitarea unei sume este
bazat a pe induct ia matematic a. De exemplu, s a demonstr am c a seria arit-
metic a
n

k=1
k are valoarea
1
2
n(n+1). Putem verica usor pentru n = 1, n = 2
asa c a facem ipoteza de induct ie c a formula este adev arat a pentru orice n si
demonstr am c a are loc pentru n + 1. Avem
n+1

k=1
k =
n

k=1
k + (n + 1) =
1
2
n(n + 1) + (n + 1) =
1
2
(n + 1)(n + 2). (A.9)
Nu ntotdeauna putem determina valoarea exact a a unei sume. Pe noi
oricum ne intereseaz a ordinul sumei (deci constantele multiplicative si ter-
menii mici nu sunt ntotdeauna esent iali
1
). De exemplu, s a demonstr am c a
n

k=0
2
k
c2
n
pentru o anumit a constant a c, de la un rang nncolo (saun alt a
notat ie:
n

k=0
2
k
=O(2
n
)). Pentru condit ia init ial a n = 0 avem
0

k=0
2
k
= 1 c1,
c at timp c 1. Presupun and proprietatea de m arginire are loc pentru n s a
demonstr am c a are loc si pentru n + 1. Avem:
n+1

k=0
2
k
=
n

k=0
2
k
+ 2
n+1
c 2
n
+ 2
n+1
=
_
1
2
+
1
c
_
c 2
n+1
c 2
n+1
(A.10)
1
Dar: (2
3n
) = (2
n
); n acest caz constanta 3 nu poate neglijat a
128
c at timp (1/2 + 1/c) 1 sau, echivalent, c 2. Astfel,
n

k=0
2
k
= O(2
n
), ceea
ce am dorit s a ar at am.
Atent ion am cititorul asupra unui viciu de procedur a n cazul utiliz arii
acestui instrument matematic, care se reg aseste n urm atoarea demonstrat ie
corect a: ar at am c a
n

k=1
k = O(n). Desigur,
1

k=1
k = O(1). Accept and
delimitarea pentru n, o demonstr am acum pentru n + 1:
n+1

k=1
k =
n

k=1
k + (n + 1)
= O(n) + (n + 1) gresit !
= O(n + 1).
Greseala n argumentat ie este aceea c a O ascunde o constant a care
creste n funct ie de n si deci nu este constant a. Ar trebui s a ar at am c a exist a
o constant a care se ascunde n notat ia O() si care este deci valabil a pentru
tot i n.
A.2.2 Aproximarea prin integrale
C and o sum a poate exprimat a ca
n

k=m
f(k), unde f(k) este o funct ie
monoton cresc atoare, o putem m argini prin integrale:
_
n
m1
f(x)dx
n

k=m
f(k)
_
n+1
m
f(x)dx. (A.11)
Justicarea (geometric a, intuitiv a) pentru aceast a aproximare este ar atat a
n gura A.1. Suma este reprezentat a prin aria dreptunghiului din gur a,
iar integrala este regiunea hasurat a de sub curb a. C and f(k) este o funct ie
monoton descresc atoare, putem utiliza o metod a similar a pentru a obt ine
marginile
_
n+1
m
f(x)dx
n

k=m
f(k)
_
n
m1
f(x)dx. (A.12)
Aproximat ia integral a (A.12) d a o estimare str ans a pentru al n - lea
num ar armonic. Pentru o limit a inferioar a, obt inem
n

k=1
1
k

_
n+1
1
dx
x
= ln(n + 1). (A.13)
129
(a) M arginire inferioar a (b) M arginire superioar a
Figura A.1: M arginire prin integrale.
Pentru limita superioar a, deducem inegalitatea
n

k=2
1
k

_
n
1
dx
x
= ln n, (A.14)
care d a limita
n

k=1
1
k
ln n + 1. (A.15)
Avantajul acestei tehnici este c a permite at at determinarea unei m arginiri
inferioare, c at si a unei m arginiri superioare, care pot duce la o exprimare a
complexit at ii cu notat ia (mai exact a dec at O sau ).
Propunem cititorului s a aplice aceast a tehnic a pentru sumele prezentate
anterior
A.3 Analiza algoritmilor recursivi
Analiza unui algoritm recursiv implic a rezolvarea unui sistem de recurent e.
Vom vedea n continuare cum pot rezolvate astfel de recurent e.

Incepem
cu tehnica cea mai banal a.
A.3.1 Metoda iterat iei
Tehnica urm atoare cere ceva mai mult a tehnic a matematic a, dar rezul-
tatele sunt destul de expresive. Traiectoria ar : se execut a c at iva pasi, se
intuieste forma general a, iar apoi se demonstreaz a prin induct ie matema-
tic a c a aceast a form a este corect a. S a consider am, de exemplu, recurent a
130
problemei turnurilor din Hanoi. Pentru un n > 1 obt inem succesiv
t(n) = 2t(n1) +(1) = 2
2
t(n2) +(2) +(1) = . . . = 2
n1
t(1) +
n2

i=0
2
i
.
(A.16)
Rezult a t(n) = 2
n
1. Prin induct ie matematic a se demonstreaz a acum
cu usurint a c a aceast a formul a este corect a.
A.3.2 Recurent e liniare omogene
Vom prezenta modul de rezolvare al unor ecuat ii recurente liniare omo-
gene, adic a de forma:
a
0
t
n
+a
1
t
n1
+. . . +a
k
t
nk
= 0 (A.17)
unde t
i
sunt valorile pe care le c aut am, iar coecient ii a
i
sunt constante.
Vom atasa recurent ei (A.17) ecuat ia:
a
0
x
n
+a
1
x
n1
+. . . +a
k
x
nk
= 0 (A.18)
Solut iile acestei ecuat ii sunt e solut ia trivial a x = 0, care nu ne intereseaz a,
e solut iile ecuat iei de grad k
a
0
x
k
+a
1
x
k1
+. . . +a
k
= 0 (A.19)
care este ecuat ia caracteristic a a recurent ei (A.17).
Presupun and deocamdat a c a cele k r ad acini r
1
, r
2
, . . . , r
k
ale acestei ecuat ii
caracteristice sunt distincte, orice combinat ie liniar a
t
n
=
k

i=1
c
i
r
n
i
(A.20)
este o solut ie a recurent ei (A.17), unde constantele c
1
, c
2
, . . . , c
k
sunt deter-
minate de condit iile init iale.
S a exemplic am prin recurent a care deneste sirul lui Fibonacci:
t
n
= t
n1
+t
n2
, n 2 (A.21)
iar t
0
= 0, t
1
= 1. Putem s a rescriem aceast a recurent a sub forma
t
n
t
n1
t
n2
= 0 (A.22)
care are ecuat ia caracteristic a
x
2
x 1 = 0 (A.23)
131
cu r ad acinile r
1,2
= (1

5)/2. Solut ia general a are forma


t
n
= c
1
r
n
1
+c
2
r
n
2
. (A.24)
Impun and condit iile init iale, obt inem
c
1
+c
2
= 0, n = 0
r
1
c
1
+r
2
c
2
= 1, n = 1
de unde determin am
c
1,2
= 1/

5.
Deci, t
n
= 1/

5(r
n
1
r
n
2
). Observ am c a r
1
= = (1 +

5)/2, r
2
=
1
si
obt inem
t
n
= 1/

5(
n
()
n
)
Ca atare, implementarea recursiv a pentru determinarea celui de-al nlea ter-
men al sirului lui Fibonacci duce la o complexitate exponent ial a
2
.
Dac a r ad acinile ecuat iei caracteristice nu sunt distincte, se procedeaz a
dup a cum urmeaz a: dac a r este o r ad acin a de multiplicitate m a ecuat iei
caracteristice, atunci t
n
= r
n
, t
n
= nr
n
, t
n
= n
2
r
n
, . . . , t
n
= n
m1
r
n
sunt
solut ii pentru (A.17). Solut ia general a pentru o astfel de recurent a este
atunci o combinat ie liniar a a acestor termeni si a termenilor provenit i de la
celelalte r ad acini ale ecuat iei caracteristice. Ca mai sus, trebuie determinat
exact k constante din condit iile init iale.
Vom da din nou un exemplu. Fie recurent a
t
n
= 5t
n1
8t
n2
+ 4t
n3
, n 3 (A.25)
iar t
0
= 0, t
1
= 1, t
2
= 2. Ecuat ia caracteristic a are r ad acinile 1 (de multipli-
citate 1) si 2 (de multiplicitate 2). Solut ia general a este:
t
n
= c
1
1
n
+c
2
2
n
+c
3
n2
n
.
Din condit iile init iale, obt inem c
1
= 2, c
2
= 2, c
3
= 1/2.
A.3.3 Recurent e liniare neomogene
Consider am acum recurent e de urm atoarea form a mai general a
a
0
t
n
+a
1
t
n1
+. . . +a
k
t
nk
= b
n
p(n) (A.26)
unde b este o constant a, iar p(n) este un polinom n n de grad d
2
Pentru o complexitatea logaritmic a, a se vedea capitolul 5.
132
Pentru a rezolva (A.26), este sucient s a lu am urm atoarea ecuat ie carac-
teristic a:
(a
0
x
k
+a
1
x
k1
+. . . +a
k
)(x b)
d+1
= 0. (A.27)
Odat a ce s-a obt inut aceast a ecuat ie, se procedeaz a ca n cazul omogen.
Vom rezolva acum recurent a corespunz atoare problemei turnurilor din
Hanoi:
t
n
= 2t
n1
+ 1, n 1
iar t
0
= 0. rescriem recurent a astfel
t
n
2t
n1
= 1
care este de forma (A.26 ) cu b = 1 si p(n) = 1, un polinom de gradul 0.
Ecuat ia caracteristic a este atunci (x2)(x1) = 0, cu solut iile 1, 2. Solut ia
general a a recurent ei este
t
n
= c
1
1
n
+c
2
2
n
.
Avem nevoie de dou a condit ii init iale. Stim c a t
0
= 0; pentru a g asi cea de-a
doua condit ie calcul am
t
1
= 2t
0
+ 1.
Din condit iile init iale, obt inem
t
n
= 2
n
1.
din care se deduce c a t
n
= (2
n
).
133
134
Anexa B
Rezolvari
B.1 Rezolvari pentru capitolul 3
1. Problema 1.
(a) Exemplul 1. acest program cont ine doar instruct iuni elementare
care cer un timp constant de execut ie. Ca atare, timpul total este
m arginit superior de o constant a, fapt gurat prin notat ia (1).
(b) Exemplul 2: justicarea este aceeasi cu cea de la punctul prece-
dent, deci complexitatea este (1).
(c) Exemplul 3: citirea datelor de intrare are un cost de t
1
(n) = c
1

(n+1), unde c
1
este o constant a reprezent and timpul necesar citirii
unei valori. Atribuirea s = 0 se execut a ntr-un timp constant
t
2
= c
2
, independent de dimensiunea datelor de intrare. Ciclarea
nseamn a t
3
= c
3
n, unde c
3
este timpul necesar pentru calculul
sumei si efectuarea atribuirii; de asemenea, c
3
nu depinde de n.
Asarea se face n timpul t
4
= c
4
(constant).
Ca atare,
T(n) = t
1
(n) +t
2
(n) +t
3
(n) +t
4
(n) = c
1
(n +1) +c
2
+c
3
n +c
4
Conform propriet at ii 5, pagina 24, avem c a:
T(n) = (c
1
(n + 1) +c
2
+c
3
n +c
4
)
= (max(c
1
(n + 1) +c
3
n), c
2
+c
4
)
= (c
1
(n + 1) +c
2
n) = ((c
1
+c
3
)n +c
1
)
= ((c
1
+c
2
)n) = (n),
ultima egalitate av and loc datorit a propriet at ii 7, pagina 24.
135
(d) Exemplul 4: citirea datelor este t
1
(n) = c
1
(n + 1); atribuirile
nseamn a t
2
(n) = 3 c
2
, unde c
2
este timpul necesar unei atribu-
iri. Ciclul cu num arator nseamn a t
2
(n) = c
3
n, timpul c
3
ind
constant din cauz a c a se fac evalu ari de expresii logice si atribuiri,
costul ec arei operat ii n parte ind independent de n.
Deci
T(n) = t
1
(n)+t
2
(n)+t
3
(n) = (c
1
(n + 1) + 3 c
2
+c
3
n) = (n)
O alt a justicare: sirul este parcurs o singur a dat a, pentru e-
care element al s au efectu anduse operat ii cu cost (1); n total
complexitatea este (n).
(e) Exemplul 5: analiza algoritmului lui Euclid este destul de dicil a.
Complexitatea algoritmului este (log (min(a, b))). A se vedea de
exemplu [2].
(f) Exemplul 6: corpul ciclului cel mai interior se execut a n timp
constant deoarece cont ine doar instruct iuni elementare (atribuire,
asare). Se execut a de un num ar constant de ori, deci ciclul repet a
. . . p an a c and k = 5 se execut a ntr-un timp constant. La fel este
si cu ciclul repet a . . . p an a c and j = 4: corpul s au se excut a n
timp constant, de un num ar constant de ori. Idem n cazul ciclu-
lui cu contor exterior pentru. Ca atare, timpul total de execut ie
este m arginit superior de o constant a, complexitatea ind (1).
Propunem cititorului scrierea unui algoritm pentru listarea com-
bin arilor c ate 3 din mult imea 1, 2, . . . , n. Care este n acest caz
complexitatea?
2. Problema 2:
Start ProdusScalar
citeste( n, (a(i), i = 1, n), (b(i), i = 1, n) )
ps = 00 este element neutru pentru adunare
pentru i = 1, n
dac a pasul este 1, se poate omite
ps = ps +a(i) b(i)
sf arsit pentru
scrie( Produsul scalar este: , ps )
Stop
Complexitatea este (n).
3. Problema 3.
Ideea este de a parcurge sirul si a compara ecare element cu x; dac a
136
acest element este g asit, atunci este oprit a c autarea, altfel se merge la
urm atorul element. La sf arsit se raporteaz a rezultatul.
Pentru a semnala faptul c a x a fost g asit, vom folosi o variabil a boolean a
gasit care va primi valoarea adevarat dac a x a fost g asit n sir, fals n
caz contrar.
Start C autareLiniar a
citeste( n, (a(i), i = 1, n), x )
gasit = falsdeocamdat a nu am g asit pe x n a
i = 1i este indicele elementului curent din sir
repet a
dac a a(i) = x atunci
gasit = adevarat
pozitie = ipozitie este pozitia elementului x n sir
altfel
i = i + 1
sf arsit dac a
p an a c and i > n sau (gasit = adevarat)
dac a gasit = adevarat atunci
scrie( Am g asit , x, pe pozit ia , pozitie )
altfel
scrie( x, nu a fost g asit )
sf arsit dac a
Stop
Complexitatea este (n), cazul cel mai defavorabil ind c and x nu se
a a n sir.
Observat ie: Deoarece execut ia instruct iunilor din interiorul ciclului tre-
buie s a se fac a cel put in o dat a, este corect a utilizarea unui ciclu repet a.
4. Problema 4: vom folosi un algoritm asem an ator cu cel de la problema
precedent a, folosind informat ia c a sirul este ordonat cresc ator. Vom da
dou a variante, cu analiz a de complexitate.
(a) Prima variant a: ncepem c autarea, dar vom impune o condit ie
suplimentar a: trebuie ca permanent x a(i). Dac a avem x >
a(i), atunci este clar c a x nu mai poate g asit la dreapta indicelui
i.
Start C autareLiniar aCresc ator
citeste( n, (a(i), i = 1, n), x )
gasit = falsdeocamdat a nu am g asit pe x n a
i = 1i este indicele elementului curent din sir
137
repet a
dac a a(i) = x atunci
gasit = adevarat
pozitie = ipozitie este pozitia elementului x n sir
altfel
i = i + 1
sf arsit dac a
p an a c and i > n sau gasit = adevarat sau x > a(i)
dac a gasit = adevarat atunci
scrie( Am g asit , x, pe pozit ia , pozitie )
altfel
scrie( x, nu a fost g asit )
sf arsit dac a
Stop
Complexitatea este aceeasi ca la algoritmul precedent: (n).
Observat ie Este esent ial ca testarea i > n s a se fac a nainte de
testarea a(i) x; dac a spre exemplu locul lor ar fost inversat,
atunci era posibil ca s a avem i = n + 1, iar condit ia a(i) x s a
e testat a, desi a(n + 1) nu exist a.
(b) A doua variant a speculeaz a mai inteligent faptul c a sirul este gata
sortat. Putem mp art i sirul n dou a subsiruri de dimensiuni c at
mai apropiate. Se testeaz a dac a elementul de la mijloc este egal
cu x. Dac a da, atunci c autarea se opreste cu succes. Dac a nu, si
x <elementul din mijloc, atunci c autarea va continua s a se fac a n
prima jum atate a sirului (e clar c a n a doua jum atate nu poate
g asit); dac a x este mai mare dec at elementul de la jumatate,
atunci c autarea se va continua n a doua jum atate. C autarea
continu a p an a c and e se g aseste x n sir, e nu mai avem nici un
element de cercetat, caz care nseamn a c autare f ar a succes.
Acest algoritm se numeste algoritmul c aut arii binare (prin nju-
m at at ire).
Start C autareBinar a
citeste( n, (a(i), i = 1, n), x )
gasit = falsvariabila gasit are aceeasi semnicat ie ca n
algoritmul anterior
stanga = 1
dreapta = n
stanga si dreapta reprezint a capetelentre care se face c autarea
lui x
Initial, c autarea se face n tot vectorul
138
c at timp gasit = fals si stanga dreapta
nu l-am g asit pe x si mai avem unde c auta
mijloc =
_
stanga+dreapta
2

m a pozitionez la jum atatea sirului


dac a a(mijloc) = x atunci
gasit = adevarat
altfel
dac a x < a(mijloc) atunci
dreapta = mijloc 1
altfel
stanga = mijloc + 1
sf arsit dac a
caut doar n jum atatea corespunz atoare
sf arsit dac a
sf arsit c at timp
dac a gasit = adevarat atunci
scrie( Am g asit , x, pe pozit ia , pozitie )
altfel
scrie( x, nu a fost g asit )
sf arsit dac a
Stop
Complexitate: Timpul T(n) pentru rezolvarea problemei de di-
mensiune n satisface ecuat ia: T(n) = T(n/2)+c, c ind o constat a
necesar a test arilor si atribuirilor (operat ii elementare, al c aror cost
n parte nu depinde de n). Conform teoremei centrale (enunt at a
la capitolul Divide et impera) obt inem c a
T(n) = (log
2
(n)) ,
adic a mult mai performant dec at n varianta 4a.
5. Problema 4: presupunem c a minimul este primul element din sir. Lu am
apoi ecare din celelalte elemente ale vectorului a si le compar am cu
minimul curent cunoscut: dac a acest element este mai mic dec at mi-
nimul, atunci e clar c a am descoperit un minim mai bun, deci noul
minim va elementul curent. Procedeul continu a p an a c and se epui-
zeaz a elementele din sir. La sf arsit minimul g asit va de fapt minimul
absolut al sirului, ceea ce trebuia determinat.
Start Minim
citeste( n, (a(i), i = 1, n) )
minim = a(1)
pentru i=2,n
139
dac a a(i) < minim atunci
minim = a(i)
sf arsit dac a
sf arsit pentru
scrie( minimul este , minim )
Stop
Num arul de comparat ii este n 1. Nu se poate cobor sub aceasta
(demonstrat ia se face prin induct ie).
Observat ie. Exist a varianta de a init ializa minim cu o valoare foarte
mare, considerat a + pentru tipul de date care este folosit. De multe
ori limbajele de programare pun la dispozit ie constante reprezent and
valorile cele mai mari (mici) repezentabile pe un anumit tip de date
numeric (Pascal, C/C++, Java, C#).
6. Problema 5: vom folosi un contor (o variabil a) pentru a urm ari de c ate
ori apare minimul.
(a) Vom rezolva probleman doi pasi: vom determina minimul printr-
o parcurgere a sirului, ca mai sus, iar apoi vom parcurge sirul nc a
o dat a pentru a num ara de c ate ori a ap arut acesta.
Start ContorMinim1
citeste( n, (a(i), i = 1, n) )
minim = a(1)
pentru i=2,n
dac a a(i) < minim atunci
minim = a(i)
sf arsit dac a
sf arsit pentru
contor = 0
pentru i = 2, n
dac a minim = a(i) atunci
contor = contor + 1
sf arsit dac a
sf arsit pentru
scrie( minimul este , minim )
scrie( apare de , contor, ori )
Stop
Complexitate: (n), deoarece sirul se parcurge de dou a ori, pen-
tru ecare element efectu anduse operat ii elementare ce nu de-
pind de n (dimensiunea intr arii).
140
(b) Vom rezolva problema printro singur a parcurgere a sirului; com-
plexitatea teoretic a r am ane aceeasi.
Start ContorMinim2
citeste( n, (a(i), i = 1, n) )
minim = a(1)
contor = 1
pentru i = 2, n
dac a minim > a(i) atunci
minim = a(i)am g asit un minim mai bun
contor = 1reset am contorul la 1
altfel
dac a minim = a(i) atunci
contor = contor + 1am mai g asit o valoare egal a cu
minimul curent
sf arsit dac a
sf arsit dac a
sf arsit pentru
scrie( minimul este , minim )
scrie( apare de , contor, ori )
Stop
7. Problema 6: vom construi doi vectori: unul ret ine numerele distincte
din a, iar cel alalt contorizeaz a num arul de aparit ii pentru ecare num ar.
Vom scrie un subalgoritm de tip funct ie de c autare liniar a a unui ele-
ment x ntr-un vector v care cont ine un anumit num ar de elemente.
Aceast a funct ie returneaz a pozit ia pe care se g aseste elementul x n v
sau 0 n cazul n care x nu este cuprins n v:
CautaLiniar(x, v, l)
pozitie = 0
gasit = fals
i = 1
repet a
dac a x = v(i) atunci
gasit = adevarat
pozitie = i
altfel
i = i + 1
sf arsit dac a
p an a c and i > l sau gasit = adevarat
CautaLiniar = pozitie
Return
141
Start CelMaiDes
citeste( n, (a(i), i = 1, n) )
k = 0k este num arul de elemente distincte din a
pentru i = 1, n
pozitieInDiferite =Caut aLiniar (a(i), diferite, k)
dac a pozitieInDiferite = 0 atunci
k = k + 1a(i) nu a mai fost g asit nainte
punem a(i) n vectorul diferite
diferite(k) = a(i)
contor(k) = 1
altfel
a(i) a mai ap arut o nainte n a
contor(pozitieInDiferite) = contor(pozitieInDiferite)+1l-
am mai g asit o dat a
sf arsit dac a
sf arsit pentru
acum c aut am n vectorul contor s a vedem care num ar a ap arut
cel mai des
maximAparitii = contor(1)
pozMax = 1
pentru i = 2, k
dac a contor(i) > maximAparitii atunci
maximAparitii = contor(i)
pozMax = i
sf arsit dac a
sf arsit pentru
scrie( Num arul cel mai frecvent: , diferite(pozMax) )
scrie( Apare de , maximAparitii, ori )
Stop
Complexitate: cazul cel mai defavorabil este atunci c and avem doar ele-
mente distincten sirul a.

In acest caz, un apel CautaLiniar(a(i), diferite, k)
are costul de forma a k + b, a si b constante. Ciclul din programul
principal duce la un timp
T(n) =
n

k=1
(a k +b) = (n
2
)
Exemplu: pentru n = 4, a = (10, 20, 30, 40) vom avea:
142
diferit = (10, 20, 30, 40)
contor = (1, 1, 1, 1)
k = 4
cel mai frecvent: 10
frecvent a: 1
8. Problema 8: vom prota de faptul c a vectorul dat este sortat cresc ator.
Vom c auta o secvent a de numere constante, de lungime maxim a.
Start CelMaiDes
inceputSecventa = 1
sfarsitSecventa = 1
lungimeSecventaMaxima = 0
suntInSir = adevarat
c at timp suntInSir = adevarat
c at timp sfarsitSecventa n si a(inceputSecventa) = a(sfarsitSecventa)
sfarsitSecventa = sfarsitSecventa + 1
sf arsit c at timp
dac a sfarsitSecventainceputSecventa > lungimeSecventaMaxima
atunci
apareMaxim = a(inceputSecventa)
lungimeSecventaMaxima = sfarsitSecventainceputSecventa
sf arsit dac a
inceputSecventa = sfarsitSecventa
dac a inceputSecventa > n atunci
suntInSir = falsam parcusr tot sirul
sf arsit dac a
sf arsit c at timp
scrie( Num arul cel mai frecvent: , apareMaxim )
scrie( Apare de , lungimeSecventaMaxima, ori )
Stop
Complexitate: se observ a c a valoarea sfarsitSecventa ia pe r and va-
lorile 1, 2, . . . , n+1; de ecare dat a sunt efectuate operat ii elementare,
deci avem T(n) = (n + 1) = (n).
Observat ie: Pentru a rezolva problema de la punctul anterior, am pu-
tea face o sortare a sirului, dup a care s a aplic am algoritmul de mai
sus. Complexitatea total a ar : sortarea implic a un timp (nlog n),
algoritmul anterior (n), deci per total (nlog n), sensibil mai bine
dec at (n
2
) care fusese obt inut anterior.
9. Problema 9:
143
Start Matrice
citeste( n )
citeste( ((a(i, j), j = 1, n), i = 1, n) )
subpunctul a
p = 11 este element neutru pentru nmult ire
pentru i = 1, n
pentru j = 1, n
dac a a(i, j) ,= 0 atunci
p = p a(i, j)
sf arsit dac a
sf arsit pentru
sf arsit pentru
scrie( Produsul elementelor nenule din matrice este: , p )
subpunctul b
p = 1
pentru i = 1, n
dac a a(i, i) ,= 0 atunci
p = p a(i, j)
sf arsit dac a
sf arsit pentru
scrie( Produsul elementelor nenule de pe diagonala principal a este:
, p )
subpunctul c
p = 1
pentru i = 2, n
pentru j = 1, i 1
dac a a(i, j) ,= 0 atunci
p = p a(i, j)
sf arsit dac a
sf arsit pentru
sf arsit pentru
scrie( Prod. elem. de sub diagonala principal a este:, p )
Stop
Complexitate:
(a) (n
2
) (ecare element al matricii este luat n considerare o sin-
gur a dat a, efectu andu-se cu el operat ii elementare);
(b) (n);
(c) T(n) =
n

i=2
(i 1)c = c
n

i=2
(i 1) = c
n(n1)
2
, deci T(n) = (n
2
).
144
B.2 Rezolvari pentru capitolul 4
1. Problema 1: Vom folosi pentru memorarea elementelor din coad a un
vector v de n elemente. Vom presupune c a indicii vectorului sunt ntre
0 si n 1. Deoarece coada este circular a, dup a locat ia de indice n 1
urmeaz a locat ia de indice 0. Init ial, coada este vid a, fapt semnalat prin
inceput = sfarsit = 0.
x Coada
sfarsit = (sfarsit + 1)mod n
dac a sfarsit = inceput atunci
Coada este plin a
altfel
v(sfarsit) = x
sf arsit dac a
Return
x Coada
dac a inceput = sfarsit atunci
Coada este vid a
altfel
inceput = (inceput + 1)mod n
x = v(inceput)
sf arsit dac a
Return
Complexitatea ec arui subalgoritm este (1). Init ial avem inceput =
sfarsit = 0.
Observat ie: Se folosesc efectiv doar n 1 locat ii ale vectorului; dar n
acest mod se poate distinge ntre situat iile de coad a plin a si coad a vid a.
2. Problema 2:
(a) Parcurgerea n inordine, iterativ:
InordineIterativ(rad)
i = rad
S = S este o stiv a
repet a
c at timp LS(i) ,=
i S
i = LS(i)
sf arsit c at timp
scrie( INFO(i) )
145
c at timp LD(i) =
dac a S = atunci
Return se iese din subalgoritm, deci si din ciclul innit
sf arsit dac a
i S
scrie( INFO(i) )
sf arsit c at timp
i = LD(i)
p an a c and falsciclu innit, din care se iese datorit a lui Return
(b) Parcurgerea n postordine, iterativ:
PostordineIterativ( rad )
i = rad
S = S este o stiv a
repet a
c at timp LS(i) ,=


i S
i = LS(i)
sf arsit c at timp
c at timp LD(i) =

repet a
scrie( INFO(i) )
dac a S = atunci
Returnse iese din subalgoritm, deci si din ciclul in-
nit
sf arsit dac a
j = i
i S
p an a c and j = LS(i)
sf arsit c at timp
i S
i = LD(i)
p an a c and falsciclu innit, din care se iese datorit a lui Return
Apelul subalgoritmilor de mai sus se face av and drept parametru de
apel rad, reprezent and adresa r ad acinii arborelui.
Complexitatea ec areia din proceduri este de (n), unde n este num arul
de v arfuri ale arborelui.
3. Problema 3:
Vom extrage succesiv v arful stivei S si l vom depune ntr-o alt a stiv a
146
T. Extragerile nceteaz a e c and S devine vid a, e c and x este g asit.
Elementele din T vor depuse napoi n S.
Extrage( S, x )
T =
gasitx = fals
c at timp S ,= si gasitx = fals
a S scoatem v arful stivei
dac a a ,= x atunci
a T l depunem n T
altfel
gasitx = adevarat
sf arsit dac a
sf arsit c at timp
c at timp T ,=
a T
a S
sf arsit c at timp
Return
Complexitate: cazul cel mai defavorabil este acela n care x nu se
g aseste n S.

In acest caz, tot cont inutul lui S este trecut n T si
apoi repus n S. Complexitatea este deci ([S[), unde [S[ reprezint a
num arul de elemente aate init ial n S.
Observat ie: Primul ciclu c at timp poate scris mai adecvat ca un ciclu
repet a, av andn vedere faptul c a execut ia ciclui se face cel put in o dat a.
4. Problema 4:
Rezolvarea este asem anatoare cu cea de la punctul precedent.
Insereaza( S, x, y )
T =
gasitx=fals
c at timp S ,= si gasitx = fals
a S scoatem v arful stivei
dac a a ,= x atunci
a T l depunem n T
altfel
gasitx = adevarat
a S
sf arsit dac a
sf arsit c at timp
dac a gasitx = adevarat atunci
147
y S
sf arsit dac a
c at timp T ,=
a T
a S
sf arsit c at timp
Return
Complexitatea este ([S[ + 1) = ([S[), motivat ia ind asem an atoare
cu cea de la punctul precedent.
5. Problema 5:
Vom folosi dou a stive: Stiva1, Stiva2.
x Coada
dac a Stiva1 = atunci
Goleste(Stiva2, Stiva1)Goleste elementele din Stiva2 n Stiva1
sf arsit dac a
x Stiva1
Return
x Coada
dac a Stiva2 = atunci
Goleste(Stiva1, Stiva2)Goleste elementele din Stiva1 n Stiva2
sf arsit dac a
dac a Stiva2 = atunci
Coada este vida
altfel
x Stiva2
sf arsit dac a
Return
Subalgoritmul Goleste(A, B) unde A si B sunt stive va trece toate ele-
mentele din An B, prin extrageri repetate.
Goleste(A, B)
c at timp A ,=
x A
x B
sf arsit c at timp
Return
Num arul de operat ii de inserare si extragere n ecare caz zunt:
(a) Subalgoritmul Goleste(A, B) efectueaz a 2[A[ extrageri ([A[ este
148
num arul de elemente din stiva A);
(b) Subalgoritmul x Coada efectueaz a 2[Stiva2[+1 = 2[Coada[+1
operat ii de inserare/extragere;
(c) Subalgoritmul x Coada efectueaz a 2[Stiva1[+1 = 2[Coada[+1
operat ii de inserare/extragere;
6. Problema 6:
Vom folosi dou a cozi: Coada1, Coada2.
x Stiva
x Coada1
Return
x Stiva
dac a Coada1 = atunci
eroare: stiva vid a
altfel
c at timp Coada1 ,=
x Coada1
dac a Coada1 ,= atunci
x nu este ultimul element din Coada1
x Coada2
sf arsit dac a
sf arsit c at timpGoleste Coada2 n Coada1
c at timp Coada2 ,=
y Coada2
y Coada1
sf arsit c at timp
sf arsit dac a
Return
Num arul de operat ii de inserare/extragere pentru ecare din cei doi
subalgoritmi sunt:
(a) Subalgoritmul x Stiva efectueaz a o inserare
(b) Subalgoritmul x Stiva are num arul de operat ii cerut egal cu
2([Coada1[ 1) + 1 (primul ciclu) adunat cu 2([Coada1[ 1), n
total 4[Coada1[ 3 = 4[Stiva[ 3.
Suger am cititorului s a g aseasc a si alte soluct ii pentru aceast a pro-
blem a.
149
B.3 Rezolvari pentru capitolul 5
1. Problema 1. Denim maximul unui sir x = (x(1), x(2), . . . , x(n)) sub
form a recursiv a astfel:
maxim(x(1 . . . n)) =
_
x(1), dac a n=1
maxx(n), x(1 . . . n 1), dac a n > 1
unde maxa, b este maximul dintre a si b. Algoritmul este dat mai
jos:
Start MaximRec
citeste( n, (x(i), i = 1, n) )
M = Maxim(x, n)
scrie( M )
Stop
unde subalgoritmul recursiv Maxim este:
Maxim(x, n)
dac a n = 1 atunci
MaximRec = x(1)
altfel
MaximRec = maxx(n), Maxim(x, n 1)
sf arsit dac a
Return
Complexitatea este dat a de ecuat ia T(n) = T(n1)+c care are solut ia
T(n) = (n).
2. Problema 2. Denim suma elementelor unu sir x = (x(1), . . . , x(n))
sub form a recursiv a astfel:
suma(x(1 . . . n)) =
_
0, dac a n=0
x(n) +suma(x(1 . . . n 1)), dac a n > 0
Start SumaRec
citeste( n, (x(i), i = 1, n) )
S = Suma(x, n)
scrie( S )
Stop
unde subalgoritmul recursiv Suma este:
Suma(x, n)
dac a n = 0 atunci
150
Suma = 0
altfel
Suma = x(n) +Suma(x, n 1)
sf arsit dac a
Return
Complexitatea este dat a de ecuat ia T(n) = T(n1)+c care are solut ia
T(n) = (n).
3. Problema 3. Vom da o formul a recursiv a de calcul a puterii naturale a
unui num ar.
a
n
=
_

_
1, dac a n = 0
a, dac a n = 1
_
a
n/2
_
2
, dac a n > 1, n par
a
_
a
n/2
_
2
, dac a n > 1, n impar
Subalgoritmul recursiv este:
Putere(a, n)
dac a n = 0 atunci
Putere = 1
Return
sf arsit dac a
dac a n = 1 atunci
Putere = a
Return
sf arsit dac a
temp = Putere(a, n/2|)
dac a n mod 2 = 0 atunci
n este par
Putere = temp
altfel
Putere = a temp
sf arsit dac a
Return
Complexitatea este dat a de ecuat ia T(n) = T(n/2)+c, de unde T(n) =
(log n) (rezultat al teoremei 1, pagina 72).
4. Problema 4. Pentru a
15
, conform algoritmului precedent, avem:
a
15
=
_
_
(a)
2
a
_
2
a
_
2
a
151
deci n total 6 nmult iri.
Dar a
15
se poate calcula astfel: se calculeaz a termenii a
2
, a
3
= a
2
a, a
6
=
a
3
a
3
, a
12
= a
6
a
6
, a
15
= a
12
a
3
, deci cu 5 nmult iri.
5. Problema 5. S a consider am matricea:
A =
_
0 1
1 1
_
Calcul and produsul:
A
_
f
n1
f
n
_
obt inem matricea
_
f
n
f
n+1
_
de unde deducem
_
f
n1
f
n
_
= A
n1

_
f
0
f
1
_
Modic and algoritmul de la problema 3 s a ridice la putere o matrice n
loc de un scalar, obt inem termenul f
n
n timp (log n).
6. Problema 6. Algoritmuii recusrivi pentru parcurgeri sunt urm atorii:
(a) Parcurgerean preordine se efectueaz a astfel: se prelucreaz a informa-
t ia r ad acinii, apoi se prelucreaz a recursiv subarborele st ang, apoi
subarborele drept.
Preordine(Rad)
dac a Rad ,= atunci
scrie( Info(Rad) )Sau orice alt subalgoritm de prelucrarea
a informat iei din Rad
Preordine(LS(Rad))
Preordine(LD(Rad))
sf arsit dac a
Return
Apelul acestui subalgoritm se face cu Preordine(Rad), unde Rad
reprezint a r ad acina subarborelui.
(b) Parcurgerea recursiv a n postordine se efectueaz a astfel: se par-
curge recursiv subarborele st ang, apoi subarborele drept, apoi se
prelucreaz a informat ia din r ad acin a.
152
Postordine(Rad)
dac a Rad ,= atunci
Postordine(LS(Rad))
Postordine(LD(Rad))
scrie( Info(Rad) )Sau orice alt subalgoritm de prelucrarea
a informat iei din Rad
sf arsit dac a
Return
Apelul se face ce n cazul anterior.
(c) Parcurgerea recursiv a n inordine se efectueaz a astfel: se par-
curge recursiv subarborele st ang, apoi se prelucreaz a informat ia
din r ad acin a, apoi se parcurge recursiv subarborele drept.
Inordine(Rad)
dac a Rad ,= atunci
Inordine(LS(Rad))
scrie( Info(Rad) )Sau orice alt subalgoritm de prelucrarea
a informat iei din Rad
Inordine(LD(Rad))
sf arsit dac a
Return
Apelul se face ce n cazul anterior.
B.4 Rezolvari pentru capitolul 6
1. Problema 1.
Vom da dou a variante de rezolvare: iterativ a si recursiv a. Ambele
variante vor folosi doi vectori de s arituri: sarituraI si sarituraJ cu
c ate 8 elemente, reprezent and cele 8 deplas ari de la pozit ia curent a: de
exemplu, dac a pozit ia curent a este pe linia i si coloana j, atunci prima
s aritur a va duce calul la coordonatele (i+sarituraI(1), j+sarituraJ(1)
(cu condit ia s a nu se ias a din perimetrul tablei).
(a) Varianta iterativ a: pentru refacerea pasului napoi vom folosi
o matrice p atratic a deLa de ordinul n, care va ret ine pentru ecare
celul a de coordonate (i, j) indicele s ariturii care a determinat atingerea
pozit iei respective (vom putea sti astfel de unde sa s arit n pozit ia
curent a). Solut ia se d a sub forma unei matrice p atratice de ordinul n
cont in and n ecare celul a de coordonate (i, j) indicele s ariturii ce se
face n continuare (cu except ia ultimei celule n care se sare).
153
Start CalSah
citeste( n )
sarituraI(1) = +1, sarituraJ(1) = +2
sarituraI(2) = 1, sarituraJ(2) = +2
sarituraI(3) = +1, sarituraJ(3) = 2
sarituraI(4) = 1, sarituraJ(4) = 2
sarituraI(5) = +2, sarituraJ(5) = +1
sarituraI(6) = 2, sarituraJ(6) = +1
sarituraI(7) = +2, sarituraJ(7) = 1
sarituraI(8) = 2, sarituraJ(8) = 1
pentru i = 1, n
pentru j = 1, n
deLa(i, j) = 0
tabla(i, j) = 0
sf arsit pentru
sf arsit pentru
nrSaritura = 1
i = j = 1
c at timp nrSaritura > 0
dac a nrSaritura = n
2
atunci
ScrieSolutie(tabla, n)
indiceSarituraInapoi = deLa(i, j)
tabla(i, j) = 0
i = i sarituraI(indiceSarituraInapoi)
j = j sarituraJ(indiceSarituraInapoi)
nrSaritura = nrSaritura 1
sf arsit dac a
dac a tabla(i, j) < 8 atunci
tabla(i, j) = tabla(i, j) + 1
iInainte = i +sarituraI(tabla(i, j))
jInainte = j +sarituraJ(tabla(i, j))
dac a PoateSari(iInainte, jInainte, tabla, n)=adevarat atunci
deLa(iInainte, jInainte) = tabla(i, j)
i = iInainte
j = jInainte
nrSaritura = nrSaritura + 1
sf arsit dac a
altfel
dac a nrSaritura > 1 atunci
iInapoi = i sarituraI(deLa(i, j))
jInapoi = j sarituraJ(deLa(i, j))
154
tabla(i, j) = 0
i = iInapoi
j = jInapoi
sf arsit dac a
nrSaritura = nrSaritura 1
sf arsit dac a
sf arsit c at timp
Stop
ScrieSolutie(tabla, n)
pentru i = 1, n
pentru j = 1, n
scrie( tabla(i, j) )
sf arsit pentru
sf arsit pentru
Return
PoateSari(linie, coloana, tabla, n)
dac a linie > 0 si linie < n + 1 si coloana > 0 si coloana < n + 1 si
tabla(linie, coloana) = 0 atunci
rezultat = adevarat
altfel
rezultat = fals
sf arsit dac a
PoateSari = rezultat
Return
(b) Varianta recursiv a
Cal(i, j, n, nrSaritura, tabla)
dac a nrSaritura = n n atunci
ScrieSolutie(tabla, n)
altfel
pentru indiceSaritura = 1, 8
iInainte = i +sarituraI[indiceSaritura]
jInainte = j +sarituraJ[indiceSaritura]
dac a PoateSari(iUrmator, jUrmator, tabla, n)=adev atunci
tabla[iInainte, jInainte] = nrSaritura + 1
Cal(iInainte, jInainte, n, nrSaritura + 1, tabla)
tabla[iInainte, jInainte] = 0
sf arsit dac a
sf arsit pentru
sf arsit dac a
Return
155
Subalgoritmii ScrieSolutie si PoateSari sunt identici cu cei de la varianta
iterativ a.
Start CalSah
citeste( n )
sarituraI(1) = +1, sarituraJ(2) = +2
sarituraI(2) = 1, sarituraJ(2) = +2
sarituraI(3) = +1, sarituraJ(3) = 2
sarituraI(4) = 1, sarituraJ(4) = 2
sarituraI(5) = +2, sarituraJ(5) = +1
sarituraI(6) = 2, sarituraJ(2) = +1
sarituraI(7) = +2, sarituraJ(2) = 1
sarituraI(1) = 2, sarituraJ(2) = 1
pentru i = 1, n
pentru j = 1, n
tabla(i, j) = 0
sf arsit pentru
sf arsit pentru
tabla(1, 1) = 1
Cal(1, 1, n, 1, tabla)
Stop
2. Problema 2.
Sa demonstrat cu ajutorul calculatorului c a 4 culori sunt suciente
pentru a colora cu restrict iile date orice hart a. Vom da dou a variante,
iterativ a si recursiv a.

In ambele variante vectorul culoare de n elemente
va cont ine culorile t arilor.
(a) Varianta iterativ a.
Start ColorareHarti
citeste( n )
citeste( ((a(i, j), j = 1, n), i = 1, n) )
pentru i = 1, n
culoare(i) = 0
sf arsit pentru
numarTara = 1
c at timp numarTara > 0
dac a numarTara = n + 1 atunci
scrie( (culoare(i), i = 1, n) )
numarTara = numarTara 1
sf arsit dac a
dac a culoare(numarTara) < 4 atunci
156
culoare(numarTara) = culoare(numarTara) + 1
dac a BineColorat(a, numarTara, culoare) = adev atunci
numarTara = numarTara + 1
sf arsit dac a
altfel
culoare(numarTara) = 0
numarTara = numarTara 1
sf arsit dac a
sf arsit c at timp
Stop
Subalgoritmul BineColorat(vecin, numarTara, culoare) returneaz a adev arat
dac a culoarea t arii curente (numarTara)satisface restrict iile cerute fat a
de t arile anterior colorate.
BineColorat(a, numarTara, culoare)
corect = adevarat
i = 1
c at timp corect = adevarat si i < numarTara
dac a a(i, numarTara) = 1 si culoare(i) = culoare(numarTara)
atunci
corect = fals
altfel
i = i + 1
sf arsit dac a
sf arsit c at timp
BineColorat = corect
Return
(b) Varianta recursiv a.
Coloreaza(a, n, culoare, numarTara)
dac a numarTara = n + 1 atunci
scrie( (culoare(i), i = 1, n) )
altfel
pentru k = 1, 4
culoare(numarTara) = k
dac a BineColorat(a, numarTara, culori)= adev atunci
Coloreaza(a, n, culoare, numarTara + 1)
sf arsit dac a
sf arsit pentru
sf arsit dac a
Return
157
Subalgoritmul BineColorat este identic cu cel de la varianta iterativ a.
Utilizarea subalgoritmului recursiv se face astfel:
Start ColorareHarti
citeste( n )
citeste( ((vecin(i, j), j = 1, n), i = 1, n) )
Coloreaza(vecin, n, culoare, 1)
Stop
3. Problema 3.
Vom nota b arbat ii cu b
1
, . . . , b
n
iar femeile cu f
1
, . . . , f
m
. Vom genera
delegat iile folosind doi vectori, unul pentru indicii de b arbat i, cel alalt
pentru indicii de femei (vectorii vb, respectiv vf). Fiecare vector are o
componennt a de indice 0 care va avea permanent valoarea 0.

In vectorul
vf vom avea generate p componente (k p m), iar n vectorul vb
vom avea q elemente (0 q n); varianta q = 0 exist a deoarece se
pot forma delegat ii n care s a nu existe nici un b arbat.
Varianta dat a mai jos este recursiv a. Pentru subalgoritmul Generare-
Delegatii, parametrii fc si bc reprezint a indicele de vector vf, respectiv
vb pentru care se efectueaz a alegerea unei femei, respectiv b arbat.
GenerareDelegatii(p, fc, m, q, bc, n, vf, vb)
dac a fc = p + 1 atunci
am generat tot i indiciii pentru femei
dac a bc = q + 1 atunci
am generat tot i indiciii pentru b arbat i
scrie( (vf(i), i = 1, p) )
scrie( (vb(i), i = 1, q) )
altfel
pentru i = vb(bc 1) + 1, n q +bc
vb(bc) = i
GenerareDelegatii(p, fc, m, q, bc + 1, n, vf, vb)
sf arsit pentru
sf arsit dac a
altfel
pentru i = vf(fc 1) + 1, mp +fc
vf(fc) = i
GenerareDelegatii(p, fc + 1, m, q, bc, n, vf, vb)
sf arsit pentru
sf arsit dac a
Return
Start Delegatii
158
citeste( m, n, k )
vf(0) = vb(0) = 0
pentru p = k, m
pentru q = 0, n
GenerareDelegatii(p, 1, m, q, 1, n, vf, vb)
sf arsit pentru
sf arsit pentru
Stop
Pentru o variant a iterativ a, a se citi capitolul 7, sectiunea 7.5 (generare
de combin ari).
4. Problema 4.
Vom da mai jos o variant a recursiv a. Consider am rest ca ind res-
tul care mai este de pl atit, solutie un vector cu n elemente, 0
solutie(i) b(i), bc tipul bancnotei curente.
Plata(rest, n, solutie, bc)
dac a rest = 0 atunci
scrie( (solutie(i), i = 1, bc 1) )
altfel
dac a rest > 0 si bc n atunci
pentru k = 0, b(bc)
solutie(bc) = k
Plata(rest k v(bc), solutie, bc + 1)
sf arsit pentru
sf arsit dac a
sf arsit dac a
Return
Start PlataSuma
citeste( n, S )
citeste( (b(i), i = 1, n) )
citeste( (v(i), i = 1, n) )
Plata(S, n, solutie, 1)
Stop
Observat ie Orice problem a cu datele ca mai sus poate transformat a
ntruna n care vectorul b cont ine doar valoarea 1, prin crearea unui
vector v

care va cont ine valoarea v(i) de b(i) ori.


Pentru o variant a iterativ a n cazul b(i) = 1, i = 1, n a se vedea
capitolul 7, sect iunea 7.8
159
B.5 Rezolvari pentru capitolul 7
1. Problema 1.
(a) Produs cartezian:
CartezianRecursiv(m, n, k, x)
dac a k = n + 1 atunci
Asare(x, m)sau orice subalgoritm care prelucreaz a informat ia
obt inut a
altfel
pentru p = 1, n(k)
x(k) = p
CartezianRecursiv(m, n, k + 1, x)
sf arsit pentru
sf arsit dac a
Return
Subalgoritmul Asare este:
Asare(a, l)
pentru i = 1, l
scrie( a(i) )
sf arsit pentru
Return
Programul principal este:
Start Cartezian
citeste( m, (n(i), i = 1, m) )
CartezianRecrsiv(m, n, 1, x)
Stop
Subalgoritmul recursiv genereaz a solut iile n ordine lexicograc a.
(b) Submult imi: vom folosi un subalgoritm recursiv cu forma: Sub-
multimiRecursiv(n, k, cate, x) unde n este dat a de intrare repre-
zent and num arul elementelor mult imii init iale, k este indicele cu-
rent pentru care se ncearc a generarea, cate reprezint a num arul
de elemente ale submult imii care se genereaz a (1 k cate,
pentru cate > 0), iar x este vectorul solut ie. Vom considera c a
x are un elemente de indice 0 care va avea permanent valoarea
0.
SumbultimiRecursiv(n, k, cate, x)
dac a k > cate atunci
160
ScrieSolutie(x, cate)sau orice subalgoritm care prelucreaz a
informat ia dat a
altfel
pentru p = x(k 1), n cate +k
x(k) = p
SubmultimiRecursiv(n, k + 1, cate, x)
sf arsit pentru
sf arsit dac a
Return
Subalgoritmul ScrieSolutie este o variatie a celui anterior, care
n plus ia n considerare cazul ncare s-a generat mult imea vid a:
ScrieSolutie(a, l)
dac a l = 0 atunci
scrie( multimea vida )
altfel
pentru i = 1, l
scrie( a(i) )
sf arsit pentru
sf arsit dac a
Return
Subalgoritmul principal este:
Start Submultimi
citeste( n )
x(0) = 0
pentru cate = 0, n
SubmultimiRecursiv(n, 1, cate, x)
sf arsit pentru
Stop
Subalgoritmul recursiv genereaz a submult imile n ordine lexico-
grac a.
(c) Combin ari: subalgoritmul este acelasi cu cel de la generarea re-
cursiv a a submult imilor, cu acceeasi semnicat ie a parametrilor
de apel. Programul principal este:
Start Combinari
citeste( n, m )
x(0) = 0
CombinariRecursiv(n, 1, m, x)
161
Stop
Subalgorimul recursiv genereaz a combin arile n ordine lexicogra-
c a.
(d) Permut ari:
PermutariRecursiv(k, x, n)
dac a k = 0 atunci
ScrieSolutie(v, n)
altfel
pentru i = 1, k
v(k) v(i)
PermutariRecursiv(k 1, x, n)
v(k) v(i)
sf arsit pentru
sf arsit dac a
Return
Subalgoritmul de ScrieSolutie este cel de la produs cartezian.
Programul principal ar :
Start Permutari
citeste( n )
pentru i = 1, n
v(i) = i
sf arsit pentru
PermutariRecursiv(n, x, n)
Stop
Subalgoritmul recursiv nu genereaz a permut arile n ordine lexi-
cograc a. Suger am cititorului scrierea unei variante bazate pe
backtracking recursiv, care s a genereze permut arile n ordine le-
xicograc a.
B.6 Rezolvari pentru capitolul 8
1. Problema 1. Vom proceda n felul urm ator: dac a trebuie s a umplem
un vector al c arui cap at st ang este st si cel drept este dr, atunci la
mijloc se pune perechea (i, j), dup a care se completeaz a jum atatea
st ang a a vectorului, urmat a de cea dreapt a. Varianta de mai jos este
iterativ a, folosind o stiv a pentru simularea recursivit at ii. Solut iile vor
memorate ntro matrice cu 2
n
1 linii si 2 coloane.
162
Start Hanoi
citeste( n )
i = 1
j = 2
st = 1
dr = 2
n
1
S = S este stiv a
(i, j, st, dr) S
c at timp S ,=
(i, j, st, dr) S
sol(
st+dr
2
, 1) = i
sol(
st+dr
2
, 2) = j
dac a st
st+dr
2
1 atunci
(i, 6 i j, st,
st+dr
2
1) S
sf arsit dac a
dac a
st+dr
2
+ 1, dr atunci
(6 i j, j,
st+dr
2
+ 1, dr) S
sf arsit dac a
sf arsit c at timp
scrie( (sol(i, 1), sol(1, 2), i = 1, 2
n
1) )
Stop
Ad ancimea stivei S este (log
2
(2
n
1)) = (n), iar complexitatea este
evident (2
n
).
2. Problema 2. A se vedea rezolvarea de la varianta 4b, pagina 138. Com-
plexitatea obt inut a este T(n) = (log n).
3. Problema 3. A se vedea rezolvarea de la varianta 4a, pagina 137, pentru
care se obt inea o complexitate liniar a.
4. Problema 4. La ecare pas din ciclul repet a al algoritmului de part it ionare
i creste cu o unitate, iar j scade cu o unitate. Part it ionarea se opreste
atunci c and j este la jum atatea sirului, deci mp art irea este echilibrat a.
Ca atare, complexitatea este Dat a de T(n) = T(n/2) + c n, de unde
T(n) = (n logn).
5. Problema 5. Vom crea o funct ie care determin a dac a un num ar este
sau nu situat ntre alte dou a numere:
Intre(x, y, z)returneaz a adevarat dac a x este ntre y si z, fals altfel
dac a (y x si x z) sau (z x si x y) atunci
Intre = adevarat
163
altfel
Return fals
sf arsit dac a
Algoritmul de partit ionare modicat este:
Partitie(a, p, q)
r =
p+q
2
dac a Intre(a(p, a(q), a(r))) atunci
indiceMediana = p
sf arsit dac a
dac a Intre(a(q), a(p), a(r)) atunci
indiceMediana = q
sf arsit dac a
dac a Intre(a(r), a(p), a(q) atunci
indiceMediana = r
sf arsit dac a
dac a p ,= indiceMediana atunci
a(p) a(indiceMediana)
sf arsit dac a
pivot = a(p)
i = p 1
j = r + 1
terminat = fals
repet a
repet a
j = j 1
p an a c and a(j) pivot
repet a
i = i + 1
p an a c and a(i) pivot
dac a i < j atunci
a(i) a(j)
altfel
k = j
terminat = adevarat
sf arsit dac a
p an a c and terminat = adevarat
Return
164
B.7 Rezolvari pentru capitolul 9
1. Problema 1. Rezolvarea problemei se face n doi pasi:
(a) Se determin a mediana sirului init ial x = (x(1), . . . , x(n)); e ea
med
x
(b) Se calculeaz a sirul auxiliar y = (y(i), i = 1, n) unde y(i) = [x(i)
med
x
[
(c) Se determin a a k-a statistic a de ordine a sirului y; e ea med
y
(d) Se determin a k elemente mai mici sau egale cu med
y
; indicii aces-
tor elemente sunt indicii elementelor c autate din sirul x.
Complexitatea ec arui pas de mai sus este (n), deci complexitatea
algoritumului schit at este (n). Subalgoritmul n pseudocod este:
Start Apropiate
citeste( n, k, (x(i), i = 1, n) )
Selectie(x, 1, n, k, med
x
)
ObtineY(x, n, y, med
x
)
Selectie(x, 1, n, k, margine
y
)
Vecini(x, y, n, margine
y
, z)
Stop
Subalgoritmul Selectie este cel care determin a a k-a statistic a de ordine
a unui sir (cu complexitate liniar a pentru cazul cel mai defavorabil);
subalgoritmul ObtineY este:
ObtineY(x, n, y, med
x
)
pentru i = 1, n
y(i) = [x(i) med
x
[
sf arsit pentru
Return
Subalgoritmul Vecini va determina cei mai apropiat i k vecini ai sirului
x fat a de mediana sa:
Vecini(x, y, n, margine
y
, z)
lungZ = 0
pentru i = 1, n
dac a y(i) margine
y
atunci
lungZ = lungZ + 1
165
z(lungZ) = x(i)
sf arsit dac a
sf arsit pentru
Return
2. Problema 2. Vom folosi faptul c a cele dou a siruri sunt sortate si au
aceeasi lungime. De asemenea ne folosim de observat ia evident a c a
mediana unui sir sortat se determin a n timp constant: dac a i este
indicele primului element din sir, iar j este indicele ultimului element
al sirului, atunci mediana este pe pozit ia k =
i+j
2
|.
Pentru dou a siruri A(i
A
. . . j
A
) si B(i
B
. . . j
B
) cu acelasi num ar de ele-
mente (j
A
i
A
= j
B
i
B
) proced amn felul urm ator: dac a lungimile lor
sunt mai mici sau egale cu 2, atunci le putem interclasa si obt inem me-
diana lor (timp (1)). Dac a num arul de elemente este mai mare dec at
2, atunci e k
A
respectiv k
B
indicii mijloacelor vectorilor A(i
A
. . . j
A
)
si B(i
B
. . . j
B
). Dac a A(k
A
) < B(k
B
) atunci vom ignora elementele din
A(i
A
. . . j
A
) aate la st anga indicelui k
A
si elementele din B(i
B
. . . j
B
)
aate la dreapta indicelui k
B
si vom considera doar vectorii A(k
A
. . . j
A
)
si B(k
b
. . . j
B
). Analog se procedeaz a dac a A(k
A
) B(k
B
). Procesul
se reia pentru vectorii njum at at iti.
Justic am faptul c a prin eliminarea unei jum at at i din ecare vector
nu se pierde mediana c autat a. Fie de exemplu A(k
A
) < B(k
B
). Fie
n = j
A
i
A
= j
B
i
B
. Fie i astfel nc at i
A
i < k
A
. Atunci
A(i) A
(
k
A
) A
(
p) p = k
A
, . . . j
A
, A(i) A(k
A
) < B(k
B
)
B(q) q = k
B
, . . . j
B
. Obt inem c a A(i) este mai mic sau egal dec at
2
_
n
n+1
2
| + 1
_
elemente. Dar 2
_
n
n+1
2
| + 1
_
n + 1, deci A(i)
este mai mic sau egal dec at cel put in n + 1 elemente. Ca atare,
ignor andule, nu pierdem mediana. Analog se demonstreaz a c a eli-
min and jum atatea dreapt a a lui B nu se pierde mediana. Demonstrat ia
este asem an atoare pentru cazul n care A(k
A
) B(k
B
).
Algoritmul este dat mai jos:
Start MedianaSiruri
citeste( n, (A(i), B(i), i = 1, n) )
i
A
= i
B
= 1
j
A
= j
B
= n
c at timp i
A
< i
B
k
A
=
i
A
+j
A
2
k
B
=
i
B
+j
B
2
n =
n
2
dac a A(k
A
) < B(k
B
) atunci
166
i
A
= k
A
j
B
= k
B
altfel
j
A
= k
A
i
B
= k
B
sf arsit dac a
sf arsit c at timp
scrie( max(A(i
A
), B(i
B
)) )
Stop
unde max returneaz a maximul a dou a numere. Complexitatea este:
T(n) = T(n/2) + (1) = (log n)
3. Problema 3. Se poate proceda n mai multe moduri:
(a) Sort am numerele si alegem cele mai mari i numere
(b) Construim un (max)heap si extragem din el de i ori maximul
(c) Prin utilizarea unui algoritm de statistic a de ordine
L as am n seama cititorului scrierea algoritmulor pentru cazurile 3a si
3b. Pentru situat ia 3c determin am a n i + 1a statistic a de ordine
(e ea x) si apoi printro parcurgere a sirului numerele mai mari sau
egale cu x. Complexitatea este de (n +i log i). Suger am cititorului
compararea acestei complexit at i cu cea obt inut a la punctele 3a si 3b.
4. Problema 4, pagina 4. Ideea este de a deplasa elementele dea lungul
axei astfel nc at s a devin a toate pozitive (caz pentru care algoritmul Co-
untsort funct ioneaz a). Aceast a deplasare se obt ine adun and o cantitate
potrivit a, care poate luat a ca min
i=1,n
x(i)!. Dup a ce se efectueaz a
sortarea, se revine la valorile originale prin sc aderea cantit at ii adunate
anterior.
Start CountSortModicat
citeste( n, (x(i), i = 1, n) )
min = MinimSir(x, n)Functie care determina minimul unui sir
pentru i = 1, n
x(i) = x(i) + (min)
sf arsit pentru
Aici apare algoritmul CountSort
pentru i = 1, n
167
y(i) = y(i) (min)
sf arsit pentru
Stop
B.8 Rezolvari pentru capitolul 10
1. Problema 1. Pentru ecare element x(i) se determin a dac a apare si n
sirul y.

In caz armativ, x(i) va face parte si din mult imea intersect ie.
Faptul c a n acest fel se obt ine mult imea intersect ie este (sper am) evi-
dent. Complexitatea algoritmului este dependent a de modul n care se
face c autarea lui x(i) n y.
Dac a se face c autare liniar a (vezi rezolvarea 3, pagina 136), atunci
complexitatea este (mn)
Dac a se cauta binar (vezi rezolvarea de la 4b, pagina 138), atunci:
y trebuie sortatn prealabil, deci avem o complexitate (mlog
2
m)
x(i) este c autat binar n y, pentru i = 1, n, deci se mai
adaug a complexitatea (nlog
2
m)

In total se obt ine o complexitate de ((m + n) log m). Este mai


avantajos ca s a se fac a sortarea si c autarea n sirul cel mai scurt.
L as am cititorul s a conceap a algotritmul pentru rezolvarea acestei pro-
bleme.

In ceea ce priveste funct ia care se optimizeaz a, este vorba de:
max f(x, y) = [a : a n x si a n y[
([A[ reprezint a num arul de elemente ale mult imii A), care se reg aseste
si n algoritmul prezentat (cu toate c a nu este evident).
2. Problema 2. Ideea algoritmului este de a calcula pentru ecare obiect
valoarea lui unitar a, i.e. c at se c astig a din transportarea unei unit at i
din obiectul respectiv. Suntem mai interesat i n a considera obiectele
protabile (pret mare, greutate mic a) naintea celor pentru care rapor-
tul pret /greutate este mic. Algoritmul dat mai jos sintetizeaz a aceast a
strategie.
Start RucsacContinuu
citeste( n, G, (c(i), g(i), i = 1, n) )
pentru i = 1, n
168
v(i) =
c(i)
g(i)
sf arsit pentru
Sortare(c, g, v, n)
gc = 0gc reprezint a greutatea curent a pus a n rucsac
k = 1k este num arul obiectului curent care se ncearc a a pu n
rucsac
S = 0S este suma realizat a prin luarea obiectelor
c at timp k n si gc < G
dac a gc +g(k) G atunci
f(k) = 1f(k) reprezint a fract iunea care se ia din obiectul k
gc = gc +g(k)
S = S +c(k)
k = k + 1
altfel
f(k) =
Ggc
g(k)
gc = G
S = S +f(k)g(k)
sf arsit dac a
sf arsit c at timp
dac a k > n atunci
k = n

In cazul n care G este mai mare sau egal cu greutatea


tuturor obiectelor
sf arsit dac a
pentru
i = 1, k
scrie( f(i) )
sf arsit pentru
Stop
Subalgoritmul Sortare(c, g, v, n) rearanjeaz a elementele vectorilor c, g, v
astfel nc at v(1) v(2) v(n). Corectitudinea algoritmului de
mai sus este dat a de propozit ia de mai jos:
Propozitia 1. Algoritmul precedent determin a c astigul maxim n res-
trict iile impuse problemei.
Demonstrat ie. Dac a G >
n

i=1
g(i), atunci n mod evident solut ia dat a
de vectorul f va avea forma f = (1, 1, . . . , 1) (se iau toate obiectele),
ceea ce evident nseamn a optim. Vom considera deci cazul n care
G <

g(i). Este usor de v azut c a solut ia dat a de vectorul f are


169
forma:
f = (1, 1, . . . , 1, , 0, 0, . . . 0) (B.1)
unde 0 < 1 si apare pe pozit ia k (k ind variabila din algoritm).
Avem c a:
S =
n

i=1
f(i)c(i) (B.2)
si
G =
k

i=1
f(i)g(i) (B.3)
Fie S

c astigul maxim care se poate realiza n condit iile problemei si e


f

= (f

(1), . . . , f

(n)) (B.4)
fract iunile din obiecte care se iau, pentru a realiza S

:
S

=
n

i=1
f

(i)c(i) (B.5)
Avem:
G

=
n

i=1
f

(i)g(i) (B.6)
unde G

este greutatea total a care se transport a pentru c at igul S

.
Putem avea urm atoarele situat ii:
(a) Dac a (prin absurd) S

< S, atunci se contrazice optimalitatea lui


S

; deci aceast a situat ie nu poate s a apar a.


(b) Dac a S

= S, atunci S este optimal si nu mai avem ce demonstra.


(c) Dac a (prin absurd) S

> S, atunci proced am dup a cum urmeaz a.


Fie p cel mai mic indice pentru care f

(p) ,= 1 (n ipoteza n
care un asemenea p exist a). Vom transforma f

(p) n f

(p) =
f

(p)+ = 1, obt in and un surplus de greutate de g(p) (dep asim


greutatea maxim a G). Acest surplus de greutate va sc azut
dintrun alt obiect de indice t, t > p (sau din mai multe obiecte
de indici mai mari dec at p, dar tratarea este analoag a cu cea
pentru un singur obiect). Vom schimba deci f

(t) f

(t) =
f

(t) 0, astfel nc at
g(t) = g(p) (B.7)
170
Pentru i ,= p, t vom avea f

(i) = f

(i). Atunci:
S

i
f

(i)c(i) =

i=p,t
f

(i)c(i) + (f

(p) +)c(p) +
(f

(t) )c(t) = S

+c(p) c(t) (B.8)


Dar: c(p) c(t) = v(p)g(p) v(t)g(t) si conform relat iei
(B.7) obt inem c a:
S

= S

+g(p)(v(p) v(t)) (B.9)


Dac a v(p) v(t) = 0, atunci S

= S

si procedeul se continu a cu
urm atorul p. Dac a S

< S

se contrazice optimalitatea lui S

.
Dac a nu (mai) exist a nici un p cu proprietatea f

(p) < f(p) =


1, mai avem de studiat relat ia dintre f(k) = si f

(k). Dac a
f

(k) < , atunci printrun procedeu analog de m arire a lui f

(k)
la (si sc aderea unui f

(t), t > k) vom obt ine e o contradict ie,


e S

= S

(ca mai sus). Dac a f

(k) > , atunci se contrazice


modul de alegere al lui f

(k) = din algoritm.



In sf atrsit, dac a
f

(k) = , atunci avem c a f

poate adus la forma f f ar a a pierde


din c astig.
Deci am demonstrat c a S dat de f (conform algoritmului) nu poate
mai mic dec at S

, de unde rezult a propozit ia.


3. Problema 3. Algoritmul sugerat n [4] este:
(a) Se sorteaz a spectacolele dup a ora termin arii lor.
(b) Primul spectacol programat este cel care ncepe cel mai devreme.
(c) Se alege primul spectacol din cele ce urmeaz a n sir ultimului
spectacol programat care ndeplineste conmdit ia c a ncepe dup a
ce sa terminat ultimul spectacol programat.
(d) dac a tentativa de mai sus a esuat (nu am g asit un astfel de spec-
tacol), algoritmul se termin a, altfel se programeaz a spectacolul
g asit si se reia pasul 3c.
Demonstrat ia faptului c a acest algoritm duce la solut ia optim a este
dat a n [4].
Algoritmul este:
171
Start Spectacole
citeste( n, (st(i), sf(i), i = 1, n) )
Sortare(st, sf, n)
scrie( Spectacol care ncepe la , st(1), si se sf arseste la, sf(1)
)
k = 1
pentru i = 2, n
dac a st(i) sf(k) atunci
scrie( Spectacol care ncepe la , st(i), si se sf arseste la,
sf(i) )
k = i
sf arsit dac a
sf arsit pentru
Stop
Algoritmul Sortarest, sf, n interschimb a elementele din st, respectiv sf
astfel nc at sf(1) sf(2) sf(n).
Complexitate: avem o sortare care se poate face n timp (nlog n) si
o parcurgere a sirului st, deci n total (nlog n).
4. Problema 4. Desi problema are un caracter teoretic pronunt at, rezul-
tatul obt inut poate folosit n numeroase cazuri.

In [4] se arat a c a
strategia pentru aceast a problem a este:
(a) Se sorteaz a elementele celor dou a mult imi
(b) Dac a A = a
1
, . . . , a
m
are k elemente negative si p elemente
pozitive, se aleg primele k elemente ale lui B si ultimele p elemente
ale lui B.
Algoritmul este:
Start Maxim
citeste( m, n, (a(i), i = 1, m), (b(i), i = 1, n) )
Sortare(a, m)
Sortare(b, n)
k = 1
c at timp k m si a(k) < 0
k = k + 1
sf arsit c at timp
k = k 1
suma = 0
172
pentru i = 1, k
suma = suma +a(i) b(i)
sf arsit pentru
pentru i = k + 1, m
suma = suma +a(i) b(n m+i)
sf arsit pentru
Stop
5. Problema 5. Timpul de asteptare pentru un client este compus din
timpii de servire ai client ilor care sunt procesat i naintea lui adunat cu
timpul de servire pentru el nsusi. De aceea timpul total de asteptare
nu este indiferent fat a de ordinea de servire. De exemplu, dac a avem
doi client i, cu t
1
= 1 si t
2
= 2, atunci servirea n ordinea 1, 2 duce la un
timp de asteptare de 1 + (1 + 2) = 4, pe cdac a ar procesat i invers,
sar ajunge la timpul 2 + (2 + 1) = 5. Intuitiv, este mai bine dac a
client ii sunt procesat i n ordinea vresc atoare a timpilor de servire (n
acest fel un timp de servire mare are un impact mai t arziu).
Fie p o permutare a indicilor client ilor (corespunz and unei ordini de
intrare); client ii sunt preluat i n ordinea p
1
, p
2
, . . . , p
n
. Pentru aceas a
ordine, timpul total de servire este:
T(p) = t
p
1
+(t
p
1
+t
p
2
) + +(t
p
1
+t
p
2
+ +t
pn
) =
n

i=1
(n i +1)t
p
k
(B.10)
Fie p permutarea care determin a T din (B.10) minim. Fie p

permuta-
rea care se obt ine din p printro inversiune: p

(i) = p(j), p

(j) = p(i)
(i < j), p

(k) = p(k), k ,= i, j. Atunci avem c a T(p) T(p

), ceea ce
este echivalent cu (j i)(t
p
i
t
p
j
) 0, ceea ce conduce la t
p
i
< t
p
j
,
ceea ce conrm a valabilitatea strategiei.
Algoritmul este:
Start Procesare
citeste( n, (t(i), i = 1, n) )
pentru i = 1, n
p(i) = i
sf arsit pentru
Sortaret, p, n
pentru i = 1, n
scrie( p(i) )
sf arsit pentru
Stop
173
Algoritmul Sortare(t, p, n) sorteaz a elementele lui t, n paralel f ac and
aceleasi interschimb ari n vectorul de permutare p.
B.9 Rezolvari pentru capitolul 11
1. Problema 1. Tablourile m si s, analoage celor din Tabelul 11.2, pagina
116, au valorile:
1 2 3 4 5 6 1 2 3 4 5 6
0 150 330 405 1655 2010 0 1 2 2 4 2
0 0 360 330 2430 1950 0 0 2 2 2 2
0 0 0 180 930 1770 0 0 0 3 4 4
0 0 0 0 3000 1860 0 0 0 0 4 4
0 0 0 0 0 1500 0 0 0 0 0 5
0 0 0 0 0 0 0 0 0 0 0 0
De aici tragem concluzia c a num arul optim de nmult iri scalare este
m(1, 6) = 2010. Pentru determinarea modului n care se facenmult irea,
folosim informat ia din matricea s: s(1, 6) = 2, deci vom avea paranteza-
rea (A
1
A
2
) (A
3
. . . A
6
). Pentru a determina cum se face parantezarea
pentru produsul A
36
, folosim s(3, 6) = 4, de unde deducem c a grup am
A
3...6
= (A
3
A
4
) (A
5
A
6
).

In nal, obt inem parantezarea complet a:
((A
1
A
2
) ((A
3
A
4
) (A
5
A
6
)))
2. Problema 2. Demonstrat ia se face prin induct ie matematic a dup a
num arul n de matrici. Fie P(n) propozit ia parantezarea complet a
a unui sir cu n matrici are exact n 1 paranteze.
Vericarea:
(a) P(1): o matrice reprezint a o expresie complet parantezat a
(b) P(2): (A
1
A
2
) este singura expresie complet parantezat a asociat a
produsului a dou a matrici, deci avem o pereche de paranteze.
Demonstrat ie: presupunem propozit ia adev arat a p an a la n 1
si demonstr am c a si P(n) este adev arat a. Fie A
1...n
= (A
1...p

A
p+1...n
), 1 p < n. Atunci: conform propozit iei P(p) avem
c a num arul de perechi de paranteze pentru A
1...p
este p 1, iar
pentru A
p...n
este n (p + 1). Pentru A
1...n
avem nevoie de (p
174
1) + (n p 1) + 1 perechi de paranteze (ultimul termen din
sum a se datoreaz a perechii de paranteze exterioare). Deci P(n)
este adev arat a, de unde concluzia din enunt ul problemei.
(c) Problema 3. Relat ia dup a care se calculeaz a optimul este:
m(i, j) = min
ik<j
m(i, k) +m(k + 1, j) +p
i1
p
k
p
j
(B.11)
Fie . m(, ) este accesat n cadrul (B.11) e ca m(i, k), e
ca m(k + 1, j). Fie t(, ) num arul de apeluri ce se face pentru
m(, ) n primul caz si T(, ) num arul de apeluri ce rezult a
din al doilea caz.
Pentru primul caz, avem i = , k = . Putem avea j +1, n,
deci T(, ) = n . Pentru U(, ) se poate r ata analog c a
U(, ) = n . Obt inem:
R(, ) = T(, ) =
n

=1
n

=
(n + 1) = =
n
3
n
3
(d) Problema 4. Fie a = (a(i, j)) matricea triunghiular a dat a la in-
trare (1 i n, 1 j i). Observ am c a avem 2
n1
posibilit at i
de a forma drumuri de la a(1, 1) la ultima linie (demonstrat ia se
face prin induct ie matematic a dup a n). Ca atare, o metod a de
abordare de tip brute force este de la nceput sortit a esecului.
De asemenea se observ a c a o strategie de tipul coboar a la num arul
cel mai mare aat pe linia imediat urm atoare nu duce la solut ie
optim a. Vom da un algoritm bazat pe programare dinamic a.
Fie T drumul de la a(1, 1) la ultima linie care d a suma mai-
xim a. Fie S(i, j) un element de pe acest drum, aat pe linia i
si coloana j. Atunci S(i, j) este valoarea maxim a care se poate
obt ine plec and din (i, j) p an a la ultima linie. Dac a nu ar asa,
atunci nseamn a c a ar exista un alt drum de la (i, j) la ultima
linie care d a valoare mai mare, iar prin modicarea lui T astfel
nc at s a includ a acest ultim drum am obt ine o valoare mai mare,
contradict ie cu alegerea lui T. Ca atare, putem deduce c a:
S(i, j) =
_
S(n, j) dac a i = n
a(i, j) + maxS(i + 1, j), S(i + 1, j + 1) dac a i < n
(B.12)
pentru 1 i n, 1 j i; ceea ce ne duce la algoritm. Calculul
lui S(i, j) nu se face recursiv, ci folosind o matrice triunghiular a.
175
Pentru reconstituirea solut iei se foloseste o matrice triunghilar a
sol
Start Triunghi
citeste( n, (a(i, j), i = 1, n, j = 1, i) )
pentru j = 1, n
s(n, j) = a(n, j)
sf arsit pentru
pentru i = n 1, 1, 1
pentru j = 1, i
dac a s(i + 1, j) > s(i + 1, j + 1) atunci
s(i, j) = a(i, j) +s(i + 1, j)
sol(i, j) = j
altfel
s(i, j) = a(i, j) +s(i + 1, j)
sol(i, j) = j + 1
sf arsit dac a
sf arsit pentru
sf arsit pentru
scrie( Suma maxim a este, s(1, 1) )
scrie( Ea se obt ine astfel: )
i = j = 1
scrie( a(1, 1) )
pentru k = 1, n 1
j = sol(i, j)
i = i + 1
scrie( a(i, j) )
sf arsit pentru
Stop
3. Problema 5. Suger am cititorului s a urm areasc a rezolvarea problemei
1. Rezolvarea se bazeaz a pe un algoritm de tip Divide et Impera din
cauz a c a pentru un produs de tipul A
i...j
vom determina indicele k
pentru care facem descompunerea A
i...j
= (A
i...k
) (A
k+1...j
), ecare din
cele dou a matrici ind la r andul lor parantezate independent, p an a
c and se ajunge la c ate o singur a matrice.
Descompunere(s.i, j)
dac a i = j atunci
scrie( i )
Return
sf arsit dac a
dac a j i = 1 atunci
176
scrie( (, i,*, j, ) )
Return
sf arsit dac a
k = s(i, j)
scrie( ( )
Inmultiri(s, i, k)
scrie( )*( )
Inmultiri(s, k + 1, j)
scrie( ) )
Return
Propunem cititorului interesat crearea unui algoritm care s a determine
toate modalit at ile de nmult ire a matricelor astfel nc at s a se ajung a la
un num ar de nmult iri scalare minim. (Indicat ie: nu se mai foloseste
informat iua din s, ci doar cea din m)
177
178
Bibliograe
[1] Andonie, R azvan, and G arbacea, Ilie. Algoritmi fundamentali. O perspec-
tiv a C++. Editura Libris, 1995. Download de la: http://vega.unitbv.ro/
andonie.
[2] Cormen, Thomas H, Leiserson, E Charles, and Rivest, Ronald R. Intro-
ducere n algoritmi. Computer Libris Agora, 2000.
[3] Livovschi, Leon and Georgescu, Horia. Sinteza si analiza algoritmilor.
Editura Stiint ic a si Enciclopedic a, 1986.
[4] Tudor, Sorin. Tehnici de programare (Manual pentru clasa a X-a). L&S
Infomat, 1996.
179

You might also like