Sei sulla pagina 1di 192

Ministerul Educaiei al Republicii Moldova

tiina, 2014

CZU 004(075.3)
G 80
Elaborat conform curriculumului disciplinar n vigoare i aprobat prin Ordinul ministrului educaiei al
Republicii Moldova (nr. 267 din 11 aprilie 2014). Editat din sursele financiare ale Fondului Special pentru
Manuale.
Comisia de evaluare: Gheorghe Curbet, profesor colar, grad didactic superior, Liceul Teoretic Mihai Eminescu, Bli; Arcadie Malearovici, ef direcie, Centrul Tehnologiilor Informaionale i Comunicaionale n
Educaie, MET; Varvara Vanovscaia, profesor colar, grad didactic superior, Liceul Teoretic Vasile Alecsandri, Chiinu
Recenzeni: Gheorghe Cpin, doctor inginer, confereniar universitar, Universitatea de Stat din Moldova;
Alexei Colbneac, maestru n arte, profesor universitar, Academia de Muzic, Teatru i Arte Plastice, Chiinu;
Tatiana Cartaleanu, doctor n filologie, confereniar universitar, Universitatea Pedagogic de Stat Ion Creang, Chiinu; Mihai leahtichi, doctor n psihologie i n pedagogie, confereniar universitar, Universitatea
Liber Internaional din Moldova; Valeriu Cabac, doctor n tiine fizico-matematice, confereniar universitar, Universitatea de Stat Alecu Russo, Bli
Redactor: Vasile Bahnaru
Corectori: Mariana Belenciuc, Elena Pistrui, Maria Cornesco
Redactor tehnic: Nina Duduciuc
Machetare computerizat: Anatol Andrichi
Copert: Vitalie Ichim

ntreprinderea Editorial-Poligrafic tiina,


str. Academiei, nr. 3; MD-2028, Chiinu, Republica Moldova;
tel.: (+373 22) 73-96-16; fax: (+373 22) 73-96-27;
e-mail: prini@stiinta.asm.md; prini_stiinta@yahoo.com
www.stiinta.asm.md
DIFUZARE:
Republica Moldova: M Societatea de Distribuie a Crii PRO-NOI
str. Alba-Iulia, 75; MD-2051, Chiinu;
tel.: (+373 22) 51-68-17, 71-96-74; fax: (+373 22) 58-02-68;
e-mail: info@pronoi.md; www.pronoi.md
Toate drepturile asupra acestei ediii aparin ntreprinderii Editorial-Poligrafice tiina.
Descrierea CIP a Camerei Naionale a Crii
Gremalschi, Anatol
Informatic: Man. pentru clasa a 11-a/Anatol Gremalschi; Min. Educaiei al Rep. Moldova. Ch.:
.E.P. tiina, 2014 (Tipografia BALACRON SRL). 192 p.
ISBN 978-9975-67-877-3
004(075.3)

ISBN 978-9975-67-877-3

Anatol Gremalschi. 2008, 2014


.E.P. tiina. 2008, 2014

Introducere
Capitolul 1. FUNCII I PROCEDURI

1.1. Subprograme
1.2. Funcii
1.3. Proceduri
1.4. Domenii de vizibilitate
1.5. Comunicarea prin variabile globale
1.6. Efecte colaterale
1.7. Recursia
1.8. Sintaxa declaraiilor i apelurilor de subprograme

Capitolul 2. STRUCTURI DINAMICE DE DATE

2.1. Variabile dinamice. Tipul referin


2.2. Structuri de date
2.3. Liste unidirecionale
2.4. Prelucrarea listelor unidirecionale
2.5. Stiva
2.6. Cozi
2.7. Arbori binari
2.8. Parcurgerea arborilor binari
2.9. Arbori de ordinul m
2.10. Tipul de date pointer
Capitolul 3. METODE DE ELABORARE A PRODUSELOR
PROGRAM
3.1. Programarea modular
3.2. Testarea i depanarea programelor
3.3. Elemente de programare structurat
Capitolul 4. ANALIZA ALGORITMILOR
4.1. Complexitatea algoritmilor
4.2. Estimarea necesarului de memorie
4.3. Msurarea timpului de execuie
4.4. Estimarea timpului cerut de algoritm
4.5. Complexitatea temporal a algoritmilor

Capitolul 7. PROBLEME RECAPITULATIVE


Bibliografie

Pagina

Opional

Capitolul 5. TEHNICI DE ELABORARE A ALGORITMILOR


5.1. Iterativitate sau recursivitate
5.2. Metoda trierii
5.3. Tehnica Greedy
5.4. Metoda relurii
5.5. Metoda desparte i stpnete
5.6. Programarea dinamic
5.7. Metoda ramific i mrginete
5.8. Aplicaiile metodei ramific i mrginete
5.9. Algoritmi exaci i algoritmi euristici
Capitolul 6. ALGORITMI DE REZOLVARE A UNOR
PROBLEME MATEMATICE
6.1. Operaii cu mulimi
6.2. Analiza combinatorie

Real

Coninuturi

Umanist

CUPRINS

4
5
5
6
10
14
18
20
23
26
30
30
34
35
40
46
51
55
62
67
72
80
80
87
90
93
93
95
100
104
109
113
113
118
122
126
133
140
144
147
159
170
170
175
183
190

Dragi prieteni,
Manualul este elaborat n conformitate cu Curriculumul disciplinar de informatic i
are drept scop nsuirea de ctre elevi a cunotinelor necesare pentru formarea culturii
informaionale i dezvoltarea gndirii algoritmice. Cu ajutorul acestui manual vei studia
funciile i procedurile limbajului PASCAL, structurile dinamice de date i metodele de
elaborare a produselor program. De asemenea, vei studia cele mai rspndite tehnici de
programare: trierea, tehnica Greedy, reluarea, metoda desparte i stpnete, programarea
dinamic, metoda ramific i mrginete, algoritmii euristici. n manual snt expuse metode de estimare a necesarului de memorie i a timpului cerut de algoritmi, recomandri
ce vizeaz utilizarea recursiei i iterativitii.
Modul de expunere a materialului este similar celui din manualele de informatic
pentru clasele precedente. Mai nti se prezint sintaxa i semantica unitilor respective
ale limbajului PASCAL, urmate de exemple de aplicare i recomandri pentru elaborarea
de programe ce pot fi lansate pe calculator. n cazul tehnicilor de programare, snt expuse
noiunile de baz i suportul matematic al tehnicii respective, urmate de modul de organizare a datelor, descrierea algoritmilor, elaborarea i depanarea programelor PASCAL.
O atenie deosebit se acord metodelor de implementare a tehnicilor de programare, interdependenei dintre performanele calculatorului i complexitatea problemelor ce pot
fi rezolvate cu ajutorul mijloacelor respective.
Implementarea tehnicilor de programare este ilustrat cu ajutorul mai multor probleme frecvent ntlnite n viaa cotidian i studiate n cadrul disciplinelor colare din ciclul
liceal. Totodat, n manual au fost incluse i probleme de o real importan practic,
rezolvarea crora este posibil doar cu aplicarea calculatorului.
Fiind strns legate de cunotinele din alte domenii, temele din manual snt axate pe
metodele de rezolvare a problemelor ce necesit un volum foarte mare de calcul, evideniindu-se rolul esenial al gndirii matematice n apariia i dezvoltarea informaticii. Exemplele, exerciiile i sarcinile individuale din manual vor contribui la perceperea
adecvat a rolului i locului calculatorului, a influenei lui asupra dezvoltrii matematicii, fizicii, chimiei, tiinelor socioumane. Pentru majoritatea temelor din manual au
fost elaborate programe destinate instruirii asistate de calculator, fapt ce permite individualizarea procesului de predarenvare, organizarea leciilor practice i dezvoltarea
capacitilor creative ale fiecrui elev.
n ansamblu, materialul inclus n Manualul de informatic pentru clasa a XI-a va contribui la dezvoltarea urmtoarelor competene: analiza structural a problemei; divizarea
problemelor complexe n probleme mai simple i reducerea lor la cele deja rezolvate;
estimarea complexitii algoritmilor destinai soluionrii problemelor propuse; utilizarea metodelor formale pentru elaborarea algoritmilor i scrierea programelor respective.
Evident, aceste caliti snt strict necesare nu numai viitorilor informaticieni, dar i
fiecrui om cult care, la sigur, va tri i va lucra ntr-un mediu bazat pe cele mai moderne
tehnologii informaionale.
Autorul

Capitolul 1
FUNCII I PROCEDURI
1.1. Subprograme
E cunoscut faptul c o problem complex poate fi rezolvat prin divizarea ei
ntr-un set de pri mai mici (subprobleme). Pentru fiecare parte se scrie o anumit
secven de instruciuni, denumit subprogram. Problema n ansamblu se rezolv
cu ajutorul programului principal, n care pentru rezolvarea subproblemelor se folosesc apelurile subprogramelor respective. Cnd n programul principal se ntlnete
un apel, execuia continu cu prima instruciune din programul apelat (fig. 1.1). Cnd
se termin executarea instruciunilor din subprogram, se revine la instruciunea imediat urmtoare apelului din programul principal.

Programul
Programul
principal
principal

Subprogram 1

Subprogram 2
Apeluri de
subprograme

Fig. 1.1. Interaciunea ntre program i subprogram

n limbajul PASCAL exist dou tipuri de subprograme, i anume, funcii i proceduri:


<Subprograme> ::= { <Funcie>; | <Procedur>; }

Funciile snt subprograme care calculeaz i returneaz o valoare. Limbajul


PASCAL conine un set de funcii predefinite, cunoscute oricrui program: sin,
cos, eof etc. n completare, programatorul poate defini funcii proprii, care se apeleaz n acelai mod ca i funciile-standard. Prin urmare, conceptul de funcie extinde noiunea de expresie PASCAL.
Procedurile snt subprograme care efectueaz prelucrarea datelor comunicate n
momentul apelului. Limbajul conine procedurile predefinite read, readln, write, writeln .a., studiate n clasele precedente. n completare, programatorul poate
defini proceduri proprii, care se apeleaz n acelai mod ca procedurile-standard.
Prin urmare, conceptul de procedur extinde noiunea de instruciune PASCAL.
Subprogramele se definesc, n ntregime, n partea declarativ a unui program.
Evident, apelurile de funcii i proceduri se includ n partea executabil a programului.
Un subprogram poate fi apelat chiar de el nsui, caz n care apelul este recursiv.

ntrebri i exerciii
Explicai termenii program principal i subprogram.
Cum interacioneaz programul i subprogramul?
Care este diferena dintre proceduri i funcii?
Cum se apeleaz o funcie? n care instruciuni ale limbajului pot aprea apeluri de funcii?
Cum se apeleaz o procedur?
Numii tipul argumentului i tipul rezultatului furnizat de funciile predefinite abs, chr,
eof, eoln, exp, ord, sin, sqr, sqrt, pred, succ, trunc.
Numii tipul parametrilor actuali ai procedurilor read i write.
Ce prelucrri de date efectueaz procedurile read i write?

1.2. Funcii
Textul PASCAL al unei declaraii de funcie are forma:
function f(x1, x2, ..., xn) : tr;
D;
begin
...
f := e;
...
end;

Prima linie este antetul funciei, format din:


f numele funciei;
(x1, x2, ..., xn) lista opional de parametri formali reprezentnd argumentele
funciei;
tr tipul rezultatului; acesta trebuie s fie numele unui tip simplu sau tip referin.

Antetul este urmat de corpul funciei, format din declaraiile locale opionale D
i instruciunea compus begin ... end.
Declaraiile locale snt grupate n seciunile (eventual vide) label, const, type,
var, function/procedure.
Numele f al funciei apare cel puin o dat n partea stng a unei instruciuni de
atribuire care se execut: f := e. Ultima valoare atribuit lui f va fi ntoars n programul principal.
n mod obinuit, un parametru formal din lista (x1, x2, ..., xn) are forma:
v1, v2, ..., vk : tp
unde v1, v2, ..., vk snt identificatori, iar tp este un nume de tip.
Utilizarea funciei f se specific printr-un apel de forma:
f (a1, a2, ..., an)
unde (a1, a2, ..., an) este lista de parametri actuali. De obicei, parametrii actuali snt expresii,
valorile crora snt comunicate funciei. Corespondena ntre un parametru actual i parametrul formal se face prin poziia ocupat de acetia n cele dou liste. Parametrul actual
trebuie s fie compatibil din punctul de vedere al atribuirii cu tipul parametrului formal.
Exemplu:
Program P97;
{Declararea i utilizarea funciei Putere }
type Natural=0..MaxInt;
var a : real;
b : Natural;
c : real;
s : integer;
t : integer;
v : real;
function Putere(x : real; n : Natural) : real;
{calcularea lui x la puterea n }
var p : real;
i : integer;
begin
p:=1;
for i:=1 to n do p:=p*x;
Putere:=p;
end; { Putere }
begin
a:=3.0;
b:=2;
c:=Putere(a, b);
writeln(a:10:5, b:4, c:10:5);

s:=2;
t:=4;
v:=Putere(s, t);
writeln(s:5, t:4, v:10:5);
readln;
end.
Funcia Putere are doi parametri formali: x de tipul real i n de tipul Natural.
Funcia returneaz o valoare de tipul real. n corpul funciei snt declarate variabilele locale p i i.
La execuia apelului Putere(a,b) valorile 3.0 i 2 ale parametrilor actuali a, b
se transmit parametrilor formali, respectiv, x i n. De menionat c tipul lui a coincide cu tipul lui x i tipul lui b coincide cu tipul lui n.
n cazul apelului Putere(s,t) tipul parametrilor actuali s,t nu coincide cu
tipul parametrilor formali, respectiv, x i n. Totui apelul este corect, ntruct tipurile
respectve snt compatibile din punctul de vedere al atribuirii.

ntrebri i exerciii
Se consider urmtoarea declaraie:
function Factorial(n : integer) : integer;
var p, i : integer;
begin
p:=1;
for i:=1 to n do p:=p * i;
Factorial:=p;
end;
Numii tipul parametrului formal i tipul rezultatului returnat de funcie. Precizai variabilele declarate n corpul funciei. Elaborai un program care afieaz pe ecran valorile n!
pentru n=2, 3 i7.
n care loc al programului principal se includ declaraiile de funcii?
Comentai programul ce urmeaz:
Program P98;
{ Eroare }
function Factorial(n : 0..7) : integer;
var p, i : integer;
begin
p:=1;
for i:=1 to n do p:=p*i;
Factorial:=p;
end; { Factorial }
begin
writeln(Factorial(4));
readln;
end.

Se consider antetul
function F(x : real; y : integer; z : char) : boolean;
Care din apelurile ce urmeaz snt corecte:
a) F(3.18, 4, a)

e) F(3.18, 4, 4)

b) F(4, 4, 4)

f)

c)

F(4, 4, 4)

d) F(4, 3.18, a)

F(3.18, 4, 4)

g) F(15, 21, 3)
h) F(15,21,3)

Elaborai o funcie care calculeaz:


a) suma numerelor reale a, b, c, d;
b) media numerelor ntregi i, j, k, m;
c) minimumul din numerele a, b, c, d;
d) numrul de vocale ntr-un ir de caractere;
e) numrul de consoane ntr-un ir de caractere;
f) rdcina ecuaiei ax+b=0;
g) cel mai mic divizor al numrului ntreg n>0, diferit de 1;
h) cel mai mare divizor comun al numerelor naturale a, b;
i) cel mai mic multiplu comun al numerelor naturale a, b;
j) ultima cifr n notaia zecimal a numrului ntreg n>0;
k) cte cifre snt n notaia zecimal a numrului ntreg n>0;
l) cifra superioar n notaia zecimal a numrului ntreg n>0;
m) numrul de apariii ale caracterului dat ntr-un ir de caractere.
Se consider urmtoarele declaraii:
const nmax=100;
type Vector=array [1..nmax] of real;
Elaborai o funcie care calculeaz:
a) suma componentelor unui vector;
b) media componentelor vectorului;
c) componenta maxim;
d) componenta minim.
Se consider urmtoarele tipuri de date:
type Punct=record
x, y : real
end;
Segment=record
A, B : Punct
end;

Triunghi=record
A, B, C : Punct
end;
Dreptunghi=record
A, B, C, D : Punct
end;
Cerc=record
Centru : Punct;
Raza : real
end;
Elaborai o funcie care calculeaz:
a) lungimea segmentului;
b) lungimea cercului;
c) aria cercului;
d) aria triunghiului;
e) aria dreptunghiului.
Variabila A este introdus prin declaraia
var A : set of char;
Elaborai o funcie care returneaz numrul de caractere din mulimea A.
Elaborai o funcie care s calculeze diferena n secunde ntre dou momente de timp
date prin or, minute i secunde.
Un triunghi este definit prin coordonatele vrfurilor sale. Scriei funcii care, pentru dou
triunghiuri date, s studieze dac:
a) au aceeai arie;
b) snt asemenea;
c) primul este n interiorul celui de-al doilea.

1.3. Proceduri
Forma general a textului unei declaraii de procedur este:
procedure p(x1, x2, ..., xn);
D;
begin
...
end;

n antetul procedurii apar:


p numele procedurii;
x1, x2, ..., xn lista opional de parametri formali;
n corpul procedurii snt incluse:
D declaraiile locale (opionale) grupate dup aceleai reguli ca i n cazul funciilor;

10

begin ... end instruciune compus; ea nu conine vreo atribuire asupra


numelui procedurii.
Procedura poate s ntoarc mai multe rezultate, dar nu prin numele ei, ci prin
variabile desemnate special (cu prefixul var) n lista de parametri formali.
Parametrii din list introdui prin declaraii de forma
v1, v2, ..., vk : tp
se numesc parametri-valoare. Acetia servesc pentru transmiterea de valori din programul principal n procedur.
Parametrii formali introdui n list prin declaraii de forma
var v1, v2, ..., vk : tp
se numesc parametri-variabil i servesc pentru ntoarcerea rezultatelor din procedur n programul principal.
Activarea unei proceduri se face printr-un apel de forma
p(a1, a2, ..., an)
unde a1, a2, ..., an este lista de parametri actuali. Spre deosebire de funcie,
apelul de procedur este o instruciune; aceasta se insereaz n programul principal
n locul n care snt dorite efectele produse de execuia procedurii.
n cazul unui parametru-valoare drept parametru actual poate fi utilizat orice
expresie de tipul respectiv, n particular o constant sau o variabil. Modificrile
parametrilor-valoare nu se transmit n exteriorul subprogramului.
n cazul unui parametru-variabil drept parametri actuali pot fi utilizate numai
variabile. Evident, modificrile parametrilor n studiu vor fi transmise programului
apelant.
Exemplu:
Program P99;
{Declararea i utilizarea procedurii Lac }
var
a, b, c, t, q : real;
procedure Lac(r : real; var l, s : real);
{lungimea i aria cercului
}
{r - raza; l - lungimea; s - aria }
const Pi=3.14159;
begin
l:=2*Pi*r;
s:=Pi*sqr(r);
end; {Lac }
begin
a:=1.0;
Lac(a, b, c);
writeln(a:10:5, b:10:5, c:10:5);

11

Lac(3.0, t, q);
writeln(3.0:10:5, t:10:5, q:10:5);
readln;
end.

Procedura Lac are trei parametri formali: r, l i s. Parametrul r este un parametru-valoare, iar l i s snt parametri-variabil.
Execuia instruciunii Lac(a,b,c) determin transmiterea valorii 1.0 drept valoare a parametrului formal r i a locaiilor (adreselor) variabilelor b i c drept locaii
(adrese) ale parametrilor formali l i s. Prin urmare, secvena de instruciuni
a:=1.0;
Lac(a, b, c)
este echivalent cu secvena
b:=2*Pi*1.0;
c:=Pi*sqr(1.0).
n mod similar, instruciunea
Lac(3.0,t,q)
este echivalent cu secvena
t:=2*Pi*3.0;
q:=Pi*sqr(3.0).

ntrebri i exerciii
Care este diferena dintre un parametru-valoare i un parametru-variabil?
Se consider declaraiile:
var k, m, n : integer;
a, b, c : real;
procedure P(i : integer; var j : integer;
x : real; var y : real);
begin
{...}
end.
Care din apelurile ce urmeaz snt corecte?
a) P(k,m,a,b)

d) P(m,m,a,b)

b) P(3,m,a,b)

e) P(m,k,6.1,b)

c)

12

P(k,3,a,b)

f)

P(n,m,6,b)

g) P(n,m,6,20)

i)

P(i,i,i,i)

h) P(a,m,b,c)

j)

P(a,a,a,a)

Argumentai rspunsul.
Comentai programul ce urmeaz:
Program P100;
{Eroare }
var a : real;
b : integer;
procedure P(x : real; var y : integer);
begin
{... }
end; { P }
begin
P(a, b);
P(0.1, a);
P(1, b);
P(a, 1);
end.
Ce va afia pe ecran programul ce urmeaz?
Program P101;
{Parametru-valoare i parametru-variabil }
var a, b : integer;
procedure P(x : integer; var y : integer);
begin
x:=x+1;
y:=y+1;
writeln(x=, x, y=, y);
end; {P }
begin
a:=0;
b:=0;
P(a, b);
writeln(a=, a, b=, b);
readln;
end.
Argumentai rspunsul.
Elaborai o procedur care:
a) calculeaz rdcinile ecuaiei ax2+bx+c=0;
b) radiaz dintr-un ir caracterul indicat n apel;
c) ncadreaz un ir de caractere ntre simbolurile #;

13

d) ordoneaz componentele unui tablou array [1..100] of real n ordine cresctoare;


e) ordoneaz componentele unui fiier file of integer n ordine descresctoare;
f) calculeaz i depune ntr-un tablou numerele prime mai mici dect un numr natural dat n.
Se consider urmtoarele tipuri de date
type Data = record
Ziua : 1..31;
Luna : 1..12;
Anul : integer;
end;
Persoana = record
NumePrenume : string;
DataNasterii : Data;
end;
ListaPersoane = array [1..50] of Persoana;
Elaborai o procedur care primete din programul principal o list de persoane i restituie:
a) persoanele nscute n ziua z a lunii;
b) persoanele nscute n luna l a anului;
c) persoanele nscute n anul a;
d) persoanele nscute pe data z.l.a;
e) persoana cea mai n vrst;
f) persoana cea mai tnr;
g) vrsta fiecrei persoane n ani, luni, zile;
h) lista persoanelor care au mai mult de v ani;
i) lista persoanelor n ordine alfabetic;
j) lista persoanelor ordonat conform datei naterii;
k) lista persoanelor de aceeai vrst (nscui n acelai an).
Elaborai o procedur care:
a) creeaz o copie de rezerv a unui fiier text;
b) exclude dintr-un fiier text liniile vide;
c) numeroteaz liniile unui fiier text;
d) concateneaz dou fiiere text ntr-unul singur;
e) concateneaz n fiiere text (n >2) ntr-unul singur.
Vom numi mari numerele naturale care conin mai mult de 20 de cifre semnificative. S
se defineasc un tip de date pentru numerele naturale mari i s se scrie proceduri care
s adune i s scad astfel de numere.

1.4. Domenii de vizibilitate


Corpul unui program sau subprogram se numete bloc. Deoarece subprogramele
snt incluse n programul principal i pot conine la rndul lor alte subprograme, re-

14

zult c blocurile pot fi imbricate (incluse unul n altul). Aceast imbricare de blocuri
este denumit structura de bloc a programului PASCAL.
ntr-o structur fiecrui bloc i se ataeaz cte un nivel de imbricare. Programul
principal este considerat de nivel 0, un bloc definit n programul principal este de
nivel 1. n general, un bloc definit n nivelul n este de nivelul n + 1.
Pentru exemplificare, n figura 1.2 este prezentat structura de bloc a programului P105.
Program P105;
{ Structura de bloc a programului }
var a : real;
{1}

{nivel 0}

procedure P(b : real);


var c : real;
{2}

{nivel 1}

procedure Q(d : integer);


{3}
var c : char;
{4}
begin
c:=chr(d);
writeln(In procedura Q
end; {5}
begin
writeln(b=, b);
c:=b+1;
writeln(In procedura P
Q(35);
end; {6}

{nivel 2}

c=, c);

c=, c);

function F(x : real) : real;


begin
f:=x/2;
end;

{nivel 1}

begin
a:=F(5);
writeln(a=, a);
P(a);
readln;
end {7}.
Fig. 1.2. Structura de bloc a unui program PASCAL

15

De regul, un bloc PASCAL include declaraii de etichete, variabile, funcii, parametri .a.m.d. O declaraie introduce un nume, care poate fi o etichet sau un identificator. O declaraie dintr-un bloc poate redefini un nume declarat n exteriorul lui.
n consecin, n diferite pri ale programului unul i acelai nume poate desemna
obiecte diferite.
Prin domeniul de vizibilitate al unei declaraii se nelege textul de program,
n care numele introdus desemneaz obiectul specificat de declaraia n studiu.
Domeniul de vizibilitate ncepe imediat dup terminarea declaraiei i se sfrete
odat cu textul blocului respectiv. Deoarece blocurile pot fi imbricate, domeniul de
vizibilitate nu este neaprat o poriune continu din textul programului. Domeniul
de vizibilitate al unei declaraii dintr-un bloc inclus acoper domeniul de vizibilitate
al declaraiei ce implic acelai nume din blocul exterior.
De exemplu, n programul P105 domeniul de vizibilitate al declaraiei var a :
real este textul cuprins ntre punctele marcate {1} i {7}. Domeniul de vizibilitate
al declaraiei var c : real este format din dou fragmente de text cuprinse ntre
{2}, {3} i {5}, {6}. Domeniul de vizibilitate al declaraiei var c : char este
textul cuprins ntre {4} i {5}.
Cunoaterea domeniilor de vizibilitate ale declaraiilor este necesar pentru determinarea obiectului curent desemnat de un nume.
De exemplu, identificatorul c din instruciunea
c:=chr(d)
a programului P105 desemneaz o variabil de tip char. Acelai identificator din
instruciunea
c:=b+1
desemneaz o variabil de tip real.
De reinut c declaraia unui nume de funcie/procedur se consider terminat
la sfritul antetului. Prin urmare, domeniul de vizibilitate al unei astfel de declaraii
include i corpul funciei/procedurii respective. Acest fapt face posibil apelul recursiv: n corpul funciei/procedurii aceasta poate fi referit, fiind vizibil. Evident,
declaraia unui parametru formal este vizibil numai n corpul subprogramului respectiv.
De exemplu, domeniul de vizibilitate al declaraiei procedure Q este textul
cuprins ntre punctele marcate {3}i {6}. Domeniul de vizibilitate al declaraiei
d:integer este textul cuprins ntre {3}i {5}.

ntrebri i exerciii
Cum se determin domeniul de vizibilitate al unei declaraii?
Determinai domeniile de vizibilitate ale declaraiilor b : real i x : real din programul P105 (fig.1.2).
Precizai structura de bloc a programului ce urmeaz. Indicai domeniul de vizibilitate al
fiecrei declaraii i determinai obiectele desemnate de fiecare apariie a identificatorilor c i x.

16

Program P106;
{Redefinirea constantelor }
const c=1;
function F1(x : integer) : integer;
begin
F1:=x+c;
end; { F1 }
function F2(c : real) : real;
const x=2.0;
begin
F2:=x+c;
end; { F2 }
function F3(x : char) : char;
const c=3;
begin
F3:=chr(ord(x)+c);
end; { F3 }
begin
writeln(F1=, F1(1));
writeln(F2=, F2(1));
writeln(F3=, F3(1));
readln;
end.
Ce va afia pe ecran programul n studiu?
Determinai domeniile de vizibilitate ale identificatorilor P i F din programul P105 (fig.1.2).
Comentai programul ce urmeaz:
Program P107;
{ Eroare }
var a : real;
procedure P(x : real);
var a : integer;
begin
a:=3.14;
writeln(x+a);
end; { P }
begin
a:=3.14;
P(a);
end.
Cum se determin obiectul desemnat de apariia unui nume ntr-un program PASCAL?

17

1.5. Comunicarea prin variabile globale


Execuia unui apel de subprogram presupune transmiterea datelor de prelucrat
funciei sau procedurii respective. Dup executarea ultimei instruciuni din subprogram, rezultatele produse trebuie ntoarse n locul de apel. Cunoatem deja c datele de
prelucrat i rezultatele produse pot fi transmise prin parametri. Parametrii formali se
specific n antetul funciei sau procedurii, iar parametrii actuali n locul apelului.
n completare la modul de transmitere a datelor prin parametri, limbajul PASCAL
permite comunicarea prin variabile globale.
Orice variabil este local n subprogramul n care a fost declarat. O variabil
este global relativ la un subprogram atunci cnd ea este declarat n programul
sau subprogramul ce l cuprinde fr s fie redeclarat n subprogramul n studiu.
ntruct variabilele globale snt cunoscute att n subprogram, ct i n afara lui, ele
pot fi folosite pentru transmiterea datelor de prelucrat i returnarea rezultatelor.
Exemplu:
Program P108;
{Comunicarea prin variabile globale }
var a,
{variabil global n P }
b : real;
{variabil global n P, F }
procedure P;
var c : integer;
begin
c:=2;
b:=a*c;
end; { P }

{variabil local n P }

function F : real;
var a : 1..5;
{variabil local n F }
begin
a:=3;
F:=a+b;
end; { F }
begin
a:=1;
P;
writeln(b);
writeln(F);
readln;
end.

{se afieaz 2.0000000000E+00 }


{se afieaz 5.0000000000E+00 }

Datele de prelucrat se transmit procedurii P prin variabila global a. Rezultatul


produs de procedur se returneaz n blocul de apel prin variabila global b. Valoarea

18

argumentului funciei F se transmite prin variabila global b. Menionm c variabila a este local n F i nu poate fi folosit pentru transmiterea datelor n aceast
funcie.
De obicei, comunicarea prin variabile globale se utilizeaz n cazurile n care mai
multe subprograme prelucreaz aceleai date. Pentru exemplificare amintim funciile cu argumente de tip tablou, procedurile care prelucreaz tablouri i fiiere de
angajai, persoane, elevi etc.

ntrebri i exerciii
Explicai termenii variabil global relativ la un subprogram i variabil local ntr-un
subprogram.
Numii variabilele globale i variabilele locale din programul P105 (fig.1.2).
Poate fi oare o variabil local n acelai timp i o variabil global relativ la un subprogram?
Numii variabilele globale i variabilele locale din programul ce urmeaz. Ce va afia pe
ecran acest program?
Program P109;
{Comunicarea prin variabile globale }
var a : integer;
procedure P;
var b, c, d : integer;
procedure Q;
begin
c:=b+1;
end; { Q }
procedure R;
begin
d:=c+1;
end; { R }
begin
b:=a;
Q;
R;
a:=d;
end; { P }
begin
a:=1;
P;
writeln(a);
readln;
end.

19

Se consider declaraiile
Type

Ora=0..23;
Grade=-40..+40;
Temperatura=array [Ora] of Grade;

Componentele unei variabile de tip Temperatura reprezint temperaturile msurate


din or n or pe parcursul a 24 de ore. Elaborai o procedur care:
a) indic maximumul i minimumul temperaturii;
b) indic ora (orele) la care s-a nregistrat o temperatur maxim;
c) nscrie ora (orele) la care s-a nregistrat o temperatur minim ntr-un fiier text.
Comunicarea cu procedurile respective se va face prin variabile globale.
Se consider fiiere arbitrare de tip text. Elaborai o funcie care:
a) returneaz numrul de linii dintr-un fiier;
b) calculeaz numrul de vocale dintr-un text;
c) calculeaz numrul de cuvinte dintr-un text (cuvintele reprezint iruri de caractere
separate prin spaiu sau sfrit de linie);
d) returneaz lungimea medie a liniilor din text;
e) calculeaz lungimea medie a cuvintelor din text;
f) returneaz numrul semnelor de punctuaie din text.
Comunicarea cu funciile respective se va face prin variabile globale.

1.6. Efecte colaterale


Destinaia unei funcii este s ntoarc ca rezultat o singur valoare. n mod
obinuit, argumentele se transmit funciei prin parametri-valoare, iar rezultatul
calculat se returneaz n locul de apel prin numele funciei. n completare, limbajul PASCAL permite transmiterea argumentelor prin variabile globale i parametri-variabil.
Prin efect colateral se nelege o atribuire (n corpul funciei) a unei valori la o variabil global sau la un parametru formal variabil. Efectele colaterale pot influena
n mod neateptat execuia unui program i complic procesele de depanare.
Prezentm n continuare exemple defectuoase de programare, care folosesc funcii cu efecte colaterale.
Program P110;
{Efect colateral - atribuire la o variabil global}
var a : integer; { variabil global }
function F(x : integer) : integer;
begin
F:=a*x;
a:=a+1;
{atribuire defectuoas }
end; { F }
begin
a:=1;

20

writeln(F(1));
writeln(F(1));
writeln(F(1));
readln;
end.

{ se afieaz 1 }
{ se afieaz 2 }
{ se afieaz 3 }

n programul P110 funcia F returneaz valoarea expresiei a*x. Pe lng aceasta


ns, atribuirea a:=a+1 altereaz valoarea variabilei globale a. n consecin, pentru
una i aceeai valoare 1 a argumentului x funcia returneaz rezultate diferite, fapt
ce nu se ncadreaz n conceptul uzual de funcie.
Program P111;
{Efect colateral - atribuire la un parametru formal}
var a : integer;
function F(var x : integer) : integer;
begin
F:=2*x;
x:=x+1;
{ atribuire defectuoas }
end; { F }
begin
a:=2;
writeln(F(a));
writeln(F(a));
writeln(F(a));
readln;
end.

{ se afieaz 4 }
{ se afieaz 6 }
{ se afieaz 8 }

n programul P111 funcia F returneaz valoarea expresiei 2*x. ntruct x este


un parametru formal variabil, atribuirea x:=x+1 schimb valoarea parametrului
actual din apel, i anume a variabilei a din programul principal. Faptul c apelurile
textual identice F(a), F(a) i F(a) returneaz rezultate ce difer poate crea confuzii n procesul depanrii.
n cazul procedurilor, atribuirile asupra variabilelor globale produc efecte colaterale similare celor discutate pentru astfel de atribuiri la funcii. ntruct mijlocul-standard de ntoarcere de rezultate din procedur este prin parametri formali
variabil, atribuirile asupra unor astfel de parametri nu snt considerate ca efecte
colaterale.
Efectele colaterale introduc abateri de la procesul-standard de comunicare, prin
care variabilele participante snt desemnate explicit ca parametri formali n declaraie i parametri actuali n apel. Consecinele efectelor colaterale se pot propaga
n domeniul de vizibilitate al declaraiilor globale i pot interfera cu cele similare,
produse la execuia altor proceduri i funcii. n astfel de condiii, utilizarea variabilelor globale devine riscant. Prin urmare, la elaborarea programelor complexe se
vor aplica urmtoarele recomandri:

21

1. Comunicarea funciilor cu mediul de chemare se va face prin transmiterea de


date spre funcie prin parametri formali valoare i ntoarcerea unui singur rezultat
prin numele ei.
2. Comunicarea procedurilor cu mediul de chemare se va face prin transmiterea
de date prin parametri formali valoare sau variabil i ntoarcerea rezultatelor prin
parametri formali variabil.
3. Variabilele globale pot fi folosite pentru transmiterea datelor n subprograme,
ns valorile lor nu trebuie s fie schimbate de acestea.

ntrebri i exerciii
Care este cauza efectelor colaterale? Ce consecine pot avea aceste efecte?
Precizai ce vor afia pe ecran programele ce urmeaz:
Program P112;
{Efecte colaterale }
var a, b : integer;
function F(x : integer) : integer;
begin
F:=a*x;
b:=b+1;
end; { F }
function G(x : integer) : integer;
begin
G:=b+x;
a:=a+1;
end; { G }
begin
a:=1; b:=1;
writeln(F(1));
writeln(G(1));
writeln(F(1));
writeln(G(1));
readln;
end.
Program P113;
{Efecte colaterale }
var a : integer;
b : real;
function F(var x : integer) : integer;
begin
F:=x;
x:=x+1;
end; { F }

22

procedure P(x,y:integer; var z:real);


begin
z:=x/y;
end; { P }
begin
a:=1;
P(F(a), a, b);
writeln(a,
, b);
readln;
end.
Program P114;
{Efecte colaterale }
var a, b : real;
procedure P(var x, y : real);
{Interschimbarea valorilor variabilelor x, y }
begin
a:=x;
x:=y;
y:=a;
end; { P }
begin
a:=1; b:=2;
P(a, b);
writeln(a, b);
a:=3; b:=4;
P(a, b);
writeln(a, b);
readln;
end.
Cum pot fi evitate efectele colaterale?

1.7. Recursia
Recursia se definete ca o situaie n care un subprogram se autoapeleaz fie direct, fie prin intermediul altei funcii sau proceduri. Subprogramul care se autoapeleaz se numete recursiv.
De exemplu, presupunem c este definit tipul
type Natural = 0..MaxInt;
Funcia factorial

23

dac
dac
poate fi exprimat n PASCAL, urmnd direct definiia, n forma:
function F(n : Natural) : Natural;
begin
if n=0 then F:=1
else F:=n*F(n-1)
end; {F}

Efectul unui apel F(7) este declanarea unui lan de apeluri ale funciei F pentru
parametrii actuali 6, 5, ..., 2, 1, 0:
F(7) -> F(6) -> F(5) -> ... -> F(1) -> F(0).

Apelul F(0) determin evaluarea direct a funciei i oprirea procesului repetitiv; urmeaz revenirile din apeluri i evaluarea lui F pentru 1, 2, ..., 6, 7, ultima
valoare fiind ntoarcerea n locul primului apel.
Funcia
dac
dac
dac
are ca valori numerele lui Fibonacci. Urmnd definiia, obinem:
function Fib(n:Natural):Natural;
begin
if n=0 then Fib:=0
else if n=1 then Fib:=1
else Fib:=Fib(n-1)+Fib(n-2)
end; {Fib}

Fiecare apel al funciei Fib pentru n > 1 genereaz dou apeluri Fib(n-1),
Fib(n-2) .a.m.d., de exemplu:
Fib(4) ->
Fib(3), Fib(2) ->
Fib(2), Fib(1), Fib(1), Fib(0) ->
Fib(1), Fib(0).

Din exemplele n studiu se observ c recursia este util pentru programarea unor calcule repetitive. Repetiia este asigurat prin execuia unui subprogram care conine un apel
la el nsui: cnd execuia ajunge la acest apel, este declanat o nou execuie .a.m.d.
Evident, orice subprogram recursiv trebuie s includ condiii de oprire a procesului repetitiv. De exemplu, n cazul funciei factorial procesul repetitiv se oprete cnd n
ia valoarea 0; n cazul funciei Fib procesul se oprete cnd n ia valoarea 0 sau 1.
La orice apel de subprogram, n memoria calculatorului vor fi depuse urmtoarele informaii:

24

valorile curente ale parametrilor transmii prin valoare;


locaiile (adresele) parametrilor-variabil;
adresa de retur, adic adresa instruciunii ce urmeaz dup apel.
Prin urmare, la apeluri recursive spaiul ocupat din memorie va crete rapid,
riscnd depirea capacitii de memorare a calculatorului. Astfel de cazuri pot fi
evitate, nlocuind recursia prin iteraie (instruciunile for, while, repeat). Pentru
exemplificare prezentm o form nerecursiv a funciei factorial:
function F(n: Natural): Natural;
var i, p : Natural;
begin
p:=1;
for i:=1 to n do p:=p*i;
F:=p;
end; {F}

Recursia este deosebit de util n cazurile n care elaborarea unor algoritmi nerecursivi este foarte complicat: translatarea programelor PASCAL n limbajul codmain, grafica pe calculator, recunoaterea formelor .a.

ntrebri i exerciii
Cum se execut un subprogram recursiv? Ce informaii se depun n memoria calculatorului la execuia unui apel recursiv?
Care este diferena dintre recursie i iteraie?
Elaborai o form nerecursiv a funciei lui Fibonacci.
Scriei un subprogram recursiv care:
a) calculeaz suma S(n)=1+3+5+...+(2n1);
b) calculeaz produsul P(n) = 1 4 7 ... (3n 2);
c) inverseaz un ir de caractere;
d) calculeaz produsul P(n) = 2 4 6 ... 2n.
Elaborai un program care citete de la tastatur numerele naturale m, n i afieaz pe
ecran valoarea funciei lui Ackermann:

dac
dac
dac
Calculai a(0, 0), a(1, 2), a(2, 1) i a(2, 2). ncercai s calculai a(4, 4) i a(10, 10). Explicai
mesajele afiate pe ecran.
Se consider declaraia
type Vector=array [1..20] of integer;
Elaborai un subprogram recursiv care:
a) afieaz componentele vectorului pe ecran;
b) calculeaz suma componentelor;

25

c) inverseaz componentele vectorului;


d) calculeaz suma componentelor pozitive;
e) verific dac cel puin o component a vectorului este negativ;
f) calculeaz produsul componentelor negative;
g) verific dac cel puin o component a vectorului este egal cu un numr dat.
Elaborai o form nerecursiv a funciei ce urmeaz:
function S(n:Natural):Natural;
begin
if n=0 then S:=0
else S:=n+S(n-1)
end; {S}
Scriei o funcie recursiv care returneaz valoarea true dac irul de caractere s este
conform definiiei
<Numr>::=<Cifr>|<Cifr><Numr>
Indicaie. Forma unei astfel de funcii deriv din formula metalingvistic. Varianta nerecursiv
function N(s : string) : boolean;
var
i : integer;
p : boolean
begin
p:=(s<>);
for i=1 to length(s) do
p:=p and (s[i] in [0..9]);
N:=p;
end;
deriv din definiia
<Numr>::=<Cifr>{<Cifr>}
Se consider urmtoarele formule metalingvistice:
<Numr>::=<Cifr>{<Cifr>}
<Semn>::=+|
<Expresie>::=<Numr>|<Expresie><Semn><Expresie>
Scriei o funcie recursiv care returneaz valoarea true dac irul de caractere s este
conform definiiei unitii lexicale <Expresie>.

1.8. Sintaxa declaraiilor i apelurilor de subprograme


n general, definirea unei funcii se face cu ajutorul urmtoarelor formule metalingvistice:
<Funcie> ::= <Antet funcie>; <Corp>
| <Antet funcie>; <Directiv>
| function <Identificator>; <Corp>

26

<Antet funcie> ::=


function <Identificator> [<List parametri formali>] : <Identificator>
Diagramele sintactice snt prezentate n figura 1.3.

function

function

Fig. 1.3. Sintaxa declaraiilor de funcii

Procedurile se definesc cu ajutorul urmtoarelor formule:


<Procedur>::=<Antet procedur>;<Corp> | <Antet procedur>;<Directiv>
| procedure <Identificator>;<Corp>
<Antet procedur> := procedure <Identificator> [<List parametri formali>]
Diagramele sintactice snt prezentate n figura 1.4.

Antet procedur

procedure
<Antet procedur>
procedure

Fig. 1.4. Sintaxa declaraiilor de proceduri

27

Listele de parametri formali au urmtoarea sintax:


<List parametri formali> ::=
(<Parametru formal> {; <Parametru formal>})
<Parametru formal> ::=
[var] <Identificator> {, <Identificator>} : <Identificator>
| <Antet funcie>
| <Antet procedur>
Diagrama sintactic este prezentat n figura 1.5.
<List parametri formali>
(

var

Identificator

,
Identificator
Antet funcie
Antet procedur

;
Fig. 1.5. Diagrama sintactic <List parametri formali>

Amintim c n lipsa cuvntului-cheie var identificatorii din list specific parametrii-valoare. Cuvntul var prefixeaz parametrii-variabil. Antetul unei funcii
(proceduri) din list specific un parametru-funcie (procedur). n Turbo PASCAL
astfel de parametri se declar explicit ca aparinnd unui tip procedural i au forma
parametrilor-valoare. Limbajul PASCAL extinde sensul uzual al noiunii de funcie,
permind returnarea valorilor nu numai prin numele funciei, ci i prin parametrivariabil.
Un apel de funcie are forma:
<Apel funcie> ::= <Nume funcie > [<List parametri actuali>]
iar o instruciune apel de procedur:
<Apel procedur> ::= <Nume procedur > [<List parametri actuali>]
Parametrii actuali se specific cu ajutorul formulelor:
<List parametri actuali> ::= (<Parametru actual > {,<Parametru actual>})
<Parametru actual > ::=<Expresie> | <Variabil> | <Nume funcie>
| <Nume procedur >
Diagrama sintactic este prezentat n figura 1.6.

28

<Apel funcie>
<Nume funcie>

List parametri actuali

<Apel procedur>
Nume procedur

List parametri actuali

<List parametri actuali>


(

Expresie

Variabil
Nume funcie
Nume procedur
,
Fig. 1.6. Sintaxa apelurilor de funcii i proceduri

Corespondena ntre un parametru actual i parametrul formal se face prin poziia ocupat de acetia n cele dou liste.
n cazul unui parametru-valoare drept parametru actual poate fi utilizat orice expresie, n particular, o constant sau o variabil. Expresia respectiv trebuie
s fie compatibil din punctul de vedere al atribuirii cu tipul parametrului formal.
Modificrile parametrilor-valoare nu se transmit n exteriorul subprogramului.
n cazul unui parametru-variabil drept parametri actuali pot fi utilizate numai variabile. Modificrile parametrilor-variabil se transmit n exteriorul subprogramului.
n cazul unui parametru-funcie (procedur) drept parametru actual poate fi utilizat orice nume de funcie (procedur), antetul creia are forma specificat n lista
parametrilor formali.

ntrebri i exerciii
Cnd se utilizeaz declaraiile de forma
function <Identificator>; <Corp> ?
Indicai pe diagramele sintactice din figurile1.3 i 1.5 drumurile care corespund declaraiilor de funcii din programul P106, paragraful 1.4.
Care este diferena dintre un parametru-valoare i un parametru-variabil?
Indicai pe diagramele sintactice din figurile1.4 i 1.5 drumurile care corespund declaraiilor de proceduri din programul P101, paragraful 1.3.
Indicai pe diagramele sintactice din figurile1.31.6 drumurile care corespund declaraiilor i apelurilor de subprograme din programul P105, paragraful1.4.

29

Capitolul 2
STRUCTURI DINAMICE
DE DATE
2.1. Variabile dinamice. Tipul referin
Variabilele declarate n seciunea var a unui program sau subprogram se numesc variabile statice. Numrul variabilelor statice se stabilete n momentul scrierii
programului i nu poate fi schimbat n timpul execuiei. Exist ns situaii n care
numrul necesar de variabile nu este cunoscut din timp.
De exemplu, presupunem c este necesar prelucrarea datelor referitoare la persoanele care formeaz un ir de ateptare (o coad) la o cas de bilete. Lungimea
cozii este nedefinit. De fiecare dat cum apare o persoan nou, trebuie s se creeze
o variabil de tipul respectiv. Dup ce persoana pleac, variabila corespunztoare
devine inutil.
Variabilele care snt create i eventual distruse n timpul execuiei programului se
numesc variabile dinamice.
Accesul la variabilele dinamice se face prin intermediul variabilelor de tip referin. De obicei, un tip referin se definete printr-o declaraie de forma:
type Tr = ^Tb;

unde Tr este numele tipului referin, iar Tb este tipul de baz. Semnul ^ se citete
adres. Evident, pot fi utilizate i tipuri referin anonime. Diagrama sintactic
<Tip referin> este prezentat n figura 2.1.

<Tip referin>
^

Tip

Fig. 2.1. Diagrama sintactic <Tip referin>

Mulimea de valori ale unui tip de date referin const din adrese. Fiecare adres
identific o variabil dinamic ce aparine tipului de baz. La aceast mulime de
adrese se mai adaug o valoare special, notat nil (zero), care nu identific nicio
variabil.
Exemplu:
type AdresaInteger=^integer;
AdresaChar=^char;

30

var

i : AdresaInteger;
r : ^real;
c : AdresaChar;

Valoarea curent a variabilei i va indica o variabil dinamic de tipul integer. ntr-un mod similar, variabilele de tip referin r i c identific variabile de tipul real i, respectiv, char. Subliniem faptul c tipurile de date AdresaInteger,
AdresaChar i tipul anonim ^real snt tipuri referin distincte.
Operaiile care se pot face cu valorile unui tip de date referin snt = i <>. Valorile
de tip referin nu pot fi citite de la tastatur i afiate pe ecran.
Crearea unei variabile dinamice se realizeaz cu procedura predefinit new (nou).
Apelul acestei proceduri are forma
new(p)

unde p este o variabil de tip referin.


Procedura aloc spaiu de memorie pentru variabila nou-creat i returneaz
adresa zonei respective prin variabila p. n continuare variabila dinamic poate fi
accesat prin aa-zisa dereperare: numele variabilei de tip referin p este urmat de
semnul de ^. Dereperarea unei variabile de tip referin cu coninutul nil va declana o eroare de execuie.
Exemplu:
new(i); i^:=1 crearea unei variabile dinamice de tipul integer; variabilei
create i se atribuie valoarea 1;
new(r); r^:=2.0 crearea unei variabile dinamice de tipul real; variabilei
create i se atribuie valoarea 2.0;
new(c); c^:=* crearea unei variabile dinamice de tipul char; variabilei
create i se atribuie valoarea *.
Subliniem faptul c variabila dinamic p^ obinut printr-un apel new(p) este
distinct de toate variabilele create anterior. Prin urmare, executarea instruciunilor
new(p); new(p); ...; new(p)

conduce la crearea unui ir v1 , v2 , ..., vn de variabile dinamice. Numai ultima variabil


creat, vn , este referit prin p^. ntruct valorile variabilelor de tip referin reprezint adresele anumitor zone din memoria intern a calculatorului, variabilele n studiu
se numesc indicatori de adres.
Distrugerea unei variabile dinamice i eliberarea zonei respective de memorie se
realizeaz cu procedura predefinit dispose (a dispune). Apelul acestei proceduri
are forma:
dispose(p)
unde p este o variabil de tip referin.
Exemple:
dispose(i); dispose(r); dispose(c)

31

Dup executarea instruciunii dispose(p) valoarea variabilei de tip referin p


este nedefinit.
Asupra variabilelor dinamice se pot efectua toate operaiile admise de tipul de
baz.
Exemplu:
Program P117;
{Operaii cu variabile dinamice }
type AdresaInteger=^integer;
var i, j, k : AdresaInteger;
r, s, t : ^real;
begin
{crearea variabilelor dinamice de tipul integer }
new(i); new(j); new(k);
{operaii cu variabilele create }
i^:=1; j^:=2;
k^:=i^+j^;
writeln(k^);
{crearea variabilelor dinamice de tipul real }
new(r); new(s); new(t);
{operaii cu variabilele create }
r^:=1.0; s^:=2.0;
t^:=r^/s^;
writeln(t^);
{distrugerea variabilelor dinamice }
dispose(i); dispose(j); dispose(k);
dispose(r); dispose(s); dispose(t);
readln;
end.

Spre deosebire de variabilele statice, care ocup zone de memorie stabilite de


compilator, variabilele dinamice ocup zone de memorie oferite de procedura new.
Zonele respective snt eliberate de procedura dispose i pot fi reutilizate pentru
crearea unor variabile dinamice noi. Prin urmare, procedurile new i dispose asigur alocarea (rezervarea) dinamic a memoriei: spaiul de memorie este atribuit
unei variabile dinamice numai pe durata existenei ei.
Numrul de variabile dinamice ce pot exista concomitent n timpul execuiei unui
program PASCAL depinde de tipul variabilelor i spaiul de memorie disponibil.
n cazul n care tot spaiul de memorie este deja ocupat, apelul procedurii new va
declana o eroare de execuie.
Exemplu:
Program P118;
{Eroare: depirea capacitii memoriei }
label 1;
var i : ^integer;

32

begin
1 : new(i);
goto 1;
end.

Alocarea dinamic a memoriei necesit o atenie sporit din partea programatorului care este obligat s asigure crearea, distrugerea i referirea corect a variabilelor dinamice.

ntrebri i exerciii
Care este diferena dintre variabilele statice i variabilele dinamice?
Cum se identific variabilele dinamice?
Indicai pe diagrama sintactic din figura2.1 drumurile care corespund declaraiilor de
tipuri referin din programul P117.
Se consider declaraiile:
type AdresaReal=^real;
var r : AdresaReal;
Precizai mulimea de valori ale tipului de date AdresaReal i mulimea de valori pe
care le poate lua variabila dinamic r^.
Ce operaii se pot efectua cu valorile unui tip de date referin? Cu variabilele dinamice?
Se consider declaraiile:
type AdresaTablou = ^array [1..10] of integer;
var t : AdresaTablou;
Precizai mulimea de valori ale tipului de date AdresaTablou i mulimea de valori
pe care le poate lua variabila dinamic t^.
Comentai programul:
Program P119;
{Eroare }
var r, s : ^real;
begin
r^:=1; s^:=2;
writeln(r^=, r^,
readln;
end.

s^=, s^);

Elaborai un program n care se creeaz dou variabile dinamice de tipul ir de caractere.


Atribuii valori variabilelor create i afiai la ecran rezultatul concatenrii irurilor respective.
Ce va afia pe ecran programul ce urmeaz?
Program P120;
var i : ^integer;

33

begin
new(i); i^:=1;
new(i); i^:=2;
new(i); i^:=3;
writeln(i^);
readln;
end.
Comentai programul:
Program P121;
{Eroare }
var i, j : ^integer;
begin
new(i);
i^:=1;
dispose(i);
new(j);
j^:=2;
dispose(j);
writeln(i^=, i^,
readln;
end.

j^=, j^);

Explicai expresia alocarea dinamic a memoriei.

2.2. Structuri de date


O structur de date este format din datele propriu-zise i relaiile dintre ele. n
funcie de modul de organizare, o structur de date poate fi implicit sau explicit.
Tablourile, irurile de caractere, articolele, fiierele i mulimile studiate n capitolele precedente snt structuri implicite de date. Relaiile dintre componentele acestor
sructuri snt predefinite i nemodificabile. De exemplu, toate componentele unui ir
de caractere au un nume comun, iar caracterul s[i+1] este succesorul caracterului
s[i] n virtutea poziiei ocupate.
ntruct structura tablourilor, irurilor de caractere, articolelor, mulimilor i fiierelor nu se modific n timpul execuiei oricrui program sau subprogram, variabilele respective reprezint structuri statice de date.
Folosind date cu structur implicit, putem rezolva reprezentativ o clas limitat
de probleme. n multe cazuri relaiile dintre componente nu numai c se modific
dinamic, dar n acelai timp pot deveni deosebit de complexe.
De exemplu, n cazul unui fir de ateptare la o cas de bilete relaiile dintre persoane se modific: persoanele nou-sosite se aaz la rnd; persoanele n criz de timp
pleac far s-i mai procure bilete; persoanele care au plecat pentru un timp i pstreaz rndul .a.m.d. n cazul proiectrii asistate de calculator a reelelor de circula-

34

ie, staiile, rutele, capacitatea de trafic .a. pot fi stabilite interactiv de ctre utilizator.
n astfel de situaii utilizarea datelor cu structur implicit devine nenatural, dificil
i ineficient.
Prin urmare, este necesar folosirea unor structuri de date n care relaiile dintre
componente s fie reprezentate i prelucrate n mod explicit. Acest efect se poate
obine atand fiecrei componente o informaie ce caracterizeaz relaiile acesteia
cu alte date ale structurii. n cele mai multe cazuri, informaia suplimentar, numit
informaie de structur, se reprezint prin variabilele de tipul referin.
Structurile de date componentele crora snt create i eventual distruse n timpul execuiei programului se numesc structuri dinamice de date. Structurile dinamice frecvent
utilizate snt: listele unidirecionale, listele bidirecionale, stivele, cozile, arborii .a.
O structur de date este recursiv dac ea poate fi descompus n date cu aceeai
structur. Pentru exemplificare menionm listele unidirecionale i arborii care vor
fi studiai n paragrafele urmtoare.

ntrebri i exerciii
Explicai termenul structur de date. Dai exemple.
Care este diferena dintre structurile implicite i structurile explicite de date?
O structur de date este omogen dac toate componentele snt de acelai tip. n caz
contrar, structura de date este eterogen. Dai exemple de structuri omogene i structuri eterogene de date.
Care este diferena dintre structurile statice i structurile dinamice de date?
Explicai termenul structur recursiv de date.

2.3. Liste unidirecionale


Listele unidirecionale snt structuri explicite i dinamice de date formate din
celule. Fiecare celul este o variabil dinamic de tipul record ce conine, n principal, dou cmpuri: cmpul datelor i cmpul legturilor. Cmpul datelor memoreaz informaia prelucrabil asociat celulei. Cmpul legturilor furnizeaz indicatorul de adres corespunztor celulei la care se poate ajunge din celula curent.
Se consider c orice celul poate fi atins pornind de la o celul privilegiat, numit baza listei.
Pentru exemplificare, n figura 2.2 este prezentat o list unidirecional format
din 4 celule. Celulele conin elementele A, B, C i D.
Datele necesare pentru crearea i prelucrarea unei liste unidirecionale pot fi definite prin declaraii de forma:
type AdresaCelula=^Celula;
Celula=record
Info : string;

35

Urm : AdresaCelula;
end;
var P : AdresaCelula;

Informaia util asociat unei celule se memoreaz n cmpul Info, iar adresa
celulei urmtoare n cmpul Urm. Pentru simplificare se consider c cmpul Info
este de tipul ir de caractere. Ultima celul din list va avea n cmpul Urm valoarea
nil. Adresa primei celule (adresa de baz) este memorat n variabila de tip referin P (fig. 2.2).

P
cmp
date
A

celul

indicator
de adres
B

cmp legturi

nil

Fig. 2.2. Lista unidirecional

Subliniem faptul c n definiia tipului referin AdresaCelula tipul de baz


Celula nc nu este cunoscut. Conform regulilor limbajului PASCAL, acest lucru
este posibil numai n cazul variabilelor dinamice, cu condiia ca tipul de baz s fie
definit mai trziu n aceeai declaraie.
O list unidirecional poate fi creat adugnd la vrful listei cte un element.
Iniial lista n curs de construcie este vid, adic nu conine nicio celul.
Exemplu:
Program P122;
{Crearea listei unidirecionale A->B->C->D }
type AdresaCelula=^Celula;
Celula=record
Info : string;
Urm : AdresaCelula;
end;
var P,
{adresa de baz }
R, V : AdresaCelula;
begin
{1 - iniial lista este vid }
P:=nil;
{2 - adugarea celulei A }
new(R);
{crearea unei celule }
P:=R;
{iniializarea adresei de baz }

36

R^.Info:=A; {ncrcarea informaiei utile }


R^.Urm:=nil; {nscrierea indicatorului sfrit
V:=R;
{memorarea adresei vrfului }
{3 - adugarea celulei B }
new(R);
{crearea unei celule }
R^.Info:=B; {ncrcarea informaiei utile }
R^.Urm:=nil; {nscrierea indicatorului sfrit
V^.Urm:=R;
{crearea legturii A -> B }
V:=R;
{actualizarea adresei vrfului }
{4 - adugarea celulei C }
new(R);
{crearea unei celule }
R^.Info:=C; {ncrcarea informaiei utile }
R^.Urm:=nil; {nscrierea indicatorului sfrit
V^.Urm:=R;
{crearea legturii B -> C }
V:=R;
{actualizarea adresei vrfului }
{5 - adugarea celulei D }
new(R);
{crearea unei celule }
R^.Info:=D; {ncrcarea informaiei utile }
R^.Urm:=nil; {nscrierea indicatorului sfrit
V^.Urm:=R;
{crearea legturii C -> D }
V:=R;
{actualizarea adresei vrfului }
{afiarea listei create }
R:=P;
while R<>nil do begin
writeln(R^.Info);
R:=R^.Urm
end;
readln;
end.

de list }

de list }

de list }

de list }

Procesul de construire a listei n studiu este prezentat n figura 2.3. Variabila V


(adresa vrfului) din programul P122 reine adresa ultimei celule deja create pentru
a-i poziiona indicatorul de adres V^.Urm. Se procedeaz astfel pentru c n momentul n care completm cmpurile R^.Info i R^.Urm ale celulei curente nc nu
se cunoate adresa celulei ce urmeaz.
Listele cu un numr arbitrar de celule pot fi create i afiate cu ajutorul procedurilor respective din programul P123:
Program P123;
{ Crearea listelor unidirectionale}
type AdresaCelula=^Celula;
Celula=record
Info : string;
Urm : AdresaCelula;
end;

37

1 iniial lista este vid


P

2 adugarea celulei A
P
V
A

3 adugarea celulei B
P

V
A

4 adugarea celulei C
V
P
A

5 adugarea celulei D
V
A

V
C

Fig. 2.3. Crearea listei unidirecionale

38

var p,q,r : AdresaCelula;


s : string;
i: integer;
procedure Creare;
begin
p:=nil;
write(s=); readln(s);
new(r); r^.Info:=s; r^.Urm:=nil;
p:=r; q:=r;
write(s=);
while not eof do
begin
readln(s);write(s=);
new(r); r^.Info:=s; r^.Urm:=nil;
q^.Urm:=r; q:=r
end;
end; { Creare }
procedure Afisare;
begin
r:=p;
while r<>nil do
begin
writeln(r^.Info);
r:=r^.Urm;
end;
readln;
end; { Afisare }
begin
Creare;
Afisare;
end.

Orice list unidirecional poate fi definit recursiv dup cum urmeaz:


a) o celul este o list unidirecional;
b) o celul ce conine o legtur ctre o alt list unidirecional este o list unidirecional.
Pentru a sublinia faptul c listele unidirecionale snt structuri recursive de date,
declaraiile respective pot fi transcrise n forma:
type Lista=^Celula;
Celula=record
Info : string;
Urm : Lista
end;
var P : Lista;

39

Proprietile listelor unidirecionale pot fi reproduse parial prin memorarea elementelor respective ntr-un tablou unidimensional. De exemplu, datele din figura 2.2
pot fi reprezentate n forma:
var L : array [1..4] of string;
...
L[1]:= A;
L[2]:= B;
L[3]:= C;
L[4]:= D;
...

ns o astfel de reprezentare nu permite crearea i prelucrarea structurilor de date


cu un numr arbitrar de elemente.

ntrebri i exerciii
Cum se definesc datele necesare pentru crearea unei liste?
Care este destinaia cmpului datelor din componena unei celule? Care este destinaia
cmpului legturilor? Ce informaie se nscrie n acest cmp?
Scriei un program care creeaz lista unidirecional din figura2.2, adugnd cte un element la baza listei.
Elaborai o procedur care schimb cu locul dou elemente din list.
De la tastatur se citesc numere ntregi diferite de zero. Se cere s se creeze dou liste,
una a numerelor negative, iar alta a numerelor pozitive.
Prin ce se explic faptul c listele unidirecionale snt structuri recursive de date?

2.4. Prelucrarea listelor unidirecionale


Operaiile frecvent utilizate n cazul listelor unidirecionale snt:
parcurgerea listei i prelucrarea informaiei utile asociate fiecrei celule;
cutarea unui anumit element, identificat prin valoarea sa;
includerea (inserarea) unui element ntr-un anumit loc din list;
excluderea (tergerea) unui element dintr-o list .a.
Presupunem c exist o list nevid (fig. 2.2) definit prin declaraiile:
type

AdresaCelula=^Celula;
Celula=record;
Info : string;
Urm : AdresaCelula
end;

Variabila P indic adresa de baz a listei n studiu.


Parcurgerea listei se realizeaz conform urmtoarei secvene de instruciuni:

40

R:=P; {poziionare pe celula de baz }


while R<>nil do
begin
{prelucrarea informaiei din cmpul R^.Info }
R:=R^.Urm; { poziionare pe celula urmtoare }
end;

Cutarea celulei ce conine elementul specificat de variabila Cheie este realizat


de secvena:
R:=P;
while R^.Info<>Cheie do R:=R^.Urm;

Adresa celulei n studiu va fi reinut n variabila R.


Subliniem faptul c aceast secven se execut corect numai n cazul n care lista
include cel puin o celul ce conine informaia cutat. n caz contrar, se ajunge la
vrful listei, variabila R ia valoarea nil, iar dereperarea R^ provoac o eroare de
execuie. Pentru a evita astfel de erori, se utilizeaz secvena:
R:=P;
while R<>nil do
begin
if R^.Info=Cheie then goto 1;
R:=R^.Urm
end;
1: ...

ntruct listele unidirecionale snt structuri recursive de date, operaia de cutare


poate fi realizat i de un subprogram recursiv:
type Lista=^AdresaCelula;
Celula=record;
Info : string;
Urm : Lista;
end;
var P : Lista;
...
function Caut(P : Lista; Cheie : string):Lista;
begin
if P=nil then Caut:=nil
else
if P^.Info=Cheie then Caut:=P
else Caut:=Caut(P^.Urm, Cheie)
end;

Funcia Caut returneaz adresa de baz a sublistei ce conine n prima celul,


dac exist, elementul specificat de parametrul Cheie.
Includerea celulei referite de indicatorul Q dup celula referit de indicatorul R
(fig. 2.4) este realizat de secvena de instruciuni:

41

...
...
Q

a)
R

...
...
Q

b)
Fig. 2.4. Includerea unui element n list:
a lista pn la includere; b lista dup includere

Q^.Urm:=R^.Urm;
R^.Urm:=Q;

Excluderea celulei R din list necesit aflarea adresei Q a celulei precedente i


modificarea indicatorului de adres Q^.Urm (fig. 2.5):
Q:=P;
while Q^.Urm<>R do Q:=Q^.Urm;
Q^.Urm:=R^.Urm;

Menionm c includerea sau excluderea elementului din baza listei necesit actualizarea adresei de baz P.
Exemplu:
Program P124;
{Crearea i prelucrarea unei liste unidirecionale }
type AdresaCelula=^Celula;
Celula=record
Info : string;
Urm : AdresaCelula;
end;

42

...
...
a)
Q

...
...
b)
Fig. 2.5. Excluderea unui element din list:
a lista pn la excludere; b lista dup excludere

var P : AdresaCelula; {adresa de baz }


c : char;
procedure Creare;
var R, V : AdresaCelula;
begin
if P<>nil then writeln(Lista exist deja)
else begin
writeln(Dai lista:);
while not eof do
begin
new(R);
readln(R^.Info);
R^.Urm:=nil;
if P=nil then begin P:=R; V:=R end
else begin V^.Urm:=R; V:=R end;
end;
end;
end; {Creare }
procedure Afis;
var R : AdresaCelula;
begin
if P=nil then writeln(Lista este vid)
else begin
writeln(Lista curent:);
R:=P;
while R<>nil do

43

begin
writeln(R^.Info);
R:=R^.Urm;
end;
end;
readln;
end; {Afis }
procedure Includ;
label 1;
var Q, R : AdresaCelula;
Cheie : string;
begin
new(Q);
write(Dai elementul ce urmeaz);
writeln( s fie inclus:);
readln(Q^.Info);
write(Indicai elementul dup care);
writeln( se va face includerea:);
readln(Cheie);
R:=P;
while R<>nil do
begin
if R^.Info=Cheie then goto 1;
R:=R^.Urm;
end;
1:if R=nil then begin
writeln(Element inexistent);
dispose(Q);
end;
else begin
Q^.Urm:=R^.Urm;
R^.Urm:=Q;
end;
end; { Includ }
procedure Exclud;
label 1;
var Q, R : AdresaCelula;
Cheie : string;
begin
write(Dai elementul ce urmeaz);
writeln( s fie exclus:);
readln(Cheie);
R:=P;
Q:=R;

44

while R<>nil do
begin
if R^.Info=Cheie then goto 1;
Q:=R;
R:=R^.Urm;
end;
1:if R=nil then writeln(Element inexistent)
else begin
if R=P then P:=R^.Urm else Q^.Urm:=R^.Urm;
dispose(R);
end;
end; { Exclud }
begin
P:=nil; { iniial lista este vid }
repeat
writeln(Meniu:);
writeln(C - Crearea listei);
writeln(I - Includerea elementului);
writeln(E - Excluderea elementului);
writeln(A - Afiarea listei la ecran);
writeln(O - Oprirea programului);
write(Opiunea=); readln(c);
case c of
C : Creare;
I : Includ;
E : Exclud;
A : Afis;
O :
else writeln(Opiune necunoscut)
end;
until c=O;
end.

Procedura Creare formeaz o list unidirecional cu un numr arbitrar de celule. Informaia util asociat fiecrei celule se citete de la tastatur. Procedura Afis
afieaz elementele listei la ecran. Procedura Includ citete de la tastatur elementul ce urmeaz s fie inclus i elementul dup care se va face includerea. n continuare se caut celula ce conine elementul specificat, dup care, dac exist, este inclus
celula nou-creat. Procedura Exclud caut i elimin, dac exist, celula ce conine
elementul citit de la tastatur.

ntrebri i exerciii
Scriei o funcie nerecursiv care returneaz adresa vrfului listei unidirecionale.
Transcriei aceast funcie ntr-o form recursiv.
Transcriei procedurile Includ i Exclud din programul P124, fr a utiliza instruciunea goto.

45

Se consider urmtoarele tipuri de date:


type

AdresaCandidat=^Candidat;
Candidat=record
NumePrenume : string;
NotaMedie : real;
Urm : AdresaCandidat
end;

Elaborai un program care:


a) creeaz o list unidirecional cu componente de tipul Candidat;
b) afieaz lista pe ecran;
c) exclude din list candidatul care i retrage actele;
d) include n list candidatul care depune actele;
e) afieaz pe ecran candidaii cu media mai mare de 7,5;
f) creeaz o list suplimentar format din candidaii cu media mai mare de 9,0;
g) exclude din list toi candidaii cu media mai mic de 6,0.
Elaborai o procedur care:
a) reordoneaz elementele listei unidirecionale conform unui anumit criteriu;
b) concateneaz dou liste unidirecionale;
c) descompune o list n dou liste;
d) selecteaz din list elementele care corespund unui anumit criteriu.
Elementele listei unidirecionale snt memorate ntr-un tablou unidirecional. Elaborai
procedurile necesare pentru:
a) parcurgerea listei;
b) cutarea unui anumit element;
c) includerea unui element;
d) excluderea unui element.
Care snt avantajele i neajunsurile acestei reprezentri? Se consider c lista va conine
cel mult 100 de elemente.
Scriei o funcie recursiv ce returneaz numrul de celule dintr-o list unidirecional.
Scriei un subprogram recursiv care exclude o anumit celul din list.
Prin cuvnt se nelege orice secven nevid format din literele alfabetului latin.
Elaborai un program care formeaz lista cuvintelor ntlnite ntr-un fiier text i calculeaz numrul de apariii al fiecrui cuvnt. Examinai cazurile:
a) cuvintele se includ n list n ordinea primei lor apariii n text;
b) cuvintele se includ n list n ordine alfabetic.
Se consider c literele mari i mici snt identice.

2.5. Stiva
Prin stiv (n limba englez stack) nelegem o list unidirecional cu proprietatea c operaiile de introducere i extragere a elementelor se fac la un singur capt

46

al ei. Poziia ocupat n stiv de ultimul element introdus poart numele de vrf. O
stiv fr niciun element se numete stiv vid.
Pentru exemplificare, n figura 2.6 este prezentat o stiv care conine elementele
A, B, C.
S

B
S
A

C
B
A
b)

a)
Fig. 2.6. Stiva:
a reprezentarea detaliat; b reprezentarea generalizat

Datele necesare pentru crearea i prelucrarea unei stive pot fi definite prin declaraii de forma:
type AdresaCelula=^Celula;
Celula=record
Info : string;
Prec : AdresaCelula
end;
var S : AdresaCelula;

Adresa vrfului stivei este memorat n variabila de tip referin S. Adresa celulei
precedente din stiv este memorat n cmpul Prec.
Operaia de introducere a unui element n stiv (fig. 2.7) este efectuat de secvena de instruciuni:
new(R); { crearea unei celule }
{ncrcarea informaiei utile n cmpul R^.Info }
R^.Prec:=S; { crearea legturii ctre celula precedent
din stiv }
S:=R; { actualizarea adresei vrfului }

unde R este o variabil de tipul AdresaCelula.

47

S
S

a)

b)

c)

Fig. 2.7. Introducerea i extragerea elementelor din stiv:


a stiva iniial; b introducerea elementului D; c extragerea elementelor D, C

Extragerea unui element din stiv (fig. 2.7) este efectuat de secvena:
R:=S; { memorarea adresei celulei extrase }
{ prelucrarea informaiei din cmpul R^.Info }
S:=S^.Prec; { eliminarea celulei din stiv }
dispose(R); { distrugerea celulei extrase }

Exemplu:
Program P127;
{Crearea i prelucrarea unei stive }
type AdresaCelula=^Celula;
Celula=record
Info : string;
Prec : AdresaCelula;
end;
var S : AdresaCelula; {adresa vrfului }
c : char;
procedure Introduc;
var R : AdresaCelula;
begin
new(R);
write(Dai elementul ce urmeaz);
writeln( s fie introdus:);
readln(R^.Info);
R^.Prec:=S;
S:=R;
end; { Includ }

48

procedure Extrag;
var R : AdresaCelula;
begin
if S=nil then writeln(Stiva este vid)
else begin
R:=S;
write(Este extras);
writeln( elementul:);
writeln(R^.Info);
S:=S^.Prec;
dispose(R);
end;
end; { Extrag }
procedure Afis;
var R : AdresaCelula;
begin
if S=nil then writeln(Stiva este vid)
else begin
writeln(Stiva include elementele:);
R:=S;
while R<>nil do begin
writeln(R^.Info);
R:=R^.Prec;
end;
end;
readln;
end; { Afis }
begin
S:=nil; { iniial stiva este vid }
repeat
writeln(Meniu:);
writeln(I - Introducerea elementului;);
writeln(E - Extragerea elementului);
writeln(A - Afiarea stivei pe ecran);
writeln(O - Oprirea programului);
write(Opiunea=); readln(c);
case c of
I : Introduc;
E : Extrag;
A : Afis;
O :
else writeln(Opiune necunoscut)
end;
until c=O;
end.

49

Stivele mai poart i numele de liste LIFO (last in, first out ultimul element care
a intrat n stiv va fi primul care va iei din ea) i snt frecvent utilizate pentru alocarea dinamic a memoriei n cazul procedurilor i funciilor recursive. Evident, stivele
pot fi simulate utiliznd tablourile unidimensionale array [1..n] of ..., ns o
astfel de reprezentare este limitat de cele n componente ale tablourilor.

ntrebri i exerciii
Care este ordinea de introducere i extragere a datelor din stiv?
De la tastatur se citesc mai multe numere naturale. Afiai numerele n studiu pe ecran
n ordinea invers citirii.
n figura2.8 este reprezentat schema de manevrare a vagoanelor de tren ntr-un depou. Elaborai un program care citete de la tastatur i afieaz pe ecran datele despre
fiecare vagon intrat sau ieit din depou. Datele n studiu includ:
numrul de nmatriculare (integer);
staia de nmatriculare (string);
anul fabricrii (1960..2000);
tipul vagonului (string);
capacitatea de ncrcare (real);
proprietarul vagonului (string).

Intrare

Ieire

Linie moart

Fig. 2.8. Schema de manevrare a vagoanelor de tren

Colectivele temporare de munc snt formate i desfiinate n ordinea ultimul angajat va


fi primul care va fi concediat. Elaborai un program care citete de la tastatur i afieaz
pe ecran datele despre fiecare persoan angajat sau concediat. Datele n studiu includ:
numele (string);
prenumele (string);
anul naterii (1930..1985);
data angajrii (ziua, luna, anul).
Se consider iruri finite de caractere formate din parantezele (, ), [, ], {, }. Un ir este corect numai atunci cnd el poate fi construit cu ajutorul urmtoarelor reguli:
a) irul vid este corect;

50

b) dac A este un ir corect, atunci (A), [A] i {A} snt iruri corecte;
c) dac A i B snt iruri corecte, atunci AB este un ir corect.
De exemplu, irurile ( ), [ ], { }, [( )], ((({[ ]}))([ ])) snt corecte, iar irurile ([, ( )[ ]{{, ([)] nu snt
corecte. Elaborai un program care verific dac irul citit de la tastatur este corect.
Indicaie. Problema poate fi rezolvat printr-o singur parcurgere a irului supus verificrii.
Dac caracterul curent este (, [ sau {, el este depus n stiv. Dac vrful stivei i caracterul
curent formeaz una din perechile (), [] sau {}, paranteza respectiv este scoas din stiv.
n cazul unui ir corect, dup examinarea ultimului caracter din ir stiva rmne vid.
Elementele stivei snt memorate ntr-un tablou unidimensional. Elaborai procedurile necesare pentru introducerea i extragerea elementelor din stiv. Care snt avantajele i neajunsurile acestei reprezentri? Se consider c stiva conine cel mult 100 de elemente.

2.6. Cozi
Prin coad (n englez queue) nelegem o list unidirecional n care toate introducerile se efectueaz la unul din capete, iar extragerile se efectueaz la cellalt
capt. O coad fr niciun element se numete coad vid.
Pentru exemplificare, n figura 2.9 este prezentat o coad care conine elementele A, B, C.
U

a)
U

b)
Fig. 2.9. Coada:
a reprezentarea detaliat; b reprezentarea generalizat

Datele necesare pentru crearea i prelucrarea unei cozi pot fi definite prin declaraii de forma:
type

AdresaCelula=^Celula;
Celula=record
Info : string;

51

Urm : AdresaCelula
end;
var P, U : AdresaCelula;

Adresa primului element din coad este memorat n variabila de tip referin P,
iar adresa ultimului element n variabila U. Adresa celulei urmtoare din coad este
memorat n cmpul Urm.
Operaia de introducere a unui element (fig. 2.10) este efectuat de secvena de
instruciuni:
new(R); {crearea unei celule }
{ncrcarea informaiei utile n cmpul R^.Info }
R^.Urm:=nil; { nscrierea indicatorului ultimul element }
U^.Urm:=R;
{ adugarea celulei la coad }
U:=R;
{ actualizarea adresei ultimei celule }

a)
U

b)
U

c)
Fig. 2.10. Introducerea i extragerea elementelor din coad:
a coada iniial; b introducerea elementului D;
c extragerea elementelor A, B

52

Extragerea unui element din coad (fig. 2.10) este efectuat de secvena:
R:=P; { memorarea adresei primei celule }
{prelucrarea informaiei din cmpul R^.Info }
P:=P^.Urm; {eliminarea primei celule }
dispose(R); {distrugerea celulei extrase }

Exemplu:
Program P128;
{Crearea i prelucrarea unei cozi }
type AdresaCelula=^Celula;
Celula=record
Info : string;
Urm : AdresaCelula;
end;
var P,
{adresa primului element }
U : AdresaCelula; {adresa ultimului element }
c : char;
procedure Introduc;
var R : AdresaCelula;
begin
new(R);
write(Dai elementul ce urmeaz);
writeln( s fie introdus:);
readln(R^.Info);
R^.Urm:=nil;
if P=nil then begin P:=R; U:=R end
else begin U^.Urm:=R; U:=R end;
end; { Introduc }
procedure Extrag;
var R : AdresaCelula;
begin
if P=nil then writeln(Coada este vid)
else begin
R:=P;
write(Este extras);
writeln( elementul:);
writeln(R^.Info);
P:=P^.Urm;
dispose(R);
end;
end; { Extrag }

53

procedure Afis;
var R : AdresaCelula;
begin
if P=nil then writeln(Coada este vid)
else begin
write(Coada include);
writeln( elementele:);
R:=P;
while R<>nil do
begin
writeln(R^.Info);
R:=R^.Urm;
end;
end;
readln;
end; { Afis }
begin
P:=nil; U:=nil; { iniial coada este vid }
repeat
writeln(Meniu:);
writeln(I - Introducerea elementului;);
writeln(E - Extragerea elementului;);
writeln(A - Afiarea cozii la ecran;);
writeln(O - Oprirea programului);
write(Opiunea=); readln(c);
case c of
I : Introduc;
E : Extrag;
A : Afis;
O :
else writeln(Opiune necunoscut)
end;
until c=O;
end.

Cozile mai poart numele de liste FIFO (first in, first out primul element intrat
n coad va fi primul ieit din coad). Menionm c simularea cozilor cu ajutorul tablourilor unidimensionale este ineficient din cauza migrrii elementelor cozii spre
ultima component a tabloului.

ntrebri i exerciii
Elaborai o funcie care returneaz numrul elementelor unei cozi.
Avioanele care solicit aterizarea pe o anumit pist a unui aeroport formeaz un fir de
ateptare. Elaborai un program care citete de la tastatur i afieaz pe ecran datele

54

despre fiecare avion care solicit aterizarea i avionul care aterizeaz. Datele n studiu
includ:
numrul de nmatriculare (integer);
tipul avionului (string);
numrul rutei (integer).
Prin coad cu prioriti vom nelege o coad n care elementul de introdus se insereaz
nu dup ultimul element al cozii, ci naintea tuturor elementelor cu o prioritate mai mic.
Prioritile elementelor se indic prin numere ntregi. Elaborai un program care:
a) creeaz o coad cu prioriti;
b) introduce n coad elementele specificate de utilizator;
c) extrage elementele din coad;
d) afieaz coada cu prioriti pe ecran.

2.7. Arbori binari


Prin nod se nelege o variabil dinamic de tipul record care conine un cmp
destinat memorrii informaiilor utile i doi indicatori de adres.
Arborele binar se definete recursiv dup cum urmeaz:
a) un nod este un arbore binar;
b) un nod ce conine legturi ctre ali doi arbori binari este un arbore binar.
Prin convenie, arborele vid nu conine niciun nod. Pentru exemplificare, n figura 2.11 este prezentat un arbore binar nodurile cruia conin informaia util A, B, C,
D, E, F, G, H, I, J. Datele necesare pentru crearea i prelucrarea unui arbore binar pot
fi definite prin declaraii de forma:
type AdresaNod=^Nod;
Nod=record
Info : string;
Stg, Dr : AdresaNod
end;
var T : AdresaNod;

Pentru a sublinia faptul c arborii binari snt structuri recursive de date, declaraiile n studiu pot fi transcrise n forma:
type Arbore=^Nod;
Nod=record
Info : string;
Stg, Dr : Arbore;
end;
var T : Arbore;

Nodul spre care nu este ndreptat nicio legtur se numete rdcin. Adresa
rdcinii se memoreaz n variabila de tip referin T. n cazul unui arbore vid
T=nil.

55

Cei doi arbori conectai la rdcin se numesc subarborele stng i subarborele


drept. Adresa subarborelui stng se memoreaz n cmpul Stg, iar adresa subarborelui drept n cmpul Dr.
Nivelul unui nod este, prin convenie, 0 pentru nodul-rdcin i i + 1, pentru nodul conectat la un nod de nivelul i. n mod obinuit, n reprezentarea grafic a unui
arbore binar nodurile se deseneaz pe niveluri: rdcina se afl pe nivelul 0, vrfurile
conectate la rdcin pe nivelul 1 .a.m.d. (fig. 2.11).
T
A

a)
nivel 0

nivel 1
nivel 2

B
D

C
E

nivel 3

b)
Fig. 2.11. Arborele binar:
a reprezentarea detaliat; b reprezentarea generalizat

56

Nodurile de pe nivelul i + 1, conectate la un nod de pe nivelul i, se numesc descendenii acestuia. n figura 2.11 nodul B este descendentul stng, iar nodul C este
descendentul drept al nodului A; nodul D este descendentul stng, iar nodul E
descendentul drept al nodului B .a.m.d.
Dac un nod x este descendentul altui nod y, l numim pe acesta din urm printele nodului x. n figura 2.11 nodul A este printele nodurilor B i C; nodul B este
printele nodurilor D i E .a.m.d.
Un nod la care nu este conectat niciun subarbore este un nod terminal. n caz contrar, nodul este neterminal. Prin nlimea arborelui binar nelegem numrul de nivel
maxim asociat nodurilor terminale. Arborele din figura 2.11 are nlimea 3; nodurile
D, H, F, I i J snt noduri terminale; nodurile A, B, C, E i G snt noduri neterminale.
Arborii binari pot fi construii n memoria calculatorului cu ajutorul algoritmilor
iterativi sau algoritmilor recursivi.
Algoritmul iterativ creeaz nodurile n ordinea apariiei lor pe niveluri:
se creeaz nodul-rdcin;
nodul-rdcin se introduce ntr-o coad;
pentru fiecare nod extras din coad se creeaz, dac exist, descendentul stng
i descendentul drept;
nodurile nou-create se introduc n coad;
procesul de construire a arborelui se ncheie cnd coada devine vid.
Nodurile arborelui din figura 2.11 vor fi create de algoritmul iterativ n ordinea:
A, B, C, D, E, F, G, H, I, J.
Un algoritm similar poate fi utilizat pentru parcurgerea arborelui binar i afiarea
nodurilor respective pe ecran:
se creeaz o coad care conine un singur element nodul-rdcin;
fiecare nod extras din coad este afiat pe ecran;
descendenii nodului extras se introduc n coad;
procesul de afiare se ncheie cnd coada devine vid.
Exemplu:
Program P129;
{Crearea unui arbore binar - iteraie }
type AdresaNod=^Nod;
Nod=record
Info : string;
Stg, Dr : AdresaNod
end;
AdresaCelula=^Celula;
Celula=record
Info : AdresaNod;
Urm : AdresaCelula
end;
var T : AdresaNod;
{rdcina }
Prim,
{primul element din coad }
Ultim : AdresaCelula; { ultimul element din coad }

57

procedure IntroduInCoada(Q : AdresaNod);


var R : AdresaCelula;
begin
new(R);
R^.Info:=Q;
R^.Urm:=nil;
if Prim=nil then begin Prim:=R; Ultim:=R end
else begin Ultim^.Urm:=R; Ultim:=R end;
end; {IntroduInCoada}
procedure ExtrageDinCoada(var Q : AdresaNod);
var R : AdresaCelula;
begin
if Prim=nil then writeln(Coada este vid)
else begin
R:=Prim;
Q:=R^.Info;
Prim:=Prim^.Urm;
dispose(R);
end;
end; { ExtrageDinCoada }
procedure CreareArboreBinar;
var R, Q : AdresaNod;
s : string;
begin
T:=nil;
{iniial arborele este vid }
Prim:=nil; Ultim:=nil; {iniial coada este vid }
writeln(Dai rdcina:); readln(s);
if s<> then
begin
new(R); {crearea rdcinii }
R^.Info:=s;
T:=R;
{iniializarea adresei rdcinii }
IntroduInCoada(T);
end;
while Prim<>nil do {ct coada nu e vid }
begin
ExtrageDinCoada(R);
writeln(Dai descendenii nodului, R^.Info);
write( stng: ); readln(s);
if s= then R^.Stg:=nil
else
begin
new(Q); R^.Stg:=Q;
Q^.Info:=s;
IntroduInCoada(Q);
end; { else }

58

write( drept: ); readln(s);


if s= then R^.Dr:=nil
else
begin
new(Q); R^.Dr:=Q;
Q^.Info:=s;
IntroduInCoada(Q);
end; { else }
end; { while }
end; { CreareArboreBinar }
procedure AfisareArboreBinar;
var R : AdresaNod;
begin
if T=nil then writeln(Arbore vid)
else
begin
writeln(Arborele este format din:);
Prim:=nil; Ultim:=nil;
IntroduInCoada(T);
while Prim<>nil do
begin
ExtrageDinCoada(R);
writeln(Nodul , R^.Info);
write( descendeni: );
if R^.Stg=nil then write(nil, )
else begin
write(R^.Stg^.Info, , );
IntroduInCoada(R^.Stg);
end;
if R^.Dr=nil then writeln(nil)
else begin
writeln(R^.Dr^.Info);
IntroduInCoada(R^.Dr);
end;
end; { while }
end; { else }
readln;
end; { AfisareArboreBinar }
begin
CreareArboreBinar;
AfisareArboreBinar;
end.

Informaia util asociat fiecrui nod se citete de la tastatur. Absena descendentului se semnaleaz prin apsarea tastei <ENTER> (programul citete de la tas-

59

tatur un ir vid de caractere). Menionm c coada creat de programul P129 nu


conine nodurile propriu-zise, ci adresele acestor noduri.
Algoritmul recursiv construiete arborii binari urmnd direct definiia respectiv:
se creeaz nodul-rdcin;
se construiete subarborele stng;
se construiete subarborele drept.
Nodurile arborelui binar din figura 2.11 vor fi create de algoritmul recursiv n
ordinea: A, B, D, E, H, C, F, G, I, J.
Exemplu:
Program P130;
{Crearea unui arbore binar - recursie }
type Arbore=^Nod;
Nod=record
Info : string;
Stg, Dr : Arbore
end;
var

T : Arbore;

{rdcina }

function Arb : Arbore;


{crearea arborelui binar }
var R : Arbore;
s : string;
begin
readln(s);
if s= then Arb:=nil
else begin
new(R);
R^.Info:=s;
write(Dai descendentul stng);
writeln( al nodului , s, :);
R^.Stg:=Arb;
write(Dai descendentul drept);
writeln(al nodului , s, :);
R^.Dr:=Arb;
Arb:=R;
end;
end; {Arb }
procedure AfisArb(T : Arbore; nivel : integer);
{afisarea arborelui binar }
var i : integer;
begin
if T<>nil then

60

begin
AfisArb(T^.Stg, nivel+1);
for i:=1 to nivel do write(
writeln(T^.Info);
AfisArb(T^.Dr, nivel+1);
end;
end; {AfisareArb }

);

begin
writeln(Dai rdcina:);
T:=Arb;
AfisArb(T, 0);
readln;
end.

Funcia Arb citete de la tastatur informaia util asociat nodului n curs de creare. Dac se citete un ir vid, nu se creeaz niciun nod i funcia returneaz valoarea
nil. n caz contrar, funcia creeaz un nod, nscrie irul de caractere n cmpul Info
i returneaz adresa nodului. n momentul cnd trebuie completate cmpurile Stg
(adresa subarborelui stng) i Dr (adresa subarborelui drept), funcia se autoapeleaz, trecnd astfel la construcia subarborelui respectiv.
Procedura AfisArb afieaz arborele binar pe ecran. Se afieaz subarborele stng,
rdcina i apoi subarborele drept. Nivelul fiecrui nod este redat prin inserarea
numrului respectiv de spaii.
Comparnd programele P129 i P130, se observ c prelucrarea structurilor recursive de date, i anume a arborilor binari, este mai natural i mai eficient n cazul
utilizrii unor algoritmi recursivi.
Arborii binari au numeroase aplicaii, una dintre cele specifice fiind reprezentarea
expresiilor n scopul prelucrrii acestora n translatoarele limbajelor de programare.

ntrebri i exerciii
Cum se definete un arbore binar? Explicai termenii: rdcin, subarborele stng, subarborele drept, descendent, nivel, nod terminal, nod neterminal, nlimea arborelui binar.
Formulai algoritmii iterativi destinai crerii i afirii arborilor binari.
Cum se construiete un arbore binar cu ajutorul algoritmului recursiv?
Elaborai un program care construiete arborele genealogic propriu pe parcursul a trei
sau patru generaii. Nodul-rdcin conine numele, prenumele i anul naterii, iar nodurile descendente conin datele respective despre prini.
Cum trebuie modificat procedura AfisArb din programul P130 pentru ca arborele
binar s fie afiat n ordinea: subarborele drept, nodul-rdcin, subarborele stng?
Scriei o funcie recursiv care returneaz numrul nodurilor unui arbore binar. Transcriei
aceast funcie ntr-o form nerecursiv.
Organizarea unui turneu prin eliminare este redat cu ajutorul unui arbore binar.
Nodurile arborelui n studiu conin urmtoarea informaie:

61

numele (string);
prenumele (string);
data naterii (ziua, luna, anul);
cetenia (string).
Fiecrui juctor i corespunde un nod terminal, iar fiecrui meci un nod neterminal. n
fiecare nod neterminal se nscriu datele despre ctigtorul meciului la care au participat
cei doi juctori din nodurile descendente. Evident, rdcina arborelui va conine datele
despre ctigtorul turneului.
Scriei un program care creeaz n memoria calculatorului i afieaz pe ecran arborele
unui turneu prin eliminare.
Indicaie: Se pornete de la o list a juctorilor. Ctigtorii meciurilor din prima etap se
includ ntr-o alt list. n continuare se formeaz lista ctigtorilor meciurilor din etapa
a doua .a.m.d.
Cum trebuie modificat funcia Arb din programul P130 pentru ca arborele binar s se
construiasc n ordinea: A, C, G, J, I, F, B, E, H, D?
Funcia Arb din programul P130 construiete arborii binari n ordinea: nodul-rdcin,
subarborele stng, subarborele drept. Scriei o procedur nerecursiv care construiete
arborii binari n aceeai ordine.
Indicaie: Se utilizeaz o stiv elementele creia snt noduri. Iniial stiva va conine numai
nodul-rdcin. Pentru fiecare nod din vrful stivei se va construi subarborele stng, iar
apoi subarborele drept. Nodurile nou-create se introduc n stiv. Dup construirea
subarborelui drept, nodul respectiv este scos din stiv.

2.8. Parcurgerea arborilor binari


Operaiile care se pot efectua asupra arborilor binari se mpart n dou mari categorii:
operaii care modific structura arborelui (inserarea sau eliminarea unui nod);
operaii care pstreaz intact structura arborelui (cutarea unei informaii, tiprirea informaiilor asociate unui nod etc.).
Una din problemele care apar n mod frecvent la efectuarea acestor operaii este
necesitatea de a parcurge sau a traversa arborele binar.
Prin parcurgerea unui arbore se nelege examinarea n mod sistematic a nodurilor sale astfel nct informaia din fiecare nod s fie prelucrat o singur dat. Exist
trei modaliti de parcurgere a arborilor binari: nodurile pot fi vizitate n preordine,
inordine i postordine. Aceste trei metode snt definite recursiv: dac arborele este
vid, atunci el este parcurs fr a se face nimic; astfel parcurgerea se face n trei etape.
Parcurgerea n preordine sau traversarea RSD:
1) se viziteaz rdcina;
2) se traverseaz subarborele stng;
3) se traverseaz subarborele drept.
Parcurgerea n inordine sau traversarea SRD:
1) se traverseaz subarborele stng;
2) se viziteaz rdcina;
3) se traverseaz subarborele drept.

62

Parcurgerea n postordine sau traversarea SDR:


1) se traverseaz subarborele stng;
2) se traverseaz subarborele drept;
3) se viziteaz rdcina.
Notaiile RSD, SRD i SDR reprezint ordinea n care vor fi vizitate rdcina (R),
subarborele stng (S) i subarborele drept (D). Metodele de parcurgere a arborilor
binari snt ilustrate n figura 2.12.

preordine (RSD)

inordine (SRD)
R

postordine (SDR)

Fig. 2.12. Metodele de parcurgere a arborilor binari

Pentru arborele din figura 2.11 parcurgerea n preordine furnizeaz nodurile n


ordinea:
A, B, D, E, H, C, F, G, I, J;
parcurgerea n inordine furnizeaz nodurile n ordinea:
D, B, E, H, A, F, C, I, G, J;
iar parcurgerea n postordine conduce la:
D, H, E, B, F, I, J, G, C, A.
Prezentm mai jos un program PASCAL de parcurgere a unui arbore binar dup
toate cele trei metode.
Program P131;
{Parcurgerea arborelui binar }
type Arbore=^Nod;
Nod=record
Info : string;
Stg, Dr : Arbore
end;
var T : Arbore;
{rdcina }

63

function Arb : Arbore;


{crearea arborelui binar }
var R : Arbore;
s : string;
begin
readln(s);
if s= then Arb:=nil
else begin
new(R);
R^.Info:=s;
write(Dai descendentul stng);
writeln( al nodului , s, :);
R^.Stg:=Arb;
write(Dai descendentul drept);
writeln( al nodului , s, :);
R^.Dr:=Arb;
Arb:=R;
end;
end; {Arb }
procedure AfisArb(T : Arbore; nivel : integer);
{afiarea arborelui binar }
var i : integer;
begin
if T<>nil then
begin
AfisArb(T^.Stg, nivel+1);
for i:=1 to nivel do write(
);
writeln(T^.Info);
AfisArb(T^.Dr, nivel+1);
end;
end; {AfisareArb }
procedure Preordine(T : Arbore);
{traversare RSD }
begin
if T<>nil then begin
writeln(T^.Info);
Preordine(T^.Stg);
Preordine(T^.Dr)
end;
end; {Preordine }
procedure Inordine(T : Arbore);
{traversare SRD }
begin
if T<>nil then begin

64

Inordine(T^.Stg);
writeln(T^.Info);
Inordine(T^.Dr)
end;
end; {Preordine }
procedure Postordine(T : Arbore);
{traversare SDR }
begin
if T<>nil then begin
Postordine(T^.Stg);
Postordine(T^.Dr);
writeln(T^.Info)
end;
end; { Postordine }
begin
writeln(Dai rdcina:);
T:=Arb;
AfisArb(T, 0);
readln;
writeln(Parcurgere n preordine:);
Preordine(T);
readln;
writeln(Parcurgere n inordine:);
Inordine(T);
readln;
writeln(Parcurgere n postordine:);
Postordine(T);
readln;
end.

Menionm c funcia Arb creeaz nodurile, parcurgnd arborele binar n curs de


construcie n preordine. Procedura AfisArb afieaz nodurile, parcurgnd arborele
binar n inordine.

ntrebri i exerciii
Ce operaii pot fi efectuate asupra arborilor binari?
Explicai metodele de parcurgere a arborilor binari. Dai exemple.
Scriei listele de noduri obinute n urma celor trei metode de parcurgere a arborelui
binar din figura2.13.
Transcriei procedurile Preordine, Inordine i Postordine din programul P131
n form nerecursiv.
Scriei un subprogram care returneaz nlimea arborelui binar.

65

10

Fig. 2.13. Arborele binar

Elaborai un program care afieaz pe ecran toate nodurile aflate pe un nivel dat ntr-un
arbore binar.
Elaborai o procedur recursiv care parcurge un arbore binar n ordinea:
a) RDS (rdcina subarborele drept subarborele stng);
b) DRS (subarborele drept rdcina subarborele stng);
c) DSR (subarborele drept subarborele stng rdcina).
Transcriei procedura elaborat ntr-o form nerecursiv.
Scriei un subprogram care afieaz la ecran nivelul fiecrui nod dintr-un arbore binar.
Se d un arbore binar n care nodurile terminale reprezint numere ntregi, iar cele neterminale operaiile binare +, -, *, mod, div. Arborele n studiu poate fi considerat ca o
reprezentare a unei expresii aritmetice. Valoarea acestei expresii se calculeaz efectund
operaia din nodul-rdcin asupra valorilor subexpresiilor reprezentate de subarborele
stng i subarborele drept.
Scriei o funcie care returneaz valoarea expresiilor aritmetice reprezentate prin arbori
binari.
Se consider expresiile aritmetice formate din operanzi i operatorii binari +, -, *, /. Operanzii
snt variabile numele crora este format dintr-o singur liter i constante alctuite dintr-o
cifr. Fiecrei expresii aritmetice i se poate asocia un arbore binar dup cum urmeaz:
a) expresiei aritmetice formate dintr-un singur operand i se asociaz un arbore binar
format doar din nodul ce conine operandul respectiv;
b) expresiei aritmetice de forma E1E2, unde E1 i E2 snt expresii aritmetice, i se asociaz
un arbore binar care are n nodul-rdcin operatorul , ca subarbore stng arborele asociat expresiei E1, iar ca subarbore drept arborele asociat expresiei E2.
Valoarea expresiei se calculeaz efectund operaia din nodul-rdcin asupra valorilor
subexpresiilor reprezentate de subarborele stng i subarborele drept.
Scriei un program care:
a) construiete arbori binari asociai expresiilor aritmetice citite de la tastatur;
b) evalueaz expresiile aritmetice reprezentate prin arborii binari.
Indicaie. Algoritmul va urma definiia recursiv a arborelui n studiu. Ca operator curent
se poate desemna orice operator +, - din expresia supus prelucrrii. Operatorii *, /
pot fi desemnai ca operatori cureni numai cnd expresia supus prelucrrii nu conine
operatorii +, -.

66

2.9. Arbori de ordinul m


Se consider variabile dinamice de tipul record care au n cmpul legturilor indicatori de adres. Ca i n cazul arborilor binari vom numi astfel de variabile noduri.
Arborele de ordinul m se definete recursiv dup cum urmeaz:
a) un nod este un arbore de ordinul m;
b) un nod ce conine cel mult m legturi ctre ali arbori de ordinul m este un arbore de ordinul m.
Se consider c n arbore exist cel puin un nod care subordoneaz exact m subarbori. Prin convenie, arborele vid nu conine niciun nod.
Arborii de ordinul 2 se numesc arbori binari i au fost studiai n paragrafele precedente. Arborii de ordinul 3, 4, 5 .a.m.d. se numesc arbori multici (n englez multiway tree).
Pentru exemplificare, n figura 2.14 este prezentat un arbore de ordinul 4. Evident,
pentru arborii multici termenii rdcin, subarbore, nivel, printe, descendent, nod
terminal, nod neterminal, nlime au aceeai semnificaie ca i pentru arborii binari.
Terminologia utilizat n structurile de date n studiu include chiar cuvinte ca fiu,
tat, frai, unchi, veri, strbunic etc. cu neles similar celui din vorbirea curent pentru
noduri aflate pe diverse niveluri. ntr-un limbaj simplist, structurile de date n studiu
exprim relaii de ramificare ntre noduri, asemntoare configuraiei arborilor
din natur, cu deosebirea c n informatic arborii cresc n jos.
nivel 0

nivel 1

nivel 2

nivel 3

Fig. 2.14. Arborele de ordinul 4

Datele necesare pentru crearea i prelucrarea unui arbore binar de ordinul m pot
fi definite prin declaraii de forma:
type Arbore = ^Nod;
Nod = record;
Info : string;
Dsc : array [1..m] of Arbore
end;
var T : Arbore;

67

Adresele descendenilor unui nod se memoreaz n componentele Dsc[1],


Dsc[2], ..., Dsc[m] ale tabloului Dsc. Adresa rdcinii se reine n variabila de
tip referin T.
Cele mai uzuale metode de parcurgere a arborilor de ordinul m snt parcurgerea
n lime i parcurgerea n adncime.
Parcurgerea n lime presupune vizitarea nodurilor n ordinea apariiei lor pe
niveluri. De exemplu, pentru arborele din figura 2.14 nodurile vor fi vizitate n ordinea: A, B, C, D, E, F, G, H, I, J, K.
n mod obinuit, parcurgerea n lime se realizeaz cu ajutorul unui algoritm
iterativ care utilizeaz o structur auxiliar de date, i anume o coad format din
adresele nodurilor care vor fi vizitate.
Parcurgerea n adncime se definete recursiv: dac arborele este vid, el este parcurs fr a se face nimic; altfel se viziteaz nti rdcina, apoi subarborii de la stnga
la dreapta. Pentru arborele din figura 2.14 parcurgerea n adncime furnizeaz nodurile n ordinea: A, B, C, E, F, J, K, G, H, D, I. Parcurgerea n adncime se realizeaz
foarte simplu cu ajutorul unui algoritm recursiv.
Exemplu:
Program P133;
{Arbori de ordinul m }
const m=4;
type Arbore=^Nod;
Nod=record
Info : string;
Dsc : array [1..m] of Arbore
end;
AdresaCelula=^Celula;
Celula=record
Info : Arbore;
Urm : AdresaCelula
end;
var T : Arbore;
{rdcina }
Prim,
{primul element din coad }
Ultim : AdresaCelula; {ultimul element din coad }
procedure IntroduInCoada(Q : Arbore);
var R : AdresaCelula;
begin
new(R);
R^.Info:=Q;
R^.Urm:=nil;
if Prim=nil then begin Prim:=R; Ultim:=R end
else begin Ultim^.Urm:=R; Ultim:=R end;
end; {IntroduInCoad }

68

procedure ExtrageDinCoada(var Q : Arbore);


var R : AdresaCelula;
begin
if Prim=nil then writeln(Coada este vid)
else begin
R:=Prim;
Q:=R^.Info;
Prim:=Prim^.Urm;
dispose(R);
end;
end; {ExtrageDinCoad }
procedure CreareArbore(var T : Arbore);
var R, Q : Arbore;
s : string;
i : integer;
begin
T:=nil;
{iniial arborele este vid }
Prim:=nil; Ultim:=nil; {iniial coada este vid }
writeln(Dai rdcina: ); readln(s);
if s<> then
begin
new(R); {crearea rdcinii }
R^.Info:=s;
T:=R;
{iniializarea adresei rdcinii }
IntroduInCoada(T);
end;
while Prim<>nil do {ct coada nu e vid }
begin
ExtrageDinCoada(R);
for i:=1 to m do R^.Dsc [i]:=nil;
writeln(Dai descendenii nodului,R^.Info);
i:=1; readln(s);
while (i<=m) and (s<>) do
begin
new(Q); R^.Dsc [i]:=Q; Q^.Info:=s;
IntroduInCoada(Q);
i:=i+1; readln(s);
end;
end;
end; {CreareArbore }
procedure AfisareArbore(T : Arbore);
var R : Arbore;
i : integer;
begin
if T=nil then writeln(Arbore vid)

69

begin
writeln(Arborele este format din:);
Prim:=nil; Ultim:=nil;
IntroduInCoada(T);
while Prim<>nil do
begin
ExtrageDinCoada(R);
writeln(Nodul , R^.Info);
write( Descendeni: );
for i:=1 to m do
if R^.Dsc [i]<>nil then
begin
write(R^.Dsc [i]^.Info, );
IntroduInCoada(R^.Dsc [i]);
end; {then }
writeln;
end; {while }
end; {else }
readln;
end; {AfisareArbore }
procedure InLatime(T : Arbore);
var R : Arbore;
i : integer;
begin
if T<>nil then
begin
Prim:=nil; Ultim:=nil;
IntroduInCoada(T);
while Prim<>nil do
begin
ExtrageDinCoada(R);
writeln(R^.Info);
for i:=1 to m do
if R^.Dsc [i]<>nil then IntroduInCoada(R^.Dsc [i]);
end; {while }
end; {then }
end; {InLatime }
procedure InAdincime(T : Arbore);
var i : integer;
begin
if T<>nil then
begin
writeln(T^.Info);
for i:=1 to m do InAdincime(T^.Dsc [i]);
end;
end; {InAdincime }

70

begin
CreareArbore(T);
AfisareArbore(T);
writeln(Parcurgerea arborelui n lime:);
InLatime(T);
readln;
writeln(Parcurgerea arborelui n adncime:);
InAdincime(T);
readln;
end.

Informaia util asociat fiecrui nod se citete de la tastatur. Absena descendenilor se semnaleaz prin apsarea tastei <ENTER>. Menionm c procedura CreareArbore creeaz nodurile parcurgnd n lime arborele n curs de
construcie. Evident, procedura AfisareArbore viziteaz nodurile n ordinea
crerii.
Operaiile frecvent efectuate asupra arborilor multici snt: inserarea sau eliminarea unui nod, cutarea unei informaii, prelucrarea informaiilor utile asociate nodurilor .a. De obicei, arborii multici snt utilizai n cazul aplicaiilor care necesit
prelucrarea unor mari cantiti de date organizate ierarhic pe suporturile externe
de informaie. De exemplu, amintim modul de organizare a discurilor magnetice i
optice n sistemele de operare MS-DOS, UNIX etc. Arborii n studiu snt de asemenea
utilizai n aplicaiile grafice pentru reprezentarea relaiilor dinamice dintre componentele imaginilor procesate.

ntrebri i exerciii
Dai exemple de arbori de ordinul 3, 5, 6.
Cum se definete un arbore de ordinul m? Ce operaii pot fi efectuate asupra arborilor n
studiu?
Explicai metodele de parcurgere a arborilor multici. Dai exemple.
Scriei un program recursiv care construiete n memoria calculatorului un arbore multici. Informaia util asociat nodurilor se citete de la tastatur.
Scriei o funcie care returneaz:
a) numrul nodurilor unui arbore multici;
b) nivelul unui anumit nod din arbore;
c) nlimea arborelui.
Transcriei procedura InAdincime din programul P133 ntr-o form nerecursiv.
Cum trebuie modificat procedura InLatime din programul P133 ca nodurile arborelui din figura6.18 s fie vizitate n ordinea: A, D, C, B, I, H, G, F, E, K, J?
Cum trebuie modificat procedura InAdincime din programul P133 pentru ca nodurile arborelui din figura2.14 s fie vizitate n ordinea: A, D, I, C, H, G, F, K, J, E, B?
Se d un arbore multici, informaiile din noduri fiind iruri de caractere. S se afieze pe
ecran toate irurile de caractere de lungime par.

71

Organizarea datelor de pe discurile magnetice este redat cu ajutorul unui arbore multici. Nodurile terminale reprezint fiierele, iar nodurile neterminale directoarele.
Informaia util asociat fiecrui nod include:
numele fiierului sau directorului (string[8]);
extensia (string[3]);
data i ora ultimei actualizri (respectiv ziua, luna, anul i ore, minute, secunde);
lungimea (integer);
atributele (A, H, R, S).
Elaborai un program care simuleaz operaiile de cutare, creare i tergere a fiierelor
i directoarelor.
n unele cazuri ordinul m al arborelui multici nu este cunoscut n momentul scrierii
programului, fapt ce nu permite utilizarea structurilor de date de tipul array[1..m]
of Arbore. Pentru a depi acest inconvenient, tabloul respectiv poate fi nlocuit cu o
list uni- sau bidirecional.
Elaborai subprogramele necesare pentru crearea i prelucrarea arborilor multici de
ordin arbitrar.

2.10. Tipul de date pointer


Acest paragraf se refer n ntregime la implementarea Turbo PASCAL.
Mulimea de valori ale tipului predefinit de date pointer (indicator) const din
adrese i valoarea special nil. ns, spre deosebire de tipurile de date referin
adresele crora identific numai variabilele dinamice ce aparin tipului de baz, valorile de tip pointer pot identifica variabile dinamice de orice tip. Evident, valoarea
nil nu identific nicio variabil dinamic. Prin convenie, tipul de date pointer
este compatibil cu orice tip de date referin.
Operaiile care se pot face cu valori de tipul de date pointer snt = i <>. Valorile
de acest tip nu pot fi citite de la tastatur i afiate pe ecran.
O variabil de tip pointer se introduce printr-o declaraie de forma:
var p : pointer;

ntruct astfel de declaraii nu conin informaii despre tipul de baz, tipul variabilei dinamice p^ este necunoscut. Prin urmare, variabilele de tip pointer nu pot fi
dereperate, iar scrierea caracterului ^ dup astfel de variabile constituie o eroare.
Programul ce urmeaz ilustreaz utilizarea variabilelor de tip pointer pentru
memorarea temporar a valorilor variabilelor de tip referin.
Program P134;
{ Tipul de date pointer }
var p : pointer;
i, j : ^integer;
x, y : ^real;
r, s : ^string;
begin
{p va identifica o variabil dinamic de tipul integer }
new(i); i^:=1;

72

p:=i;
new(i); i^:=2;
j:=p;
writeln(j^=, j^); { se afieaz 1 }
{p va identifica o variabil dinamic de tipul real }
new(x); x^:=1;
p:=x;
new(x); x^:=2;
y:=p; writeln(y^=, y^); {se afieaz 1.0000000000E+00 }
{p va identifica o variabil dinamic de tipul string }
new(r); r^:=AAA;
p:=r;
new(r); r^:=BBB;
s:=p;
writeln(s^=, s^); { se afieaz AAA }
readln;
end.

Domeniul principal de utilizare a variabilelor de tip pointer este gestionarea


memoriei interne a calculatorului. n Turbo PASCAL alocarea variabilelor dinamice
se execut ntr-o zon special a memoriei interne numit heap (grmad). Adresa
de nceput a heap-ului, numit adresa de baz, este depus n variabila predefinit de
tip pointer HeapOrg. Variabila de tip pointer HeapPtr conine adresa primei
locaii libere, numit vrful heap-ului (fig. 2.15).

Zon
liber
HeapPtr

HeapOrg

Zon ocupat de
variabilele
dinamice

Fig. 2.15. Structura heap-ului

Variabilele dinamice snt create i depuse n heap de procedura new. Ori de cte ori
n vrful heap-ului se creeaz o variabil dinamic coninutul variabilei HeapPtr este
actualizat: valoarea curent este incrementat cu dimensiunea spaiului de memorie
necesar variabilei dinamice.
Memoria ocupat n heap de o variabil dinamic se elibereaz printr-un apel al
procedurii dispose. Dimensiunea spaiului ce se elibereaz depinde de tipul variabilei dinamice.

73

Ordinea de apelare a procedurii dispose nu coincide n general cu ordinea crerii variabilelor dinamice de ctre procedura new. n consecin, n heap pot aprea
goluri. Golurile aprute pot fi refolosite de procedura new, dac variabila dinamic
n curs de creare ncape n spaiul respectiv.
Eliberarea memoriei ocupate de o structur dinamic de date poate fi efectuat
apelnd procedura dispose pentru fiecare component. ntruct n program snt cunoscute numai adresele componentelor privilegiate, de regul baza i vrful listei, rdcina arborelui etc., cutarea celorlalte componente cade n sarcina programatorului. Mai mult dect att, ordinea de apelare a procedurii dispose trebuie s asigure
pstrarea legturilor ctre componentele care nc nu au fost distruse. n caz contrar,
componentele respective nu mai snt referite de niciun indicator de adres i devin
inaccesibile. Prin urmare, utilizarea procedurii dispose pentru eliberarea memoriei
ocupate de structuri complexe de date este greoaie i ineficient. Acest inconvenient
poate fi depit cu ajutorul procedurilor predefinite mark i release.
Apelul procedurii mark are forma:
mark(p)

unde p este o variabil de tip pointer. Procedura memoreaz adresa vrfului din
HeapPtr n variabila p.
Apelul procedurii release are forma:
release(p)

Aceast procedur reface adresa vrfului n starea nregistrat anterior cu procedura mark: valoarea coninut n variabila de tip pointer p este depus n indicatorul HeapPtr.
Zona de memorie destinat alocrii variabilelor dinamice poate fi gestionat cu
ajutorul algoritmului ce urmeaz:
1) se memoreaz adresa vrfului cu procedura mark;
2) se creeaz variabilele dinamice cu procedura new;
3) se utilizeaz variabilele dinamice create;
4) cnd variabilele dinamice nu mai snt necesare, spaiul ocupat din heap este
eliberat cu procedura release.
Exemplu:
Se consider urmtoarele declaraii:
var i, j, k, m, n : ^integer;
p : pointer;

S presupunem c snt executate instruciunile:


new(i); i^:=1;
new(j); j^:=2;
mark(p);
new(k); k^:=3;
new(m); m^:=4;
new(n); n^:=5;

74

Starea heap-ului este prezentat n figura 2.16 a. Instruciunea mark(p) a memorat


n variabila de tip pointer p valoarea actual din HeapPtr nainte de crearea variabilei dinamice k^.

HeapPtr

HeapOrg

Zon
liber
5

Zon
liber

n
m
k

HeapPtr

HeapOrg

a)

b)

Fig. 2.16. Starea heap-ului pn (a) i dup executarea instruciunii release(p) (b)

Dac acum se execut instruciunea


release(p)

memoria ocupat de variabilele dinamice create dup apelul procedurii mark, i


anume, k^, m^ i n^, va fi eliberat (fig. 2.16 b).
Deoarece variabila predefinit HeapOrg reine adresa de baz a heap-ului, tot spaiul destinat alocrii variabileler dinamice poate fi eliberat cu ajutorul instuciunii
release(HeapOrg)

Programul ce urmeaz ilustreaz utilizarea procedurilor mark i release.


Program P135;
{Gestionarea memoriei interne }
type Lista=^Celula;
Celula=record
Info : string;
Urm : Lista
end;
Stiva=Lista;
end;
var L : Lista;
S : Stiva;
T : Arbore;
p : pointer;
function Lst : Lista;
{crearea listei unidirecionale }

75

var R : Lista;
s : string;
begin
write(Info=); readln(s);
if s= then Lst:=nil
else
begin
new(R);
R^.Info:=s;
R^.Urm:=Lst;
Lst:=R;
end;
end; {Lst }
procedure AfisLst(L : Lista);
{afiarea listei }
begin
if L<>nil then
begin
writeln(L^.Info);
AfisLst(L^.Urm);
end;
end; {AfisLst }
procedure Stv(var S : Stiva);
{crearea unei stive }
var R : Stiva;
st : string;
begin
S:=nil;
write(Info=); readln(st);
while st<> do
begin
new(R);
R^.Info:=st;
R^.Urm:=S;
S:=R;
write(Info=); readln(st);
end;
end; { Stv }
function Arb : Arbore;
{crearea arborelui binar }
var R : Arbore;
s : string;

76

begin
readln(s);
if s= then Arb:=nil
else begin
new(R);
R^.Info:=s;
write(Dai descendentul stng);
writeln( al nodului , s, :);
R^.Stg:=Arb;
write(Dai descendentul drept);
writeln( al nodului , s, :);
R^.Dr:=Arb;
Arb:=R;
end;
end; { Arb }
procedure AfisArb(T : Arbore; nivel : integer);
{ afiarea arborelui binar }
var i : integer;
begin
if T<>nil then
begin
AfisArb(T^.Stg, nivel+1);
for i:=1 to nivel do write(
);
writeln(T^.Info);
AfisArb(T^.Dr, nivel+1);
end;
end; {AfisArb }
begin
writeln(Dai lista:);
L:=Lst;
writeln(Lista creat:);
AfisLst(L);
mark(p);
{ p reine adresa din HeapPtr }
writeln(Dai rdcina:);
T:=Arb;
writeln(Arborele creat:);
AfisArb(T, 0);
release(p);{eliberarea memoriei ocupate de arbore }
writeln(Dai stiva:);
Stv(S);
writeln(Stiva creat);
AfisLst(S);
release(HeapOrg); {eliberarea memoriei ocupate de list i
stiv }
readln;
end.

77

Subliniem faptul c n implementrile actuale procedurile dispose i release nu atribuie valoarea nil indicatorilor de adres variabilele dinamice ale crora
au fost distruse (fig. 2.16b). ntruct memoria eliberat este refolosit, atribuirile
efectuate asupra variabilelor distruse pot altera valorile variabilelor dinamice noucreate.

ntrebri i exerciii
Care este mulimea de valori ale tipului de date pointer? Ce operaii pot fi efectuate
cu aceste valori?
Comentai urmtorul program:
Program P136;
{Eroare }
var i : ^integer;
j, k : integer;
p : pointer;
begin
new(i); i^:=1;
p:=i;
new(i); i^:=2;
j:=i^; k:=p^;
writeln(j+k=, j+k);
end.
Care este domeniul de utilizare a variabilelor de tip pointer?
Este oare heap-ul o structur de date de tip stiv? Argumentai rspunsul.
Lansai n execuie programele ce urmeaz. Explicai rezultatele afiate pe ecran.
Program P137;
var i, j, k, m, n : ^integer;
p : pointer;
begin
{crearea variabilelor i^, j^, k^ }
new(i); new(j); new(k);
i^:=1; j^:=2; k^:=3;
p:=j; {p reine adresa din j }
{distrugerea variabilei j^ i crearea variabilei m^}
dispose(j); new(m); m^:=4;
j:=p; {refacerea adresei din j }
writeln(i^=, i^, j^=, j^, k^=, k^);
{distrugerea variabilei m^ i crearea variabilei n^ }
dispose(m); new(n); n^:=5;
writeln(i^=, i^, j^=, j^, k^=, k^);
readln;
end.

78

Program P138;
var i, j, k, m : ^integer;
begin
{crearea variabilelor i^, j^ }
new(i); new(j);
i^:=1; j^:=2;
{eliberarea memoriei heap-ului }
release(HeapOrg);
{crearea variabilelor k^ i m^ }
new(k); new(m);
k^:=1; m^:=2;
writeln(k^=, k^, m^=, m^);
i^:=3; j^:=4;
writeln(k^=, k^, m^=, m^);
readln;
end.
Scriei o procedur care elibereaz memoria ocupat de:
a) o list unidirecional;
b) un arbore binar;
c) un arbore multici.
Memoria trebuie eliberat apelnd procedura dispose pentru fiecare component a
structurii dinamice de date.
Scriei un program n care se creeaz mai nti o coad, iar apoi un arbore multici. Spaiul
de memorie eliberat dup distrugerea cozii trebuie refolosit pentru alocarea arborelui.

79

Capitolul 3
METODE DE ELABORARE
A PRODUSELOR PROGRAM
3.1. Programarea modular
Programarea modular urmrete reducerea complexitii programelor mari prin
descompunerea acestora n module.
Modulul este un produs program format din descrieri de date i subprograme
destinate prelucrrii acestora. Modulele pot fi scrise independent i compilate separat nainte de a fi ncorporate n programul n curs de elaborare. Menionm c
pentru program se mai utilizeaz i denumirea de modul principal.
Limbajul-standard nu prevede mijloace pentru programarea modular. Se consider c programele PASCAL snt entiti monolit care trebuie compilate mpreun
cu subprogramele pe care, eventual, le conin. Acest lucru devine incomod n cazul
programelor mari care pot include zeci i chiar sute de subprograme.
n versiunea Turbo PASCAL modulele snt implementate prin uniti de program. Forma general a unei uniti de program este:
unit <Nume>;
interface
[uses <Nume> {,<Nume>};]
[<Constante>]
[<Tipuri>]
[<Variabile>]
[{<Antet funcie>; | <Antet procedur>;}]
implementation
[uses <Nume> {,<Nume};]
[<Etichete>]
[<Constante>]
[<Tipuri>]
[<Variabile>]
[<Subprograme>]
[{function <Identificator>;
<Corp>; |
procedure <Identificator>;
<Corp>;}]
[begin
[<Instruciune> {; <Instruciune }]]
end.

80

n esen, o unitate de program const din trei seciuni: de interfa, de implementare i de iniializare.
Seciunea de interfa ncepe cu cuvntul-cheie interface. Aici se declar constantele, tipurile, variabilele i subprogramele exportate de unitate. Aceste elemente
pot fi referite de orice modul care utilizeaz direct sau prin tranzitivitate unitatea
respectiv. Menionm c n seciunea de interfa apar doar antetele funciilor i
procedurilor exportate. Dac unitatea actual utilizeaz alte uniti, numele acestora
snt specificate n clauza uses.
Seciunea de implementare ncepe cu cuvntul-cheie implementation. Aceast
seciune conine declaraii locale de etichete, constante, tipuri, variabile i subprograme. Elementele definite aici snt ascunse i nu pot fi referite de modulele care
utilizeaz unitatea actual. Dup declaraiile locale urmeaz corpul procedurilor i
funciilor, ale cror antete au fost definite n seciunea de interfa. Fiecare subprogram specificat n interfa trebuie s aib un corp. Dup cuvntul-cheie function
sau procedure se scrie doar numele subprogramului. Menionm c nu este necesar descrierea listei de parametri i a valorii returnate.
Seciunea de iniializare ncepe, dac exist, cu cuvntul-cheie begin. Seciunea
const dintr-o secven de instruciuni i servete pentru atribuirea valorilor iniiale
variabilelor definite n seciunea de interfa. Dac un program utilizeaz mai multe
uniti, execuia programului este precedat de execuia seciunilor de iniializare n
ordinea n care aceste uniti apar n clauza uses din program.
Exemplu:
Unit U1;
{Prelucrarea vectorilor }
interface
const nmax=100;
type Vector=array [1..nmax] of real;
var n : 1..nmax;
function sum(V : Vector) : real;
function min(V : Vector) : real;
function max(V : Vector) : real;
procedure Citire(var V : Vector);
procedure Afisare(V : Vector);
implementation
var i : 1..nmax;
s : real;
function sum;
begin
s:=0;
for i:=1 to n do s:=s+V [i];
sum:=s;
end; {sum }

81

function min;
begin
s:=V [1];
for i:=2 to n do
if s>V [i] then s:=V [i];
min:=s;
end; {min }
function max;
begin
s:=V [1];
for i:=2 to n do
if s<V [i] then s:=V [i];
max:=s;
end; {max }
procedure Citire;
begin
for i:=1 to n do readln(V [i]);
end; {Citire }
procedure Afisare;
begin
for i:=1 to n do writeln(V [i]);
end; {Afisare }
begin
write(n=); readln(n);
end.

Unitatea U1 export constanta nmax, tipul Vector, variabila n, funciile sum,


min, max, procedurile Citire i Afisare. Valoarea iniial a variabilei n este citit
de la tastatur. Elementele n studiu pot fi referite n orice program ce conine clauza
uses U1.
Exemplu:
Program P139;
{Utilizarea unitii U1 }
uses U1;
var A : Vector;
begin
writeln(Dai un vector:);
Citire(A);
writeln(Ai introdus:);
Afisare(A);
writeln(sum=, sum(A));

82

writeln(min=, min(A));
writeln(max=, max(A));
readln;
end.

Domeniile de vizibilitate ale declaraiilor din unitile de program se stabilesc


conform regulilor ce urmeaz.
1. Declaraiile din seciunea de implementare snt vizibile numai n unitatea actual.
2. Declaraiile din seciunea de interfa snt vizibile n:
unitatea actual;
modulele care utilizeaz direct unitatea actual;
modulele care utilizeaz unitatea actual prin tranzitivitate.
Referirea oricrui identificator id declarat ntr-o unitate v utilizat prin tranzitivitate se face prin v.id.
3. Dac unul i acelai identificator este declarat n mai multe module, este luat
n considerare declaraia cea mai recent.
Exemplu:
Program P140;
uses U2;
var x : integer;
begin
x:=4;
writeln(Programul P140:);
writeln(n=, U3.n);
writeln(m=, m);
writeln(x=, x);
readln;
end.
Unit U2;
interface
uses U3;
var m : integer;
x : real;
implementation
begin
writeln(Unitatea U2:);
m:=2;
writeln(
m=, m);
x:=3.0;
writeln(
x=, x);
end.

83

Unit U3;
interface
var n : integer;
implementation
begin
writeln(Unitatea U3:);
n:=1;
writeln(n=, n);
end.

n programul P140 unitatea U2 este utilizat direct, iar unitatea U3 prin tranzitivitate. Variabila n din modulul U3 este referit prin U3.n. Identificatorul x apare
n declaraiile var x: real din unitatea U2 i var x: integer din programul
P140. Compilatorul ia n considerare ultima declaraie.
Unitile de program se clasific n unitile-standard, livrate odat cu compilatorul Turbo PASCAL, i unitile scrise de utilizator. n continuare prezentm o
caracteristic succint a unitilor-standard frecvent utilizate.
System conine toate subprogramele predefinite din Turbo PASCAL. Unitatea n
studiu se ncorporeaz automat n toate programele, fr a fi necesar clauza uses.
Crt permite utilizarea funciilor i procedurilor referitoare la lucrul cu ecranul
n mod text, precum i cu tastatura i difuzorul. Accesibilitatea subprogramelor se
realizeaz prin clauza uses crt.
Graph implementeaz subprogramele destinate unor prelucrri grafice: definiri de ferestre i pagini, definiri de culori i palete, desenarea arcurilor, cercurilor,
poligoanelor i a altor figuri, salvarea imaginilor etc. Serviciile unitii de program
pot fi accesate prin clauza uses graph.
Printer asigur redirectarea operaiilor de scriere n fiierul text cu numele
lst la imprimant. Utiliznd unitatea n studiu, programatorul nu mai trebuie s declare, s deschid i s nchid acest fiier. Serviciile unitii Printer devin accesibile
unui program sau unei uniti de program prin specificarea clausei uses printer.
Destinaia i modul de utilizare a constantelor, tipurilor de date, variabilelor,
funciilor i procedurilor din unitile-standard este inclus n ghidurile de utilizare
i sistemele de asisten Turbo PASCALs Online Help.
Elabornd propriile uniti de program, orice utilizator i poate crea biblioteci de subprograme ce descriu algoritmi din diverse domenii: rezolvarea ecuaiilor, calcule statistice, procesarea textelor, crearea i prelucrarea structurilor dinamice de date etc. Divizarea
unui program mare n module uureaz activitatea de elaborare a produselor program
n echip. n astfel de cazuri fiecare programator scrie, testeaz i documenteaz cteva
module relativ simple, ceea ce contribuie la mbuntirea produsului program rezultat.

ntrebri i exerciii
Care snt avantajele programrii modulare? Prevede oare limbajul-standard mijloace
pentru programarea modular?
Care este forma-standard a unei uniti de program? Precizai structura i destinaia seciunilor de interfa, de implementare i de iniializare.

84

Cum se determin domeniile de vizibilitate ale declaraiilor din unitile de program?


Precizai ce va afia pe ecran programul ce urmeaz.
Program P141;
uses U4;
var s : string;
begin
s:=BBB;
writeln(U5.k=, U5.k);
writeln(U5.m=, U5.m);
writeln(U5.s=, U5.s);
writeln(U4.m=, U4.m);
writeln(U4.s=, U4.s);
writeln(m=, m);
writeln(s=, s);
readln;
end.
Unit U4;
interface
uses U5;
var m : real;
s : char;
implementation
begin
m:=4.0;
s:=A;
end.
Unit U5;
interface
var k, m : integer;
s : real;
implementation
begin
k:=1;
m:=2;
s:=3.0;
end.
Comentai programul:
Program P142;
{Eroare }
uses U6;
begin
writeln(k=, k);
writeln(m=, m);
readln;
end.

85

Unit U6;
interface
var k : integer;
implementation
var m : integer;
begin
k:=1;
m:=2;
end.
Completai unitatea de program U1 din paragraful n studiu cu un subprogram care:
a) returneaz media aritmetic a componentelor unui vector;
b) aranjeaz componentele n ordine cresctoare;
c) returneaz produsul componentelor unui vector;
d) returneaz numrul componentelor pozitive;
e) aranjeaz componentele n ordine descresctoare.
Scriei o unitate de program care ofer descrieri de date i subprograme pentru prelucrarea matricelor.
Numerele ntregi n, n 10254, pot fi reprezentate n calculator prin iruri formate din caracterele +, , 0, 1, 2, ..., 9. Elaborai o unitate de program care conine
funciile i procedurile necesare pentru efectuarea urmtoarelor operaii:
a) citirea numerelor de la tastatur;
b) afiarea numerelor pe ecran;
c) +, -, *, mod, div;
d) calcularea factorialului;
e) citirea i scrierea numerelor n fiiere secveniale.
irurile de caractere de lungime n, n 500, pot fi reprezentate n programele Turbo
PASCAL prin variabile de tipul:
type lungime = 0..500;
SirDeCaractere = record
n: lungime;
s: array [1..500] of char
end;
Elaborai o unitate de program care conine funciile i procedurile necesare pentru
efectuarea urmtoarelor operaii:
a) citirea irurilor de la tastatur;
b) afiarea irurilor pe ecran;
c) concatenarea irurilor;
d) compararea lexicografic;
e) calcularea lungimii unui ir.
Elaborai o unitate de program pentru prelucrarea:
a) listelor unidirecionale;
b) cozilor;
c) stivelor;

86

d) arborilor binari;
e) arborilor multici.
Utilizai n acest scop declaraiile de tipuri, funcii i proceduri din capitolul2.
Gsii n sistemul de asisten Turbo PASCAL s Online Help descrierea unitilor-standard
instalate pe calculatorul dvs. Afiai pe ecran textul fiecrei uniti, determinai destinaia i modul de utilizare a funciilor i procedurilor respective.

3.2. Testarea i depanarea programelor


Un program este corect dac:
a) dup lansarea n execuie procesul de calcul se termin;
b) rezultatele obinute reprezint o soluie a problemei pentru rezolvarea creia a
fost scris programul.
n caz contrar programul conine erori.
Asigurarea corectitudinii unui program presupune execuia sa pentru fiecare
combinaie posibil de valori ale datelor de intrare. n majoritatea cazurilor acest
lucru este imposibil, deoarece domeniul de valori al datelor de intrare este, practic,
infinit, iar soluiile respective snt necunoscute.
Testarea este o etap n elaborarea programelor ce are drept scop eliminarea erorilor. Ea se realizeaz executnd programul cu anumite seturi de date de intrare numite date de testare sau, mai simplu, teste. n funcie de modul de selecie a datelor
de testare, deosebim:
testarea funcional sau metoda cutiei negre;
testarea structural sau metoda cutiei transparente.
Amintim c termenul cutie neagr este folosit pentru un sistem, structura intern
a cruia este necunoscut.
n cazul testrii funcionale datele de testare snt astfel concepute, nct s se asigure c fiecare funcie a programului este pe deplin realizat. Programul este vzut
ca o cutie neagr, a crei funcionare este determinat prin introducerea unor date i
analiza rezultatelor obinute. Selectarea datelor de intrare depinde, n mare msur,
de ndemnarea i experiena celui care efectueaz testarea. n mod obinuit, se selecteaz valori tipice i valori netipice din domeniul datelor de intrare.
Exemplu. Se consider programul P143. Textul programului nu este deocamdat
prezentat pentru a sublinia faptul c n metoda testrii funcionale el nu este necesar.
Programul realizeaz urmtoarele funcii:
citete de la tastatur un ir de numere reale;
afieaz pe ecran media aritmetic a numerelor pozitive din ir.
Evident, domeniul datelor de intrare este format din iruri de numere reale.
Datele de testare vor include:
a) valorile netipice:
ir vid;
ir ce nu conine numere pozitive;
ir ce conine un singur numr pozitiv;

87

b) valorile tipice:
ir cu dou numere pozitive;
ir cu trei sau mai multe numere pozitive.
n testarea structural testele snt elaborate examinnd structura programului:
declaraiile de date, proceduri i funcii, instruciunile simple, instruciunile structurate etc. Datele de testare vor asigura:
a) execuia fiecrei instruciuni simple (atribuiri, apeluri de proceduri, salturi goto);
b) execuia fiecrui ciclu for de zero, unu i de mai multe ori;
c) execuia fiecrei instruciuni if, repeat, while pentru valorile true i false ale expresiilor booleene de control;
d) execuia fiecrui caz din componena instruciunilor case.
Exemplu. Prezentm textul programului care calculeaz media aritmetic a numerelor pozitive dintr-un ir:
Program P143;
{ Media numerelor pozitive dintr-un ir }
var n, k : integer;
x, s : real;
begin
n:=0;
k:=0;
s:=0;
writeln(Dai un ir de numere reale:);
while not eof do
begin
readln(x);
n:=n+1;
if x>0 then
begin
k:=k+1;
s:=s+x;
end;
end; { while }
if n=0 then writeln(ir vid)
else if k=0 then writeln(irul nu conine numere
pozitive)
else writeln(Media=, s/k);
readln;
end.

Testul trebuie s asigure execuia instruciunilor while i if pentru valorile


true i false ale expresiilor booleene not eof, x>0, n=0 i k=0. Prin urmare, datele de testare vor include:
un ir vid (not eof=false, n=0);
un ir nevid (not eof=true, n0);
un ir ce conine cel puin un numr pozitiv (x>0, k0);
un ir nevid ce nu conine numere pozitive (x0, k=0).

88

Metoda cutiei transparente poate fi utilizat independent sau mpreun cu metoda cutiei negre pentru a mbunti un test deja obinut. De exemplu, n cazul
programului P143 irul ce conine cel puin un numr pozitiv poate fi nlocuit cu
trei iruri ce conin, respectiv unul, dou, trei sau mai multe numere pozitive. Aceste
date vor asigura execuia instruciunilor k:=k+1, s:=s+x i calcularea expresiei
s/k pentru valorile tipice i valorile netipice ale variabilelor k i s.
Dificultile n aplicarea testrii structurale snt legate de prezena instruciunilor
de decizie (if, case), a celor iterative (for, while, repeat) sau a celei de transfer
(goto). Acestea determin apariia unui numr foarte mare de combinri, n care
instruciunile de atribuire i apelurile de proceduri pot fi executate.
Depanarea programului const n localizarea zonelor din program care au
condus la apariia unei erori, identificarea cauzelor erorii i corectarea acesteia.
Depanarea poate fi fcut static (dup executarea programului) i dinamic (n timpul executrii).
n metoda depanrii statice cauzele erorii se stabilesc analiznd rezultatele derulrii programului i mesajele sistemului de operare. Pentru a facilita procesul de
depanare, n program temporar se includ instruciuni care afieaz pe ecran valorile
intermediare ale variabilelor-cheie.
n metoda depanrii dinamice localizarea erorilor se face urmrind executarea
programului la nivel de instruciuni. Implementrile actuale ale limbajului permit
efectuarea urmtoarelor operaii de depanare dinamic:
execuia pas cu pas a programului;
observarea valorilor unor expresii specificate;
crearea i eliminarea unor puncte de suspendare a executrii;
modificarea valorilor unor variabile;
trasarea apelurilor de funcii i proceduri;
tratarea erorilor de intrareieire, a erorilor de depire etc.
Descrierea detaliat a operaiilor n studiu este inclus n sistemul de asisten
Turbo PASCALs Online Help.
Eficiena depanrii depinde de modul n care este scris i testat programul, calitatea mesajelor de eroare generate de calculator i tipul erorii. De regul, un test care
semnaleaz prezena unei erori este urmat de alte texte organizate n aa fel, nct s
izoleze eroarea i s furnizeze informaii pentru corectarea ei.
S-a constatat c testarea i depanarea ocup mai mult de jumtate din perioada de
timp necesar realizrii unui produs program. Complexitatea acestor procese poate
fi redus prin divizarea programelor mari n subprograme sau module i aplicarea
metodelor programrii structurate.
Subliniem faptul c testarea programelor este un mijloc eficient de a depista erorile, ns nu i un mijloc de a demonstra absena lor. Cu toate c testarea nu demonstreaz corectitudinea programului, ea este deocamdat singura metod practic de
certificare a produselor program. n prezent se elaboreaz metode de verificare bazate pe demonstrarea formal a corectitudinii programului, ns rezultatele cunoscute
n aceast direcie nu snt aplicabile programelor complexe.

89

ntrebri i exerciii
Cnd un program PASCAL este corect? Cum poate fi asigurat corectitudinea unui program?
Cum se selecteaz datele de intrare n metoda testrii funcionale?
Elaborai un test funcional pentru programul P124 din paragraful 2.4. Programul realizeaz urmtoarele funcii:
creeaz o list unidirecional;
afieaz lista pe ecran;
include un anumit element n list;
exclude din list elementul specificat de utilizator.
Precizai funciile realizate de programele ce urmeaz i elaborai testele funcionale:
a) P117 i P120 din paragraful 2.1;
b) P122 i P123 din paragraful 2.2;
c) P127 din paragraful 2.5 i P128 din paragraful 2.6.
Cum se selecteaz datele de intrare n metoda testrii structurale?
Elaborai teste structurale pentru programele ce urmeaz:
a) P117 i P120 din paragraful 2.1;
b) P122 i P123 din paragraful 2.2;
c) P127 din paragraful 2.5.
Care este diferena dintre depanarea static i depanarea dinamic?
Gsii n sistemul de asisten Turbo PASCAL s Online Help descrierea operaiilor de depanare dinamic. Efectuai aceste operaii pentru programele elaborate de dvs.

3.3. Elemente de programare structurat


nc din primii ani de activitate n domeniul prelucrrilor de date s-a constatat c
testarea, depanarea i modificarea programelor necesit un mare volum de munc.
Mai mult dect att, programele complexe ce conin sute i mii de instruciuni devin
greu accesibile chiar i pentru autorii lor.
Programarea structurat reprezint un stil, o manier de concepere a programelor potrivit unor reguli bine stabilite, bazate pe teorema de structur. Conform teoremei de structur, orice algoritm poate fi reprezentat ca o combinaie a trei structuri
de control:
secvena (succesiune de dou sau mai multe atributuri i/sau apeluri de proceduri);
decizia (if... then... sau if... then... else...);
ciclul cu test iniial (while... do...).
Programarea structurat admite i utilizarea altor structuri de control, cum snt:
selecia (case... of...);
ciclul cu test final (repeat... until...);
ciclul cu contor (for... do...).

90

Regulile de baz ale programrii structurate snt:


1. Structura oricrui program sau subprogram va fi conceput ca o combinaie a
structurilor de control admise: secvena, decizia, selecia, ciclul.
2. Structura datelor utilizate n program trebuie s corespund specificului problemelor rezolvate.
3. Lungimea maxim a unei funcii sau proceduri este de 50100 de linii. Folosirea
variabilelor globale nu este ncurajat.
4. Identificatorii folosii pentru constante, tipuri, variabile, funcii, proceduri i
uniti de program trebuie s fie ct mai sugestivi.
5. Claritatea textului trebuie asigurat prin inserarea comentariilor i alinierea
textului n conformitate cu structura logic i sintactic a instruciunilor.
6. Operaiile de intrareieire vor fi localizate n subprograme separate. Corectitudinea datelor de intrare se verific imediat dup citirea lor.
7. ncuibarea insturciunilor if mai mult de trei ori trebuie evitat prin folosirea
istruciunilor case.
Programele obinute conform regulilor n studiu snt testabile, clare, ordonate,
fr salturi i reveniri. Menionm c, conform teoremei de structur, orice program
poate fi scris fr a utiliza instruciunea goto. Totui unii autori admit utilizarea
acestei instruciuni cu condiia ca ea s fie folosit la minimum, iar salturile s fie
efectuate numai n jos.

ntrebri i exerciii
Care este justificarea teoretic a programrii structurate?
Precizai structurile de control necesare i suficiente pentru reprezentarea oricrui algoritm.
Formulai regulile de baz ale programrii structurate.
Care snt avantajele programrii structurate?
Corespund oare programele P124, P130 i P135 din capitolul 2 regulilor de baz ale
programrii structurate?
Programul ce urmeaz afieaz pe ecran toate reprezentrile posibile ale numrului natural n ca sum de numere naturale consecutive.
Program P144;
var a,i,l,s,n : integer;
b : boolean;
begin
write(n=); readln(n);
b:=true;
for i:=1 to ((n+1) div 2) do
begin
a:=i;
s:=0;
while (s<n) do
begin
s:=s+a;
a:=a+1;
end;

91

if s=n then
begin
b:=false;
write(n, =, i);
for l:=i+1 to (a-1) do write(+,l);
writeln;
end;
end;
if b then writeln(Reprezentri nu exist);
readln;
end.
De exemplu, pentru n=15 obinem:
15=1+2+3+4+5;
15=4+5+6;
15=7+8.
Reprezentrile n studiu se calculeaz prin metoda trierii, examinndu-se irurile:
1, 2, 3, ..., k;
2, 3, ..., k;
3, ..., k
.a.m.d., unde k=(n+1) div 2. Termenii 1, 2, 3, ..., k se calculeaz cu ajutorul relaiei recurente a=a+1. Aliniai textul programului n conformitate cu structura logic i sintaxa
fiecrei instruciuni.

92

Capitolul 4
ANALIZA ALGORITMILOR
4.1. Complexitatea algoritmilor
Valoarea practic a programelor PASCAL depinde n mod decisiv de complexitatea algoritmilor ce stau la baza lor. Amintim c algoritmul reprezint o succesiune
finit de operaii (instruciuni, comenzi) cunoscute, care, fiind executate ntr-o ordine bine stabilit, furnizeaz soluia unei probleme.
E cunoscut faptul c unul i acelai algoritm poate fi descris prin diverse metode:
scheme logice, formule matematice, texte scrise ntr-un limbaj de comunicare ntre oameni, cu ajutorul limbajelor de programare. Evident, i n acest manual algoritmii pe
care i vom studia vor fi descrii cu ajutorul mijloacelor oferite de limbajul PASCAL:
instruciuni, funcii, proceduri i programe ce pot fi derulate pe calculator.
Complexitatea algoritmului se caracterizeaz prin necesarul de memorie i durata
de execuie. Metodele de estimare a acestor indicatori se studiaz ntr-un compartiment special al informaticii, denumit analiza algoritmilor. n cadrul acestui compartiment se utilizeaz urmtoarele notaii:
n un numr natural ce caracterizeaz mrimea datelor de intrare ale unui algoritm. n majoritatea cazurilor n reprezint numrul de elemente ale unei mulimi,
gradul unei ecuaii, numrul de componente ale unui tablou etc.;
V(n) volumul de memorie intern necesar pentru pstrarea datelor cu care
opereaz algoritmul;
T(n) timpul necesar executrii algoritmului. De obicei, n acest timp nu se include durata operaiilor de introducere a datelor iniiale i de extragere a rezultatelor.
Evident, volumul de memorie V(n) i timpul de execuie T(n) depind, n primul
rnd, de caracteristica n a datelor de intrare, fapt accentuat i prin folosirea notaiilor
ce reprezint funcii de argumentul n.
Aplicarea practic a unui algoritm este posibil numai atunci cnd necesarul de
memorie i timpul cerut nu ncalc restriciile impuse de mediul de programare i
capacitatea de prelucrare a calculatorului utilizat.
De exemplu, presupunem c pentru rezolvarea unei probleme exist doi algoritmi diferii, notai prin A1 i A2. Necesarul de memorie i timpul cerut de algoritmul
A1 este:
V1(n) = 100n2 + 4;
T1(n) = n3 10-3 ,
iar de algoritmul A2:
V2(n) = 10n + 12;
T2(n) = 2n 10-6 .

93

n aceste formule volumul de memorie se calculeaz n octei, iar timpul n secunde.


Necesarul de memorie i timpul cerut de algoritmii A1, A2 pentru diferite valori
ale lui n este prezentat n tabelul 4.1.
Tabelul 4.1.
Complexitatea algoritmilor A1 i A2
n

10

20

30

40

50

V1(n)

9,77 Koctei

39,06 Koctei

87,89 Koctei

V2(n)

112 octei

212 octei

312 octei

412 octei

512 octei

T1(n)

1 secund

8 secunde

9 secunde

16 secunde

25 secunde

T2(n)

0,001 secunde

1,05 secunde

18 secunde

13 zile

36 ani

156,25 Koctei 244,14 Koctei

Din tabelul 4.1 se observ c algoritmul A2 devine practic inutilizabil pentru datele de intrare caracteristica crora n > 30. Pentru astfel de date timpul de execuie
a algoritmului A1 este mult mai mic, ns necesarul de memorie V1(n) poate depi
limita impus de mediul de programare (64 Koctei pentru variabilele statice din programele Turbo PASCAL 7.0).
Determinarea necesarului de memorie V(n) i a timpului de execuie T(n) prezint un interes deosebit la etapa de elaborare a algoritmilor i a programelor respective. Evident, anume pe parcursul acestei etape pot fi eliminai din start acei
algoritmi care necesit memorii prea mari sau care au un timp de execuie inacceptabil.
Menionm c existena unor calculatoare cu memorii din ce n ce mai performante fac ca atenia informaticienilor s fie ndreptat n special asupra necesarului de
timp sau, cu alte cuvinte, asupra complexitii temporale a algoritmilor.

ntrebri i exerciii
Explicai termenul complexitatea algoritmului. Numii indicatorii ce caracterizeaz complexitatea algoritmilor.
Cum credei, care factori influeneaz complexitatea unui algoritm?
De ce depinde necesarul de memorie i timpul cerut de un algoritm? Cnd este posibil
aplicarea practic a unui algoritm?
Algoritmii A1 i A2 (vezi tabelul 4.1) vor derula n mediul de programare Turbo PASCAL
7.0. Cum credei, care algoritm trebuie utilizat n cazul datelor de intrare cu caracteristica: a) n = 10; b) n = 20; c) n = 30? Pentru care valori ale lui n algoritmul A1 poate fi utilizat
n mediul de programare Turbo PASCAL 7.0?
Complexitatea unui algoritm, notat prin A3, se caracterizeaz prin
V3(n) = 600n3 + 18;
T3(n) = 3 n 10 -2 .

94

Cum credei, pentru care valori ale lui n algoritmul A3 poate derula n mediul de programare Turbo PASCAL 7.0?
Determinai mrimea datelor de intrare a celor mai reprezentativi algoritmi elaborai de
dvs. n procesul studierii limbajului de programare PASCAL.

4.2. Estimarea necesarului de memorie


Evaluarea necesarului de memorie V(n) poate fi fcut nsumnd numrul de octei alocai pentru fiecare variabil din program. Numrul de octei alocat unei variabile nestructurate integer, real, boolean, char, enumerare, subdomeniu, referin depinde de implementarea limbajului. Numrul de octei alocat unei variabile
depinde de implementarea limbajului. n mediul de programare Turbo PASCAL 7.0
memoria se aloc conform tabelului 4.2.
Tabelul 4.2
Alocarea memoriei interne n Turbo PASCAL 7.0
Tipul variabilei

Numrul de octei

integer

real

boolean

char

enumerare

subdomeniu

conform tipului de baz

referin

pointer

n cazul tipurilor structurate de date volumul de memorie necesar unei variabile


se calculeaz nsumnd numrul de octei alocai pentru fiecare component.
De exemplu, necesarul de memorie pentru variabilele A, B, p i s din declaraiile:
var A
B
p
s

este

:
:
:
:

array[1..n, 1..n] of real;


array[1..n] of integer;
boolean;
string[10];
V(n) = 6n2 + 2n + 11 (octei).

n general, necesarul de memorie al unui program PASCAL depinde nu numai de


tipul variabilelor utilizate, dar i de modul de gestionare a memoriei interne a calcu-

95

latorului. n procesul derulrii unui program PASCAL spaiul de memorie intern


este divizat n trei seciuni (fig. 4.1):
segmentul date, destinat alocrii variabilelor globale. Aceste variabile se declar n seciunea var a programului PASCAL;
stiva, destinat alocrii parametrilor actuali, variabilelor locale, valorilor returnate de funcii i adreselor de revenire pe durata execuiei subprogramelor PASCAL.
Apelul unui subprogram implic depunerea datelor respective n stiv, iar ieirea din
subprogram eliminarea lor. Accentum c n cazul parametrului-variabil n stiv
se depune numai adresa variabilei din programul apelant, iar n cazul parametruluivaloare n stiv va fi depus o copie a datelor din lista parametrilor actuali.
heap-ul, utilizat pentru alocarea variabilelor dinamice. Aceste variabile snt create i, eventual, distruse cu ajutorul procedurilor new i dispose.
Segmentul
date

Stiva

Vs(n)

Vd(n)
variabile
globale

parametri
actuali;
variabile
locale;
valori
de funcii;
adrese
de revenire

Heap-ul

Vh(n)
variabile
dinamice

Fig. 4.1. Gestionarea memoriei interne

Prin urmare, estimarea necesarului de memorie presupune evaluarea urmtoarelor caracteristici ale unui program (fig. 4.1):
Vd(n) volumul de memorie ocupat de variabilele globale n segmentul date;
Vs(n) volumul de memorie ocupat de parametrii actuali i de variabilele locale
n stiv;
Vh(n) volumul de memorie ocupat de variabilele dinamice n heap.
De obicei, n mediul de programare Turbo PASCAL 7.0 se cere ca Vd(n) 64 Koctei,
Vs(n) 16 Koctei i Vh(n) 256 Koctei. Dimensiunile stivei i ale heap-ului pot fi modificate cu ajutorul directivelor de compilare sau a comenzilor mediului de programare.
Exemplu:
Program P145;
{ Gestionarea memoriei interne }
const n = 100;
type Matrice = array[1..n, 1..n] of real;
Vector = array[1..n] of real;

96

var A : Matrice;
i : integer;
p, q : ^Matrice;
procedure Prelucrare(var B:Matrice);
var C : Vector;
begin
{...prelucrarea elementelor matricei B...}
end; { Prelucrare }
begin
{...introducerea matricei A...}
Prelucrare(A);
new(p);
new(q);
{...prelucrarea variabilelor dinamice p^ si q^...}
dispose(p);
dispose(q);
{...afiarea rezultatelor...}
writeln(Sfrit);
readln;
end.

Variabilele globale A, i, p i q din programul P145 vor fi depuse n segmentul date


(fig. 4.2). Necesarul de memorie pentru aceste variabile:
Vd(n) = 6n2 + 2 + 2 4 = 6n2 + 10.
Execuia instruciunii apel de procedur Pr(A) implic depunerea n stiv a
adresei matricei A, a adresei de revenire n programul principal i a variabilei locale
C. Necesarul de memorie pentru aceste date:
Vs(n) = 6n + 8.
Dup ieirea din procedur, datele respective vor fi eliminate din stiv.
Instruciunile new(p) i new(q) creeaz n heap variabilele dinamice p^ i q^ de
tipul Matrice. Necesarul de memorie pentru aceste variabile:
Vh(n) = 6n2 + 6n2 = 12n2 .
Dup execuia instruciunilor dispose(p) i dispose(q), variabilele dinamice
din heap snt distruse, iar spaiul respectiv de memorie devine liber.

ntrebri i exerciii
Determinai cu ajutorul sistemului de asisten al mediului de programare cu care lucrai dvs. necesarul de memorie pentru variabilele nestructurate.
Cum se evalueaz volumul de memorie intern necesar pentru nmagazinarea datelor
unui algoritm?

97

Segmentul
date

Stiva

Heap-ul

q
Matricea q^

p
q

i
Vectorul C
Matricea A

Matricea p^

Adresa matricei A
Adresa de revenire

Fig. 4.2. Gestionarea memoriei n programul P145

Explicai cum se gestioneaz memoria intern n cazul unui program PASCAL.


Determinai cu ajutorul sistemului de asisten dimensiunile segmentului date, ale stivei i
ale heap-ului. Cum pot fi modificate dimensiunile stivei i ale heap-ului?
Calculai necesarul de memorie pentru variabilele din urmtoarele declaraii:

98

a)

var A : array[1..n, 1..n] of integer;


B : string;
C : array [1..n, 1..n, 1..n] of boolean;

b)

type Vector = array[1..n] of real;


Matrice = array[1..n] of Vector;
var A, B, C : Matrice;
D : Vector;

c)

type Elev = record


Nume : string;
Prenume : string;
NotaMedie : real
end;
ListaElevi = array[1..n] of Elev;
var A, B, C : ListaElevi;

d)

type Angajat = record


NumePrenume
ZileLucrate
PlataPeZi :
PlataPeLuna
end;

: string;
: 1..31;
real;
: real

ListaDePlata = array[1..n] of Angajat;


var L1, L2 : ListaDePlata;
e)

type Elev = record


Nume : string;
Prenume : string;
NotaMedie : real
end;
FisierElevi = file of Elev;
var FE : FisierElevi;
E : Elev;
str : string;
i, n : integer;;

Evaluai necesarul de memorie pentru programul ce urmeaz. Compilai acest program pentru valorile 50, 60, 70, 80 i 100 ale constantei n. Explicai mesajele afiate pe
ecran.
Program P146;
{ Dimensiunile segmentului date }
const n = 50;
type Matrice = array[1..n, 1..n] of real;
var A, B : Matrice;
begin
{...introducerea datelor...}
{...prelucrarea matricelor A i B...}
writeln(Sfrit);
readln;
end.
Se consider urmtorul program:
Program P147;
{ Dimensiunile stivei }
var n : integer;
function S(n:integer):real;
begin
if n=0 then S:=0
else S:=S(n-1)+n;
end; { S }
begin
write(n=); readln(n);
writeln(s=, S(n));
readln;
end.

99

n acest program suma


S(n) = 0 + 1 + 2 + ... + n
este calculat cu ajutorul funciei recursive

Estimai necesarul de memorie al programului P147. Determinai valoarea maximal a


lui n pentru care programul P147 deruleaz fr erori.
Determinai necesarul de memorie al programului ce urmeaz. Pentru care valori ale lui
n programul va derula fr erori?
Program P148;
{ Dimensiunile heap-ului }
type Vector = array[1..100] of real;
var p : ^Vector;
i, n : integer;
begin
write(n=); readln(n);
for i:=1 to n do new(p);
writeln(Sfrit);
readln;
end.

4.3. Msurarea timpului de execuie


n cazul programelor deja elaborate timpul T(n) cerut de un algoritm poate fi aflat
prin msurri directe. Vom folosi n acest scop unitatea de program U7:
Unit U7;
{ Masurarea timpului }
interface
function TimpulCurent : real;
implementation
uses Dos;
var ore : word;
minute : word;
secunde : word;
sutimi : word;
function TimpulCurent;
begin
GetTime(ore, minute, secunde, sutimi);
TimpulCurent:=3600.0*ore+60.0*minute+
1.0*secunde+0.01*sutimi;
end; { TimpulCurent }
end.

100

Unitatea de program U7 ofer programatorului funcia TimpulCurent, care


returneaz o valoare de tip real timpul n secunde. Indicaiile ceasului de sistem n ore, minute, secunde i sutimi de secund se citesc cu ajutorul procedurii GetTime din unitatea de program DOS a mediului de programare Turbo
PASCAL 7.0.
Pentru exemplificare prezentm programul P149 n care se msoar timpul de
execuie a procedurii Sortare:
Program P149;
{ Timpul de execuie a procedurii Sortare }
uses U7;
type Vector = array[1..10000] of real;
var
A : Vector;
i, n : integer;
T1, T2 : real; { timpul in secunde }
procedure Sortare(var A:Vector; n:integer);
{ Sortarea elementelor vectorului A }
var i, j : integer;
r : real;
begin
for i:=1 to n do
for j:=1 to n-1 do
if A[j]>A[j+1] then
begin
r:=A[j];
A[j]:=A[j+1];
A[j+1]:=r;
end;
end; { Sortare }
begin
write(Dai numarul de elemente n=);
readln(n);
{ atribuim lui A valoarea (n, n-1, ..., 3, 2, 1) }
for i:=1 to n do A[i]:=n-i+1;
T1:=TimpulCurent;
Sortare(A, n);
T2:=TimpulCurent;
writeln(Durata de execuie, (T2-T1):7:2,
readln;
end.

secunde);

101

Procedura Sortare ordoneaz elementele vectorului A prin metoda bulelor. n


aceast metod vectorul A este parcurs de n ori, la fiecare parcurgere efectundu-se
n-1 comparri ale elementelor vecine A[j] i A[j+1]. Dac A[j]>A[j+1], elementele vecine i schimb locul.
Pentru a evita introducerea de la tastatur a unui numr mare de date, n programul P149 vectorului A i se atribuie valoarea iniial
A = (n, n-1, n-2, ..., 3, 2, 1).
De exemplu, pentru n=4, vectorul iniial va fi
A=(4, 3, 2, 1).
n procesul sortrii avem:
i = 1,
i = 2,
i = 3,
i = 4,

A = (3, 2, 1, 4);
A = (2, 1, 3, 4);
A = (1, 2, 3, 4);
A = (1, 2, 3, 4).

Timpul de execuie a procedurii Sortare n cazul unui calculator Pentium cu frecvena


ceasului de sistem 500 MHz este prezentat n tabelul 4.3, iar graficul respectiv n figura 4.3.
Timpul de execuie a procedurii Sortare

7000

8000

Tabelul 4.3

1000

2000

3000

4000

5000

6000

9000 10000

T(n), s

0,27

1,10

2,47

4,50

7,03

10,16 13,84 18,02 22,85 28,18

ntrebri i exerciii
Cum credei, ce legtur exist ntre timpul necesar execuiei unui program PASCAL,
frecvena ceasului de sistem i capacitatea de prelucrare a calculatorului?
Msurai timpul de execuie a procedurii Sortare (vezi programul P149) n cazul calculatorului cu care lucrai dvs. Construii un grafic similar celui din figura 4.3.
Reprezentai grafic pe un singur desen timpul de execuie a procedurilor ce urmeaz.

102

a)

procedure N2(n : integer);


var i, j, k : integer;
r : real;
begin
for i:=1 to n do
for j:=1 to n do
for k:=1 to 300 do
r:=1.0;
end; { N2 }

b)

procedure N3(n : integer);


var i, j, k : integer;
r : real;

t, s
30

20

10

2000

4000

6000 8000 10000

Fig. 4.3. Timpul de execuie a procedurii Sortare

begin
for i:=1 to n do
for j:=1 to n do
for k:=1 to n do
r:=1.0;
end; { N3 }
c)

procedure N4(n : integer);


var i, j, k, m : integer;
r : real;
begin
for i:=1 to n do
for j:=1 to n do
for k:=1 to n do
for m:=1 to n do
r:=1.0;
end; { N4 }

Pentru exemplificare, n figura 4.4 snt prezentate graficele respective n cazul unui calculator Pentium, frecvena ceasului de sistem 500 MHz.
Care este precizia de msurare a timpului cu ajutorul funciei TimpulCurent?
Argumentai rspunsul dvs.

103

t, s
13
12

N4
N3

11
10
9
8
7
6
5
4
3

N2

2
1
0

2000

4000

6000

8000 10000 n

Fig. 4.4. Timpul de execuie a procedurilor N2, N3 i N4

4.4. Estimarea timpului cerut de algoritm


n procesul implementrii practice a oricrui algoritm apare necesitatea estimrii
timpului de execuie T(n) pn la testarea i depanarea definitiv a programului ce-l
realizeaz. Cu regret, prin metode teoretice este foarte greu de determinat o expresie
exact pentru T(n). Din aceste motive se caut o limit superioar a timpului cerut de
algoritm, analizndu-se doar cazurile cele mai defavorabile.
Presupunem, n scopuri didactice, c execuia oricrui operator PASCAL (+, -,
or, *, /, div, and, <, <=, not etc.) necesit cel mult uniti de timp. Acelai timp
este necesar pentru indexarea componentelor unui tablou [ ], pentru atribuirea :=
i instruciunea goto. Valoarea concret a mrimii depinde de mediul de programare, capacitatea de prelucrare a calculatorului utilizat i este de ordinul 10 -9 ... 10 -7
secunde. n continuare vom estima timpul T(n) n forma:
T(n) = Q(n) ,
unde Q(n) este numrul de operaii elementare adunarea, scderea, nmulirea,
compararea etc. necesare pentru soluionarea unei probleme.
Admitem c ntr-o expresie E apar m operatori PASCAL i k apeluri ale funciei
F. Evident, numrul QE de operaii elementare necesare pentru calcularea expresiei
E se determin ca

104

QE = m + k QF ,
unde QF este numrul de operaii elementare necesare pentru calcularea funciei F.
Exemple:
Expresia E
a*b+c

Numrul de operaii elementare QE


2

b) (a<b)or(c>d)

a)

c)

sin(x)+cos(y)

d)

a+M[i]

e)

sin(x+y)+sin(x-y)

1 + Qsin + Qcos
2
3 + 2Qsin

Numrul de operaii elementare QI necesare pentru execuia unei instruciuni I a


limbajului PASCAL se estimeaz conform formulelor din tabelul 4.4.
Tabelul 4.4
Numrul de operaii elementare necesare pentru execuia
unei instruciuni PASCAL
Nr. crt.

Instruciunea PASCAL

Atribuirea := E

Numrul de operaii elementare


QE + 1

Apelul procedurii P

QP + 1

Selecie
if E then I1 else I2

QE + max{QI , QI } + 1

Selecie multipl
case E of I1; I2; ...; Ik end

QE + max{QI , QI , ..., QI } + k + 1

Ciclu cu contor
for := E1 to/downto E2 do I

QE + QE + mQI + m + 1

Ciclu cu test iniial


while E do I

(m + 1)QE + mQI + 1

Ciclu cu test final


repeat I until E

mQI + mQE + 1

Instruciunea compus
begin I1; I2; ...; Ik end

QI + QI + ... + QI + 1

Instruciunea
with do I

QI + 1

10

Saltul goto

Formulele din tabelul 4.4 pot fi deduse urmnd modul de execuie a fiecrei instruciuni PASCAL. n acest tabel reprezint o variabil sau un nume de funcie, E o
expresie, iar I o instruciune. Numrul de execuii ale instruciunii I din cadrul unui
ciclu for, while sau repeat este notat prin m. Menionm c ciclurile unui program
PASCAL pot fi organizate i cu ajutorul instruciunilor if i goto, ns o astfel de
utilizare a acestor instruciuni contravine regulilor programrii structurate.

105

Pentru exemplificare vom estima numrul de operaii elementare Q(n) necesare


ordonrii elementelor unui vector prin metoda bulelor:
procedure Sortare(var A:Vector; n:integer);
var i, j : integer;
r : real;
{1} begin
{2} for i:=1 to n do
{3}
for j:=1 to n-1 do
{4}
if A[j]>A[j+1] then
{5}
begin
{6}
r:=A[j];
{7}
A[j]:=A[j+1];
{8}
A[j+1]:=r;
end;
end; { Sortare }

Instruciunile I1, I2, ... , I8 ale procedurii Sortare vor fi referite cu ajutorul comentariilor {1}, {2}, ..., {8} din partea stng a liniilor de program. Prin Qj vom nota
numrul de operaii elementare necesare pentru executarea instruciunii Ij :
Q6 = 2;
Q7 = 4;
Q8 = 3;
Q5 = Q6 + Q7 + Q8 + 1 = 10;
Q4 = 4 + Q5 + 1 = 15;
Q3 = 0 + 1 + (n1)Q4 + (n1) + 1 = 16n 14;
Q2 = 0 + 0 + nQ3 + n + 1 = 16n2 13n + 1;
Q1 = Q2 +1 = 16n2 13n + 2.
Prin urmare, numrul de operaii elementare
Q(n) = 16n2 13n + 2,
iar timpul cerut de procedura Sortare
T(n) = (16n2 13n + 2) .
Din exemplul studiat mai sus se observ c ordinea parcurgerii instruciunilor
este impus de structura programelor PASCAL. Evident, mai nti se analizeaz instruciunile simple, iar apoi cele structurate. n cazul instruciunilor imbricate, mai
nti se analizeaz instruciunile din interior, apoi cele care le cuprind.
Expresiile analitice T(n) obinute n urma analizei programelor PASCAL pot fi
folosite pentru determinarea experimental a timpului necesar efecturii unei operaii elementare. De exemplu, pentru procedura Sortare (vezi tabelul 4.3) n = 10000
i T(n) = 28,18 s. Din ecuaia
(16n2 13n + 2) = 28,18
obinem 1,8 10 -8 secunde.

106

Evident, aceast valoare este valabil numai pentru mediul de programare Turbo
PASCAL 7.0 i calculatorul Pentium cu frecvena ceasului de sistem 500 MHz, utilizate n procesul de msurare a timpului de execuie a procedurii Sortare. De
exemplu, n cazul unui calculator Pentium cu frecvena ceasului de sistem 150 MHz
se obine valoarea 6,0 10 -8 secunde.

ntrebri i exerciii
Determinai cu ajutorul programului P149 valoarea pentru mediul de programare i
calculatorul cu care lucrai dvs.
Determinai numrul de operaii elementare QI necesare pentru execuia urmtoarelor
instruciuni PASCAL:
a) x:=2*a-6*(y+z);
b)

p:=not(a=b)and(c>d);

c)

p:=(a in R)and(b in P);

d)

if a>b then x:=0 else x:=a+b;

e)

case i of
1: x:=0;
2: x:=a+b;
3: x:=a+b+c;
end;

f)

for i:=1 to n do A[i]:=2*A[i];

g)

for i:=1 to n do A[i]:=B[i+1]-C[i-2];

h)

i:=0; while i<n do begin i:=i+1 end;

i) i:=n; repeat i:=i-1 until i=0;


j) begin i:=0; s:=0; r:=0 end;
k) with A do begin x:=0; y:=0 end.
Estimai numrul operaiilor elementare Q(n) din procedurile ce urmeaz:
a)

procedure N2(n : integer);


var i, j, k : integer;
r : real;
begin
for i:=1 to n do
for j:=1 to n do
for k:=1 to 300 do
r:=1.0;
end; { N2 }

107

b)

procedure N3(n : integer);


var i, j, k : integer;
r : real;
begin
for i:=1 to n do
for j:=1 to n do
for k:=1 to n do
r:=1.0;
end; { N3 }

c)

procedure N4(n : integer);


var i, j, k, m : integer;
r : real;
begin
for i:=1 to n do
for j:=1 to n do
for k:=1 to n do
for m:=1 to n do
r:=1.0;
end; { N4 }

n cazul procedurii Sortare pentru un calculator Pentium cu frecvena ceasului de sistem f1 = 500 MHz s-a obinut 1 1,8 10 -8 s. Pentru acelai tip de calculator, ns cu
frecvena ceasului de sistem f2 = 150 MHz, s-a obinut 2 6,0 10 -8 s. Se observ c
i

.
Cum credei, prin ce se explic acest fapt?
n procesul compilrii, instruciunile limbajului PASCAL snt translatate n una sau mai
multe instruciuni din limbajul cod-main. Numrul concret de instruciuni depinde de
mediul de programare i tipul calculatorului utilizat. Elaborai planul unui experiment
care ne-ar permite s estimm numrul de instruciuni cod-main n care este translatat fiecare instruciune PASCAL.
E cunoscut faptul c timpul de execuie a instruciunilor din limbajul cod-main depinde de tipul lor. De exemplu, o instruciune care adun dou numere ntregi este mai
rapid dect instruciunea care adun dou numere reale. n consecin, valorile , determinate prin msurarea timpului de execuie a unui program PASCAL, depind de tipul
datelor utilizate. Verificai experimental aceast afirmaie n cazul calculatorului cu care
lucrai dvs.
Capacitatea de prelucrare a unui calculator se msoar n Mips Megainstruciuni pe
secund. De exemplu, calculatoarele personale au capacitatea de prelucrare 500800
Mips. Pentru a msura aceast caracteristic, productorii de calculatoare utilizeaz
instruciunile limbajului cod-main. Evident, pentru un programator PASCAL ar prezenta interes i capacitatea de prelucrare exprimat n instruciuni PASCAL pe secund.
Elaborai planul unui experiment care ar permite estimarea acestei caracteristici pentru
calculatorul cu care lucrai dvs.

108

4.5. Complexitatea temporal a algoritmilor


n informatic complexitatea temporal a algoritmilor se caracterizeaz prin timpul de execuie T(n) sau numrul de operaii elementare Q(n). ntruct calculatoarele
moderne au o vitez de calcul foarte mare 108 ... 1010 instruciuni pe secund, problema timpului de execuie se pune numai pentru valorile mari ale lui n. n consecin, n formulele ce exprim numrul de operaii elementare Q(n) prezint interes
numai termenul dominant, adic acel care tinde ct mai repede la infinit. Importana
termenului dominant fa de ceilali este pus n eviden n tabelul 4.5.
Tabelul 4.5
Valorile termenilor dominani
n

log2 n

n2

n3

n4

2n

16

16

64

256

16

64

512

4096

256

16

256

4096

65536

65536

32

1024

32768

1048576

4294967296

De exemplu, numrul de operaii elementare ale procedurii Sortare se exprim


prin formula:
Q(n) = 16n2 13n + 2.
Termenul dominant din aceast formul este 16n2. Evident, pentru valorile mari
ale lui n numrul de operaii elementare
Q(n) 16n2,
iar timpul de execuie

T(n) 16n2.

n funcie de complexitatea temporal, algoritmii se clasific n:


algoritmi polinomiali;
algoritmi exponeniali;
algoritmi nederminist polinomiali.
Un algoritm se numete polinomial dac termenul dominant are forma Cnk, adic
Q(n) Cnk ; T(n) Cnk,
unde:
n este caracteristica datelor de intrare;
C o constant pozitiv;
k un numr natural.
Complexitatea temporal a algoritmilor polinomiali este redat prin notaia
O(nk) care se citete algoritm cu timpul de execuie de ordinul nk sau, mai pe
scurt, algoritm de ordinul nk. Evident, exist algoritmi polinomiali de ordinul
n, n2, n3 etc.

109

De exemplu, algoritmul de sortare a elementelor unui vector prin metoda bulelor


este un algoritm polinomial de ordinul n2. Acest lucru se observ i din graficul timpului de execuie T(n) a procedurii Sortare, grafic prezentat n figura 4.3.
Un algoritm se numete exponenial dac termenul dominant are forma Ckn, adic
Q(n) Ckn;

T(n) Ckn,

unde k>1. Complexitatea temporal a algoritmilor exponeniali este redat prin notaia O(kn).
Menionm faptul c tot exponeniali se consider i algoritmii de complexitatea
nlog n, cu toate c aceast funcie nu este exponenial n sensul strict matematic al
acestui cuvnt.
Din comparaia vitezei de cretere a funciilor exponenial i polinomial (vezi
tabelul 4.5) rezult c algoritmii exponeniali devin inutilizabili chiar pentru valori
nu prea mari ale lui n. Pentru exemplificare amintim tabelul 4.1 n care este prezentat
timpul de execuie T1(n) a unui algoritm polinomial de ordinul O(n3) i timpul de
execuie T2(n) a unui algoritm exponenial de ordinul O(2n).
Algoritmii nederminist polinomiali se studiaz n cursurile avansate de informatic.
n funcie de complexitatea temporal se consider c o problem este uor rezolvabil dac pentru soluionarea ei exist un algoritm polinomial. O problem
pentru care nu exist un algoritm polinomial se numete dificil. Accentum faptul
c aceast clasificare se refer doar la analiza asimptotic a algoritmilor, adic la
comportarea lor pentru valori mari ale lui n. Pentru valorile mici ale lui n situaia
poate fi diferit.
De exemplu, presupunem c pentru soluionarea unei probleme exist doi algoritmi, unul polinomial cu timpul de execuie T1(n) i altul exponenial cu timpul de
execuie T2(n):
T1(n) = 1000n2 ;
T2(n) = 2n.
Prin calcule directe se poate verifica c pentru n = 1, 2, 3, ..., 18 timpul T2(n) < T1(n).
Prin urmare, n situaia n 18 vom prefera algoritmul exponenial.
n practic, elaborarea programelor de calculator presupune parcurgerea urmtoarelor etape:
formularea exact a problemei;
determinarea complexitii temporale a problemei propuse problem uor
rezolvabil sau problem dificil;
elaborarea algoritmului respectiv i implementarea lui pe un sistem de calcul.
Evident, n cazul unor probleme uor rezolvabile, programatorul va depune toate
eforturile pentru a inventa algoritmi polinomiali, adic algoritmi de ordinul nk, astfel
nct parametrul k s ia valori ct mai mici. n cazul problemelor dificile se va da prioritate algoritmilor care minimizeaz timpul de execuie cel puin pentru datele de intrare frecvent utilizate n aplicaiile practice. Metodele de clasificare a problemelor n
cele uor i cele dificil rezolvabile se studiaz n cursurile avansate de informatic.

110

ntrebri i exerciii
Indicai termenii dominani:
a)

12n + 5;

b)

6n2 + 100n + 18;

c)

15n3 + 1000n2 25n + 6000;

d)

2000n3 + 2n + 13;

e)

nlog2n + n5 + 300n2 + 6;

f)

3n + 2n + 14n3 + 21;

g)

n5 + 10n4 + 200n3 + 300n2 + 1000n.

Cum se clasific algoritmii n funcie de complexitatea temporal?


Determinai tipul algoritmilor, cunoscnd complexitatea temporal:
a)

Q(n) = 200n + 15;

b)

Q(n) = 2n + 25n2 + 1000;

c)

Q(n) = n3 + 3n + 6000n2 + 106;

d)

Q(n) = 3n + 2n + n10 + 4000

e)

Q(n) = nlog2n + n3 + n2 + 1500;

f)

Q(n) = 100n2 + 15n3 + 8n + 900.

Cum credei, prin ce se explic importana termenului dominant n analiza complexitii


temporale a algoritmilor?
Se consider procedurile N2, N3 i N4 din paragraful precedent. n urma estimrii numrului de operaii elementare s-a obinut:
QN2(n) = 602n2 + 2n + 2;
QN3(n) = 2n3 + 2n2 + 2n + 2;
QN4(n) = 2n4 + 2n3 + 2n2 + 2n + 2.
Determinai ordinul de complexitate temporal a algoritmilor descrii cu ajutorul acestor proceduri. Comparai viteza de cretere a timpilor de execuie TN2(n), TN3(n) i TN4(n),
folosind n acest scop graficele din figura 4.4.
Se consider un algoritm format din k cicluri imbricate:
for i1:=1 to n do
for i2:=1 to n do
...
for ik:=1 to n do P

111

Numrul de operaii elementare QP efectuate n procedura P este o mrime constant.


Estimai complexitatea temporal a algoritmului.
Schiai un algoritm pentru rezolvarea urmtoarei probleme:
Se consider mulimea A format din n numere ntregi. Determinai dac exist cel puin
o submulime B, BA, suma elementelor creia este egal cu m. De exemplu, pentru
A={-3, 1, 5, 9} i m=7, o astfel de submulime exist, i anume, B={-3, 1, 9}.
Estimai complexitatea temporal a algoritmului elaborat.

112

Capitolul 5
TEHNICI DE ELABORARE
A ALGORITMILOR
5.1. Iterativitate sau recursivitate
Pe parcursul dezvoltrii informaticii s-a stabilit c multe probleme de o real importan practic pot fi rezolvate cu ajutorul unor metode standard, denumite tehnici de programare: recursia, trierea, metoda relurii, metodele euristice .a.
Una din cele mai rspndite tehnici de programare este recursia. Amintim c recursia se definete ca o situaie n care un subprogram se autoapeleaz fie direct, fie
prin intermediul altui subprogram. Tehnicile n studiu se numesc respectiv recursia direct i recursia indirect i au fost studiate n cadrul temei Funcii i proceduri.
n general, elaborarea unui program recursiv este posibil numai atunci cnd se
respect urmtoarea regul de consisten: soluia problemei trebuie s fie direct
calculabil ori calculabil cu ajutorul unor valori direct calculabile. Cu alte cuvinte,
definirea corect a unui algoritm recursiv presupune c n procesul derulrii calculelor trebuie s existe:
cazuri elementare, care se rezolv direct;
cazuri care nu se rezolv direct, ns procesul de calcul n mod obligatoriu progreseaz spre un caz elementar.
De exemplu, n definiia recursiv a funciei factorial fact: NN,

deosebim:
Cazul elementar n = 0. n acest caz valoarea fact(0) este direct calculabil i
anume fact(0)=1.
Cazurile neelementare n > 0. n astfel de cazuri valorile fact(n) nu snt direct
calculabile, ns procesul de calcul progreseaz ctre cazul elementar fact(0).
De exemplu, pentru n = 3 obinem:
fact(3) = 3 fact(2) = 3 2 fact(1) = 3 2 1 fact(0) = 3 2 1 1 = 6.
Prin urmare, definiia recursiv a funciei fact(n) este o definiie consistent.
Amintim c funcia fact(n) poate fi exprimat n PASCAL, urmnd direct definiia,
n forma:

113

function Fact(n:Natural):Natural;
begin
if n=0 then Fact:=1
else Fact:=nFact(n-1)
end;

Modul de gestionare a stivei n cazul apelului Fact(3) este prezentat n figura 5.1.
Evoluia n stiv
Fact(3)

Fact(2)

Fact(1)

Fact(0)

Eliberarea stivei
Fact = 1

Fact = 1

Fact = 2

Fact = 6

Fig. 5.1. Gestionarea stivei n cazul apelului Fact(3):


AR adresa de revenire; n valoarea curent a parametrului actual;
*** spaiu pentru memorarea valorii f returnate de funcia Fact

ntr-un mod similar, n definiia recursiv a funciei incons: NN,

deosebim cazul elementar n=0 i cazurile neelementare n0. ns, spre deosebire de
funcia fact(n), pentru n 0 valorile incons(n) nu pot fi calculate, ntruct procesul de
calcul progreseaz ctre incons().

114

De exemplu, pentru n=3 obinem:


incons(3) = 3 incons(4) = 3 4 incons(5) = 3 4 5 incons(6) = .
Prin urmare, definiia recursiv a funciei incons(n) este o definiie inconsistent
i teoretic procesul de calcul va dura la nesfrit. n practic calculele vor fi ntrerupte
de sistemul de operare n momentul depirii capacitii de memorare a stivei sau n
cazul depirii capacitii dispozitivului aritmetic.
Accentum faptul c mediile actuale de programare nu asigur verificarea consistenei algoritmilor recursivi, acest lucru revenindu-i programatorului.
Dup cum s-a vzut n capitolele precedente, orice algoritm recursiv poate fi transcris ntr-un algoritm iterativ i invers. Alegerea tehnicii de programare iterativitate sau recursivitate ine, de asemenea, de competena programatorului. Evident,
aceast alegere trebuie fcut lund n considerare avantajele i neajunsurile fiecrei
metode, care variaz de la caz la caz. Pentru exemplificare, n tabelul 5.1. snt prezentate rezultatele unui studiu comparativ al ambelor tehnici de programare n cazul
prelucrrii automate a textelor.
Tabelul 5.1
Studiul comparativ al iterativitii i recursivitii
(prelucrarea automat a textelor)
Nr. crt.

Caracteristici

Iterativitate
mic

Recursivitate

1.

Necesarul de memorie

mare

2.

Timpul de execuie

3.

Structura programului

complicat

simpl

4.

Volumul de munc necesar


pentru scrierea programului

mare

mic

5.

Testarea i depanarea programelor

simpl

complicat

acelai

Propunem cititorului n calitate de exerciiu efectuarea unui studiu comparativ al


iterativitii i recursivitii n cazul algoritmilor destinai crerii i prelurii structurilor dinamice de date din Capitolul 2.
n general, algoritmii recursivi snt recomandai n special pentru problemele ale
cror rezultate snt definite prin relaii de recuren: analiza sintactic a textelor, prelucrarea structurilor dinamice de date, procesarea imaginilor .a. Un exemplu tipic
de astfel de probleme este analiza gramatical a programelor PASCAL, sintaxa crora, dup cum se tie, este definit prin relaii de recuren.

ntrebri i exerciii
Explicai termenul tehnici de programare.
Care este diferena dintre recursia direct i recursia indirect? Dai exemple.
Ce condiii trebuie respectate pentru ca definiia unui algoritm recursiv s fie corect?
Care este diferena dintre definiiile recursive consistente i definiiile recursive inconsistente?

115

Se consider urmtoarele definiii recursive de funcii. Care din aceste definiii snt consistente? Argumentai rspunsul.
a) f : NN,
b) f : NN,
c) f : ZZ,
d) f : NN,
g : NN,
e) f : NN,

dac
dac
dac
dac
dac
dac
dac
dac
dac
dac
dac
div

dac

Lansai n execuie programul ce urmeaz. Explicai mesajele afiate la ecran.


Program P150;
{ Depirea capacitii de memorare a stivei }
type Natural = 0..Maxint;
function Incons(n:Natural):Natural;
{ Definiie recursiv inconsistent }
begin
writeln(Apel recursiv n=, n);
if n=0 then Incons:=1
else Incons:=n*Incons(n+1);
end; { Incons }
begin
writeln(Incons(3));
readln;
end.
Reprezentai pe un desen similar celui din figura 5.1 modul de gestionare a stivei n cazul
apelului Incons(3).
Indicai cazurile elementare i cele neelementare pentru urmtorii algoritmi recursivi:
a) funcia Arb i procedura AfisArb din programul P130;
b) procedurile Preordine, Inordine i Postordine din programul P131;
c) procedura InAdincime din programul P133.
Suma primelor n numere naturale S(n) poate fi calculat cu ajutorul funciei iterative

116

sau al funciei recursive

dac
dac
Utiliznd ca model tabelul 5.1, efectuai un studiu comparativ al algoritmilor destinai
calculrii sumei S(n).
Se consider urmtoarele formule metalingvistice:
Cifr ::= 0123456789
Numr ::= Cifr Cifr
Semn ::= +-*/
Expresie ::= Numr (Expresie)ExpresieSemnExpresie
Scriei o funcie recursiv care returneaz valoarea true dac irul de caractere S este
conform definiiei unitii lexicale Expresie i false n caz contrar.
Efectuai un studiu comparativ al algoritmilor iterativi i algoritmilor recursivi destinai
creri i prelucrrii urmtoarelor structuri dinamice de date:
a) liste unidirecionale;
b) stiva;
c) cozi;
d) arbori binari;
e) arbori de ordinul m.
Scriei o funcie iterativ care returneaz valoarea true dac irul de caractere S este
conform definiiei unitii lexicale Expresie din exerciiul 9 i false n caz contrar.
Utiliznd ca model tabelul 5.1, efectuai un studiu comparativ al algoritmului iterativ i
algoritmului recursiv.
Elaborai un subprogram recursiv care calculeaz suma cifrelor unui numr natural n.
Examinai cazurile n MaxInt i n 10250.
Imaginile n alb-negru (fig. 5.2) pot fi codificate cu ajutorul unei matrice binare B =
= ||bij||nm, 1 n, m 30. Elementul bij indic culoarea microzonei respective: neagr (bij
=1) sau alb (bij =0).

a)

b)

Fig. 5.2. Colorarea unei suprafee nchise:


a imaginea iniial; b imaginea final

Elaborai o procedur recursiv pentru colorarea unei suprafee nchise, specificate prin
coordonatele (i, j) ale oricrei microzone A din interiorul ei.

117

Elaborai o procedur care determin cte obiecte conine o imagine n alb-negru.


Imaginea este mprit n microzone i codificat cu ajutorul matricei binare B = ||bij||nm.
Elementul bij indic culoarea microzonei cu coordonatele (i, j).
Efectuai un studiu comparativ al algoritmilor iterativi i algoritmilor recursivi destinai
soluionrii problemelor din exerciiile 13 i 14.

5.2. Metoda trierii


Metoda trierii presupune c soluia unei probleme poate fi gsit analiznd consecutiv elementele si ale unei mulimi finite

S = {s1, s2, , si, , sk},


denumit mulimea soluiilor posibile. n cele mai simple cazuri elementele si, si
S, pot fi reprezentate prin valori aparinnd unor tipuri ordinale de date: integer,
boolean, char, enumerare sau subdomeniu. n problemele mai complicate sntem nevoii s reprezentm aceste elemente prin tablouri, articole sau mulimi. Menionm
c n majoritatea problemelor soluiile posibile s1, s2, , sk nu snt indicate explicit n
enunul problemei i elaborarea algoritmilor pentru calcularea lor cade n sarcina
programatorului.
Schema general a unui algoritm bazat pe metoda trierii poate fi redat cu ajutorul unui ciclu:
for i:= 1 to k do
if SolutiePosibila(si) then PrelucrareaSolutiei(si)

unde SolutiePosibila este o funcie boolean care returneaz valoarea


true dac elementul si satisface condiiile problemei i false n caz contrar, iar
PrelucrareaSolutiei este o procedur care efectueaz prelucrarea elementului
selectat. De obicei, n aceast procedur soluia si este afiat la ecran.
n continuare vom analiza dou exemple care pun n eviden avantajele i neajunsurile algoritmilor bazai pe metoda trierii.
Exemplul 1. Se consider numerele naturale din mulimea {0, 1, 2, ..., n}. Elaborai
un program care determin pentru cte numere K din aceast mulime suma cifrelor
fiecrui numr este egal cu m. n particular, pentru n = 100 i m = 2, n mulimea
{0, 1, 2, , 100} exist 3 numere care satisfac condiiile problemei: 2, 11 i 20. Prin
urmare, K = 3.
Rezolvare. Evident, mulimea soluiilor posibile S = {0, 1, 2, , n}. n programul ce
urmeaz suma cifrelor oricrui numr natural i, iS, se calculeaz cu ajutorul funciei
SumaCifrelor. Separarea cifrelor zecimale din scrierea numrului natural i se efectueaz de la dreapta la stnga prin mprirea numrului i i a cturilor respective la baza 10.
Program P151;
{ Suma cifrelor unui numr natural }
type Natural=0..MaxInt;
var i, K, m, n : Natural;

118

function SumaCifrelor(i:Natural):Natural;
var suma : Natural;
begin
suma:=0;
repeat
suma:=suma+(i mod 10);
i:=i div 10;
until i=0;
SumaCifrelor:=suma;
end; { SumaCifrelor }
function SolutiePosibila(i:Natural):boolean;
begin
if SumaCifrelor(i)=m then SolutiePosibila:=true
else SolutiePosibila:=false;
end; { SumaCifrelor }
procedure PrelucrareaSolutiei(i:Natural);
begin
writeln(i=, i);
K:=K+1;
end; { PrelucrareaSolutiei }
begin
write(Dai n=); readln(n);
write(Dai m=); readln(m);
K:=0;
for i:=0 to n do
if SolutiePosibila(i) then PrelucrareaSolutiei(i);
writeln(K=, K);
readln;
end.

Din analiza programului P151 rezult c complexitatea temporar a algoritmului respectiv este O(n).
Exemplul 2. Se consider mulimea P = {P1, P2, , Pn} format din n puncte (2 n
30) pe un plan euclidian. Fiecare punct Pj este definit prin coordonatele sale xj, yj.
Elaborai un program care afieaz la ecran coordonatele punctelor Pa, Pb distana
dintre care este maxim.
Rezolvare. Mulimea soluiilor posibile S = PP. Elementele (Pj, Pm) ale produsului
cartezian PP pot fi generate cu ajutorul a dou cicluri imbricate:
for j:=1 to n do
for m:=1 to n do
if SolutiePosibil(Pj, Pm) then PrelucrareaSolutiei(Pj, Pm)

119

Distana dintre punctele Pj, Pm se calculeaz cu ajutorul formulei:


.
Program P152;
{ Puncte pe un plan euclidian }
const nmax=30;
type Punct = record
x, y : real;
end;
Indice = 1..nmax;
var P : array[Indice] of Punct;
j, m, n : Indice;
dmax : real; { distana maxima }
PA, PB : Punct;
function Distanta(A, B : Punct) : real;
begin
Distanta:=sqrt(sqr(A.x-B.x)+sqr(A.y-B.y));
end; { Distanta }
function SolutiePosibila(j,m:Indice):boolean;
begin
if j<>m then SolutiePosibila:=true
else SolutiePosibila:=false;
end; { SolutiePosibila }
procedure PrelucrareaSolutiei(A, B : Punct);
begin
if Distanta(A, B)>dmax then
begin
PA:=A; PB:=B;
dmax:=Distanta(A, B);
end;
end; { PrelucrareaSolutiei }
begin
write(Dati n=); readln(n);
writeln(Dai coordonatele x, y ale punctelor);
for j:=1 to n do
begin
write(P[, j, ]: ); readln(P[j].x, P[j].y);
end;
dmax:=0;
for j:=1 to n do
for m:=1 to n do

120

if SolutiePosibila(j, m) then
PrelucrareaSolutiei(P[j], P[m]);
writeln(Soluia: PA=(, PA.x:5:2, ,, PA.y:5:2, ));
writeln(
PB=(, PB.x:5:2, ,, PB.y:5:2, ));
readln;
end.

Complexitatea temporal a algoritmului descris cu ajutorul programului P152


este O(n2).
Din exemplele prezentate mai sus se observ c n algoritmii bazai pe metoda trierii se calculeaz, implicit sau explicit, mulimea soluiilor posibile S. n problemele
relativ simple (exemplul 1) elementele din mulimea soluiilor posibile pot fi enumerate direct. n problemele mai complicate (exemplul 2) generarea soluiilor posibile
necesit elaborarea unor algoritmi speciali. n general, aceti algoritmi realizeaz
operaiile legate de prelucrarea unor mulimi:
reuniunea;
intersecia;
diferena;
generarea tuturor submulimilor;
generarea elementelor unui produs cartezian;
generarea permutrilor, aranjamentelor sau combinrilor de obiecte etc.
Avantajul principal al algoritmilor bazai pe metoda trierii const n faptul c
programele respective snt relativ simple, iar depanarea lor nu necesit teste sofisticate. Complexitatea temporal a acestor algoritmi este determinat de numrul de
elemente k din mulimea soluiilor posibile S. n majoritatea problemelor de o real
importan practic metoda trierii conduce la algoritmii exponeniali. ntruct algoritmii exponeniali snt inacceptabili n cazul datelor de intrare foarte mari, metoda
trierii este aplicat numai n scopuri didactice sau pentru elaborarea unor programe
al cror timp de execuie nu este critic.

ntrebri i exerciii
Explicai structura general a algoritmilor bazai pe metoda trierii.
Cum poate fi realizat trierea soluiilor posibile cu ajutorul ciclurilor while i repeat?
Estimai timpul de execuie al programelor P151 i P152. Modificai programul P152
astfel, nct timpul de execuie s se micoreze aproximativ de dou ori.
Dai exemple de programe timpul de execuie al crora nu este critic.
Care snt avantajele i dezavantajele algoritmilor bazai pe metoda trierii?
Se consider mulimea P = {P1, P2, , Pn} format din n puncte (3 n 30) pe un plan
euclidian. Fiecare punct Pj este definit prin coordonatele sale xj, yj. Elaborai un program
ce determin trei puncte din mulimea P pentru care aria triunghiului respectiv este
maxim. Estimai timpul de execuie a programului elaborat.
Scriei o funcie PASCAL care, primind ca parametru un numr natural n, returneaz valoarea true dac n este prim i false n caz contrar. Estimai complexitatea temporal
a funciei respective.

121

n notaia (a)x litera x reprezint baza sistemului de numeraie, iar litera a un numr
scris n sistemul respectiv. Elaborai un program care calculeaz, dac exist, cel puin o
rdcin a ecuaiei
(a)x = b,
unde a i b snt numere naturale, iar x este necunoscuta. Fiecare cifr a numrului natural a aparine mulimii {0, 1, 2, , 9}, iar numrul b este scris n sistemul zecimal. De
exemplu, rdcina ecuaiei
(160)x = 122
este x = 8, iar ecuaia
(5)x = 10
nu are soluii. Estimai complexitatea temporal a programului elaborat.
ntr-o puculi se afl N monede de diferite valori cu greutatea total G grame. Greutatea
fiecrei monede de o anumit valoare este dat n tabelul ce urmeaz.
Valoarea monedei, lei

Greutatea monedei, grame

10

25

50

Elaborai un program care determin suma minim S care ar putea s fie n puculi.
Elaborai un program care determin cte puncte cu coordonate ntregi se conin ntr-o
sfer de raza R cu centrul n originea sistemului de coordonate. Se consider c R este
un numr natural, 1R30. Distana d dintre un punct cu coordonatele (x, y, z) i originea
sistemului de coordonate se determin dup formula
.

5.3. Tehnica Greedy


Aceast metod presupune c problemele pe care trebuie s le rezolvm au urmtoarea structur:
se d o mulime A={a1, a2, ..., an} format din n elemente;
se cere s determinm o submulime B, BA, care ndeplinete anumite condiii
pentru a fi acceptat ca soluie.
n principiu, problemele de acest tip pot fi rezolvate prin metoda trierii, genernd
consecutiv cele 2n submulimi Ai ale mulimii A. Dezavantajul metodei trierii const
n faptul c timpul cerut de algoritmii respectivi este foarte mare.
Pentru a evita trierea tuturor submulimilor Ai, AiA, n metoda Greedy se utilizeaz un criteriu (o regul) care asigur alegerea direct a elementelor necesare
din mulimea A. De obicei, criteriile sau regulile de selecie nu snt indicate explicit
n enunul problemei i formularea lor cade n sarcina programatorului. Evident, n
absena unor astfel de criterii metoda Greedy nu poate fi aplicat.
Schema general a unui algoritm bazat pe metoda Greedy poate fi redat cu ajutorul unui ciclu:

122

while ExistaElemente do
begin
AlegeUnElement(x);
IncludeElementul(x);
end

Funcia ExistaElemente returneaz valoarea true dac n mulimea A exist elemente care satisfac criteriul (regula) de selecie. Procedura AlegeUnElement
extrage din mulimea A un astfel de element x, iar procedura IncludeElementul
nscrie elementul selectat n submulimea B. Iniial B este o mulime vid.
Dup cum se vede, n metoda Greedy soluia problemei se caut prin testarea consecutiv a elementelor din mulimea A i prin includerea unora din ele n submulimea
B. ntr-un limbaj plastic, submulimea B ncearc s nghit elementele gustoase
din mulimea A, de unde provine i denumirea metodei (greedy lacom, hrpre).
Exemplu. Se consider mulimea A={a1, a2, ..., ai, ..., an} elementele creia snt numere reale, iar cel puin unul din ele satisface condiia ai>0. Elaborai un program care
determin o submulime B, BA, astfel nct suma elementelor din B s fie maxim.
De exemplu, pentru A={21,5; -3,4; 0; -12,3; 83,6} avem B={21,5; 83,6}.
Rezolvare. Se observ c dac o submulime B, BA, conine un element b0, atunci
suma elementelor submulimii B \{b} este mai mare sau egal cu cea a elementelor
din B. Prin urmare, regula de selecie este foarte simpl: la fiecare pas n submulimea B se include un element pozitiv arbitrar din mulimea A.
n programul ce urmeaz mulimile A i B snt reprezentate prin vectorii (tablourile unidimensionale) A i B, iar numrul de elemente ale fiecrei mulimi prin
variabilele ntregi, respectiv n i m. Iniial B este o mulime vid, respectiv m=0.
Program P153;
{ Tehnica Greedy }
const nmax=1000;
var A : array [1..nmax] of real;
n : 1..nmax;
B : array [1..nmax] of real;
m : 0..nmax;
x : real;
i : 1..nmax;
Function ExistaElemente : boolean;
var i : integer;
begin
ExistaElemente:=false;
for i:=1 to n do
if A[i]>0 then ExistaElemente:=true;
end; { ExistaElemente }
procedure AlegeUnElement(var x : real);
var i : integer;

123

begin
i:=1;
while A[i]<=0 do i:=i+1;
x:=A[i];
A[i]:=0;
end; { AlegeUnElement }
procedure IncludeElementul(x : real);
begin
m:=m+1;
B[m]:=x;
end; { IncludeElementul }
begin
write(Dai n=); readln(n);
writeln(Dai elementele mulimii A:);
for i:=1 to n do read(A[i]);
writeln;
m:=0;
while ExistaElemente do
begin
AlegeUnElement(x);
IncludeElementul(x);
end;
writeln(Elementele mulimii B:);
for i:=1 to m do writeln(B[i]);
readln;
end.

Menionm c procedura AlegeUnElement zerografiaz componenta vectorului A ce coninea elementul x, extras din mulimea respectiv.
Complexitatea temporal a algoritmilor bazai pe metoda Greedy poate fi evaluat urmnd schema general de calcul prezentat mai sus. De obicei, timpul cerut
de procedurile ExistaElemente, AlegeUnElement i IncludeElementul este
de ordinul n. n componena ciclului while aceste proceduri se execut cel mult de
n ori. Prin urmare, algoritmii bazai pe metoda Greedy snt algoritmi polinomiali.
Pentru comparare, amintim c algoritmii bazai pe trierea tuturor submulimilor Ai,
Ai A, snt algoritmi de ordinul O(2n), deci exponeniali. Cu regret, metoda Greedy
poate fi aplicat numai atunci cnd din enunul problemei poate fi dedus regula
care asigur selecia direct a elementelor necesare din mulimea A.

ntrebri i exerciii
Explicai structura general a algoritmilor bazai pe metoda Greedy.
Care snt avantajele i neajunsurile algoritmilor bazai pe tehnica Greedy?
Estimai timpul de execuie al programului P153.

124

Schiai un algoritm care determin submulimea B din exemplul de mai sus prin metoda trierii. Estimai complexitatea temporal a algoritmului elaborat.
Memorarea fiierelor pe benzi magnetice. Se consider n fiiere f1, f2, ..., fn care trebuie memorate pe o band magnetic. Elaborai un program care determin ordinea de
amplasare a fiierelor pe band astfel nct timpul mediu de acces s fie minim. Se presupune c frecvena de citire a fiierelor este aceeai, iar pentru citirea fiierului fi (i=1, 2,
..., n) snt necesare ti secunde.
Problema continu a rucsacului. Se consider n obiecte. Pentru fiecare obiect i (i=1,
2, ..., n) se cunoate greutatea gi i ctigul ci care se obine n urma transportului su
la destinaie. O persoan are un rucsac cu care pot fi transportate unul sau mai multe
obiecte greutatea sumar a crora nu depete valoarea Gmax. Elaborai un program
care determin ce obiecte trebuie s transporte persoana n aa fel nct ctigul s fie
maxim. n caz de necesitate, unele obiecte pot fi tiate n fragmente mai mici.
Hrubele de la Cricova. Dup o vizit la renumitele hrube* de la Cricova un informatician
a construit un robot care funcioneaz ntr-un cmp divizat n ptrele (fig. 5.3). Robotul
poate executa doar instruciunile SUS, JOS, DREAPTA, STINGA, conform crora se deplaseaz n unul din ptrelele vecine. Dac n acest ptrat este un obstacol, de exemplu, un perete sau un butoi, are loc un accident i robotul iese din funciune.

Robot

Intrare

Ieire

Fig. 5.3. Cmpul de aciune al robotului

Elaborai un program care, cunoscnd planul hrubelor, deplaseaz robotul prin ncperile subterane, de la intrarea n hrube la ieire. Colecia de vinuri fiind foarte bogat, nu se
cere vizitarea obligatorie a tuturor ncperilor subterane.
Datele de intrare. Planul hrubelor este desenat pe o foaie de hrtie liniat n ptrele. Ptrelele haurate reprezint obstacolele, iar cele nehaurate spaiile libere.
Ptrelele de pe perimetrul planului, cu excepia celor de intrare sau ieire, snt haurate prin definiie. n form numeric planul hrubelor este redat prin tabloul A cu m linii
i n coloane. Elementele A[i, j] ale acestui tablou au urmtoarea semnificaie: 0 spaiu

Hrub ncpere sau galerie subteran care servete la depozitarea produselor alimentare.
n hrubele de la Cricova pe parcursul mai multor decenii au fost depozitate cele mai bune
vinuri din Republica Moldova.

125

liber; 1 obstacol; 2 intrarea n hrube; 3 ieirea din hrube. Iniial, robotul se afl n
ptrelul pentru care A[i, j]=2.
Fiierul HRUBE.IN conine pe prima linie numerele m, n separate prin spaiu. Pe urmtoarele m linii se conin cte n numere A[i, j] separate prin spaiu.
Datele de ieire. Fiierul HRUBE.OUT va conine pe fiecare linie cte una din instruciunile SUS, JOS, DREAPTA, STINGA scrise n ordinea executrii lor de ctre robot.
Restricii. 5 m, n 100 . Timpul de execuie nu va depi 3 secunde.
Exemplu:
HRUBE.IN
HRUBE.OUT
7 9
SUS
1 1 1 1 1 1 1 1 1
DREAPTA
1 0 0 1 0 0 0 0 1
DREAPTA
1 0 1 0 0 1 0 1 1
DREAPTA
1 0 0 0 1 0 0 0 1
DREAPTA
1 0 1 0 1 0 1 0 1
SUS
1 0 0 0 0 0 1 0 1
SUS
1 2 1 1 1 1 1 3 1
DREAPTA
DREAPTA
JOS
JOS
JOS
Indicaii. La fiecare pas selectai din mulimea {SUS, JOS, DREAPTA, STINGA} cte o
instruciune n aa fel nct robotul s se deplaseze numai de-a lungul unui perete.

5.4. Metoda relurii


n metoda relurii se presupune c soluia problemei pe care trebuie s o rezolvm poate fi reprezentat printr-un vector:
X=(x1, x2 , ..., xk , ... , xn).
Fiecare component xk a vectorului X poate lua valori dintr-o anumit mulime
Ak, k = 1, 2, ..., n. Se consider c cele mk elemente ale fiecrei mulimi Ak snt ordonate
conform unui criteriu bine stabilit, de exemplu, n ordinea apariiei lor n memoria
calculatorului.
n principiu, astfel de probleme pot fi soluionate prin metoda trierii, tratnd vectorul X ca un element al produsului cartezian S = A1A2 ... An. Dezavantajul metodei trierii const n faptul c timpul cerut de algoritmul respectiv este foarte mare.
De exemplu, pentru mulimile A1, A2, ..., An formate numai din cte dou elemente,
timpul necesar este O(2n), deci exponenial.
Pentru evitarea trierii tuturor elementelor produsului cartezian A1A2 ... An, n
metoda relurii componentele vectorului X primesc valori pe rnd, n sensul c lui xk
i se atribuie o valoare numai dac au fost deja atribuite valori lui x1, x2 , ..., xk-1 . Mai
mult, odat o valoare pentru xk stabilit, nu se trece direct la atribuirea de valori lui
xk+1, ci se verific anumite condiii de continuare referitoare la x1, x2 , ..., xk. Aceste

126

condiii stabilesc situaiile n care are sens s trecem la calculul lui xk+1. Dac aceste
condiii nu snt satisfcute, va trebui s facem o alt alegere pentru xk sau, dac elementele din mulimea Ak s-au epuizat, s micorm pe k cu o unitate ncercnd s
facem o nou alegere pentru xk-1.
Menionm faptul c anume micorarea lui k d nume metodei studiate, cuvntul
reluare semnificnd revenirea la alte variante de alegere a variabilelor x1, x2 , ..., xk-1.
Evident, aceeai semnificaie o are i denumirea englez a metodei n studiu backtracking (back napoi, track urm).
Pentru exemplificare, n figura 5.4 este prezentat ordinea n care snt examinate
elementele mulimilor A1 = {a11, a12}, A2 = {a21, a22} i A3 = {a31, a32, a33}. n scopuri didactice se consider c mulimile A1 i A2 au cte dou elemente (m1 = 2, m2 = 2), iar
mulimea A3 trei elemente (m3 = 3). Elementele akj ale mulimilor respective snt
simbolizate prin cerculee. Rezultatele verificrii condiiilor de continuare snt reprezentate prin valorile binare 0 (false) i 1 (true).
k:=1

A1
k:=k+1

A2
k:=k+1

k:=k+1
0
0

k:=k1
0
0

A3

Fig. 5.4. Cutarea soluiei prin metoda relurii

Din figura 5.4 se observ c primul element a11 din mulimea A1 nu satisface condiiile de continuare i, n consecin, se trece la elementul al doilea a12 din aceeai
mulime. Mai departe n vectorul X se include primul element a21 din mulimea A2,
element care satisface condiiile de continuare, i se trece la examinarea elementelor
din mulimea A3.
ntruct niciunul din elementele a31 , a32 , a33 nu satisface condiiile de continuare,
se revine la mulimea A2 din care se alege elementul al doilea, i anume, a22. Dup
aceasta se testeaz din nou elementele mulimii A3, elementul a32 satisfcnd condiiile de continuare.
Schema general a unui algoritm recursiv bazat pe metoda relurii este redat cu
ajutorul procedurii ce urmeaz:
procedure Reluare(k:integer);
begin
if k<=n then

127

begin
X[k]:=PrimulElement(k);
if Continuare(k) then Reluare(k+1);
while ExistaSuccesor(k) do
begin
X[k]:=Succesor(k);
if Continuare(k) then Reluare(k+1)
end; { while }
end { then }
else PrelucrareaSolutiei;
end; {Reluare}

Procedura Reluare comunic cu programul apelant i subprogramele apelate prin variabilele globale ce reprezint vectorul X i mulimile A1, A2, ..., An.
Subprogramele apelate execut urmtoarele operaii:
PrimulElement(k) returneaz primul element din mulimea Ak;
Continuare(k) returneaz valoarea true dac elementele nscrise n primele
k componente ale vectorului X satisfac condiiile de continuare i false n caz contrar;
ExistaSuccesor(k) returneaz valoarea true dac elementul memorat n
componenta xk are un succesor n mulimea Ak i false n caz contrar;
Succesor(k) returneaz succesorul elementului memorat n componenta xk;
PrelucrareaSolutiei de obicei, n aceast procedur soluia reinut n
vectorul X este afiat la ecran.
Pentru o nelegere mai clar a procesului recursiv, vom urmri execuia procedurii Reluare n cazul mulimilor A1, A2, i A3 din figura 5.3.
La execuia apelului Reluare(1) n componenta x1 a vectorului X se nscrie primul element al mulimii A1:
X=(a11).
ntruct n cazul acestui vector apelul Continuare(1) returneaz valoarea false, se trece la execuia instruciunii while. Apelul ExistaSuccesor(1) returneaz valoarea true i, prin urmare, n componenta x1 a vectorului X se nscrie succesorul elementului a11:
X=(a12).
De data aceasta apelul Continuare(1) returneaz valoarea true i, prin urmare, se trece la execuia recursiv a apelului Reluare(2). Evident, n componenta x2
a vectorului X va fi nscris primul element din mulimea A2:
X=(a12, a21).
Pentru acest vector funcia Continuare returneaz valoarea true, fapt ce declaneaz execuia recursiv a apelului Reluare(3).
n cazul apelului Reluare(3) componenta x3 a vectorului X ia recursiv valorile
a31, a32 i a33:
X=(a12, a21, a31);
X=(a12, a21, a32);

128

X=(a12, a21, a33),


ns nici unul din aceti vectori nu satisface condiiile de continuare. Dup examinarea ultimului element din mulimea A3, funcia ExistaSuccesor returneaz valoarea false i, n consecin, se revine n contextul apelului Reluare(2). n acest
context n componenta x2 a vectorului X se nscrie succesorul elementului a21:
X=(a12, a22).
ntruct i pentru acest vector funcia Continuare returneaz valoarea true,
din nou se execut apelul recursiv Reluare(3). ns, spre deosebire de apelul precedent, n acest caz vectorul
X=(a12, a22, a32)
satisface condiiile de continuare, fapt ce declaneaz execuia apelului recursiv
Reluare(4). n acest apel k>n i, prin urmare, procedura PrelucrareaSolutiei
va afia coordonatele vectorului X la ecran.
Exemplu. Se consider mulimile A1, A2, ..., An, fiecare mulime fiind format din
mk numere naturale. Selectai din fiecare mulime cte un numr n aa mod nct
suma lor s fie egal cu q.
Rezolvare. Vom reprezenta mulimile A1, A2, ..., An prin liniile tabloului bidimensional (matricei) A = ||akj||. Numrul de elemente mk al fiecrei mulimi Ak va fi reinut
n componenta respectiv a tabloului unidimensional (vectorului) M = ||mk||.
Din enunul problemei rezult c toate condiiile de continuare snt respectate
numai atunci cnd suma elementelor referite de primele k componente ale vectorului
X nu depete valoarea q pentru k<n i este egal cu q pentru k = n. Pentru a simplifica scrierea programului, vom memora n vectorul X numai indicii j ai elementelor
aij selectate din mulimile A1, A2, ..., An.
Program P154;
{ Program bazat pe metoda relurii }
const mmax=50; { numrul maximal de mulimi }
nmax=50; { numrul maximal de elemente }
type Natural = 0..MaxInt;
Multime = array [1..nmax] of Natural;
var

A : array[1..nmax] of Multime;
n : 1..nmax;
{ numrul de mulimi }
M : array[1..nmax] of 1..mmax; { cardinalul mulimii S[k] }
X : array[1..nmax] of 1..mmax; { indicii elementelor
selectate }
q : Natural;
k, j : integer;
Indicator : boolean;

function PrimulElement(k : integer) : Natural;


begin
PrimulElement:=1;
end; {PrimulElement }

129

function Continuare(k : integer) : boolean;


var j : integer;
suma : Natural;
begin
suma:=0;
for j:=1 to k do suma:=suma+A[j, X[j]];
if ((k<n) and (suma<q)) or ((k=n) and (suma=q))
then Continuare:=true
else Continuare:=false;
end; { Continuare }
function ExistaSuccesor(k : integer) : boolean;
begin
ExistaSuccesor:=(X[k]<M[k]);
end; { ExistaSuccesor }
function Succesor(k : integer) : integer;
begin
Succesor:=X[k]+1;
end; { Succesor }
procedure PrelucrareaSolutiei;
var k : integer;
begin
write(Soluia: );
for k:=1 to n do write(A[k, X[k]], );
writeln;
Indicator:=true;
end; { PrelucrareaSolutiei }
procedure Reluare(k : integer);
{ Metoda reluarii - varianta recursiva }
begin
if k<=n then
begin
X[k]:=PrimulElement(k);
if Continuare(k) then Reluare(k+1);
while ExistaSuccesor(k) do
begin
X[k]:=Succesor(k);
if Continuare(k) then Reluare(k+1);
end { while }
end { then }
else PrelucrareaSolutiei;
end; { Reluare }

130

begin
write(Dai cardinalul A[, k, ]=); readln(M[k]);
write(Dai elementele mulimii A[, k, ]: );
for j:=1 to M[k] do read(A[k, j]);
writeln;
end;
Write(Dai q=); readln(q);
Indicator:=false;
Reluare(1);
if Indicator=false then writeln(Nu exist soluii);
readln;
end.

Din analiza procedurii Reluare i a ordinii de parcurgere a elementelor din mulimile A1, A2, ..., An (fig. 5.4) rezult c n cazul cel mai nefavorabil vor fi generai toi
vectorii X ai produsului cartezian A1A2...An. Prin urmare, complexitatea temporal a algoritmilor bazai pe metoda relurii este, ca i n cazul trierii, O(mn), unde
m=max(m1, m2, ..., mn).
Timpul real de execuie, cerut de un algoritm, depinde n mare msur de natura
problemei, mai exact, de esena condiiilor de continuare i ordinea n care apar elementele akj n mulimile A1, A2, ..., An. O bun alegere a condiiilor de continuare are
ca efect o important reducere a numrului de calcule. n particular, n cazul cel mai
favorabil, din fiecare mulime A1, A2, ..., An va fi testat numai cte un singur element
i, evident, timpul de execuie va fi proporional cu n.
Cu regret, n prezent nu exist o regul universal care ar permite formularea
unor condiii bune de continuare pentru orice problem ntlnit n practic.
Identificarea acestor condiii i, n consecin, reducerea timpului de calcul depinde
de iscusina programatorului. Menionm c n majoritatea problemelor mulimile
A1, A2, ..., An nu snt cunoscute apriori, iar componentele vectorului X pot aparine i
ele unor tipuri structurate de date tablouri, mulimi sau articole.

ntrebri i exerciii
Explicai structura general a algoritmilor bazai pe metoda relurii.
Indicai cazurile elementare i cele neelementare n procedura recursiv Reluare.
Elaborai o variant iterativ a procedurii Reluare.
Elaborai un studiu comparativ al algoritmilor iterativi i algoritmilor recursivi bazai pe
metoda relurii.
Reprezentai pe un desen similar celui din figura 5.4 ordinea n care snt examinate elementele mulimilor A1, A2, ..., An din programul P154:
a) A1={1}, A2={2}, A3={3}, q=4;
b) A1={1}, A2 ={2, 3}, A3={4, 5}, q=10;
c) A1={1, 2, 3}, A2={4, 5}, A3={6}, q=14;
d) A1={1, 2}, A2={3, 4}, A3={5, 6}, A4={7, 8}, q=20.

131

Precizai condiiile de continuare pentru programele n care se dorete generarea tuturor elementelor produsului cartezian A1A2...An. Pentru a verifica rspunsul scriei i
depanai programul respectiv.
Indicai pe desenul din figura 5.4 ordinea de parcurgere a elementelor din mulimile A1,
A2, A3 n cazurile cele mai favorabile i cele mai nefavorabile.
Se consider mulimea B={b1, b2, ..., bn} format n primele n litere ale alfabetului latin.
Elaborai un program bazat pe metoda relurii care genereaz toate submulimile
Bi, BiB, formate exact din q litere.
Indicaie. Fiecare submulime Bi poate fi reprezentat prin vectorul caracteristic X = ||xk||n,
unde

dac
n caz contrar.

Evident, submulimea Bi satisface condiiile problemei dac x1+x2+...+xn=q.


Colorarea hrilor. Pe o hart sunt reprezentate n ri, n30. n memoria calculatorului
harta este redat prin matricea A=||aij||nm, unde

dac rile i, j snt vecine;


n caz contrar.
Determinai numrul minim de culori m necesare pentru a colora harta. Evident, se cere
ca oricare dou ri vecine s fie colorate diferit.
Labirintul. Se consider planul unui labirint desenat pe o foaie de hrtie liniat n ptrele (fig. 5.5). Ptrelele haurate reprezint obstacolele, iar cele nehaurate camerele
i coridoarele labirintului.

Fig. 5.5. Planul unui labirint

n memoria calculatorului planul labirintului este redat prin matricea A=||aij||nm,


1n,m30, unde

dac ptrelul (i, j) este haurat;


n caz contrar.

Cltorul se poate deplasa dintr-un ptrel nehaurat n alt ptrel nehaurat numai
atunci cnd ele au o latur comun. Elaborai un program, care gsete, dac exist, un
drum din ptrelul B n ptrelul C.

132

Se consider n (n30) sculee, numerotate prin 1, 2, 3, ..., n. Sculeul i conine mi monede de aceeai valoare Vi. Elaborai un program care afieaz la ecran modul de plat a
unei sume S cu exact p monede din sculee.
Elaborai un program care afieaz la ecran toate modurile de a descompune un numr
natural n sum de k numere naturale distincte. De exemplu, pentru n=9 i k=3 soluiile
snt: 1+2+6, 2+3+4, 1+3+5.
Efectuai un studiu comparativ al algoritmilor bazai pe metoda trierii i algoritmilor
bazai pe metoda relurii n cazul problemelor din exerciiile 8 i 12.

5.5. Metoda desparte i stpnete


Metoda desparte i stpnete (n latin divide et impera) este o metod general de
elaborare a algoritmilor, care presupune:
1) mprirea repetat a unei probleme de dimensiuni mari n dou sau mai multe
subprobleme de acelai tip, dar de dimensiuni mai mici;
2) rezolvarea subproblemelor n mod direct, dac dimensiunea lor permite aceasta, sau mprirea lor n alte subprobleme de dimensiuni i mai mici;
3) combinarea soluiilor subproblemelor rezolvate pentru a obine soluia problemei iniiale.
n limbaj matematic, admitem c la un anumit pas al algoritmului se d o mulime ordonat
A = (ai, ai+1, ..., aj)
i c trebuie efectuat o prelucrare oarecare asupra elementelor sale. Pentru a mpri problema curent n dou subprobleme de aproximativ aceleai dimensiuni,
stabilim
m = (j i) div 2
i mprim mulimea A n dou submulimi care vor fi prelucrate separat:
A1 = (ai, ai+1, ..., ai+m); A2 = (ai+m+1, ai+m+2, ..., aj).
n continuare, mulimile A1 i A2 se mpart din nou n cte dou submulimi, respectiv A1-1, A1-2 i A2-1, A2-2. Acest proces va continua pn cnd soluiile ce corespund
submulimilor curente vor putea fi calculate n mod direct.
Pentru exemplificare, n figura 5.6 este prezentat modul de mprire a mulimii
A=(a1, a2, ..., a7) n cazul divizrii problemelor curente n cte dou subprobleme de
acelai tip.
Schema general a unui algoritm bazat pe metoda desparte i stpnete poate fi
redat cu ajutorul unei proceduri recursive:
procedure DesparteSiStapineste(i, j : integer; var x : tip);
var m : integer;
x1, x2 : tip;
begin
if SolutieDirecta(i, j) then Prelucrare(i, j, x)

133

else
begin
m:=(j-i) div 2;
DesparteSiStapineste(i, i+m, x1);
DesparteSiStapineste(i+m+1, j, x2);
Combina(x1, x2, x);
end;
end;

A=(a1, a2, a3, a4, a5, a6, a7)

A1=(a1, a2, a3, a4)

A1-1=(a1, a2)

A1-2=(a3, a4)

A2=(a5, a6, a7)

A2-1=(a5, a6)

A2-2=(a7)

Fig. 5.6. Descompunerea mulimii A n submulimi

Parametrii i i j din antetul procedurii definesc submulimea curent (ai, ai+1,


..., aj) supus prelucrrii. Funcia SolutieDirecta returneaz valoarea true dac
subproblema curent admite o rezolvare direct i false n caz contrar. Procedura
Prelucrare returneaz prin parametrul x soluia subproblemei curente, calculat
n mod direct. Dac calculul direct este imposibil, se execut dou apeluri recursive
unul pentru submulimea (ai, ai+1, ..., am) i altul pentru submulimea (ai+m+1, ai+m+2, ...,
aj). Procedura Combina prelucreaz soluiile x1 i x2 ale subproblemelor respective
i returneaz soluia x a problemei curente.
Exemplul 1. Se consider mulimea A={a1, a2, ..., an} format din n numere reale.
Elaborai un program care determin numrul maximal din aceast mulime.
Rezolvare. n programul ce urmeaz mulimea A este reprezentat printr-un tablou unidimensional cu n componente. Se consider c soluia unei subprobleme
poate fi calculat direct numai atunci cnd mulimea (ai, ..., aj) este format din unul
sau dou numere. Evident, n astfel de cazuri x = ai sau x = max (ai, aj).
Program P155;
{ Gasirea elementuli maximal prin metoda desparte i
stpnete }
const nmax=100;
var A : array[1..nmax] of real;
i, n : 1..nmax;
x : real;

134

function SolutieDirecta(i, j : integer) : boolean;


begin
SolutieDirecta:=false;
if (j-i<2) then SolutieDirecta:=true;
end; { SolutieDirecta }
procedure Prelucrare(i, j : integer; var x : real);
begin
x:=A[i];
if A[i]<A[j] then x:=A[j];
end; { Prelucrare }
procedure Combina(x1, x2 : real; var x : real);
begin
x:=x1;
if x1<x2 then x:=x2;
end; { Combina }
procedure DesparteSiStapineste(i, j : integer; var x : real);
var m : integer;
x1, x2 : real;
begin
if SolutieDirecta(i, j) then Prelucrare(i, j, x)
else
begin
m:=(j-i) div 2;
DesparteSiStapineste(i, i+m, x1);
DesparteSiStapineste(i+m+1, j, x2);
Combina(x1, x2, x);
end;
end; { DesparteSiStapineste }
begin
write(Dai n=); readln(n);
writeln(Dai , n, numere reale);
for i:=1 to n do read(A[i]);
writeln;
DesparteSiStapineste(1, n, x);
writeln(Numrul maximal x=, x);
readln;
readln;
end.

n programul P155 la fiecare apel al procedurii DesparteSiStapineste problema curent este rezolvat direct sau mprit n dou subprobleme de dimensiuni aproximativ egale. Evident, metoda desparte i stpnete admite mprirea problemelor curente ntr-un numr arbitrar de subprobleme, nu neaprat n dou. n

135

exemplul ce urmeaz problema curent tierea unei placi de arie maxim este
mprit n patru subprobleme de acelai tip, dar de dimensiuni mai mici.
Exemplul 2. Se consider o plac dreptunghiular de dimensiunile LH. Placa are
n guri punctiforme, fiecare gaur fiind definit prin coordonatele (xi, yi). Elaborai
un program care decupeaz din plac o bucat de arie maxim, dreptunghiular i
fr guri. Snt admise doar tieturi de la o margine la alta pe direcii paralele cu
laturile plcii verticale sau orizontale (fig. 5.7).

a)

b)

c)

Fig. 5.7. Tierea unei plci de arie maxim:


a placa iniial; b tierea pe vertical; c tierea pe orizontal

Rezolvare. Vom defini placa curent prin vectorul P=(a, b, c, d), unde a i b snt coordonatele colului stnga-jos, iar c i d coordonatele colului dreapta-sus. Evident,
placa iniial se definete prin (0, 0, L, H). Metoda desparte i stpnete poate fi realizat dup cum urmeaz:
iniial stabilim aria maxim Smax=0;
dac placa curent nu are guri, problema poate fi soluionat direct, comparnd aria curent cu valoarea Smax;
n caz contrar alegem o gaur arbitrar (xi, yi) prin care tiem placa curent n
plci mai mici, artate n figura 5.7:
P1=(a, b, xi, d), P2=( xi, b, c, d) sau P3=(a, yi, c, d), P4=(a, b, c, yi );

136

n continuare examinm n acelai mod fiecare din plcile obinute n urma tierii, memornd consecutiv n variabila Smax aria plcii de suprafa maxim.
Program P156;
{ Tierea unei placi prin metoda desparte i stpnete }
const nmax=100;
var L, H : real;
n : 1..nmax;
X,Y : array[1..nmax] of real;
Smax, amax, bmax, cmax, dmax : real;
i : integer;
function SolutieDirecta(a, b, c, d : real;
var i : integer) : boolean;
label 1;
var j : integer;
begin
SolutieDirecta:=true;
for j:=1 to n do
if (X[j]>a) and (X[j]<c) and (Y[j]>b) and (Y[j]<d) then
begin
SolutieDirecta:=false;
i:=j;
goto 1;
end;
1:end; { SolutieDirecta }
procedure PrelucrareaSolutiei(a, b, c, d : real);
var S : real;
begin
S:=(c-a)*(d-b);
if S>=Smax then
begin
Smax:=S;
amax:=a; bmax:=b; cmax:=c; dmax:=d;
end;
end; { PrelucrareaSolutiei }
procedure DesparteSiStapineste(a, b, c, d : real);
var i : integer;
begin
writeln(Examinm placa (, a:5:1, , b:5:1, ,
c:5:1, , d:5:1, ));
readln;
if SolutieDirecta(a, b, c, d, i)
then PrelucrareaSolutiei(a, b, c, d)

137

else begin
DesparteSiStapineste(a, b, X[i], d);
DesparteSiStapineste(X[i], b, c, d);
DesparteSiStapineste(a, Y[i], c, d);
DesparteSiStapineste(a, b, c, Y[i]);
end;
end; { DesparteSiStapineste }
begin
writeln(Dai dimensiunile L, H); readln(L, H);
write(Dai n=); readln(n);
writeln(Dai coordonatele X[i], Y[i]);
for i:=1 to n do read(X[i], Y[i]);
writeln;
Smax:=0;
DesparteSiStapineste(0, 0, L, H);
writeln(Placa de arie maxim (,
amax:5:1, , bmax:5:1, ,
cmax:5:1, , dmax:5:1, ));
writeln(Smax=, Smax:5:2);
readln;
end.

Funcia SolutieDirecta din programul P156 returneaz valoarea true dac


placa (a, b, c d) nu are guri i false n caz contrar. n cazul valorii false, funcia
returneaz suplimentar numrul de ordine i al uneia din gurile plcii. Aceast gaur este depistat verificnd relaiile a<xi<c i b<yi<d.
Procedura PrelucrareaSolutiei compar aria plcii curente S=(c-a)(d-b) cu valoarea Smax. Dac SSmax, procedura memoreaz placa curent n vectorul (amax, bmax, cmax, dmax).
Complexitatea temporal a algoritmilor bazai pe metoda desparte i stpnete
depinde de numrul de subprobleme k n care este divizat problema curent i de
complexitatea algoritmilor destinai rezolvrii directe a subproblemelor respective.
S-a demonstrat c n majoritatea cazurilor timpul cerut de un algoritm bazat pe metoda desparte i stpnete este de ordinul n log2 n sau n2 log2 n, deci polinomial.
Programele elaborate n baza metodei desparte i stpnete snt simple, iar timpul de
execuie este relativ mic. Cu regret, aceast metod nu este universal, ntruct ea poate
fi aplicat numai atunci cnd prelucrarea cerut admite divizarea problemei curente n
subprobleme de dimensiuni mai mici. De obicei, aceast proprietate nu este indicat explicit n enunul problemei i gsirea ei, dac exist, cade n sarcina programatorului.

ntrebri i exerciii
Explicai schema de calcul a algoritmilor bazai pe metoda desparte i stpnete.
Care snt avantajele i neajunsurile metodei desparte i stpnete?
Utiliznd metoda desparte i stpnete, elaborai un program care determin suma elementelor mulimii A={a1, a2, ..., an} format din n numere reale.

138

Indicai pe un desen similar celui din figura 5.7 ordinea examinrii plcilor curente pe
parcursul executrii programului P156:
dimensiunea plcii iniiale: 3 4;
numrul de guri ale plcii iniiale: 3;
coordonatele gurilor: (1, 1); (1, 2); (2, 2).
Estimai necesarul de memorie i complexitatea temporal a programelor P155 i P156.
Schiai un algoritm care rezolv problema tierii unei plci de arie maxim prin metoda
trierii. Estimai complexitatea temporal i necesarul de memorie al algoritmului elaborat. Efectuai un studiu comparativ al algoritmilor bazai pe metoda trierii i algoritmilor
bazai pe metoda desparte i stpnete.
Cutarea binar. Se consider mulimea A={a1, a2, ..., an}, elementele creia snt numere
ntregi sortate n ordine cresctoare. Elaborai un program care determin dac mulimea
A conine numrul dat p. Estimai complexitatea temporal a programului elaborat.
Utiliznd metoda desparte i stpnete, elaborai un program care determin cel mai
mare divizor comun al numerelor naturale a1, a2, ..., an.
Sortarea prin interclasare. Elaborai un program care sorteaz elementele irului (a1,
a2, ..., an) n ordine cresctoare dup cum urmeaz:
divizm irul curent n dou subiruri de aproximativ aceeai lungime;
dac subirul conine numai dou elemente, aranjm elementele respective n ordine
cresctoare;
avnd dou subiruri sortate, le interclasm pentru a obine irul curent sortat.
Se consider c elementele irului care trebuie sortat snt numere ntregi. De exemplu, n urma
interclasrii subirurilor sortate (-3, 4, 18) i (-2, -1, 15) obinem irul ( -3, -2, -1, 4, 15, 18).
Problema turnurilor din Hanoi.* Se consider trei tije notate prin 1, 2 i 3 i n discuri
perforate de dimensiuni diferite (fig. 5.8). Iniial toate discurile snt pe tija 1, aranjate n
ordinea descresctoare a diametrelor, considernd sensul de la baz la vrf. Elaborai un
program care mut toate discurile pe tija 2 folosind tija 3 ca tij de manevr i respectnd
urmtoarele reguli:
la fiecare pas se mut un singur disc;
orice disc poate fi aezat doar peste un disc cu diametrul mai mare.

Fig. 5.8. Problema turnurilor din Hanoi


*

Denumirea problemei provine de la o veche legend hindus conform creia dup mutarea
celor 64 de discuri va veni sfritul lumii.

139

Indicaii. Mutarea unui disc de pe tija i pe tija j poate fi reprezentat ca o pereche (i, j) cu
i, j{1, 2, 3}, ij. Prin H(m, i, j) vom nota irul mutrilor necesare pentru a muta primele m
discuri (evident, cele situate cel mai sus) de pe tija i pe tija j. De exemplu,
H(1, 1, 2)=(1, 2);
H(2, 1, 2)=(1, 3), (1, 2), (3, 2);
H(3, 1, 2)=(1, 2), (1, 3), (2, 3), (1, 2), (3, 1), (3, 2), (1, 2).
n general,

pentru
pentru
unde k=6ij. Prin urmare, problema celor n discuri se reduce la rezolvarea a dou subprobleme de acelai tip pentru (n1) discuri.

5.6. Programarea dinamic


Programarea dinamic reprezint o metod de rezolvare a problemelor soluia
crora poate fi privit ca rezultatul unui ir de decizii (d1, d2, ..., dp, ..., dq). Fiecare
decizie dp trebuie s furnizeze o soluie local care optimizeaz un criteriu global
de calitate, de exemplu, costul unei cltorii, lungimea drumului parcurs, greutatea
transportat, spaiul ocupat de un fiier pe disc etc. Pentru aplicarea acestei metode,
este necesar ca problema de rezolvat s satisfac principiul optimalitii: dac (d1,
d2, ..., dp, dp+1, ..., dq) este un ir optim de decizii, atunci irurile (d1, d2, ..., dp) i (dp+1, ...,
dq) trebuie s fie optimale.
De exemplu, dac drumul cel mai scurt dintre Chiinu i Bli trece prin Orhei,
atunci ambele poriuni din acest drum ChiinuOrhei i OrheiBli de asemenea
vor fi cele mai scurte. Prin urmare, problemele n care se cere determinarea celui mai
scurt drum satisfac principiul optimalitii.
n PASCAL metoda programrii dinamice poate fi realizat utiliznd tablouri
componentele crora se calculeaz cu ajutorul unor relaii de recuren. n general,
relaiile de recuren snt de urmtoarele dou tipuri:
1) Fiecare decizie dp depinde de deciziile dp+1, ..., dq. Spunem n acest caz c se aplic metoda nainte. Deciziile vor fi luate n ordinea dq, dq-1, ..., d1.
2) Fiecare decizie dp depinde de deciziile d1, ..., dp-1. n acest caz spunem c se aplic
metoda napoi. Deciziile vor fi luate n ordinea d1, d2, ..., dq.
Evident, pentru fiecare problem propus, programatorul va verifica mai nti
respectarea principiului optimalitii i n cazul unui rspuns pozitiv va deduce relaiile respective de recuren. n caz contrar, problema nu poate fi rezolvat prin
metoda programrii dinamice.
Exemplu. Planul unui teren aurifer de form dreptunghiular cu dimensiunile
nm este format din zone ptrate cu latura 1 (fig. 5.9). n zona din colul nord-vest se
afl un robot. Din zona cu coordonatele (i, j), 1 i n, 1 j m, robotul poate extrage
cel mult aij grame de aur. Din considerente tehnologice pe teren exist restricii de
deplasare: la fiecare pas robotul se poate mica din zona curent numai n una din

140

zonele vecine cea din est sau cea din sud. Elaborai un program care determin
cantitatea maxim de aur Cmax care poate fi extras de robot.
Robot

Fig. 5.9. Zonele unui teren aurifer

Rezolvare. n calculator informaia despre un teren aurifer poate fi reprezentat cu


ajutorul tabloului bidimensional A = ||aij||nm, unde aij reprezint cantitatea de aur ce
poate fi extras din zona cu coordonatele (i, j). Pentru exemplificare, n continuare
vom examina un teren aurifer descris cu ajutorul tabloului ce urmeaz:
1
2 3 4 5

A=

Pentru a sistematiza calculele, introducem n studiu tabloul bidimensional C =


=||cij||nm, unde componenta cij reprezint cantitatea maxim de aur pe care o poate
extrage robotul deplasndu-se din zona iniial (1,1) n zona cu coordonatele (i, j).
Evident, Cmax = cnm.
Conform condiiilor problemei, n oricare zon (i, j) se poate intra numai prin una
din zonele vecine: prin cea din vest cu coordonatele (i, j-1) sau prin cea din nord cu
coordonatele (i-1, j). Prin urmare, cantitatea maxim de aur pe care o poate extrage
robotul ajungnd n zona (i, j) este dat de formula recurent
cij = aij + max(ci,j1, ci1,j).
Ordinea de calcul a componentelor cij ale tabloului C este impus de modul de
deplasare a robotului, i anume:
pasul 1: c11;
pasul 2: c21, c12;
pasul 3: c31, c22, c13;
...
pasul n+m-1: cnm.

141

Se observ c la pasul k vor fi calculate numai acele elemente cij ale tabloului C
pentru care se respect egalitatea i + j 1 = k. Ordinea n care snt calculate elementele cij n cazul tabloului A de mai sus este prezentat n figura 5.10.
k=1

k=2

k=3

k=4

k=5

k=6

k=8

k=8

Fig. 5.10. Calcularea elementelor tabloului C

Pentru a evita verificrile legate de calcularea indicilor i i j, n programul ce urmeaz elementele cij din prima linie i din prima coloan snt calculate separat de
celelalte componente ale tabloului C.
Program P157;
{ Deplasarea robotului pe un teren aurifer }
var A , C : array [1..50, 1..50] of real;
m, n, i, j, k : integer;
function Max(a, b : real) : real;
begin
if a>b then Max:=a else Max:=b;
end; { Max }
begin
write(Dai valorile n, m: ); readln(n, m);
writeln(Dai componentele tabloului A);
for i:=1 to n do
for j:=1 to m do read(A[i,j]);
writeln;
C[1,1]:=A[1,1];
for i:=2 to n do C[i,1]:=A[i,1]+C[i-1,1];
for j:=2 to m do C[1,j]:=A[1,j]+C[1,j-1];

142

for k:=2 to n+m-1 do


for i:=2 to n do
for j:=2 to m do
if (i+j-1)=k then
C[i,j]:=A[i,j]+Max(C[i,j-1], C[i-1,j]);
writeln(Cmax=, C[n,m]);
readln;
end.

Complexitatea temporal a algoritmilor bazai pe metoda programrii dinamice


depinde de natura relaiilor de recuren i n majoritatea cazurilor este polinomial.
De exemplu, programul P157 are complexitatea O(n3).

ntrebri i exerciii
Explicai esena principiului optimalitii.
n ce ordine pot fi luate deciziile n procesul soluionrii unei probleme prin metoda
programrii dinamice?
Explicai ordinea de luare a deciziilor n problema deplasrii robotului pe un teren aurifer.
Demonstrai c problema deplasrii robotului pe un teren aurifer satisface principiul
optimalitii.
Estimai necesarul de memorie i timpul de execuie al programului P157.
Cum credei, care snt avantajele i neajunsurile algoritmilor bazai pe metoda programrii dinamice?
Problema discret a rucsacului. Se consider n obiecte. Pentru fiecare obiect i (i=1,
2, ..., n) se cunoate greutatea gi i ctigul ci care se obine n urma transportului su
la destinaie. O persoan are un rucsac cu care pot fi transportate unul sau mai multe
obiecte greutatea sumar a crora nu depete valoarea Gmax. Elaborai un program
care determin ce obiecte trebuie s transporte persoana n aa fel nct ctigul s fie
maxim. Obiectele respective nu pot fi tiate n fragmente mai mici.
Drumul de cost minim. Se consider o reea format din n orae. ntre unele orae
exist curse directe de autobuz. Costul unui bilet la o curs direct din oraul i n oraul
j este de cij lei. Evident, costul unei curse directe ntotdeauna este mai mic dect costul
unei cltorii cu transbordri: cij < cik + ckj. Elaborai un program care determin costul
minim al unei cltorii din oraul i n oraul j.
Arhivarea fiierelor. E cunoscut faptul c pe suporturile de memorie extern orice fiier
este memorat ca o secven de cifre binare. Pentru a economisi spaiul de memorare,
programele de arhivare descompun fiierul iniial ntr-o succesiune de cuvinte binare ce
aparin unui dicionar i nscriu pe disc numai numerele de ordine ale cuvintelor respective. De exemplu, n cazul unui dicionar format din 5 cuvinte binare:
1) 0;
2) 1;
3) 000;
4) 110;
5) 1101101,

143

fiierul iniial 10001101101110 va fi memorat pe disc n forma 2354. Elaborai un


program care descompune orice secven binar ntr-un numr minim de cuvinte aparinnd dicionarului propus.
Triangularea polinoamelor. Procesarea imaginilor cu ajutorul calculatoarelor presupune descompunerea poligoanelor n figuri geometrice mai simple, i anume, n triunghiuri. Admitem c poligonul convex P1P2...Pn este definit prin coordonatele (xi, yi) ale
vrfurilor Pi, i=1, 2, ..., n. Elaborai un program care descompune poligonul P1P2...Pn n
triunghiuri trasnd n acest scop un set de coarde PjPm, jm, j, m{1, 2, ..., n}, care nu se
intersecteaz. Se cere ca lungimea total a coardelor respective s fie minim.

5.7. Metoda ramific i mrginete


n metoda ramific i mrginete (n englez branch and bound) cutarea soluiei
unei probleme se efectueaz prin parcurgerea unui arbore de ordinul m, denumit
arborele soluiilor. Nodurile acestui arbore reprezint mulimea strilor
posibile S = {s1, s2, ..., sn} n care se poate afla un sistem, de exemplu, configuraiile
pieselor pe o tabl de ah, poziia unui automobil pe harta drumurilor naionale,
poziiile capului de scrierecitire ale unei uniti de disc magnetic etc. Legturile sisj
de tipul tatfiu indic faptul c din starea si sistemul poate trece direct n starea sj n
urma unor transformri sau operaii relativ simple (fig. 5.11). Pentru exemplificare
amintim deplasarea pieselor fcut alternativ de adversari n cursul unei partide
de ah, trecerea automobilului dintr-o localitate n alta, executarea unei comenzi de
scrierecitire etc. Evident, n astfel de cazuri soluia problemei poate fi reprezentat
ca un drum ce leag nodul rdcin cu unul din nodurile terminale i care optimizeaz un criteriu de calitate, de exemplu, numrul de mutri ntr-o partid de ah,
distana parcurs de automobil, timpul de scrierecitire a unui fiier etc.
Formal, astfel de probleme pot fi rezolvate prin metoda trierii, efectund n acest
scop urmtoarele operaii:
parcurgem arborele soluiilor n adncime sau n lime i gsim strile finale
ale sistemului;
construim mulimea tuturor drumurilor posibile ce leag starea iniial cu strile finale;
din mulimea drumurilor posibile l alegem pe cel ce optimizeaz criteriul de
calitate.
ntruct parcurgerea complet a arborelui necesit foarte mult timp, pentru a
micora numrul de noduri vizitate, n metoda ramific i mrginete ordinea de
parcurgere este impus de valorile unei funcii f : SR, denumit funcie de cost.
Aceast funcie este definit pe mulimea de noduri ale arborelui soluiilor, valoarea
f(si) caracteriznd cheltuielile necesare pentru a trece din starea curent si n una
din strile finale ale subarborelui de rdcin si.
Vizitarea nodurilor unui arbore n ordinea impus de valorile funciei de cost se
numete parcurgere de cost minim. Aceast parcurgere se realizeaz memornd nodurile active ntr-o list din care la fiecare pas se extrage nodul de cost minim. Pentru
comparare amintim c la parcurgerea arborilor n lime sau n adncime nodurile
active se memorizeaz ntr-o coad sau, respectiv, ntr-o stiv.

144

Starea
iniial

Starea
final

Starea
final

Fig. 5.11. Arborele soluiilor

Fiind definit o funcie de cost, metoda ramific i mrginete presupune efectuarea urmtoarelor operaii:
1. Etapa iniial: se creeaz lista nodurilor active. La nceput aceast list conine
un singur element rdcina arborelui soluiilor.
2. Etapa ramific: din lista nodurilor active se extrage nodul de cost minim i se
genereaz toi descendenii acestuia.
3. Etapa mrginete: pentru fiecare descendent se calculeaz valoarea funciei de
cost. Descendenii costul crora este inaceptabil (de obicei, subarborii respectivi nu
conin stri finale) snt exclui din studiu. Descendenii rmai se includ n lista nodurilor active.
Punctele 2 i 3 se repet pn cnd se ajunge la una din strile finale sau lista nodurilor active devine vid. Evident, n ultimul caz soluia problemei nu a fost gsit.
Pentru exemplificare, n tabelul 5.2 este reprezentat ordinea n care snt vizitate
nodurile arborelui din figura 5.11. Valorile funciei de cost snt indicate direct pe desen lng nodurile respective. Se consider c descendenii costul crora depete
valoarea 9 snt inacceptabili.
n cazul arborelui din figura 5.11 parcurgerea de cost minim se termin cnd n lista nodurilor active apare starea final s10. ntruct orice drum ce leag o stare final de
starea iniial poate fi construit urmnd legturile de tipul fiutat, soluia problemei
pentru exemplul n studiu este (s1, s3, s5, s10).

145

Tabelul 5.2

Parcurgerea de cost minim


Nr.
crt.
1.
2.

Lista nodurilor
active

Etapa

Nodul de cost
minim

Descendenii nodului
de cost minim

iniial

(s1)

ramific

s1

s 2, s 3, s 4

3.

mrginete

(s3, s4)

4.

ramific

(s3)

s4

s8, s9

5.

mrginete

(s3, s8)

6.

ramific

(s8)

s3

s 5, s 6, s 7

7.

mrginete

(s8, s5, s6, s7)

8.

ramific

(s8, s6, s7)

s5

s10, s11

9.

mrginete

(s8, s6, s7, s10, s11)

10.

stop

(s8, s6, s7, s11)

s10

Schema de calcul a metodei ramific i mrginete poate fi redat cu ajutorul urmtoarei secvene de instruciuni PASCAL:
IniializareaListei;
repeat
Ramifica;
Margineste;
until Gasit or ListaEsteVida

Complexitatea algoritmilor bazai pe metoda ramific i mrginete depinde de


faptul cum este definit funcia de cost f : SR. n cazul unor definiii nereuite vor
fi vizitate toate nodurile arborelui soluiilor, iar complexitatea temporal a algoritmului respectiv va fi egal cu cea a algoritmilor bazai pe metoda trierii. Din contra,
o alegere reuit a funciei de cost permite excluderea din studiu a subarborilor care
nu conin strile finale dorite. n cursurile avansate de informatic se demonstreaz
c o definiie bun a funciei de cost poate fi reprezentat n forma:
f(si) = niv(si) + h(si),
unde niv(si) este nivelul nodului si, iar funcia h(si) estimeaz complexitatea transformrilor (operaiilor) necesare pentru a ajunge din starea curent si n una din strile
finale ale subarborelui de rdcin si.
De exemplu, n cazul unei partide de ah funcia h(si) poate s exprime numrul
de piese grele ale adversarului, n cazul unui automobil distana pn la punctul
de destinaie, iar n cazul unei uniti de disc magnetic timpul necesar pentru a citi
sau a nscrie informaia dorit.
Accentum faptul c aplicarea practic a metodei ramific i mrginete este posibil numai atunci cnd valorile f(si) ale funciei de cost pot fi calculate fr a construi
subarborele de rdcin si. Cu regret, n prezent nu snt cunoscute reguli universale
care ar asigura definirea univoc a funciei de cost pentru orice tip de problem. Prin

146

urmare, complexitatea algoritmilor bazai pe metoda ramific i mrginete depinde


n mare msur de experiena i iscusina programatorului.

ntrebri i exerciii
Pentru care tip de probleme poate fi aplicat metoda ramific i mrginete?
Cum se construiete arborele soluiilor? Ce informaie conine fiecare nod al arborelui?
Cum se reprezint soluia unei probleme n metoda ramific i mrginete?
Care este destinaia funciei de cost ? Cum poate fi definit aceast funcie?
Explicai schema de calcul a metodei ramific i mrginete.
Scriei o procedur PASCAL care realizeaz parcurgerea de cost minim. Se consider c
fiecare nod al arborelui conine un cmp n care este indicat valoarea funciei de cost.
Estimai necesarul de memorie i complexitatea temporal a procedurii elaborate.
Indicai ordinea n care snt vizitate nodurile arborelui din figura 5.11 n urmtoarele cazuri:
a) parcurgerea n lime;
b) parcurgerea n adncime;
c) parcurgerea de cost minim.
Snt oare vizitate toate nodurile unui arbore n cazul parcurgerii de cost minim?
Argumentai rspunsul dvs.
Schiai un algoritm care caut soluia optim parcurgnd arborele soluiilor n lime
(n adncime). Estimai necesarul de memorie i complexitatea temporal a algoritmului
elaborat.
Dai exemple de probleme ce pot fi soluionate prin metoda ramific i mrginete.
ncercai s desenai nodurile de pe nivelele 0, 1 i 2 ale unui arbore ce reprezint jocul
dvs. preferat, de exemplu, lupta maritim, ah, dame etc.
Cum credei, care snt avantajele i neajunsurile algoritmilor bazai pe metoda ramific
i mrginete?

5.8. Aplicaiile metodei ramific i mrginete


Metoda ramific i mrginete poate fi aplicat numai problemelor din enunul
crora rezult regulile sau operaiile necesare pentru generarea direct a arborelui
soluiilor. De obicei, n astfel de probleme se simuleaz comportamentul unor parteneri ce au scopuri sau tendine contrare: aplicaii militare, scenarii de dezvoltare
economic n condiii de concuren, jocuri de ah sau de dame etc. Menionm c
existena unor reguli de generare direct a descendenilor face inutil construirea
complet a arborelui soluiilor, micorndu-se astfel volumul de memorie intern
cerut de algoritm.
Implementarea practic a metodei ramific i mrginete presupune rezolvarea urmtoarelor probleme:
determinarea mulimii de stri care, n funcie de natura problemei de rezolvat,
poate fi finit sau infinit;

147

stabilirea transformrilor (operaiilor) elementare n urma crora sistemul trece


dintr-o stare n alta;
definirea funciei de cost;
definirea structurilor de date necesare pentru a reprezenta strile sistemului,
arborele soluiilor i lista nodurilor active;
elaborarea subprogramelor necesare pentru generarea descendenilor, calcularea funciei de cost, selectarea nodurilor de cost minim etc.
Pentru exemplificare vom analiza modul de implementare a metodei ramific i
mrginete n cazul jocului Perspico, cunoscut i sub denumirea jocul 15. n acest joc
snt 15 plcue ptrate numerotate de la 1 la 15 (fig. 5.12).

a)

b)
Fig. 5.12. Jocul Perspico:
a starea iniial; b starea final

Plcuele snt ncadrate ntr-o ram ptrat de dimensiunile 44, o poziie din
interiorul ramei fiind liber. Orice plcu vecin cu poziia liber poate fi mutat pe
locul respectiv. Se cere a trece, folosind mutrile permise, din starea iniial n starea
final.
Starea curent a jocului Perspico poate fi exprimat printr-o distribuie a celor 15
plcue n cele 16 poziii libere. Numerotnd placa liber prin 0, putem scrie:
type Stare = array [1..4, 1..4] of 0..15;

Menionm c numrul de stri posibile este dat de numrul aranjamentelor 16


din 16 i constituie:
,
pe cnd capacitatea memoriei interne a calculatoarelor personale este de ordinul 108
octei.
Trecerea dintr-o stare n alta poate fi efectuat prin deplasarea plcuei lips
spre stnga, sus, dreapta, jos (bineneles cnd acest lucru este posibil). n PASCAL
aceast deplasare se exprim prin modificarea componentelor respective ale variabilelor de tip Stare.
Cunoscnd strile sistemului i regulile de trecere dintr-o stare n alta, putem construi arborele soluiilor, o parte din care este prezentat n figura 5.13.

148

Starea
iniial

sus

jos

stnga

dreapta

jos

dreapta

Starea
final

Fig. 5.13. Arborele soluiilor n jocul Perspico

ntruct plcua liber poate fi deplasat pe trasee ciclice, arborele soluiilor este
infinit. Pentru a evita revenirea la strile deja examinate, vom include n arbore numai strile curente noi. De asemenea, lund n considerare faptul c memoria intern
a calculatoarelor personale nu permite stocarea tuturor strilor posibile, n continuare vom examina numai primele 1015 nivele ale arborelui soluiilor. Evident, n
prezena acestei restricii nu se mai garanteaz gsirea, chiar dac exist, a irului de
mutri permise care transform starea iniial n stare final.
Funcia de cost f : S R poate fi definit n forma:
f(si) = niv(si) + h(si),
unde componenta h(si) caracterizeaz numrul de mutri necesare pentru a trece
din starea curent si n stare final. ntruct acest numr nu poate fi calculat fr a

149

construi mai nti subarborele de rdcin si, vom folosi o aproximare prin lips a
numrului necesar de mutri:
h(si) = numrul de plcue care nu se afl la locul lor.
De exemplu, pentru arborele din figura 5.13 avem:
f(s1) = niv(s1) + h(s1) = 0 + 4 = 4;
f(s2) = niv(s2) + h(s2) = 1 + 5 = 6;
f(s3) = niv(s3) + h(s3) = 1 + 3 = 4;
f(s6) = niv(s6) + h(s6) = 2 + 2 = 4;
f(s7) = niv(s7) + h(s7) = 3 + 0 = 3.
Arborele soluiilor i lista nodurilor active pot fi reprezentate n memoria calculatorului cu ajutorul urmtoarelor structuri de date:
type AdresaNod = ^Nod;
Nod = record
S : Stare;
Nivel, Cost : integer;
Drum : boolen;
D : array [1..4] of AdresaNod;
Tata : AdresaNod;
end;
AdresaCelula = ^Celula;
Celula = record
ReferintaNod : AdresaNod;
Urm : AdresaCelula;
end;
var Radacina : AdresaNod;
BazaListei : AdresaCelula;

Fiecare nod al arborelui soluiilor conine cmpurile informaionale S, Nivel,


Cost, Drum i cmpurile de legtur D, Tata. Cmpul Drum se folosete pentru a
marca nodurile ce aparin drumului care leag nodul rdcin cu nodul ce conine
starea final. Cmpul Tata se utilizeaz pentru a memora adresa nodului tat.
Fiecare celul a listei nodurilor active conine cmpul informaional ReferintaNod
n care se indic adresa nodului inclus n list. Cmpul de legtur Urm conine adresa celulei urmtoare din list. Prin urmare, lista nodurilor active conine nu nodurile
propriu-zise, ci doar adresele lor.
Subprogramele necesare pentru implementarea metodei ramific i mrginete n
cazul jocului Perspico snt incluse n programul P158.
Program P158;
{ Jocul Perspico - metoda ramifica si margineste }
const NivelMaxim=15;
type Stare=array[1..4, 1..4] of 0..15;
AdresaNod=^Nod;

150

Nod=record
S : Stare;
Nivel, Cost : integer;
Drum : boolean;
D : array [1..4] of AdresaNod; {adresele
descendentilor}
Tata : AdresaNod;
end;
AdresaCelula=^Celula;
Celula=record
ReferintaNod : AdresaNod;
Urm : AdresaCelula;
end;
var Radacina : AdresaNod;
BazaListei : AdresaCelula;
StareaInitiala, StareaFinala : Stare;
Gasit : boolean; { true cind este gasit un drum }
Finput, Foutput : text; { datele de intrare si iesire }
Str : array[1..4] of Stare; { starile descendente }
m : 0..4;
{ numarul curent de stari }
i, j : integer;
procedure CalculareaCostului(Adresa : AdresaNod);
var i, j, C : integer;
begin
C:=0;
for i:=1 to 4 do
for j:=1 to 4 do
if Adresa^.S[i,j] <> StareaFinala[i,j] then C:=C+1;
Adresa^.Cost:=Adresa^.Nivel+C;
end; { CalculareaCostului }
procedure Initializare;
{ Creeaza nodul radacina si lista nodurilor active }
{ Inscrie in lista nodurilor active nodul radacina }
var i : integer;
begin
Gasit:=false;
new(Radacina);
Radacina^.S:=StareaInitiala;
Radacina^.Nivel:=0;
CalculareaCostului(Radacina);
Radacina^.Drum:=false;
for i:=1 to 4 do Radacina^.D[i]:=nil;
Radacina^.Tata:=nil;

151

new(BazaListei);
BazaListei^.ReferintaNod:=Radacina;
BazaListei^.Urm:=nil;
end; { Initializare }
procedure Ramifica(Adresa : AdresaNod);
{ Inscrie in Str toate starile care pot fi obtinute }
{ din starea curenta prin efectuarea unei mutari permise }
label 1;
var
St : Stare;
i, j, k : integer;
begin
{ cautarea placutei 0 }
for i:=1 to 4 do
for j:=1 to 4 do
if Adresa^.S[i,j]=0 then goto 1;
1: m:=0;
{ Deplasarea placutei de sus }
if i<>1 then
begin
St:=Adresa^.S;
St[i,j]:=St[i-1, j];
St[i-1, j]:=0;
m:=m+1;
Str[m]:=St;
end;
{ Deplasarea placutei de jos }
if i<>4 then
begin
St:=Adresa^.S;
St[i,j]:=St[i+1, j];
St[i+1, j]:=0;
m:=m+1;
Str[m]:=St;
end;
{ Deplasarea placutei din stinga }
if j<>1 then
begin
St:=Adresa^.S;
St[i,j]:=St[i, j-1];
St[i, j-1]:=0;
m:=m+1;
Str[m]:=St;
end;
{ Deplasarea placutei din dreapta }
if j<>4 then

152

begin
St:=Adresa^.S;
St[i,j]:=St[i, j+1];
St[i, j+1]:=0;
m:=m+1;
Str[m]:=St;
end;
end; { Desparte }
procedure IncludeInLista(Adresa : AdresaNod);
{ Include adresa nodului in lista nodurilor active }
var R : AdresaCelula;
begin
new(R);
R^.ReferintaNod:=Adresa;
R^.Urm:=BazaListei;
BazaListei:=R;
end; { IncludeInLista }
procedure ExtrageDinLista(var Adresa : AdresaNod);
{ Extrage adresa nodului de cost minim din lista }
label 1;
var P, R : AdresaCelula;
C : integer; { costul curent }
begin
if BazaListei=nil then goto 1;
{ cautarea nodului de cost minim }
C:=MaxInt;
R:=BazaListei;
while R<>nil do
begin
if R^.ReferintaNod^.Cost < C then
begin
C:=R^.ReferintaNod^.Cost;
Adresa:=R^.ReferintaNod;
P:=R;
end; { then }
R:=R^.Urm;
end; { while }
{ excludera nodului de cost minim din lista }
if P=BazaListei then BazaListei:=P^.Urm
else
begin
R:=BazaListei;
while P<>R^.Urm do R:=R^.Urm;
R^.Urm:=P^.Urm;
end;

153

dispose(P);
1:end; { ExtrageDinLista }
function StariEgale(S1, S2 : Stare) : boolean;
{ Returneaza TRUE daca starile S1 si S2 coincid }
var i, j : integer;
Coincid : boolean;
begin
Coincid:=true;
for i:=1 to 4 do
for j:=1 to 4 do
if S1[i,j]<>S2[i,j] then Coincid:=false;
StariEgale:=Coincid;
end; { StariEgale }
function StareDejaExaminata(St : Stare) : boolean;
{ Returneaza TRUE daca starea curenta este deja inclusa in
arbore }
var EsteInArbore : boolean;
procedure InAdincime(R : AdresaNod);
{ Parcurgerea arborelui in adincime }
label 1;
var i : integer;
begin
if R<>nil then
begin
if StariEgale(St, R^.S) then
begin
EsteInArbore:=true;
goto 1;
end;
for i:=1 to 4 do InAdincime(R^.D[i]);
end;
1:end; { InAdincime }
begin
EsteInArbore:=false;
InAdincime(Radacina);
StareDejaExaminata:=EsteInArbore;
end; { StareDejaExaminata }
procedure Margineste(Adresa : AdresaNod);
{ Selectarea descendentilor si includerea lor in lista }
label 1;
var i, k : integer;
R : AdresaNod;

154

begin
k:=0;
if (Adresa^.Nivel+1) > NivelMaxim then goto 1;
for i:=1 to m do
if not StareDejaExaminata(Str[i]) then
begin
k:=k+1;
new(R);
R^.S:=Str[i];
R^.Nivel:=Adresa^.Nivel+1;
CalculareaCostului(R);
for j:=1 to 4 do R^.D[j]:=nil;
Adresa^.D[i]:=R;
R^.Tata:=Adresa;
R^.Drum:=false;
if StariEgale(R^.S, StareaFinala) then
begin
R^.Drum:=true;
Gasit:=true;
end;
IncludeInLista(R);
end;
writeln(Foutput);
writeln(Foutput, In lista au fost inclusi , k,
descendenti);
writeln(Foutput);
1:end; { Margineste }
procedure AfisareaNodului(R : AdresaNod);
var i, j : integer;
begin
writeln(Foutput, Drum=, R^.Drum,
Nivel=, R^.Nivel,
Cost=, R^.Cost);
for i:=1 to 4 do
begin
for j:=1 to 4 do write(Foutput, R^.S[i, j] : 3);
writeln(Foutput);
end;
for i:=1 to 4 do
if R^.D[i]<>nil then write(Foutput, *** )
else write(Foutput, nil );
writeln(Foutput); writeln(Foutput);
end; { AfisareaNodului }
procedure RamificaSiMargineste;
var NodulCurent : AdresaNod;

155

begin
Initializare;
repeat
ExtrageDinLista(NodulCurent);
writeln(Foutput,
NODUL EXTRAS DIN LISTA);
writeln(Foutput,
======================);
AfisareaNodului(NodulCurent);
Ramifica(NodulCurent);
Margineste(NodulCurent);
until Gasit or (BazaListei=nil);
end; { RamificaSiMargineste }
procedure AfisareaDrumului;
label 1;
var R : AdresaCelula;
P, Q : AdresaNod;
begin
if not Gasit then
begin
writeln(Foutput, DRUMUL NU A FOST GASIT);
goto 1;
end;
writeln(Foutput,
DRUMUL GASIT:);
writeln(Foutput,
=============);
{ cautarea in lista a nodului terminal}
R:=BazaListei;
while (R<>nil) and (not R^.ReferintaNod^.Drum) do R:=R^.Urm;
{ marcarea nodurilor care formeaza drumul }
P:=R^.ReferintaNod;
while P<>nil do
begin
P^.Drum:=true;
P:=P^.Tata;
end;
{ afisarea drumului }
P:=Radacina;
while P<>nil do
begin
AfisareaNodului(P);
Q:=nil;
for i:=1 to 4 do
if (P^.D[i]<>nil) and P^.D[i]^.Drum then Q:=P^.D[i];
P:=Q;
end;
writeln(Foutput, Sfirsitul drumului);
1:end; { AfisareaDrumului }

156

begin
{ Citirea starii initiale }
assign(Finput, FINPUT.TXT);
reset(Finput);
for i:=1 to 4 do
for j:=1 to 4 do read(Finput, StareaInitiala[i, j]);
{ Citirea starii finale }
for i:=1 to 4 do
for j:=1 to 4 do read(Finput, StareaFinala[i, j]);
close(Finput);
{ Deschiderea fisierului de iesire }
assign(Foutput, FOUTPUT.TXT);
rewrite(Foutput);
RamificaSiMargineste;
AfisareaDrumului;
close(Foutput);
writeln(Gasit=, Gasit);
readln;
end.

n programul P158 starea iniial i starea final snt citite din fiierul FINPUT.
TXT, iar nodurile extrase la fiecare pas din list i drumul gsit snt nscrise n fiierul
FOUTPUT.TXT. Coninutul acestor fiiere poate fi vizualizat sau modificat cu ajutorul unor editoare simple de text.

ntrebri i exerciii
Indicai ordinea n care vor fi vizitate nodurile arborelui din figura 5.13 n cazul parcurgerii de cost minim. Folosind ca model tabelul 5.2, completai un tabel cu datele referitoare
la acest arbore.
Explicai destinaia fiecrui subprogram din programul P158.
Lansai n execuie programul P158 pentru datele iniiale din figura 5.12. Comentai rezultatele nscrise n fiierul de ieire.
Lansai n execuie programul P158 pentru urmtoarele stri iniiale ale jocului
Perspico:
a)
b)
1
2
3
4
1
2
0
4

11

12

10

11

13

10

14

15

13

14

15

12

157

c)

10

13

14

d)

11

10

11

15

12

13

14

15

12

Comentai rezultatele nscrise de program n fiierul FOUTPUT.TXT.


E cunoscut faptul c pentru strile iniiale ce urmeaz:
a)
b)
1
2
3
4
1
3
4
4

13

10

11

10

11

14

15

12

13

14

15

12

programul P158 gsete soluiile respective. ns, dup introducerea modificrii


const NivelMaxim = 5;
soluia pentru cazul (a) nu mai este gsit. Cum credei, prin ce se explic acest fapt?
Se consider varianta simplificat a jocului Perspico, denumit jocul 9 (fig. 5.14). Ce modificri trebuie introduse n programul P158 pentru a calcula irul de mutri permise
destinate trecerii din starea iniial n starea final?

a)

b)

Fig. 5.14. Varianta simplificat a jocului Perspico:


a starea iniial; b starea final

Modificai programul P158 utiliznd urmtoarea funcie de cost:


F(si) = niv(si) + g(si),
unde g(si) este suma distanelor dintre fiecare plcu i locul ei n starea final, exprimat
prin numrul respectiv de mutri. De exemplu, pentru starea iniial din figura 5.12 avem:
g(si) = 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 3 = 6.

158

Verificai cum deruleaz programul modificat n cazul strilor iniiale din exerciiile 4 i 5.
Elaborai planul unui experiment care ne-ar permite s stabilim care din funciile h(si),
g(si) micoreaz timpul de calcul.
Comparai complexitatea programului P158 cu complexitatea unui program bazat pe
metoda trierii.
Se consider o tabl de ah pe care se afl o singur pies un cal de culoare alb.
Elaborai un program care determin dac piesa respectiv poate trece, utiliznd
mutrile permise, din poziia (, ) n poziia (, ). Amintim c , {A, B, ..., H}, iar
, {1, 2, ..., 8}.
Problema comis-voiajorului*. Se consider n orae ntre care exist curse aeriene directe. n oraul i se afl un comis-voiajor care trebuie s viziteze celelalte n-1 orae i s
revin n localitatea din care s-a pornit. Elaborai un program care, cunoscnd distanele
dij ntre orae, determin ordinea n care ele vor fi vizitate. Se cere ca distana parcurs
de comis-voiajor s fie ct mai mic, iar fiecare ora s fie vizitat numai o singur dat.
Scriei un program PASCAL care soluioneaz problema comis-voiajorului prin metoda
trierii. Comparai complexitatea programului elaborat cu complexitatea programului
bazat pe metoda ramific i mrginete.
Indicaii: Drumul parcurs de comis-voiajor poate fi reprezentat ca o mulime ordonat (1,
i, j, ..., k, 1) de orae n care i, j, ..., k {2, 3, ..., n}. Pentru a genera toate drumurile posibile,
se calculeaz permutrile mulimii {2, 3, ..., n}.
Efectuai un studiu comparativ al algoritmilor bazai pe metoda ramific i mrginete i
algoritmilor bazai pe metoda trierii.

5.9. Algoritmi exaci i algoritmi euristici


Algoritmii utilizai pentru rezolvarea problemelor cu ajutorul calculatorului se
mpart n dou categorii distincte: algoritmi exaci i algoritmi euristici.
Un algoritm este exact numai atunci cnd el gsete soluiile optime ale problemelor pentru rezolvarea crora a fost conceput. Desigur, acest fapt trebuie confirmat
printr-o demonstraie matematic riguroas.
Un algoritm este euristic atunci cnd el gsete soluii bune, dar nu neaprat optime. n astfel de cazuri demonstraia matematic respectiv nu exist sau nu este
cunoscut. De obicei, algoritmii euristici includ prelucrri care, chiar dac nu pot fi
justificate matematic, snt alese n virtutea experienei sau intuiiei programatorului.
Evident, algoritmii bazai pe metoda trierii snt exaci, ntruct n procesul examinrii consecutive a soluiilor posibile neaprat va fi gsit i soluia optim.
Confirmarea exactitii acestor algoritmi se reduce la demonstrarea faptului c n
procesul derulrii pe calculator vor fi generate i analizate toate elementele din mulimea soluiilor posibile. n cazul algoritmilor bazai pe celelalte tehnici de programare tehnica Greedy, metoda relurii, metoda ramific i mrginete etc. un algoritm va fi exact sau euristic n funcie de natura condiiilor care ne permit s evitm
*

Persoan care se ocup cu mijlocirea vnzrilor de mrfuri, deplasndu-se n diferite locuri n


cutarea unor beneficiari.

159

trierea tuturor soluiilor posibile. Dac aceste condiii snt alese nereuit, soluiile optime pot fi pierdute i, n consecin, algoritmul respectiv nu va mai fi exact. Pentru
exemplificare vom analiza problema ce urmeaz.
Problema drumului minim. Se consider n orae legate printr-o reea de drumuri
(fig. 5.15). Cunoscnd distanele dij dintre oraele vecine, determinai cel mai scurt
drum din oraul a n oraul b.

Fig. 5.15. Reea de drumuri

Datele iniiale ale problemei n studiu pot fi descrise cu ajutorul matricei (tabelului bidimensional) D = ||dij||nn cu n linii i n coloane, denumit matricea distanelor.
n aceast matrice componenta dij este egal cu distana dintre oraele i, j atunci cnd
ele snt vecine i 0 n caz contrar. Prin definiie, dii = 0, i = 1, 2, ..., n.
De exemplu, pentru oraele din figura 5.15 avem:

D=

Drumul minim ce leag oraele a = 1, b = 6 are lungimea 7 i include localitile


1, 3, 5, 6.
n general, drumul minim poate fi gsit prin metoda trierii, genernd consecutiv
toate permutrile mulimilor ordonate

160

unde q ia valori de la 0 la n-2. Este clar c algoritmii bazai pe generarea tuturor


permutrilor ntotdeauna determin drumul minim, ns complexitatea temporal
O(n!) a acestor algoritmi este inacceptabil.
Pentru a reduce volumul de calcule, vom ncerca s determinm drumul minim
prin metoda relurii. n aceast metod construirea drumului ncepe cu oraul iniial x1 = a i continu cu primul dintre vecinii si nevizitai, fie acesta x2, trecndu-se
la primul dintre vecinii lui x2 nevizitai nc .a.m.d. Pentru a construi drumuri ct
mai scurte, vom aplica urmtoarea regul intuitiv: la fiecare pas vom examina, n
primul rnd, vecinii nevizitai care se afl ct mai aproape de oraul curent.
Drumul n construcie poate fi reprezentat n forma unui vector:
X = (a, x2, ..., xk-1, xk, ..., b),
n care componenta xk trebuie s fie unul din vecinii oraului xk-1. Pentru a sistematiza
calculele vom memora vecinii nc nevizitai ai oraului i n mulimea Ai , i = 1, 2, ...,
n. Evident, conform regulii intuitive formulate mai sus, oraele din fiecare mulime
Ai trebuie sortate n ordinea creterii distanelor dij, j Ai.
De exemplu, pentru figura 5.15 iniial vom avea:
A1 = (2, 3, 4);
A2 = (1);
A3 = (1, 4, 5);
A4 = (3, 5, 6);
A5 = (6, 3, 4);
A6 = (5).
Condiiile de continuare n metoda relurii rezult direct din enunul problemei:
oraul xk poate fi adugat la poriunea de drum deja construit (a, x2, ..., xk-1) numai
atunci cnd:
1) xk este un vecin nc nevizitat al oraului xk-1, deci xk Ak-1;
2) oraul xk anterior nu a fost inclus n drumul n curs de construcie, deci xk a,
xk x2, ..., xk xk-1.
De exemplu, pentru figura 5.15 vectorul X va lua consecutiv urmtoarele valori:
X = (1);
X = (1, 2);
X = (1);
X = (1, 3);
X = (1, 3, 4);
X = (1, 3, 4, 5);
X = (1, 3, 4, 5, 6).
Drumul (1, 3, 4, 5, 6) construit prin metoda relurii are lungimea 11 i, evident,
nu este un drum minim. Totui acest drum este mai bun ca drumul (1, 4, 5, 6) care
are lungimea 13.
n programul ce urmeaz elementele mulimilor A1, A2, ..., An snt plasate la nceputul liniilor A[1], A[2], ..., A[n] ale tabelului bidimensional A, restul poziiilor
avnd valoarea zero.

161

Program P159;
{ Problema drumului minim - metoda relurii }
const nmax=50;
var n : integer; { numrul de orae }
D : array[1..nmax, 1..nmax] of real; { matricea distanelor }
a, b : 1..nmax;
X : array [1..nmax] of integer;
{ drumul construit }
V : array[1..nmax, 1..nmax] of integer; { vecinii }
Finput : text;
procedure InitializareVecini;
{ nscrie n V[k] vecinii oraului k }
var k, i, j, p, q, r : integer;
begin
for k:=1 to n do
begin
{ iniial mulimea V[k] este vid }
for i:=1 to n do V[k,i]:=0;
{ calculm elementele mulimii V[k] }
i:=0;
for j:=1 to n do
if D[k,j]<>0 then
begin
i:=i+1;
V[k,i]:=j;
end; { then }
{ sortarea elementelor mulimii V[k] prin metoda bulelor }
for j:=1 to i do
for p:=1 to i-1 do
if D[k, V[k,p]]>D[k, V[k, p+1]] then
begin
q:=V[k,p];
V[k,p]:=V[k, p+1];
V[k, p+1]:=q;
end; { then }
end; { for }
end; { InitializareVecini }
procedure Initializare;
var i, j : integer;
begin
assign(Finput, DRUM.IN);
reset(Finput);
readln(Finput, n);
readln(Finput, a, b);
writeln(n=, n,
a=, a, b=, b);
for i:=1 to n do
for j:=1 to n do read(Finput, D[i,j]);

162

close(Finput);
InitializareVecini;
end; { Initializare }
function MultimeVida(k : integer) : boolean;
begin
MultimeVida:=(V[X[k-1], 1]=0);
end; { MultimeVida }
function PrimulElement(k : integer) : integer;
var i : integer;
begin
PrimulElement:=V[X[k-1], 1];
for i:=1 to n-1 do V[X[k-1],i]:=V[X[k-1], i+1];
end; { PrimulElement }
function ExistaSuccesor(k : integer) : boolean;
begin
ExistaSuccesor:=(V[X[k-1], 1]<>0);
end; { ExistaSuccesor }
function Succesor(k : Integer) : integer;
var i : integer;
begin
Succesor:=V[X[k-1], 1];
for i:=1 to n-1 do V[X[k-1], i]:=V[X[k-1], i+1];
end; { Succesor }
function Continuare(k : integer) : boolean;
var i : integer;
Indicator : boolean;
begin
Continuare:=true;
for i:=1 to k-1 do
if X[i]=X[k] then Continuare:=false;
end; { Continuare }
procedure PrelucrareaSolutiei(k :
var i : integer;
s : real;
begin
writeln(Drumul gasit:);
for i:=1 to k-1 do write(X[i] :
writeln;
s:=0;
for i:=1 to k-1 do s:=s+D[X[i],
writeln(Lungimea drumului , s

integer);

3);

X[i+1]];
: 10:2);

163

readln;
halt;
end; { PrelucrareaSolutiei }
procedure Reluare(k : integer);
label 1;
var i : integer;
begin
if MultimeVida(k) then goto 1;
if X[k-1]<>b then
begin
X[k]:=PrimulElement(k);
if Continuare(k) then Reluare(k+1);
while ExistaSuccesor(k) do
begin
X[k]:=Succesor(k);
if Continuare(k) then Reluare(k+1);
end; { while }
end { then}
else PrelucrareaSolutiei(k);
1:end; { Reluare }
begin
Initializare;
X[1]:=a;
Reluare(2);
end.

Din analiza programului P159 se observ c algoritmul bazat pe metoda relurii are complexitatea O(mn), deci este exponenial. n aceast formul m reprezint
numrul maxim de vecini pe care i poate avea fiecare ora. Menionm c numrul concret de operaii efectuate de programul P159 depinde n mare msur de
configuraia reelei de drumuri i distanele respective. Evident, plata pentru
reducerea numrului de operaii n algoritmul euristic bazat pe metoda relurii n
comparaie cu algoritmul exact bazat pe metoda trierii const n pierderea soluiilor optime.
n scopul soluionrii eficiente a problemelor de o real importan practic, n
informatic se depun eforturi considerabile pentru elaborarea unor algoritmi exaci
care ar avea o complexitate polinomial. n cazul problemei drumului minim un astfel de algoritm poate fi elaborat utiliznd metoda programrii dinamice.
Amintim c metoda programrii dinamice poate fi aplicat doar problemelor care
satisfac principiul optimalitii, principiul care se respect n cazul drumurilor minime. Pentru a formula relaiile respective de recuren, introducem n studiu matricea costurilor C = ||cij||nn, elementele creia indic lungimea drumului minim ntre
oraele i, j. Componentele cij se calculeaz dup cum urmeaz:

164

1) mai nti se examineaz drumurile minime care leag oraele vecine:


dac i = j;
dac oraele i, j snt vecine;
n caz contrar;
2) n continuare se examineaz drumurile minime ntre oraele i, j formate prin
folosirea localitii k drept punct de conexiune:
cij = min(cik, cik+cjk), i, j {1, 2, ..., n}, i j, i k, j k;
3) punctul 2 se repet pentru k = 1, 2, ..., n.
Valorile curente ale matricei costurilor pentru oraele din figura 5.15 snt prezentate n figura 5.16.
Matricea iniial

k=1

k=2

k=3

k=4

k=5

k=6

Fig. 5.16. Valorile curente ale matricei costurilor

165

ntruct matricea costurilor C nu include drumurile minime propriu-zise, ci numai lungimile lor, vom construi drumul minim ce leag oraele a, b cu ajutorul tehnicii Greedy. Conform acestei tehnici, construcia drumului minim X = (x1, ..., xk-1, xk,
...) ncepe cu oraul iniial x1 = a. n continuare, la fiecare pas k se alege acel ora xk, xk
Ak-1, care satisface principiul optimalitii:
C[a, xk] + C[xk, b] = C[a, b].
De exemplu, pentru oraele a = 1, b = 6 din figura 5.15 avem:
X = (1);
X = (1, 3);
X = (1, 3, 5);
X = (1, 3, 5, 6).
Algoritmul de determinare a drumurilor minime bazat pe metoda programrii
dinamice este cunoscut n literatura de specialitate sub denumirea Roy-Floyd. n calitate de exerciiu v propunem s demonstrai c acest algoritm este exact, adic
ntotdeauna construiete numai drumuri minime.
n programul ce urmeaz algoritmul exact este implementat cu ajutorul procedurii RoyFloyd.
Program P160;
{ Problema drumului minim - metoda programrii dinamice }
const nmax=50;
Infinit=1.0E+35;
var n : integer; { numarul de orase }
D : array[1..nmax, 1..nmax] of real; { matricea distanelor }
a, b : 1..nmAx;
X : array [0..nmax+1] of integer;
{ drumul construit }
V : array[1..nmax, 1..nmax] of integer; { vecinii }
C : array[1..nmax, 1..nmax] of real; { matricea costurilor }
Finput : text;
procedure InitializareVecini;
{ nscrie in V[k] vecinii oraului k }
var k, i, j, p, q, r : integer;
begin
for k:=1 to n do
begin
{ iniial multimea V[k] este vid }
for i:=1 to n do V[k,i]:=0;
{ calculm elementele mulimii V[k] }
i:=0;
for j:=1 to n do
if D[k,j]<>0 then
begin
i:=i+1;
V[k,i]:=j;

166

end; { then }
end; { for }
end; { InitializareVecini }
procedure Initializare;
var i, j : integer;
begin
assign(Finput, DRUM.IN);
reset(Finput);
readln(Finput, n);
readln(Finput, a, b);
writeln(n=, n,
a=, a, b=, b);
for i:=1 to n do
for j:=1 to n do read(Finput, D[i,j]);
close(Finput);
InitializareVecini;
end; { Initializare }
procedure AfisareaDrumului;
var k : integer;
begin
write(Drumul gsit: );
k:=1;
repeat
write(X[k] : 3);
k:=k+1;
until X[k]=0;
writeln;
writeln(Lungimea drumului , C[a, b] : 5);
readln;
end; { PrelucrareaSolutiei }
function Min(p, q : real) : real;
{ Returneaz minimul din p si q }
var s : real;
begin
if p<q then s:=p else s:=q;
if s>Infinit then s:=Infinit;
Min:=s;
end; { Min }
procedure RoyFloyd;
var i, j, k : integer;
s : real;
ors : integer; { oraul candidat la includerea n drumul
minim }
cnd : boolean; { condiiile de includere a oraului n drum }

167

begin
{ Iniializarea matricei costurilor }
for i:=1 to n do
for j:=1 to n do
if (D[i,j]=0) and (i<>j) then C[i,j]:=Infinit
else C[i,j]:=D[i,j];
{ Calcularea matricei costurilor }
for k:=1 to n do
for i:=1 to n do
if i<>k then
for j:=1 to n do
if j<>k then C[i,j]:=Min(C[i,j], C[i,k]+C[j,k]);
{ Trasarea drumului - tehnica Greedy}
for k:=1 to n do X[k]:=0;
k:=1; X[1]:=a;
while X[k]<>b do
begin
i:=1;
while V[X[k], i]<>0 do
begin
ors:=V[X[k], i];
cnd:=true;
for j:=1 to k do if ors=X[j] then cnd:=false;
if cnd and (C[A, ors]+C[ors, B]=C[a,b])
then X[k+1]:=ors;
i:=i+1;
end; { while }
k:=k+1
end; { while }
end; { RoyFloyd }
begin
Initializare;
RoyFloyd;
AfisareaDrumului;
end.

Din analiza procedurii RoyFloyd se observ c complexitatea temporal a algoritmului exact este O(n3), deci polinomial.
n practic, pentru soluionarea unei probleme, mai nti se ncearc elaborarea
unui algoritm exact de complexitate polinomial. Dac aceast tentativ eueaz, se
elaboreaz un algoritm euristic. Pentru a sistematiza acest proces este convenabil s
se pun n eviden toate condiiile pe care le satisface o soluie optim. Condiiile
respective pot fi mprite n dou clase:
1) condiii necesare n sensul c nendeplinirea lor mpiedic obinerea unei soluii posibile pentru problem;

168

2) condiii pentru care se poate accepta un compromis, n sensul c ele pot fi nlocuite cu alte condiii ce permit apropierea de o soluie optimal.
De exemplu, n cazul drumului minim X = (a, x2, ..., xk-1, xk, ..., b) faptul c xk trebuie
s fie un vecin al oraului xk-1 este o condiie necesar, iar respectarea principiului optimalitii este o condiie de compromis. n metoda relurii condiia de compromis a
fost nlocuit cu una mai simpl, i anume, oraul xk trebuie s fie ct mai aproape de
oraul xk-1. Evident, formularea condiiilor care accept un compromis i nlocuirea
lor cu altele mai simple cade n sarcina programatorului.

ntrebri i exerciii
Care este diferena dintre algoritmii exaci i cei euristici?
n care cazuri algoritmii euristici snt mai buni dect cei exaci?
Scriei un program care determin cel mai scurt drum prin metoda trierii. Estimai complexitatea temporal a programului elaborat.
Efectuai un studiu comparativ al algoritmilor exaci i algoritmilor euristici destinai
soluionrii problemei drumului minim.
Calculai matricea distanelor pentru reeaua de drumuri auto ce leag centrele raionale.
Determinai cele mai scurte drumuri ntre centrele raionale date cu ajutorul algoritmilor
exaci i algoritmilor euristici.
Cum credei, poate fi oare aplicat metoda trierii pentru determinarea celui mai scurt
drum ntre oricare dou localiti din ar ? Argumentai rspunsul dvs.
Formulai condiiile necesare i condiiile pentru care se poate accepta un compromis n
cazul robotului ce exploreaz un teren aurifer (vezi paragraful 5.6).
Estimai complexitatea algoritmilor exaci i a algoritmilor euristici destinai soluionrii
problemelor ce urmeaz:
a) memorarea fiierelor pe benzi magnetice (exerciiul 5, paragraful 5.3);
b) problema continu a rucsacului (exerciiul 6, paragraful 5.3);
c) colorarea unei hri (exerciiul 9, paragraful 5.4);
d) problema discret a rucsacului (exerciiul 7, paragraful 5.6);
e) arhivarea fiierelor (exerciiul 9, paragraful 5.6);
f) triangularea polinoamelor (exerciiul 10, paragraful 5.6);
g) jocul Perspico (paragraful 5.8);
h) problema comis-voiajorului (exerciiul 10, paragraful 5.8).

169

Capitolul 6
ALGORlTMI DE REZOLVARE A UNOR
PROBLEME MATEMATICE
6.1. Operaii cu mulimi
Generarea soluiilor posibile ale unei probleme presupune prelucrarea elementelor ce aparin diferitor mulimi.
Fie A o mulime oarecare cu n elemente:
A = {a1, a2, , aj, , an}.
ntruct limbajul PASCAL nu permite accesul direct la elementele mulimilor descrise cu ajutorul tipului de date set, vom memora elementele mulimii A ntr-un
vector (tablou unidimensional) cu n componente A=(a1, a2, , aj, , an). Evident, o
astfel de reprezentare stabilete implicit o ordine a elementelor mulimii corespunztoare ordinii n care apar componentele n vectorul A.
Fie Ai o submulime a lui A. n PASCAL aceast submulime poate fi reprezentat
prin vectorul caracteristic al submulimii:
Bi = (b1, b2, , bj, , bn),
unde

dac
n caz contrar.

ntre submulimile Ai ale mulimii A i vectorii caracteristici Bi exist o coresponden biunivoc:


B1 = (0, 0, , 0);
A1 =
A2 = {a1}
B2 = (1, 0, , 0);
A3 = {a2}
B3 = (0, 1, , 0);
A4 = {a1, a2}
B3 = (1, 1, , 0);
...
...
Ak = {a1, a2, , an} Bk = (1, 1, , 1);
Evident, numrul tuturor submulimilor unei mulimi este k = 2n.
Reprezentarea submulimilor cu ajutorul vectorilor caracteristici presupune elaborarea unei uniti de program ce conine cte o procedur pentru fiecare din operaiile frecvent utilizate n calculul cu mulimi: reuniunea, intersecia, \ diferena, complementarea. Scrierea procedurilor respective este propus cititorului
n calitate de exerciiu.

170

O alt operaie frecvent utilizat n algoritmii bazai pe metoda trierii este generarea tuturor submulimilor unei mulimi. Realizarea acestei operaii n programele
PASCAL este prezentat cu ajutorul exemplului ce urmeaz.
Exemplul 1. Se consider mulimea A={a1, a2, , an} format din n numere ntregi.
Determinai dac exist cel puin o submulime Ai, Ai A, suma elementelor creia
este egal cu m.
Rezolvare. Soluiile posibile , {a1}, {a2}, {a1, a2} .a.m.d. pot fi generate formnd
consecutiv vectorii binari B1, B2, ..., Bk.
Program P161;
{ Generarea tuturor submulimilor unei mulimi }
const nmax=50;
type Multime = array [1..nmax] of integer;
CifraBinara = 0..1;
VectorCaracteristic = array[1..nmax] of CifraBinara;
var A : Multime;
B : VectorCaracteristic;
n, m, j : integer;
function SolutiePosibila : boolean;
var j, suma : integer;
begin
suma:=0;
for j:=1 to n do
if B[j]=1 then suma:=suma+A[j];
if suma=m then SolutiePosibila:=true
else SolutiePosibila:=false;
end; { SolutiePosibila }
procedure PrelucrareaSolutiei;
var j : integer;
begin
write(Submulimea: );
for j:=1 to n do
if B[j]=1 then write(A[j], );
writeln;
end; { PrelucrareaSolutiei }
procedure GenerareSubmultimi(var t:CifraBinara);
var j : integer;
begin
t:=1; { transportul }
for j:=1 to n do
if t=1 then
if B[j]=1 then B[j]:=0
else begin B[j]:=1; t:=0 end;
end; { GenerareSubmultimi }

171

procedure CautareSubmultimi;
var i : integer;
t : CifraBinara;
begin
for j:=1 to n do B[j]:=0;
{ ncepem cu vectorul caracteristic B=(0, 0, ..., 0) }
repeat
if SolutiePosibila then PrelucrareaSolutiei;
GenerareSubmultimi(t);
until t=1;
end; { CautareSubmultimi }
begin
write(Dai n=); readln(n);
writeln(Dai , n, numere intregi:);
for j:=1 to n do read(A[j]);
write(Dai m=); readln(m);
CautareSubmultimi;
writeln(Sfrit);
readln;
end.

n programul P161 trierea consecutiv a soluiilor posibile este organizat cu ajutorul ciclului repeat...until din componena procedurii CautareSubmultimi.
Vectorii caracteristici ai submulimilor respective snt formai cu ajutorul procedurii
GenerareSubmultimi. n aceast procedur vectorul caracteristic B este tratat ca
un numr binar valoarea cruia trebuie mrit cu o unitate la fiecare apel.
Instruciunile if din componena procedurii GenerareSubmultimi simuleaz
funcionarea unui semisumator care adun cifrele binare bj i t, variabila t reprezentnd transportul. Valoarea t = 1 a transportului din rangul n indic faptul c de la
vectorul final Bk = (1, 1, , 1) se trece la vectorul iniial B1 = (0, 0, , 0).
Complexitatea temporal a algoritmilor bazai pe generarea tuturor submulimilor unei mulimi este O(2n).
n unele probleme mulimea soluiilor posibile S poate fi calculat ca produsul
cartezian al altor mulimi.
Exemplul 2. Se consider n mulimi A1, A2, , An, fiecare mulime Aj fiind format
din mj numere ntregi. Selectai din fiecare mulime Aj cte un numr aj n aa mod,
nct produsul a1 a2 ... an s fie maxim.
Rezolvare. Mulimea soluiilor posibile S=A1A2...An. Evident, numrul soluiilor
posibile k = m1 m2 mn. Fiecare element si al produsului cartezian A1A2...An
poate fi reprezentat prin vectorul indiciilor:
Ci = (c1, c2, , cj, , cn),
unde cj este indicele elementului respectiv din mulimea Aj. De exemplu, pentru



A1 = (-6, 2, 1); A2 = (4, 9); A3 = (-8, 3, 5),

172

obinem:

s1 = (-6, 4, -8)
s2 = ( 2, 4, -8)
s3 = ( 1, 4, -8)
s4 = (-6, 9, -8)
s5 = ( 2, 9, -8)

s18= ( 1, 9, 5)

C1 = (, , );
C2 = (, , );
C3 = (, , );
C4 = (, , );
C5 = (, , );

C18 = (, , ),

unde , i snt indicii elementelor din mulimile respective.


Vectorii C1, C2, , Ck pot fi generai n ordine lexicografic pornind de la vectorul
iniial C1=(1, 1, , 1).
Program P162;
{ Generarea elementelor unui produs cartezian }
const nmax=50; { numrul maximal de mulimi }
mmax=50; { numrul maximal de elemente }
type Multime = array [1..mmax] of integer;
VectorIndicii = array[1..nmax] of 1..mmax;
var A : array[1..nmax] of Multime;
n : 1..nmax;
{ numrul de mulimi }
M : array[1..nmax] of 1..mmax; { cardinalul mulimii A[i] }
Pmax : integer;
{ produsul maximal }
C, Cmax : VectorIndicii;
i, j : integer;
procedure PrelucrareaSolutieiPosibile;
var j, p : integer;
begin
p:=1;
for j:=1 to n do p:=p*A[j, C[j]];
if p > Pmax then begin Pmax:=p; Cmax:=C end;
end; { PrelucrareaSolutieiPosibile }
procedure GenerareProdusCartezian(var t:integer);
var j : integer;
begin
t:=1; { transportul }
for j:=1 to n do
begin
C[j]:=C[j]+t;
if C[j]<=M[j] then t:=0 else C[j]:=1;
end; { for }
end; { GenerareProdusCartezian }

173

procedure CautareaProdusuluiMaximal;
var j : integer;
t : integer;
begin
Pmax:=-MaxInt;
writeln(Pmax=, Pmax);
for j:=1 to n do C[j]:=1;
{ ncepem cu vectorul indiciilor C=(1, 1, ..., 1) }
repeat
PrelucrareaSolutieiPosibile;
write(Produsul cartezian: );
for j:=1 to n do write(A[j, C[j]], ); writeln;
GenerareProdusCartezian(t);
until t=1;
end; { CautareaProdusuluiMaximal }
begin
write(Dai numrul de mulimi n=); readln(n);
for i:=1 to n do
begin
write(Dai cardinalul M[, i, ]=); readln(M[i]);
write(Dai elementele multimii A[, i, ]: );
for j:=1 to M[i] do read(A[i, j]);
writeln;
end;
CautareaProdusuluiMaximal;
writeln(Pmax=, Pmax);
write(Elementele selectate: );
for j:=1 to n do write(A[j, Cmax[j]], );
writeln;
readln;
readln;
end.

n procedura GenerareProdusCartezian vectorul indiciilor C este tratat ca


un numr natural scris ntr-un sistem mixt de numeraie. n acest sistem cifra c1
este scris n baza m1, cifra c2 n baza m2, cifra c3 n baza m3 .a.m.d. La fiecare
apel al procedurii GenerareProdusCartezian valoarea numrului nscris n
vectorul C este mrit cu o unitate. Valoarea t = 1 a transportului din rangul n
indic faptul c de la vectorul final Ck = (m1, m2, , mn) se trece la vectorul iniial
C1 = (1, 1, , 1).
Menionm c dac numrul de mulimi n este cunoscut pn la scrierea programului, generarea elementelor produsului cartezian A1A2An poate fi fcut mult
mai simplu cu ajutorul a n cicluri imbricate:

174

for j1:=1 to m1 do
for j2:=1 to m2 do
...

for jn:=1 to mn do
if SolutiePosibila(aj1, aj2 ,..., ajn)
then PrelucrareaSoluiei(aj1, aj2, ..., ajn)

Complexitatea temporal a algoritmilor bazai pe generarea tuturor elementelor


unui produs cartezian este O(mn), unde m = max(m1, m2, , mn).

ntrebri i exerciii

Submulimile Ai, Aj ale mulimii A snt reprezentate prin vectori caracteristici. Elaborai
procedurile necesare pentru efectuarea urmtoarelor operaii: Ai Aj, Ai Aj, Ai \ Aj, Ai.

Orice submulime Ai, Ai A, poate fi reprezentat printr-un vector cu n componente,


unde elementele submulimii Ai snt plasate la nceputul vectorului, iar restul poziiilor
au o valoare ce nu aparine mulimii A. Elaborai procedurile necesare pentru efectuarea
operaiilor frecvent ntlnite n calculul cu mulimi: , , \ , . Cum credei, care reprezentare a submulimilor este mai comod: prin vectorii caracteristici sau prin vectorii ce
conin chiar elementele submulimii?
Estimai timpul de execuie a procedurii CautareSubmultimi din programul P161.
Verificai aceste estimri prin msurri directe ale timpului de execuie pentru diferite
valori ale lui n.
Se consider mulimea A format din primele n caractere ale alfabetului latin. Elaborai
un program care afieaz la ecran toate submulimile acestei mulimi.
Se consider numrul natural n = 32*35*17*, format din 9 cifre zecimale. Determinai
cifrele care trebuie nscrise n poziiile marcate cu simbolul * pentru ca numrul obinut
s se mpart fr rest la m.
Estimai timpul de execuie a procedurii CautareaProdusuluiMaximal din programul P162. Verificai aceste estimri prin msurri directe ale timpului de execuie
pentru diferite valori ale lui n i m1, m2, , mn.
ntr-un co snt m mere i p pere. S se genereze toate posibilitile de a alege f fructe
dintre care k s fie mere.
Elaborai o procedur recursiv care genereaz toate elementele unui produs cartezian.
Fie A = (a1, a2, , aj, , an) o mulime ordonat de caractere numit alfabet. Numim cuvnt de lungime p orice succesiune de p caractere din alfabetul A. Elaborai o procedur
care genereaz toate cuvintele de lungimea p.

6.2. Analiza combinatorie


n rezolvarea multor probleme implementarea algoritmilor bazai pe analiza consecutiv a soluiilor posibile presupune generarea permutrilor, aranjamentelor sau
combinrilor unei mulimi.

175

Generarea permutrilor. E cunoscut faptul c numrul de permutri posibile ale


unei mulimi A={a1, a2, ..., an} cu n elemente se determin ca Pn = n!. Acest numr poate fi calculat cu ajutorul funciei factorial, exprimat n form iterativ:
Pn = 1 2 3 ... n
sau recursiv:

dac
dac

De exemplu, pentru A={a1, a2} cele P2 = 2! = 2 permutri snt (a1, a2) i (a2, a1). Pentru
A={a1, a2, a3} cele P3 = 3! = 6 permutri snt:
(a1, a2, a3);
(a2, a3, a1);

(a1, a3, a2);


(a3, a1, a2);

(a2, a1, a3);


(a3, a2, a1).

ntruct ntre permutrile mulimii A={a1, a2, ..., an} i permutrile mulimii I={1,
2, ..., n} exist o coresponden biunivoc, problema generrii permutrilor oricrei
mulimi A cu n elemente se reduce la generarea permutrilor mulimii {1, 2, ..., n},
denumite permutri de grad n.
Exist mai multe metode ingenioase de generare a permutrilor de grad n, cea
mai rspndit fiind metoda lexicografic. n aceast metod se pleac de la permutarea cea mai mic n ordine lexicografic, i anume de la permutarea identic
(1, 2, ..., n).
Avnd construit o permutare p = (p1, ..., pi-1, pi, pi+1, ..., pn), pentru determinarea
urmtoarei permutri p care i urmeaz n ordine lexicografic se caut acel indice i
care satisface relaiile:
pi < pi+1; pi+1 > pi+2 > ... > pn.
n continuare, elementul pi este nlocuit cu cel mai mic dintre elementele pi+1, ..., pn
care este mai mare dect pi, fie el pk:
(p1, ..., pi-1, pk, pi+1, ..., pk-1, pi, pk+1, ..., pn).
Permutarea cutat p se obine prin inversarea ordinii ultimilor (n i) elemente
din acest vector, astfel nct ele s apar n ordine cresctoare.
Dac nu exist niciun indice i ca mai sus, nseamn c s-a ajuns la permutarea cea
mai mare n ordine lexicografic, adic la (n, (n 1), ..., 1) i algoritmul se termin.
De exemplu, pentru n=3 se obin permutrile:
(1, 2, 3);
(2, 3, 1);

(1, 3, 2);
(3, 1, 2);

(2, 1, 3);
(3, 2, 1).

n programul ce urmeaz metoda lexicografic este realizat cu ajutorul procedurii GenerarePermutari.


Program P163;
{ Generarea permutrilor }
const nmax=100;
type Permutare=array[1..nmax] of 1..nmax;

176

var P : Permutare;
n : 2..nmax;
Indicator : boolean;
i : integer;
procedure GenerarePermutari(var Indicator : boolean);
label 1;
var i, j, k, aux : integer;
begin
{ permutarea identic }
if not Indicator then
begin
for i:=1 to n do P[i]:=i;
Indicator:=true;
goto 1;
end;
{ cutarea indicelui i }
i:=n-1;
while P[i]>P[i+1] do
begin
i:=i-1;
if i=0 then
begin
{ un astfel de indice nu mai exist }
Indicator:=false;
goto 1;
end; { then }
end; {while }
{ cutarea indicelui k }
k:=n;
while P[i]>P[k] do k:=k-1;
{ interschimbarea P[i] - P[k] }
aux:=P[i]; P[i]:=P[k]; P[k]:=aux;
{ ordonarea ultimilor (n-i) elemente }
for j:=1 to (n-i) div 2 do
begin
aux:=P[i+j];
P[i+j]:=P[n-j+1];
P[n-j+1]:=aux;
end; { for }
Indicator:=true;
1:end; { GenerarePermutari }

177

begin
write(Dai n=); readln(n);
Indicator:=false;
repeat
GenerarePermutari(Indicator);
if Indicator then
for i:=1 to n do write(P[i] : 3);
writeln;
until not Indicator;
readln;
end.

Pentru a porni de la permutarea iniial, nainte de primul apel al procedurii


GenerarePermutari, parametrului Indicator i se atribuie valoarea false. La
fiecare apel procedura nscrie n vectorul P permutarea ce urmeaz n ordine lexicografic i atribuie parametrului Indicator valoarea true. Dup generarea tuturor
permutrilor, procedura GenerarePermutari va atribui parametrului Indicator
valoarea false.
Din pcate, indiferent de metoda folosit, timpul necesar pentru generarea tuturor permutrilor este cel puin O(n!). n consecin, algoritmii bazai pe cutarea
soluiilor prin generarea tuturor permutrilor posibile pot fi aplicai numai pentru
valori mici ale lui n.
Generarea aranjamentelor. Numrul aranjamentelor de m elemente ale unei
mulimi A={a1, a2, ..., an} cu n elemente este dat de formula:

sau, pentru a evita folosirea funciei factorial,


Amn = n (n 1) (n 2) ... (n m + 2) (n m + 1).
Ca i n cazul permutrilor, putem reduce problema generrii aranjamentelor unei
mulimi arbitrare A la generarea aranjamentelor mulimii I={1, 2, ..., n}. De exemplu,
pentru I={1, 2, 3} i m=2 cele A23 = 6 aranjamente snt:
(1, 2);
(3, 1);

(2, 1);
(2, 3);

(1, 3);
(3, 2).

Generarea aranjamentelor poate fi fcut n ordine lexicografic, pornind de la


aranjamentul cel mai mic a=(1, 2, ..., m).
Fie a=(a1, a2, ..., ai, ..., am) un aranjament oarecare. Pentru a determina succesorul
a al aranjamentului a, se caut mai nti cel mai mare indice i cu proprietatea c ai
poate fi mrit. Un element ai poate fi mrit dac cel puin una din valorile ai+1, ai+2,
..., n cu care ar putea fi nlocuit ai este disponibil. Pentru a putea efectua mai uor
aceste verificri, se utilizeaz vectorul D=(d1, d2, ..., di, ..., dn), unde di este 0 sau 1 n
funcie dac valoarea i apare sau nu n aranjamentul curent a. n momentul n care a
fost determinat indicele i, elementele ai, ai+1, ..., am vor primi n ordine cresctoare cele
mai mici numere disponibile.

178

Dac nu exist un indice i cu proprietatea menionat, nseamn c s-a ajuns


la aranjamentul (nm+1, nm+2, ..., n), deci procesul generrii s-a ncheiat. Pentru
a semnala acest lucru, n programul ce urmeaz se utilizeaz variabila boolean
Indicator.
Program P164;
{ Generarea aranjamentelor }
const nmax=100;
mmax=100;
type Aranjament=array[1..mmax] of 1..nmax;
var A : Aranjament;
D : array[1..nmax] of 0..1;
n : 1..nmax;
m : 1..nmax;
i : integer;
Indicator : boolean;
procedure GenerareAranjamente(var Indicator : boolean);
label 1;
var i, j, k, l : integer;
begin
{ aranjamentul iniial }
if not Indicator then
begin
for i:=1 to m do
begin
A[i]:=i; D[i]:=1;
end;
for i:=m+1 to n do D[i]:=0;
Indicator:=true;
goto 1;
end;
{ succesorul aranjamentului curent }
for i:=m downto 1 do
begin
D[A[i]]:=0;
for j:=A[i]+1 to n do
if D[j]=0 then
begin
A[i]:=j; D[j]:=1; k:=0;
for l:=i+1 to m do
begin
repeat k:=k+1 until D[k]=0;
A[l]:=k; D[k]:=1;
end; { for }

179

goto 1;
end; { if }
end; { for }
Indicator:=false;
1:end; { GenerareAranjamente }
begin
write(Dai n=); readln(n);
write(Dai m=); readln(m);
Indicator:=false;
repeat
GenerareAranjamente(Indicator);
if Indicator then
for i:=1 to m do write(A[i] : 3);
writeln;
until not Indicator;
readln;
end.

Aadar, complexitatea temporal a algoritmilor bazai pe generarea tuturor aranjamentelor este cel mult O(n!).
Generarea combinrilor. Numrul de combinri de n elemente luate cte m (mn)
se calculeaz ca

De exemplu, pentru I={1, 2, 3} i m=2 avem C23 = 3 combinri:


{1, 2};

{1, 3};

{2, 3}.

Generarea combinrilor poate fi fcut n ordine lexicografic, pornind de la combinarea iniial {1, 2, ..., m}.
Fie dat o combinare c={c1, c2, ..., ci, ..., cm}. Combinarea c care i urmeaz imediat
n ordine lexicografic se determin astfel:
se stabilete indicele i care satisface relaiile ci<nm+1, ci+1=nm+i+1, cm-1=n1,
cm=n;
se trece la combinarea c={c1, ..., ci-1, ci+1, ci+2, ..., ci+ni+1}.
Dac nu exist un indice i care satisface condiiile de mai sus, nseamn c au fost
generate toate combinrile.
n programul ce urmeaz combinrile mulimii I={1, 2, ..., n} se genereaz consecutiv n vectorul (tabloul unidimensional) C.
Program P165;
{ Generarea combinarilor }
const nmax=100;
mmax=100;
type Combinare=array[1..mmax] of 1..nmax;

180

var C : Combinare;
n : 1..nmax;
m : 1..mmax;
i : integer;
Indicator : boolean;
procedure GenerareCombinari(var Indicator : boolean);
label 1;
var i, j : integer;
begin
{ combinarea initiala }
if not Indicator then
begin
for i:=1 to m do C[i]:=i;
Indicator:=true;
goto 1;
end;
{ succesorul combinarii curente }
for i:=m downto 1 do
if C[i]<(n-m+i) then
begin
C[i]:=C[i]+1;
for j:=i+1 to m do C[j]:=C[j-1]+1;
goto 1;
end; { then }
Indicator:=false;
1:end; { GenerareCombinari }
begin
write(Dai n=); readln(n);
write(Dai m=); readln(m);
Indicator:=false;
repeat
GenerareCombinari(Indicator);
if Indicator then
for i:=1 to m do write(C[i] :3);
writeln;
until not Indicator;
readln;
end.

Se poate demonstra c timpul cerut de un algoritm bazat pe generarea tuturor


combinrilor este de ordinul O(nk), unde k=min(m, nm+1), deci polinomial.

181

ntrebri i exerciii
Scriei un program PASCAL care afieaz la ecran numrul permutrilor Pn, numrul
aranjamentelor Amn i numrul combinrilor Cmn . Valorile n i m se citesc de la tastatur.
Elaborai o procedur recursiv pentru generarea tuturor permutrilor posibile ale mulimii I={1, 2, ..., n}.
Utiliznd metoda relurii, schiai trei algoritmi pentru generarea, respectiv, a permutrilor, aranjamentelor i combinrilor unei mulimi formate din n elemente distincte.
Se consider un tablou bidimensional T[1..n, 1..n] format din numere ntregi.
Elaborai un program care determin o permutare a coloanelor tabloului astfel nct
suma componentelor de pe diagonala principal s fie minim.
Elaborai un program care afieaz la ecran toate irurile posibile formate din caracterele A, b, C, d, E. Fiecare caracter apare n ir numai o singur dat.
Dintr-o list ce conine n candidai trebuie alese m persoane care vor fi incluse n echipa
de fotbal a unui raion. Elaborai un program care afieaz la ecran toate modalitile de
selecie a celor m persoane.
Se consider mulimea numerelor ntregi A={a1, a2, ..., an}. Elaborai un program care
determin o submulime ce conine exact m elemente ale mulimii A astfel nct suma
lor s fie maxim.
Cum credei, care snt avantajele i neajunsurile algoritmilor bazai pe generarea tuturor
permutrilor, aranjamentelor i combinrilor posibile?
Exist oare tehnici de programare care ar permite evitarea unei analize exhaustive a
tuturor permutrilor, aranjamentelor sau combinrilor posibile?
Se consider mulimea numerelor ntregi A={a1, a2, ..., an}. Elaborai un program care determin o descompunere a mulimii A n dou submulimi nevide B i C astfel nct suma
elementelor din submulimea B s fie egal cu suma elementelor din submulimea C. De
exemplu, pentru A={4, 1, 0, 1, 2, 3, 9} avem B={4, 0, 9} i C={1, 1, 2, 3}.

182

Capitolul 7
PROBLEME RECAPITULATIVE
Problemele ce urmeaz au fost propuse la diverse concursuri de informatic.
Rezolvarea lor necesit cunoaterea profund a tehnicilor de programare i a metodelor de estimare a complexitii algoritmilor.
1. Cercuri. Un ptrat cu latura a cm conine n cercuri (n 100). Fiecare cerc i este
definit prin coordonatele centrului (xi, yi) i raza ri. Elaborai un program care n cel
mult t secunde calculeaz ct mai exact aria obinut prin reuniunea celor n cercuri.
2. Puncte. Se dau n puncte n plan, n 100. S se calculeze numrul maxim de
puncte coliniare.
3. Poduri. Se consider n insule legate prin m poduri. E cunoscut faptul c pe
podul ce leag insulele i, j pot circula vehicule greutatea crora nu depete gij tone.
Determinai greutatea maxim Gab a vehicolului care poate ajunge de pe insula a pe
insula b.
4. Texte. Se consider n texte care trebuie tiprite pe foi de hrtie. Textul i este
format din ri linii. Pe o foaie pot fi tiprite cel mult m linii care pot forma unul, dou
sau mai multe texte. Pentru a le separa, ntre textele de pe aceeai foaie se insereaz o
linie vid. Fragmentarea textelor este interzis, adic toate liniile oricrui text trebuie
imprimate pe aceeai foaie. Elaborai un program care determin numrul minim de
foi necesare pentru a tipri toate textele.
5. Circumferine. Se consider n puncte pe un plan cartezian. Fiecare punct i este
definit prin coordonatele sale xi, yi. Elaborai un program care verific dac punctele
n studiu aparin unei circumferine.
6. Reeaua telefonic. Se consider n orae, n 100, care trebuie legate prin cabluri
ntr-o reea telefonic. Pentru fiecare ora i snt cunoscute coordonatele carteziene xi, yi.
Cablurile telefonice ce leag oricare dou orae nu pot avea ramificaii. Abonaii reelei
telefonice comunic ntre ei direct sau prin intermediul staiilor telefonice din alte orae.
Lungimea cablului care leag oraele i, j este egal cu distana dintre ele. Determinai
lungimea sumar minim a cablurilor necesare pentru a conecta toate oraele.
7. Evaluarea expresiilor. Se consider expresiile aritmetice formate din numere
ntregi, parantezele (, ) i operatorii binari +, -, *, mod, div. Scriei un program care
evalueaz expresiile aritmetice n studiu.
8. Psihologie. Se consider n angajai, n 100, care trebuie repartizai n m echipe.
Fiecare echip este format din k angajai, k m = n. Relaia de compatibilitate ntre
angajaii i, j se caracterizeaz prin coeficientul rij care poate lua valorile 0 (incompatibili), 1, 2, ..., 10 (compatibilitate excelent). Compatibilitatea ntregului colectiv C

183

se calculeaz nsumnd coeficienii rij pentru toate perechile posibile (i, j) din cadrul
fiecrei echipe. Determinai compatibilitatea maxim Cmax care poate fi asigurat prin
formarea corespunztoare a echipelor.
9. Compasul. Se consider n puncte pe un plan cartezian. Fiecare punct i este specificat prin coordonatele sale xi, yi. Elaborai un program care verific dac se poate
desena o circumferin cu centrul n unul din punctele n studiu i care ar trece prin
toate celelalte puncte.
10. Intersecia dreptunghiurilor. Se dau n dreptunghiuri (n 10) care au laturile
paralele cu axele de coordonate, iar coordonatele vrfurilor snt numere naturale din
mulimea {0, 1, 2, ..., 20}. Elaborai un program care calculeaz aria figurii obinute
prin intersecia celor n dreptunghiuri.
11. Reuniunea dreptunghiurilor. Se dau n dreptunghiuri (n 10) care au laturile paralele cu axele de coordonate, iar coordonatele vrfurilor snt numere reale.
Elaborai un program care calculeaz aria figurii obinute prin reuniunea celor n
dreptunghiuri.
12. Numere prime. Calculai toate numerele prime formate din 4 cifre inversul crora este la fel un numr prim, iar suma cifrelor este de asemenea un numr prim.
13. Vizibilitate. Se consider linia frnt nchis P1P2 ... PnP1, n 20, care nu se
autointersecteaz. n punctul A din interiorul liniei este situat un observator. Pentru
observator unele segmente ale liniei frnte pot fi invizibile. Elaborai un program
care calculeaz numrul segmentelor invizibile.
14. Felinare. Un parc de form dreptunghiular este mprit n ptrate de aceleai dimensiuni. n fiecare ptrat al parcului poate fi instalat cte un felinar. n general, un felinar asigur iluminarea nu numai a ptratului n care el se afl, dar i
a celor opt ptrate vecine. Elaborai un program care determin numrul minim de
felinare necesare pentru iluminarea parcului.
15. Laserul. Se consider o plac dreptunghiular cu dimensiunile mn, unde m
i n snt numere naturale. Aceast plac trebuie tiat n mn plci mai mici, fiecare
bucat avnd forma unui ptrat cu dimensiunile 11. ntruct placa este neomogen,
pentru fiecare bucat se indic densitatea dxy, unde x, y snt coordonatele colului
stnga-jos al ptratului respectiv.
Pentru operaiile de tiere se folosete un strung cu laser. Fiecare operaie de tiere include:
fixarea unei plci pe masa de tiere;
stabilirea puterii laserului n funcie de densitatea materialului de tiat;
o singur deplasare a laserului de-a lungul oricrei drepte paralele cu una din
axele de coordonate;
scoaterea celor dou plci de pe masa de tiere.
Costul unei operaii de tiere se determin dup formula c = dmax, unde dmax
este densitatea maxim a bucilor 11 peste marginile crora trece raza laserului.
Evident, costul total T poate fi determinat adunnd costurile individuale c ale tuturor
operaiilor de tiere necesare pentru obinerea bucilor 11. Scriei un program care
calculeaz costul minim T.

184

16. Judee. Teritoriul unei ri este mprit n judee (fig. 7.1). Pe hart, frontiera
rii i graniele administrative ale fiecrui jude reprezint cte un poligon definit
prin coordonatele (xi, yi) ale vrfurilor sale. Se presupune c vrfurile de poligoane
snt numerotate direct prin 1, 2, 3, ..., n, iar coordonatele lor snt numere ntregi. n
interiorul oricrui jude nu exist alte judee.

Fig. 7.1. Judeele unei ri

Un virus de calculator a distrus parial informaia despre graniele administrative, lsnd intacte urmtoarele date:
numrul n i coordonatele (xi, yi) ale tuturor vrfurilor de poligoane;
numrul de segmente m care formeaz laturi de poligoane i informaia despre
extremitile fiecrui segment.
Scriei un program care determin numrul de judee d i vrfurile fiecrui poligon ce reprezint o grani administrativ de jude.
17. Turnuri. Fie n plci dreptunghiulare numerotate de la 1 la n. Despre placa i se
tie c are grosimea hi i lungimile laturilor xi, yi. Elaborai un program care determin nlimea maxim a unui turn ce poate fi construit din plcile n studiu. Pentru a
asigura stabilitatea turnului, se vor respecta urmtoarele reguli (fig. 7.2):
plcile snt puse una peste alta orizontal, nu pe muchii sau n alt mod;
muchiile omoloage ale plcilor suprapuse snt paralele;
orice plac din componena turnului se va sprijini n ntregime pe placa de mai
jos (evident, placa de la baza tunului se sprijin pe sol);
nu se cere s folosim toate plcile.
Date de intrare. Fiierul text TURNURI.IN conine pe prima linie numrul n. Pe
fiecare din urmtoarele n linii se conin cte trei numere ntregi pozitive xi, yi, hi separate prin spaiu.
Date de ieire. Fiierul text TURNURI.OUT va conine pe o singur linie un numr
ntreg nlimea maxim a turnului.

185

Fig. 7.2. Turn construit din plci dreptunghiulare

Exemplu:
TURNURI.IN
5
3 4 2
3 4 3
4 3 2
1 5 4
2 2 1

TURNURI.OUT
8

Restricii: n 1000; xi, yi, hi < 1000. Timpul de execuie nu va depi 10 sec.
18. Speologie. Speologul este un specialist care se ocup cu explorarea i studierea peterilor. Antrenarea speologilor presupune parcurgerea unor labirinturi subterane. Un astfel de labirint const din n, n 100, peteri i coridoare (fig. 7.3). Fiecare
peter are o denumire individual format din cel mult 10 caractere alfanumerice,
fr spaii, scris pe unul din pereii ei. Petera de intrare are denumirea INTRARE,
iar cea de ieire denumirea IESIRE. La intrarea n fiecare coridor este scris denumirea peterii spre care ea duce.
Speologul nu cunoate planul labirintului. n schimb, el este echipat cu un caiet,
un creion i o lantern, fapt ce i permite s poat citi denumirile de peteri sau de
coridoare i s fac notie. Vom numi drum o succesiune de peteri cu proprietatea
c ntre oricare dou peteri consecutive din succesiune exist un coridor. Prin lungimea drumului nelegem numrul de peteri ce-l formeaz. De exemplu, drumul
INTRARE, STALAGMITE, LILIECI, IZVOARE, IESIRE are lungimea 5.
Elaborai un program care gsete unul dintre cele mai scurte drumuri de la petera INTRARE la petera IESIRE.
Date de intrare. Fiier de intrare nu exist. Totui caracteristica peterii curente
poate fi aflat prin apelul funciei predefinite UndeMaAflu de tip string. Funcia
returneaz un ir de caractere ce conine denumirea peterii n care n prezent se afl
speologul, dou puncte i denumirile de intrri de galerii, separate prin spaiu. De
exemplu, dac speologul se afl n petera LILIECI, funcia va ntoarce valoarea:
LILIECI: STALAGMITE IZVOARE LILIECI LILIECI

186

Fig. 7.3. Planul unei peteri

Trecerea speologului din petera curent n petera spre care duce galeria c se
realizeaz prin apelul procedurii predefinite TreciCoridorul(c), unde c este o
expresie de tip string. Dac se indic un coridor inexistent, speologul rmne pe
loc. Pentru ca aceste subprograme s fie accesibile, includei n partea declarativ a
programului de elaborat linia
uses LABIRINT;

Date de ieire. Fiierul text SPEOLOG.OUT va conine pe prima linie un numr


ntreg lungimea celui mai scurt drum. Pe urmtoarele linii se va scrie drumul.
Fiecare denumire de peter ocup o linie separat. Dac un astfel de drum nu exist, fiierul va conine o singur linie cu cuvntul FUNDAC.
Exemplu. Pentru labirintul din figura 7.3 avem:
SPEOLOG.OUT
4
INTRARE
STALACTITE
IZVOARE
IESIRE

Timpul de execuie nu va depi 20 sec.


19. Livada. Planul unei livezi de form dreptunghiular cu dimensiunile nm este
format din zone ptrate cu latura 1. n fiecare zon crete o singur specie de arbori. Orice
specie de arbori poate ocupa una sau mai multe zone, nu neaprat vecine. Elaborai un
program care gsete un sector dreptunghiular de arie minim ce conine cel puin k
specii de arbori. Laturile sectorului vor coincide cu laturile zonelor din plan.

187

20. Discoteca. La o discotec particip mai multe persoane, numerotate de la 1


la n. Iniial, numai un singur participant, cel cu numrul i, cunoate o tire foarte
important pe care el o comunic prietenilor si. n continuare, orice participant
j, care deja cunoate aceast tire, o comunic, de asemenea, numai prietenilor si.
Elaborai un program care determin numrul de participani p care vor afla tirea
respectiv. Relaia de prietenie este definit prin m perechi distincte de tipul {j, k}
cu semnificaia participanii j, k snt prieteni. Se consider c 3 n 1000 i
2 m 30000.
21. Genistul. O poriune de drum este mprit n n segmente. Pe fiecare segment poate fi plantat cel mult o min. Genistul a memorat informaia despre minele
plantate ntr-un tablou unidimensional M = ||mi||, n care mi = 1 dac segmentul i
conine o min i mi = 0 n caz contrar. Pentru orice eventualitate, genistul a cifrat informaia din tabloul M ntr-un alt tablou C = ||ci||n componentele cruia se determin
dup cum urmeaz:
pentru
pentru
pentru
n condiiile de lupt datele din tabloul M au fost pierdute. Elaborai un program
care calculeaz tabloul M avnd ca date de intrare tabloul C. Se consider c problema are cel puin o solue i 3 n 10000.
22. Cutii. Se consider n cutii n form de paralelipiped dreptunghiular. Pentru
fiecare cutie snt cunoscute cele trei dimensiuni xi, yi, zi. n funcie de dimensiunile
cutiilor, unele din ele pot fi puse una n alta. n general, cutiile pot fi rotite. Cutia i
poate fi pus n cutia j numai atunci cnd n urma tuturor rotirilor posibile se va gsi
o astfel de poziie pentru care dimensiunile cutiei i snt cu strictee mai mici dect
dimensiunile corespunztoare ale cutiei j. Pentru a asigura o mpachetare estetic, se
cere ca feele omoloage ale cutiilor s fie paralele (fig. 7.4). Mai mult dect att, unele
cutii pot fi imbricate sau, cu alte cuvinte, poate fi format un ir de numere de cutii
i1, i2, i3, ..., ik cu proprietatea c cutia i1 se afl n cutia i2; cutia i2 se afl n cutia i3 etc.
Scriei un program care determin numrul maxim de cutii kmax ce pot fi imbricate
ntr-un astfel de ir.

Fig. 7.4. Cutii imbricate

188

Date de intrare. Fiierul text CUTII.IN conine pe prima linie numrul natural n.
Fiecare din urmtoarele n linii conine cte trei numere naturale xi, yi, zi separate prin
spaiu.
Date de ieire. Fiierul text CUTII.OUT va conine pe o singur linie numrul natural kmax.
Exemplu:

CUTII.IN
5
4 4 4
1 3 5
2 2 3
1 1 1
1 1 2

CUTII.OUT
3

Restricii: 2 n 500; 1 xi, yi, zi 30 000. Timpul de execuie nu va depi 2 secunde.

189

Bibliografie
1. Cerchez Emanuela, erban Marinel. Informatic. Manual pentru clasa a X-a. Filiera
teoretic, profilul matematic-informatic. Iai: Editura POLIROM, 2000, 200 p.
2. Cerchez Emanuela. Informatic. Culegere de probleme pentru liceu. Iai, Editura
POLIROM, 2002, 240 p.
3. Galatan Suzana, Ghinea Diana, ntuneric Ana, Radu Stefana. Ghid de pregtire
pentru BAC. Informatic. Intensiv. Pascal C/C++. Bucureti, Editura Sigma, 2009,
539 p.
4. Giumale Cristian. Un atelier de programare. Cluj-Napoca. Editura Computer
Libris AGORA, 2000, 382 p.
5. Giumale Cristian. Introducere n analiza algoritmilor. Iai, Editura POLIROM,
2004, 456 p.
6. Gremalschi Anatol, Mocanu Iurie, Spinei Ion. Informatic. Limbajul PASCAL.
Manual pentru clasele IX-XI. Chiinu, Editura tiina, 2003, 256 p.
7. Ivac Cornelia., Prun Mona. Bazele informaticii (Grafuri i elemente de combinatoric). Proiect de manual pentru clasa a X-a. Profil informatic. Bucureti, Editura
Petrion, 1995, 175 p.
8. Livovschi Leon, Georgescu Horia. Sinteza i analiza algoritmilor. Bucureti, Editura
tiinific i Pedagogic, 1986, 458 p.
9. Moraru Florin. Bacalaureat. Informatic. Bucureti, Editura Petrion, 2000, 319 p.
10. Negreanu Dan. Probleme de matematic rezolvate cu calculatorul. Bucureti,
Editura Teora, 1998, 214 p.
11. Roca Ion Gh., Cocianu Ctlina, Uscatu Cristian. Bazele informaticii. Manual
pentru clasa a X-a, licee teoretice. Bucureti, Editura ALL EDUCAIONAL, 1999,
64 p.
12. Roca Ion Gh., State Luminia, Ghilic-Micu Bogdan, Cocianu Ctlina-Luca, Stoica
Marian, Uscatu Cristian. Informatic. Manual pentru clasa a 10-a. Profilul matematic-informatic. Bucureti, ALL EDUCAIONAL, 2000, 96 p.
13. Sorin Tudor. Informatic (Tehnici de programare). Manual pentru clasa a X-a.
Varianta Pascal. Bucureti, Editura L&S INFOMAT, 2000, 188 p.
14. Thomas H. Cormen, Charles E. Leiserson, Ronald R. Rivest. Introducere n algoritmi. Cluj-Napoca, Editura Computer Libris AGORA, 2000, 881 p.
15. ., , .
. . . : . . .: , 2003, 384 .
16. . Turbo PASCAL. . , Prut
International, 2007, 232 .
17. ., + = , .,
, 1985, 243 .
18. . , ., , 1989,
350 .

190

19. ., ., . . . , 2000, 270 .


20. .. : . .: , 2006, 366 .
21. ., . , . .,
, 1989, 255 .
22. .. : , .: .
, 2012, 272 .
23. .. . .: .
, 2004, 341 .
24. .. . .: . , 2008, 231 .
25. . .., .., .. . .: , 2006, 256 .
26. .., .. . .: , 2012, 400 .
27. .., .., .. . 2 . . 2:
11 . .: , 2008, 271 .

191

Acest manual este proprietatea Ministerului Educaiei al Republicii Moldova.


Liceul/gimnaziul __________________________________________________________
Manualul nr. _____________________________________________________________
Nr. Numele de familie i prenumele
crt. elevului

Anul colar

Aspectul manualului
la primire

la restituire

1.
2.
3.
4.
5.
Dirigintele verific dac numele elevului este scris corect.
Elevul nu trebuie s fac niciun fel de nsemnri n manual.
Aspectul manualului (la primire i la restituire) se va aprecia folosind termenii: nou, bun,
satisfctor, nesatisfctor.

Imprimare la Tipografia BALACRON SRL,


str. Calea Ieilor, 10; MD-2069
Chiinu, Republica Moldova
Comanda nr. 560

Potrebbero piacerti anche