Sunteți pe pagina 1din 31

lOMoARcPSD|12059127

Pc Cap2 - Summary Programarea calculatoarelor si limbaje


de programare
Programarea calculatoarelor si limbaje de programare (Universitatea din Craiova)

Scan to open on Studocu

Studocu is not sponsored or endorsed by any college or university


Downloaded by Mihaela Stan (miha_cio@yahoo.com)
lOMoARcPSD|12059127

2. Algoritmi

După cum s-a specificat în paragraful 1.3, etapa preliminară scrierii unui algoritm de
rezolvare a unei probleme este analiza acesteia, în cadrul căreia trebuie determinate mărimile
de intrare, cele de ieşire, precum si relaţiile ce conduc la obţinerea marimilor de ieşire. În
cadrul etapei de descriere a algoritmului de rezolvare a problemei, trebuie descrisă de fapt
succesiunea operaţiilor care realizează relaţiile determinate anterior. Un algoritm care nu este
precedat de o analiză corectă a problemei de rezolvat este de cele mai multe ori un algoritm
eronat sau neperformant.

2.1. Definirea şi proprietăţile algoritmilor

Noţiunea de algoritm se referă în mod uzual la o metodă de descriere a rezolvării unor


probleme. Mai exact, un algoritm reprezintă o multime finită de operaţii care se aplică asupra
unor mărimi de intrare ale unei probleme pentru a obţine rezultatele sau mărimile de ieşire
ale acesteia.
Principalele noţiuni implicate sunt descrierea unui algoritm si execuţia algoritmului.
Pentru a descrie corect un algoritm, trebuie ales un limbaj adecvat de descriere, cu o
suficientă putere expresivă, care să poată descrie operaţiile (din cadrul domeniului din care
face parte problema respectivă) ce se pot efectua asupra datelor problemei. Execuţia unui
algoritm se referă la componenta pragmatică a limbajului de descriere; în mod uzual un
algoritm trebuie să poată fi executat de către o persoană care are cunostinţe din domeniul
problemei de rezolvat, folosind doar creionul si hârtia.
Unul dintre primele limbaje de descriere a algoritmilor a fost limbajul natural. Acesta
are o mare flexibilitate şi permite descrierea multor tipuri de operaţii. În mod uzual, se
folosesc propoziţii pentru a descrie fiecare operaţie din cadrul algoritmilor. Pentru a evidenţia
succesiunea operaţiilor, acestea se numerotează cu numere crescătoare. O asemenea operaţie
descrisă printr-o propoziţie numerotată se mai numeşte pas. În acest mod, un algoritm este
reprezentat de o secvenţă de paşi.

Exemplul 2.1. Să se determine cel mai mare divior comun a două mumere întregi folosind
algoritmul lui Euclid.
Analiza problemei.
Vom nota cu m şi n numerele pentru care trebuie determinat cel mai mare divizor
comun. Astfel, variabilele m şi n reprezintă variabile de intrare pentru problemă. Algoritmul
lui Euclid presupune efectuarea repetată a unor operaţii de împărţire cu rest, până când se
obţine un rest zero. Fie de exemplu: m=8, n=12:
8=0*12+8 (r1=8)
12=1*8+4 (r2=4)
8=2*4+0 (r3=0)
Ultimul rest nenul (r2=4) va fi solutia problemei.

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

Vom utiliza următoarele variabile: m pentru desemnarea deâmpărţitului, n pentru desemnarea


împărţitorului şi r pentru desemnarea restului (câtul nu intervine în algoritm). Se observă
faptul că la fiecare pas (în afară de primul), valorile lui m si n se determină din valorile
pasului precedent: noua valoare a lui m este vechea valoare a lui n şi noua valoare a lui n este
vechea valoare a lui r. Astfel, ultimul rest nenul va fi memorat în variabila n, care devine si o
variabilă de ieşire.
Descrierea algoritmului:
1. Se citesc de la intrare valori pentru m şi n.
2. Se împarte m la n şi se obţine un rest r.
3. Dacă r=0, atunci scrie la ieşire n şi algoritmul se termină.
4. Dacă r0, atunci se atribuie: m=n, n=r şi se face salt la pasul 2.

Se observă că algoritmul din exemplul precedent se termină la pasul 3. O primă întrebare se


refeă la faptul dacă după un număr finit de paşi, restul devine zero pentru ca algoritmul să se
termine. O argumentare la această întrebare este următoarea afirmaţie: şirul de resturi: r1, r2,
r3, ..., este un şir descrescător de numere întregi pozitive şi care ajunge în zero.

Pe baza examinării algoritmului precedent, se pot descrie principalele caracteristici ale unui
algoritm:
1. Generalitatea unui algoritm, se referă la faptul că în mod uzual algoritmii descriu
rezolvarea unor categorii de probleme, nu a unor probleme singulare. În exemplul
precedent, algoritmul descrie determinarea celui mai mare divizor comun a oricăror
numere întregi, nu numai a numerelor 8 şi 12.
2. Intrarea în algoritm, este reprezentată de zero sau mai multe mărimi care trebuie
specificate algoritmului, pantru ca el să poată fi executat. În mod uzual intrarea în
algoritm se face prin intarmediul unor varabile de intrare, care la începutul execuţiei
algoritmului vor fi iniţializate cu valorile de intrare curente.
3. Ieşirea din algoritm, constă în una sau mai multe mărimi care sunt determinate de
către algoritm ce reprezintă rezultatele problemei aferente algoritmului. Ieşirea se
realizează în mod uzual prin intermediul unor variabile de ieşire. Dacă este posibil
algoritmii să nu aibe mărimi de intrare, ei trebuie obligatoriu să aibe mărimi de ieşire,
pentru că acestea reprezintă soluţiile problemelor aferente.
4. Cracterul finit al algoritmului, reprezintă cerinţa ca numărul de operaţii efectuate
pentru determinarea mărimilor de ieşire să fie finit, altfel algoritmul nu poate să
determine soluţiile problemei aferente.
5. Claritatea algoritmului, se referă la cerinţa ca operaţiile din algoritm să fie clar şi
concis specificate, fiind astfel înlăturate nedeterminismul şi ambiguităţile anumitor
operaţii.

Cu excepţia ultimei caracteristici, toate celelelte caracteristici sunt verificate de algoritmul


din exemplul 1. Ambiguităţile care pot apare se referă la semnificaţia operaţiilor efectuate în
algoritm: nu se specifică dacă valorile variabilelor m şi n sunt întregi sau reale. În cazul în
care valorile sunt reale, nu are sens efectuarea unor operaţii cu rest.
În general, limbajul natural nu permite eliminarea completă a ambiguităţilor
operaţiilor. Din acest motiv, pentru specificarea algoritmilor se utilizează limbaje de
descriere cu o semantică mai puternică.

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

2.2 Limbajul algoritmic

Limbajul algoritmic (sau limbajul pseudocod) reprezintă o metodă uzuală de specificare a


algoritmilor, mai formalizată decât limbajul natural. Avantajul constă în faptul că descrierea
operaţiilor unui algoritm poate fi făcută mai clar şi cu mai puţine ambiguităţi decât în cazul
utilizării limbajului natural.

2.2.1 Elemente de gramatică

Este necesară prezentarea unui set minim de reguli pentru a putea defini sintaxa acestui
limbaj.
Majoritatea propoziţiilor din limbaj sunt propoziţii imperative (instrucţiuni), fiecare
având o semnificaţie foarte clară şi desemnând operaţii precise. Puţinele propoziţii
declarative au doar rolul de a delimita din punct de vedere sintactic algoritmii, sau de a
specifica în cazul funcţiilor şi procedurilor modul în care se face transferul de informaţie între
funcţia/procedura apelată şi algoritmul apelant.
În afara acestor propoziţii, în cadrul algoritmilor pot apare propoziţii dintr-o categorie
aparte, numite comentarii. Comentariile nu sunt luate în considerare la execuţia algoritmilor,
ele având doar un rol de explicare a anumitor operaţii din cadrul acestora. Un comentariu
începe cu şirul de caractere // şi se termină la sfârşitul liniei curente.
Desemnarea acţiunilor din cadrul instrucţiunilor se face prin intermediul unuia sau a
mai multor cuvinte cheie. Acestea sunt cuvinte rezervate şi nu pot fi utilizate de către
programator în alte scopuri. A doua categorie importantă de cuvinte sunt cuvintele utilizator,
numite şi identificatori, care sunt nume date de programatori anumitor obiecte din algoritm.
Pentru a deosebi cuvintele din cele două categorii, cuvintele cheie sunt subliniate.
Identificatorii sunt şiruri de caractere alfabetice, care încep întotdeauna cu o literă.
În mod uzual, identificatorii desemnează nume de variabile. Întrucât o mare parte a
problemelor a căror rezolvare poate fi descrisă algoritmic sunt de natură ştiinţifică, o parte a
noţiunilor şi conceptelor din matematică au fost preluate în limbajul algoritmic. Astfel,
noţiunea de variabilă reprezintă o entitate cu două atribute: numele variabilei (care este un
identificator) şi valoarea sa curentă sau instantanee. În timpul execuţiei unui algoritm,
valoarea curentă a unei variabilă se poate modifica. Acţiunea prin care unei variabile i se
asociază o valoare curentă se numeşte asignarea variabilei respective.
O altă noţiune utilizată este cea de expresie. O expresie este formată din operanzi,
operatori şi perechi de paranteze rotunde. Operanzii pot fi constante, variabile şi apeluri de
funcţii. Operatorii reprezintă operaţiile elementare ce se pot efectua asupra operanzilor.
Evaluarea unei expresii presupune aplicarea operatorilor asupra operanzilor într-o anumită
ordine, pentru obţinerea rezultatului final. Schimbarea ordinii de evaluare se realizează prin
utilizarea parantezelor rotunde.
Pentru a nu formaliza excesiv acest limbaj, anumite noţiuni din limbajele de
programare de nivel înalt nu sunt luate în considerare. De exemplu, noţiunea de tip de date
este utilizată în mod implicit. Tipul de date al unei variabile reprezintă mulţimea valorilor pe
care variabila le poate lua în timpul execuţiei unui algoritm. Se subânţelege faptul că o
variabilă nu poate lua valori diferite în timpul execuţiei unui algoritm (valori întregi şi valori
logice de exemplu).

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

2.2.2 Instrucţiunile limbajului

Descrierea unui algoritm se face între două propoziţii declarative, formate fiecare dintr-un
singur cuvânt cheie:

start
sfarsit

Între cele două cuvinte se specifică secvenţa de instrucţiuni ce formează descrierea rezolvării
problemei asociate. O secvenţă de instrucţiuni reprezintă un şir de instrucţiuni, scrise în mod
uzual unele sub altele, care se execută secvenţial (una după alta).
Cele mai utilizate instrucţiuni sunt cele de citire şi scriere a datelor, de atribuire, de
selecţie şi instrucţiunile repetitive.
Corespunzător intrării şi ieşirii unui algoritm, limbajul algoritmic posedă două
instrucţiuni, numite instrucţiunea de citire, respectiv instrucţiunea de scriere. Prima este
folosită pentru citirea din afara algoritmului a datelor de intrare în algoritm, iar a doua pentru
scrierea în afara algoritmului a datelor de ieşire (a rezultatelor).

Instrucţiunea de citire are următoarea formă sintactică:

citeste lista variabile

unde lista variabile reprezintă o listă de una sau mai multe variabile de intrare ale
algoritmului, separate prin virgulă dacă sunt mai multe.

Observaţie. Cracterele ““ şi ““ nu fac parte din sintaxa limbajului algoritmic, ci din cea a
limbajului de descriere. Între cele două caractere se specifică o categorie sintactică, adică o
mulţime de construcţii sintactice grupate împreună.

Exemple de instrucţiuni de citire:


citeste x
citeste a, b, c

Execuţia unei astfel de instrucţiuni realizează următoarele acţiuni:


- se introduc din afara algoritmului a unui număr de constante egal cu numărul de
variabile din instrucţiune;
- se asignează pe rând variabilele din instrucţiune cu constantele corespunzătoare.

Observaţie. Instrucţiunea de citire este o modalitate prin care se pot asigna valori
variabilelor. După ce o constantă se asignează la o variabilă în acest fel, variabila îşi va păstra
valoarea curentă până la prima instrucţiune care o va modifica.

Instrucţiunea de scriere are următoarea formă sintactică:

scrie lista parametri

unde lista parametri reprezintă o listă de unul sau mai mulţi parametri separaţi prin
virgulă.
Există două categorii de parametri: de tip mesaj şi de tip expresie. Parametrii de tip
mesaj sunt şiruri de caractere cuprinse între două apostrofuri şi sunt utilizaţi pentru

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

tranmiterea unor mesaje în exteriorul algoritmilor. Valoarea unui astfel de parametru este
chiar şirul de caractere. Prametrii de tip expreise sunt expresii care se pot evalua. Valoarea
unui astfel de parametru este cea rezultată în urma evaluării.

Exemple de instrucţiuni de scriere:


scrie x
scrie ‘Acesta este un mesaj’
scrie ‘x=‘, x

Execuţia unei asemenea instrucţiuni decurge astfel:


- se evaluează parametrii care apar în instrucţiune;
- se afişează în afara algoritmului secvenţia valorile rezultate.
Presupunând că variabila x are asignată valoarea 7 în momentul execuţiei secvenţei
anterioare, în afara algoritmului se va afişa:
7
Acesta este un mesaj
x=7

Exemplul 2.2. Să se scrie un algoritm care determină suma şi produsul a două numere date.
Descrierea algoritmului
Notând cu x şi y variabilele de intrare corespunzătoare valorilor de intrare, algoritmul
se poate descrie astfe:

start
citeste x, y
scrie ‘suma=‘, x+y, ‘produsul=‘, x*y
sfarsit

Una dintre cele mai utilizate instrucţiuni, atât în limbajul algoritmic, cât şi în limbajele de
programare, este instrucţiunea de atribuire. Aceasta reprezintă cel de-al doilea mod prin care
se pot asigna valori variabilelor. Definiţia sintactică a instrucţiunii este:
atribuie variabila  expresie
unde variabila este numele unei variabile a algoritmului, iar expresie este o
expresie compatibilă cu variabila. Cracterul ““ reprezintă operatorul de atribuire şi are
rolul de a indica sensul de transfer al informaţiei. Întrucât operatorul de atribuire identifică
exact instrucţiunea de atribuire, cuvântul cheie atribuie se poate omite, rezultând o formă
simplificată de scriere:
variabila  expresie

Exemple de instrucţiuni de atribuire:


x  5
y  (sin(a)+b)/(sin(b)+a)
n  n+1

În mod uzual, operatorii care apar în cadrul expresiilor sunt preluaţi din matematică,
reprezentând principalele operaţii, dar mulţimea acestora poate fi extinsă pentru a cuprinde
operaţii din diferite domenii. Deşi nu se specifică în mod formal, următoarele categorii de
operatori sunt mai des utilizaţi:
- operatori aritmetici:
- +, -, *, /: reprezintă operaţiile algebrice elementare;

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

- div, mod: reprezintă operaţiile de determinare a câtului şi restului împărţirii a


doua numere întregi;
- operatori de comparare (de relaţie): <, , >, , =, ;
- operatori logici:  (şi logic),  (sau logic),  (negaţia logică).

Execuţia instrucţiunii de atribuire se realizează în două etape distincte:


- evaluarea expresiei din stânga operatorului de atribuire, în urma căreia rezultă o
valoare;
- atribuirea valorii rezultate variabilei din stânga.

În acest fel, numele unei variabile poate apare atât în stânga, cât şi în dreapta operatorului de
atribuire. Cele două valori ale variabilei se numesc: valoare veche (cea din stânga) şi valoare
nouă (cea din dreapta).
Instrucţiunea de selecţie cea mai utilizată este instrucţiunea de decizie. Ea este o
instrucţiune compusă, a cărei execuţie presupune execuţia unei secvenţe de instrucţiuni din
maxim două posibile, în funcţie de o anumită condiţie. Definiţia sintactică a instrucţiunii este
următoarea:

daca expresie atunci


 secventa 1
altfel
 secventa 2
฀

unde expresie reprezintă o expresie logică, iar secventa 1 şi secventa 2


reprezintă două secvenţe de instrucţiuni.

Pentru execuţia instrucţiunii se execută următoarele acţiuni:


- se evaluează expresia logică;
- dacă aceasta este adevărată, se execută secvenţa 1 de instrucţiuni;
- dacă expresia este falsă, se execută secvenţa 2 de instrucţiuni.

Obesrvaţie. Caracterul grafic ฀ are rolul de a delimita ultima secvenţă internă de


instrucţiuni de instrucţiunea imediat următoare celei de decizie.

Principalii operatori care apar în cadrul expresiilor logice sunt operatorii logici şi
operatorii de comparare (de relaţie). Operatorii logici corespund principalelor operaţii
logice: sau logic (), şi logic () şi negaţia logică (). Operatorii de relaţie (<, , >, , =,
) compară valoarea a doi operanzi, generând tot un rezultat logic.
Sunt cazuri în care este utilă selecţia unei secvenţe de instrucţiuni din mai multe
alternative posibile. În aceste cazuri se poate utiliza o formă extinsă a instrucţiunii de decizie,
care devine o instrucţiune de selecţie. Forma sintactică a acesteia este următoarea:

daca expresie 1 atunci


 secventa 1
altfel daca expresie 2 atunci
 secventa 2

...

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127


altfel daca expresie n atunci
 secventa n
altfel
 secventa n+1
฀

Exemplul 2.3. Să se determine valoarea funcţiei:


-2*x2-x+2, dacă x(-, -2)
f(x)= x-2, dacă x[-2, -1)
(2-x)/(x+2) , dacă x(-1, 1)
(2*x2+x-2)/(2*x+1), dacă x[1, )
într-un punct x dat.

Descrierea algoritmului.
Pentru că instrucţiunea de decizie selectează pentru execuţie o secvenţă din maxim
două posibile, în cadrul algoritmului se vor folosi o instructiune de decizie extinsă, câte o
alternativă pentru fiecare ramură a funcţiei; prima decizie determină complet doar intervalul
(-, -2), urmând ca în cazul intervalului [-2, ) să se considere următorul punct de decizie, -
1, ş.a.m.d.

start
citeste x
daca x<-2 atunci
 y  -2*x2-x+2
altfel
 daca x<-1 atunci
  y  x-1
 altfel
  daca x<1 atunci
   y  (2-x)/(x+2)
  altfel
   y  (2*x2+x-2)/(2*x+1)
  ฀
 ฀
฀
scrie x,y
sfarsit

Există cazuri în care a doua alternativă dintr-o decizie nu apare. În acest caz se poate utiliza
forma scurtă a instrucţiunii de decizie:

daca expresie atunci


 secventa
฀

În cazul în care expresia logică este adevărată, se execută secvenţa de instrucţiuni internă; în
caz contrar, instrucţiunea de decizie este inefectivă.

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

Exemplul 2.4. Să reluăm exemplul precedent, dar folosind doar instrucţiuni de decizie cu
formă scurtă: pentru fiecare ramură a funcţiei se va considera o singură instrucţiune de
decizie.

start
citeste x
daca x<-2 atunci
 y  -2*x2-x+2
฀
daca (x-2)  (x<-1) atunci
 y  x-1
฀
daca (x-1)  (x<1) atunci
 y  (2-x)/(x+2)
฀
daca x1 atunci
 y  (2*x2+x-2)/(2*x+1)
฀
scrie x,y
sfarsit

Instrucţiunile repetitive sunt, ca şi instrucţiunea de decizie, instrucţiuni compuse. Execuţia


acestora presupune execuţia repetată a unei secvenţe interne de instrucţiuni. O singură
execuţie a secvenţei interne reprezintă un pas sau o iteraţie, iar instrucţiunile repetitive se
mai numesc instrucţiuni iterative. Principalele instrucţiuni sunt: instrucţiunea repetitivă cu
test iniţial, instrucţiunea repetitivă cu test final şi instrucţiunea repetitivă cu număr
cunoscut de iteraţii (de paşi).

Instrucţiunea repetitivă cu test iniţial are următoarea formă sintactică:

cat timp expresie executa


 secventa
฀

unde expresie reprezintă o expresie logică, iar secventa o secvenţă de instrucţiuni.


Rolul expresiei logice este acela de a determina momentul încheierii execuţiei instrucţiunii.

Execuţia unei asemenea instrucţiuni decurge astfel:


1. Se evaluează expresia logică;
2. Dacă expresia este falsă, execuţia instrucţiunii repetitive se termină;
3. Dacă expresia este adevărată, atunci se execută secvenţa internă de instrucţiuni şi se
revine la pasul 1.
Se observă faptul că numărul de iteraţii poate fi zero sau mai mare. În cazul în care încă de la
începutul execuţiei instrucţiunii repetitive, expresia logică este falsă, instrucţiunea este
inefectivă.
O altă observaţie se referă la terminarea execuţiei instrucţiunii repetitive. Dacă
expresia logică nu este corect specificată, este posibil ca numărul de iteraţii să fie infinit. O
condiţie necesară (nu şi suficientă) pentru terminarea finită a execuţiei instrucţiunii este ca în
cadrul instrucţiunilor din secvenţa internă să fie modificate valorile variabilelor care apar în
expresia logică.

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

De exemplu, să considerăm următoarea secvenţă de instrucţiuni:


x  5
cat timp x<10 executa
 scrie ‘o iteratie’
฀

Instrucţiunea repetitivă precedentă reprezintă o buclă infinită, pentru că valoarea variabilei x


nu se schimbă în timpul execuţiei instrucţiunii. Modificând secvenţa precedentă, următoarea
secvenţă va afişa de cinci ori mesajul: o iteratie:

x  5
cat timp x<10 executa
 scrie ‘o iteratie’
 x  x+1
฀

Exemplul 2.5. Să se determine cel mai mare divizor comun a două numere întregi folosind
algoritmul lui Euclid.

Aanaliza problemei.
Algoritmul lui Euclid a fost prezentat anterior. Se vor utiliza două variabile de intrare,
m şi n, reprezentând iniţial cele două numere. În timpul operaţiilor repetate de determinare a
câtului, m reprezintă deîmpârţitul, n împărţitorul, iar r restul împărţirii. După fiecare iteraţie,
se vor efectua atribuirrile: mn, nr, pentru reiniţializarea variabilelor la următoarea
iteraţie. Rezultatul problemei va fi memorat în variabila n, care stochează ultimul rest nenul.

Descrierea algoritmului.

start
citeste m, n
cat timp m mod n  0 executa
 r  m mod n //se determina restul
 m  n
 n  r
฀
scrie n
sfarsit

În algoritmul precedent s-a folosit un comentariu pentru indicarea instrucţiunii care


calculează restul împărţirii lui m la n.

Instrucţiunea repetitivă cu test final se deosebeşte de precedenta instrucţiune iterativă prin


momentul când are loc testul de sfârşit al execuţiei instrucţiunii: întâi se execută secvenţa
internă de instrucţiuni, după aceea testându-se expresia logică:

repeta
secventa
cat timp expresie

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

O altă deosebire faţă de instrucţiunea precedentă constă în faptul că în cazul instrucţiunii


repretitive cu test final, secvenţa internă de instrucţiuni se execută cel puţin o dată, indiferent
de valoarea iniţială a expresiei logice.

Exemplul 2.6. Se consideră un şir de numere terminat cu numărul zero. Să se determine câte
numere pozitive sunt în şir.

Analiza problemei.
Se va utiliza o variabilă de intrare, notată cu x, prin intermediul căreia se vor citi
valorile din şir. Variabila de ieşire, notată cu np, va memora numărul de numere pozitive din
şir. Iniţial np va fi iniţializată la zero; de fiecare dată când se citeşte un număr, se compară
acesta cu zero: dacă numărul curent este pozitiv, variabila np va fi incrementată cu 1.
Iteraţiile se termină când se citeşte o valoare zero.

Descrierea algoritmului.

start
np  0
repeta
citeste x
daca x>0 atunci
 np  np+1
฀
cat timp x0
scrie np
sfarsit

În cazul precedentelor două instrucţiuni repetitive, numărul de iteraţii este greu de estimat în
faza de proiectare a algoritmului. Sunt însă situaţii în care acesta poate fi estimat relativ uşor.
În aceste cazuri este probabil preferabilă utilizarea instrucţiunii repetitive cu număr
cunoscut de iteraţii.
De data aceasta gestionarea numărului de iteraţii se realizează cu ajutorul unei
variabile numite variabila de control a instrucţiunii. Aceasta va primi în timpul execuţiei
instrucţiunii repetitive valori succesive dintr-un şir de valori monoton, mărginit de două
valori distincte numite valoare iniţială, respectiv valoare finală. Valoarea iniţială este chiar
prima valoare din sir, pe când valoarea finală este doar o margine a şirului de valori (margine
superioară în cazul unui şir crescător, sau margine inferioară în cazul unui şir descrescător).
Şirul valorilor variabilei de control are proprietatea că diferenţa între oricare două
valori consecutive este constantă. Această constantă se numeşte pas de incrementare. Astfel,
şirul valorilor unei variabile de control se poate determina dacă se cunosc valoarea iniţială,
limita finală şi pasul de incrementare.

Notând cu vi, vf şi p valoarea iniţială, limita finală, respectiv pasul de incrementare, iată
câteva exemple de şiruri de valori pentru variabila v:
a) vi=2, vf=9, p=2  v{2, 4, 6, 8}
b) vi=9, vf=2, p=-2  v{9, 7, 5, 3}
c) vi=2, vf=2, p=3  v{2}
d) vi=2, vf=9, p=0  v{2, 2, 2, ...}
Se observă faptul că între valoarea iniţială vi, limita finală vf şi pasul de incrementare p
trebuie să existe anumite relaţii:

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

- dacă vi<vf, atunci trebuie ca p>0;


- dacă vi>vf, atunci trebuie ca p<0;
- dacă vi=vf, atunci indiferent de valoarea lui p, şirul are o singură valoare;
- dacă p=0, atunci şirul valorilor este infinit; acesta este un caz nedorit, care generează
o buclă infinită.

Sintaxa acestei instrucţiuni este următoarea:

pentru variabila  expresie1 la expresie [pas expresie] executa


 secventa
฀

unde:
- variabila reprezintă numele unei unei variabile din algoritm, care este variabila
de control a instrucţiunii repetitive;
- expresie1, expresie2 şi expresie3 sunt trei expresii compatibile cu
tipul variabilei de control a căror valoare reprezintă: valoarea iniţială, valoarea finală,
respectiv pasul de incrementare.

Observaţie. Parantezele drepte nu fac parte din sintaxa instrucţiunii, ci din cea a limbajului
de descriere: între paranteze drepte se specifică acele construcţii sintactice opţionale. În cazul
în care într-o instrucţiune, pasul de incrementare nu este specificat, el are valoarea implicită
1.

De exemplu, următoarele instrucţiuni afişează următoarele valori:


pentru i1 la 10 executa
 scrie i
฀
afişează valorile: 1, 2, 3, 4, 5
pentru i1 la 10 pas 2 executa
 scrie i
฀
afişează valorile: 1, 3, 5, 7, 9
pentru i10 la 1 pas -2 executa
 scrie i
฀
afişează valorile: 10, 8, 6, 4, 2.

Exemplul 2.7. Să se determine suma cuburilor primelor n numere naturale.

Analiza problemei.
Va trebui calculată suma:
n
S=13+23+ ... +n3=  k 3
k 1
Pentru calculul lui S se va utiliza o relaţie de recurenţă. Vom nota cu Si suma cuburilor
primelor i numere naturale:
Si=13+23+ ... +i3.
Definim relaţia astfel:
(1) Si=Si-1+i3, pentru i>0,

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

S0=0.
Se observă astfel că Sn=S, suma ce trebuie determinată.
Se va utiliza proprietatea instrucţiunii de atribuire, în care o variabilă poate apare în ambele
părţi ale operatorului de atribuire, astfel încât instrucţiunea:
S  S + i3,
reprezintă chiar relaţia (1) la iteraţia I.
Folosind această observaţie, se va utiliza variabila S pentru stocarea valorilor Si la diferitele
iteraţii (adică va memora pe rând valorile S0, S1, ..., Sn). Variabila va fi iniţializată cu
valoarea 0, iar după ultima iteraţie va memora chiar valoarea dorită.

Descrierea algoritmului.

start
citeste n
s  0
pentru k1 la n executa
 s  s+k3
฀
scrie s
sfarsit

2.3 Metoda rafinărilor succesive

În cazul problememor complexe este dificilă descrierea rezolvărilor acestora direct, folosind
doar instrucţiuni executabile ale limbajului algoritmic. În mod uzual, problema iniţială va
trebui descompusă într-un amumit număr de subprobleme, a căror rezolvare trebuie descrisă
separat.
O metodă des utilizată în acest caz este metoda rafinărilor succesive. În cadrul
acesteia se face distincţie între enunţarea unei subprobleme şi descrierea rezolvării ei. Pentru
a specifica o anumită subproblemă în cadrul unui algoritm, limbajul algoritmic trebuie extins
cu o nouă clasă de propoziţii, numite propoziţii nestandard. Acestea sunt specificate în
limbajul natural şi încadrate între două caractere ‘*’. Descrierea rezolvării unei subprobleme
asociate unei propoziţii nestandard se numeşte rafinarea propoziţiei; rafinarea propoziţiilor
nestandard se va face după descrierea algoritmului principal al problemei iniţiale.

Exemplul 2.8. Să se calculeze madia aritmetică a unui sir de numere.

Analiza problemei.
În cadrul acestei probleme (simple şi a cărei rezolvare nu necesită descompunerea în
subprobleme) se pot pune în evidenţă două subprobleme: citirea şirului de numere şi
determinarea mediei aritmetice. Principalele variabile folosite în algoritm sunt:
- n, care specifică numărul de elemente din şir,
- x, care reprezintă un vector de numere cu componentele: x1, x2, ..., xn,
- medie, care reprezintă madia aritmetică a sirului de numere.

Descrierea algoritmului.
Algoritmul principal se poate descrie astfel:

start

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

citeste n
* citirea sirului de numere x1, x2, ..., xn *
* calculul mediei aritmetice:medie=(x1+ x2+ ...+ xn)/n *
scrie med
sfarsit

Urmează rafinările celor două propoziţii nestandard:

* citirea sirului de numere x1, x2, ..., xn *


pentru i  1 la n executa
 citeste xi
฀
Sfarsit

* calculul mediei aritmetice:medie=(x1+ x2+ ...+ xn)/n *


s  0
pentru i  1 la n executa
 s  s+xi
฀
medie  s/n
sfarsit

Se observă faptul că rafinarea unei propoziţii nestandard conţine trei elemente: enunţul
propoziţiei, secvenţa de instrucţiuni ce formează descrierea rezolvării problemei aferente si
cuvăntul cheie sfarsit, care are rolul de a delimita rafinarea propoziţiei curente.
În cazul în care anumite subprobleme sunt de asemenea complexe, procesul de
împărţire în subprobleme poate continua. Rezultă astfel o descriere a algoritmului pe nivele:
- pe nivelul 0 se află algoritmul principal al problemei;
- pe nivelul 1 se află refinările propoziţiilor nestandard de pe nivelul 0;
- în general, pe nivelul k se află refinările propoziţiilor nestandard de pe nivelul k-1.
Operaţia de rafinare succesivă continuă până la un nivel în care rafinările tuturor propoziţiilor
conţin doar instrucţiuni standard ale limbajului algoritmic.

Exemplul 2.9. Dându-se un număr natural k şi o matrice pătrată A de dimensiune nn, să se


determine matricea B=Ak.

Analiza problemei.
Conform definiţiei puterii unei matrici:
A0=I, Ak=Ak-1*A, pentru k>0,
se poate descrie algoritmul de rezolvare după şablonul problemei redusă la numere reale:
Dându-se un număr natural k şi un număr real a, să se determine numărul b=ak.
Un algoritm pentru acesta este:

start
citeste k
citeste a
b  1
pentru p  1 la k executa
 c  b*a
 b  c
฀

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

scrie b
sfarsit

Descrierea algoritmului.
Subproblemele puse în evidenţă corespund celor citirii matricii A şi scrierii matricii B,
instrucţiunii de atribuire, precum şi intrucţiunii repetitive. Nivelul 0 este:

start
citeste k
* citeste matricea A *
* atribuie mtricial B  I *
* determina matricea: B=Ak *
* scrie matricea B *
sfarsit

Nivelul 1 conţine rafinările propoziţiilor de pe nivelul 0:

* citeste matricea A *
pentru i  1 la n executa
 pentru j  1 la n executa
  citeste aij
 ฀
฀
sfarsit

* atribuie mtricial B  I *
pentru i  1 la n executa
 pentru j  1 la n executa
  daca i=j atunci
   bij  1
  altfel
   bij  0
  ฀
 ฀
฀
sfarsit

* determina matricea: B=Ak *


pentru p  1 la k executa
 * determina matricea: C = B*A *
 * atribuie matricial: B  C *
฀
sfarsit

* scrie matricea B *
pentru i  1 la n executa
 pentru j  1 la n executa
  scrie bij
 ฀
฀
sfarsit

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

Întrucât pe nivelul 1 există în continuare douaă propoziţii nestandard, algoritmul va conţine şi


nivelul 2:

* determina matricea C=B*A *


pentru i  1 la n executa
 pentru j  1 la n executa
  cij  0
  pentru s  1 la n executa
   cij  cij+aik*bkj
  ฀
 ฀
฀
sfarsit

* atribuie matricial: B  C *
pentru i  1 la n executa
 pentru j  1 la n executa
  scrie bij  cij
 ฀
฀
sfarsit

Execuţia algoritmilor descrişi prin metoda rafinarilor succesive nu este directă. Înainte de
execuţia propriu-zisă, va trebui ca un asemenea algoritm să fie transformat într-un algoritm
echivalent din punct de vedere paragmatic, dar care nu contine decât instrucţiuni standard ale
limbajului. Notând cu n numărul nivelulu maxim, operaţia de transformare a algoritmului se
poate descrie astfel:

pentru k  n-1 la 0 pas -1 executa


 pentru *fiecare rafinare r de pe nivelul k* executa
  pentru *fiecare propozitie nestandard p din rafinarea r* executa
   *inlocuieste propozitia p cu rafinarea sa de pe nivelul k+1*
  ฀
 ฀
฀

Cu alte cuvinte, începând de la penultimul nivel, se vor substitui toate propoziţiile nestandard
cu rafinările lor aflate pe nivelul imediat următor. Se asigură în acest mod apariţia doar a
instrucţiunilor standard ale limbajului.
În exemplul anterior, se vor substitui întâi propoziţiile nestandard: *determina
matricea:C=B*A* şi *atribuie matricial:BC* în propoziţia *determina matricea:B=Ak *.
La pasul următor se vor substitui cele patru propoziţii nestandard din algoritmul principal cu
rafinările lor, rezultând un algoritm direct executabil:

start
citeste k
pentru i  1 la n executa
 pentru j  1 la n executa
  citeste aij
 ฀
฀

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

pentru i  1 la n executa
 pentru j  1 la n executa
  daca i=j atunci
   bij  1
  altfel
   bij  0
  ฀
 ฀
฀
pentru p  1 la k executa
 pentru i  1 la n executa
  pentru j  1 la n executa
   cij  0
   pentru s  1 la n executa
    cij  cij+aik*bkj
   ฀
  ฀
 ฀
 pentru i  1 la n executa
  pentru j  1 la n executa
   cij  bij
  ฀
 ฀
฀
pentru i  1 la n executa
 pentru j  1 la n executa
  scrie bij
 ฀
฀
sfarsit

Metoda rafinărilor succesive se mai numeşte metoda top-down de proiectare a algoritmilor


(de sus în jos).

2. 4 Funcţii şi proceduri în limbajul algoritmic

Prncipalul dezavantaj al metodei rafinărilor succesive se referă la execuţia algoritmilor. Deşi


există o mare flexibilitate în ceea ce priveşte descrierea algoritmilor complecşi, execuţia unui
algoritm descris prin metoda rafinărilor succesive presupune operaţii repetate de modificare a
algoritmului iniţial prin substituirea propoziţiilor nestandard cu rafinările lor, până când
acesta ajunge să conţină doar instrucţiuni care pot fi executate direct.
O variantă des utilizată, atât în cazul folosirii limbajului algoritmic, cât mai ales în
cazul codificării algoritmilor în limbaje de programare, o constituie utilizarea funcţiilor şi
procedurilor. Procedurile şi funcţiile permit descrierea unor clase de subprobleme, având
însă un caracter mai mare de generalitate decât propoziţiile nestandard. Spre deosebire de
propoziţile nestandard, care sunt legate strict de descrierea unui anumit algoritm, funcţiile si
procedurile pot fi independente de algoritmii în care se folosesc, comunicarea cu algoritmii
făcându-se prin intermediul unor parametri formali.

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

Exemplul 2.10. Pentru exemplificare, se va relua problema determinării mediei aritmetice a


unui şir de numere reale. Subproblemele puse în evidenţă constau în citirea elementelor
şirului şi determinarea mediei aritmetice. Pentru prima subproblemă se va folosi o procedură,
numită CitireElementeSir, , iar pentru a doua se va folosi o funcţie numită
CalculMedieAritmetica, care va determina o valoare reprezentând media aritmetică a
valorilor elementelor şirului.

start
citeste n
CitireElementeSir(n,x)
medie  CalculMedieAritmetica(n,x)
scrie medie
sfarsit

Definirea procedurii CitireElementeSir presupune specificarea operaţiilor de citire a tuturor


celor n valori ale elementelor şirului:

procedura CitireElementeSir(intrare nr, iesire v)


pentru i 1 la nr executa
 citeste vi
฀
sfarsit

Funcţia CalculMedieAritmetica determină întâi suma valorilor elementelor şirului şi o


împarte la numărul elementelor:

functia CalculMedieAritmetica(intrare nr, v)


s  0
pentru i  1 la nr executa
 s  s+vi
฀
returneaza s/nr
sfarsit

Descrierea algortimului în forma prezentată mai sus are avantajul execuţiei directe a acestuia
prin apelul procedurii CitireElementeSir şi a funcţiei CalculMedieAritmetica.
Deosebirea între funcţii şi proceduri se referă la rezultatul determinat de acestea.
Funcţiile sunt folosite în cazul în care subprobleme aferente au drept scop principal
determinarea unei valori simple, pe când procedurile au drept scop principal efectuarea
anumitor operaţii. Distincţia între acestea nu este însă foarte clară, pentru că şi funcţiile pot
avea mai multe mărimi de ieşire transmise prin parametri.

Se observă dublul avantaj al folosirii funcţiilor şi procedurilor:


a) descrierea subproblememelor folosind un înalt grad de generalitate;
b) modul simplu de execuţie al algoritmilor, întrucât funcţiile şi procedurile reprezintă
elemente executabile şi care pot fi apelate.
Din acest motiv, se va analiza distinct atât operaţia de definire a funcţiilor şi procedurilor,
precum şi operaţia de apel a acestora.

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

2.4.1 Definirea funcţiilor şi procedurilor

Se observă din exemplul anterior că definirea unei funcţii sau a unei proceduri presupune
specificarea a două elemente distincte: antetul şi corpul funcţiei sau procedurii. Antetul
defineşte elementele de interacţiune ale funcţiei/procedurii cu exteriorul, pe când corpul
specifică acţiunile care trebuie îndeplinite pentru rezolvarea subproblemei asociate.
Specificarea terminării descrierii funcţiei/procedurii se face prin intermediul cuvântului cheie
sfârşit.

Sintaxa de definire a unei funcţii şi a unei proceduri este:

functia identificator ( [parametri formali] )


secventa instructiuni
sfarsit

procedura identificator ( [parametri formali] )


secventa instructiuni
sfarsit

Observaţie. Caracterele ‘[‘ şi ‘]’ nu fac parte din sintaxa limbajului algoritmic, ci din cea a
limbajului de descriere. Între două paranteze drepte se specifică în mod uzual o categorie
sintactică opţională (care poate sau nu să apară îmtr-un algoritm).

Antetul unei funcţii sau proceduri conţine un cuvânt cheie specificând tipul acesteia (funcţie
sau procedură), un identificator reprezentând numele asociat ei, precum şi parametrii formali
ai acesteia.
Parametri formali ai unei funcţii sau proceduri sunt opţionali şi reprezintă modul prin
care funcţia/procedura interacţionează cu exteriorul, specificând mărimile de intrare şi de
ieşire. O funcţie sau o procedură fiind de fapt un algoritm ce descrie modul de rezolvare al
unei subprobleme, ea poate primi la intrare valorile care sunt necesare pentru execuţia
algoritmului (care sunt parametri formali de intrare ai funcţiei/procedurii respective) şi
trebuie să determine mărimile de ieşire ale acesteia (care sunt parametri formali de ieşire).
Aceşti parametri pot fi consideraţi drept variabile locale funcţiei/procedurii, care nu au
semnificaţie în afara corpului acesteia.
Specificarea parametrilor de intrare se face cu ajutorul cuvântului cheie intrare,
iar a celor de ieşire cu ajutorul cuvântului cheie ieşire. În exemplul anterior parametrul nr
(specificând numărul de elemente al şirului) reprezintă un parametru de intrare atât în cazul
funcţiei cât şi al procedurii, iar v (specificând vectorul ce conţine elementele şirului) este un
parametru de ieşire în cazul procedurii şi unul de intrare în cazul funcţiei.

Observaţie. Nu există o distincţie formală între subproblemele a căror rezolvare se descrie cu


ajutorul funcţiilor şi cele care se descriu cu ajutorul procedurilor, acest lucru rămânând la
latitudinea programatorului. O regulă care se poate folosi sugerează că funcţiile se pot folosi
pentru acele subprobleme a căror scop este determinarea unor mărimi simple scalare.

Corpul funcţiilor şi procedurilor conţine o secvenţă de instrucţiuni care descriu rezolvarea


subproblemei aferente. Există o instrucţiune care se poate utiliza în carpul corpurilor
funcţiilor/procedurilor, dar nu se poate utiliza într-un algoritm principal, numită instrucţiune
de întoarcere, a cărei sintaxă este:

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

returneaza [expresie]

unde returnează este un cuvânt cheie, specificând locul unde execuţia procedurii sau a
funcţiei se încheie, revenindu-se în algoritmul care a apelat-o. Categoria sintactică
expresie reprezintă o expresie opţională, folosită doar în cadrul funcţiilor. În acest caz,
valoarea expresisei reprezintă chiar valoarea pe care funcţia respectivă trebuie să o determine
şi care trebuie returnată algoritmului apelant. În cazul în care expresia lipseşte, instrucţiunea
se utilizează în corpul procedurilor, în caz contrar ea utilizându-se în corpul funcţiilor. În
exemplul anterior, instrucţiunea de întoarcere este folosită doar în cadrul funcţiei
CalculMedieAritmetica, expresia s/nr reprezentând media aritmetică pe care funcţia trebuie
să o calculeze.

Observaţie. În corpul unei proceduri instrucţiunea de întoarcere este opţională; în cazul în


care instrucţiunea de întoarcere lipseşte, execuţie procedurii se termină după execuţia ultimei
instrucţiuni din corpul ei. În corpul unei funcţii trebuie să existe cel puţin o instrucţiune de
întoarcere, pentru că o funcţie întotdeauna returnează o valoare.

Operaţia de definire a funcţiilor şi procedurilor reprezintă componenta declarativă a


subproblemelor descrise, pe când execuţia lor reprezintă o componentă pragmatică,
specificând momentul şi modul de execuţia a acestora.

2.4.2 Apelul şi execuţia funcţiilor şi procedurilor

În cazul în care se folosesc funcţii sau proceduri pentru descrierea unui algoritm, trebuie
realizate două operaţii distincte: definirea funcţiilor şi/sau procedurilor folosite, precum şi
apelul acestora în cadrul algoritmului. Din punct de vedere sintactic, apelul indică numele
funcţiei/procedurii apelate, precum şi parametrii de apel, specificaţi între paranteze rotunde:

identificator ([lista parametri de apel])

În exemplul precedent, parametrii de apel în ambele cazuri au fost variabilele n şi x.

Observaţie. Există o deosebire importantă între apelul unei funcţii şi apelul unei proceduri:
apelul unei funcţii se poate face doar în cadrul unor expresii, în acele locuri din algoritm unde
este permisă utilizarea unor expresii (de exemplu, în cadrul instrucţiunilor de atribuire), pe
când apelul unei proceduri este de sine stătător, fiind considerat ca o instrucţiune distinctă,
numită instrucţiunea de apel de procedură.

Parametri de apel se mai numesc parametri actuali, iar împreună cu parametrii formali ai
funcţiei/procedurii apelate formează suportul pentru mecanismul de transfer a informaţiei
între procedura/funcţia apelată şi algoritmul apelant. Între parametri formali şi parametri
actuali trebuie să existe anumite concordanţe:
a) numărul parametrilor acuali şi al parametrilor formali trebuie să fie acelaşi;
b) tipul de date al fiecărui parametru actual trebuie să corespundă tipului de date al
parametrului formal de pe aceiaşi poziţie (în exempul precedent, parametrul actual n
este un întreg şi corespunde parametrului formal nr, iar parametrul actual x este un
vector de numere reale care corespunde parametrului formal v).

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

Apelul unei funcţii sau proceduri presupune efectuarea mai multor etape:
1) suspendarea execuţiei elgoritmului apelant în locul apelului respectiv;
2) transferul informaţiei dinspre algoritmul apelant spre procedura/funcţia apelată;
3) execuţia funcţiei/prodedurii apenate;
4) transferul informaţiei dinspre funcţia/procedura apelată spre algoritmul apelant;
5) reluarea execuţiei algoritmului apelant din locul imediat următor apelului.

Execuţia funcţiei/procedurii apelate se realizează secvenţial începând cu prima instrucţiune


din corpul acesteia. Execuţia se termină fie la întâlnirea primei instrucţiuni de întoarcere, iar
dacă aceasta nu există (în cazul procedurilor), după ultima instrucţiune.

Exemplul 2.11 Considerându-se un şir de numere reale, să se determine poziţia primului


element negativ din şir. Se va folosi o funcţie care primeşte ca parametri de intrare numărul
de elemente precun şi vectorul elementelor. Funcţia va returna poziţia primului elment
negativ din şir, iar în cazul în care şirul nu conţine elemente negative, se va returna numărul
0.

start
citeste n
CitireElementeSir(n,x)
k  DeterminaPozitia(n,x)
daca k > 0 atunci
 scrie k
altfel
 scrie ‘Nu sunt elemete negative’
฀
sfarsit

functia DeterminaPozitia(intrare dim, v)


pentru i  1 la dim executa
 daca vi < 0 atunci
  returneaza i
 ฀
฀
returneaza 0
sfarsit

Funcţia CitireElementeSir a fost definită anterior, în exemplul 2.10. Execuţia funcţiei


DeterminaPozitia se încheie când se întîlneşte primul element negativ din şir, intrucţiunea
repretitivă cu număr cunoscut de iteraţii încheindu-se forţat în acest caz (aceasta este ieşirea
normală din funcţie). Dacă după parcurgerea tuturor elementelor şirului nu s-a determinat
nici unul cu valoare negativă, execuţia funcţiei ajunge la intrucţiunea: returneaza 0, care
reprezintă a doua variantă de terminare a funcţiei.
Transferul informaţiei între algoritmul apelant şi funcţia sau procedura apelată se
realizează ptin intermediul parametrilor actuali şi a celor formali. Parametri formali de
intrare se comportă asemenea unor variabile locale, care la începutul execuţiei
funcţiei/procedurii sunt iniţializate cu mărimile de intrare ale acesteia. Din acest motiv,
parametri actuali corespunzători parametrilor formali de intrare trebuie să fie expresii care se
pot evalua, valorile rezultate după evaluare reprezentând mărimile de intrare ale
funcţiei/procedurii apelate.

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

Etapa a doua din cadrul unui apel realizează următoarele operaţii:


a) evaluarea expresiilor (în cadrul algoritmului apelant) reprezentând parametri actuali ai
funcţiei/procedurii apelate;
b) iniţializarea parametrilor formali din cadrul funcţiei/procedurii apelate cu valorile
rezulate la pasul a).

La începutul execuţiei funcţiei DeterminaPozitia din exemplul 2, parametrul formal dim se


iniţializează la valoarea variabilei n din algoritmul principal.
După execuţia funcţiei/procedurii apelate, trebuie realizat trensferul invers al
informaţiei, dinspre funcţie/procedură spre algoritmul apelant: valorile parametrilor formali
de ieşire se vor transmite spre parametri actuali corespunzători din algoritmul apelant. Pentru
aceasta, parametrii actuali corespunzători parametrilor formali de ieşire trebuie să fie
variabile: în acest mod, variabilele ce reprezintă parametri actuali pot fi asignate cu valorile
de ieşire corespunzătoare ale funcţiei/procedurii apelate.

Acesată etapă din cadrul unui apel realizează următoarele operaţii:


a) determinarea valorilor parametrilor formali din cadrul funcţiei/procedurii apelate;
b) asignarea variabilelor reprezentând parametrii actuali corespunzători parametrilor
formali de ieşire cu valorile rezulate anterior.

În cadrul procedurii de citire a elementelor unui şir de numere din exemplul 1, după execuţia
procedurii, valoarea parametrului de ieşire v (reprezentând un vector de numere) este
transmisă variabilei x din algoritmului principal.
În cazul apelului unei funcţii există o etapă suplimentară la execuţia acesteia. În acest
caz, numele unei funcţii reprezintă el însuşi un parametru de ieşire, iar după execuţia funcţiei
această valoare trebuie transmisă spre exterior. Modalitatea de transfer este asemănătoare
evaluării expresiilor algebrice: după transferul parametrilor de ieşire spre algoritmul apelant,
apelul funcţiei din cadrul expresiei apelante se înlocuieşte cu valoarea returnată de aceasta.

De exemplu, în cadrul instrucţiunii de atribuire din algoritmul din exemplul 2.11:


k  DeterminaPozitia(n,x)
expresia din partea dreaptă a operatorului de atribuire conţine doar un apel de funcţie, iar
evaluarea expresiei se reduce la înlocuirea apelului: DeterminaPozitia(n,x) cu
valoarea returnată de execuţia funcţiei respective.

Există cazuri în care pentru o anumită funcţie sau procedură, anumiţi pararmetri pot fi atât de
intrare cât şi de ieşire, în sensul că la începutul execuţiei funcţiei/procedurii intră cu anumite
valori, iar la sfârşitul execuţiei se întorc în algoritmul apelant cu valorile modificate. Aceştia
formează o categorie aparte: parametri de intrare şi ieşire, specificaţi de cuvântul cheie
intrare-iesire. Ei se comportă la fel cu parametrii de intrare la etapa a doua a apelului
şi la fel cu parametrii de ieşire la etapa a patra a apelului. Exemplul următor utilizează
parametri de intrare-ieşire.

Exemplul 2.12 Să se determine derivata de ordinul k a unui polinom.

Analiza problemei.
Fie polinomul:
P = a0 + a1X + ... + anXn,
care va fi specificat prin gradul său şi vectorul coeficienţilor.

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

Pentru a determina polinomul de ieşire:


Q = b0 + b1X + ... + bmXm, unde m=n-k,
se va repeta de k ori operaţia de derivare a polinomului iniţial, la fiecare derivare gradul
polinomului scăzând cu 1.
Să considerăm prima derivată a polinomului P:
D = d0 + d1X + ... + dn-1Xn-1, unde:
d0=a1, d1=2*a2, ..., dn-1=n*an. Se observă faptul că în momentul calculului coeficientului dk,
valorile coeficienţilor a0, ..., ak nu mai sunt necesare. Această observaţie permite o economie
de variabie: utilizarea vectorului (a0, ..., an-1) în locul vectorului (d0, ..., dn-1). Cu alte cuvinte
se vor determina valorile:
a0=a1, a1=2*a2, ..., an-1=n*an.

Descrierea algoritmului.
Algoritmul următor apelează de k ori procedura DerivataPolinom; ambii parametri
formali, dim şi a sunt parametri de intrare-ieşire.

start
citeste n, k
CitesteCoeficienti(n,a)
pentru i  1 la k executa
 DerivataPolinom(n,a)
฀
ScrieCoeficienti(n,a)
sfarsit

procedura CitesteCoeficienti(intrare dim, iesire a)


pentru i  0 la dim executa
 citeste ai
฀
sfarsit

procedura ScrieCoeficienti(intrare dim, a)


pentru i  0 la dim executa
 scrie ai
฀
sfarsit

procedura DerivataPolinom(intrare-iesire dim, a)


pentru i  0 la dim-1 executa
 ai  (i+1)*ai+1
฀
dim  dim-1
sfarsit

În cazul în care o funcţie sau o procedură are mai multe tipuri de parametri formali, în mod
uzual se declară întâi parametrii de intrare, apoi parametrii de intrare-ieşire şi parametrii de
ieşire.

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

2.5 Analiza algoritmilor

Analiza algoritmilor este o operaţie importantă în programarea calculatoarelor, deoarece


pentru anumite aplicaţii particulare există mai mulţi algoritmi disponibili şi trebuie
determinaţi algoritmii care sunt mai performanţi.
În mod uzual, performanța algoritmilor este dată de complexitatea acestora. Din acest
motiv, analiza complexitătii unui algoritm are ca scop estimarea volumului de resurse de
calcul necesare pentru execuția algoritmului. Prin resurse vom înțelege:
 Volumul de memorie necesar pentru stocarea datelor pe care le prelucrează
algoritmul
 Timpul necesar pentru execuția tuturor prelucrărilor specificate în algoritm
În mod uzual, un algoritm A este mai performat decât alt algoritm B, dacă volumul de resurse
necesar execuţiei lui A este mai mic decât cel al execuţiei lui B.
În general, volumul resurselor necesare execuției unui algoritm depinde de
dimensiunea problemei de rezolvat. Aceasta este determinată, in general, de:
 Volumul datelor de intrare
 Modul de reprezentare al datelor
Volumul datelor de intrare nu influențează în mod diferit, diferiți algoritmi care rezolvă
aceeași problemă. De exemplu: toți algoritmii care determină valoarea minimă a unui șir de
numere , vor avea același volum de date de intrare, dat de numărul elementelor șirului.
Însă modul de reprezentare al datelor în cadrul algoritmilor poate diferenția
algoritmii. De exemplu: reprezentarea internă a unei matrici rare poate fi făcută în cadrul
unui algoritm:
1. Alocând spațiu de memorie pentru toate elementele matricii
2. Alocând spațiu de memorie doar pentru elementele nenule
În primul caz, algoritmul este mai ineficient decât în al doilea caz, deoarece memorează mai
multe informații (memorează în plus toate elementele nule ale matricii), pe când în cazul al
doilea se vor memora doar elementele nenule (împreună cu indicii corespunzători acestora).
Dintre cele două resurse de calcul (spațiu și timp), resursa critică pentru evaluarea
complexității unui algoritm este cea a timpului de execuție. În continuare vom disuta doar
problema estimării timpului de execuție al unui algoritm. Acesta depinde de mărimile de
intrare. De exemplu:
 T(n) reprezintă timpul de execuție al unui algoritm care are n ca mărime de intrare,
 T(n, m) reprezintă timpul de execuție al unui algoritm care are n și m ca mărimi de
intrare.

Estimarea timpului de execuție al unui algoritm se face pe baza unor presupuneri, care
definesc un model de calcul și o unitate de măsură:
 Prelucrările din algoritmi se efectuează în mod secvențial (mașina de tip von Newman
este baza sistemelor de calcul actuale)
 Operațiile elementare sunt efectuate în timp constant, indiferent de valoarea
operanzilor
 Timpul de acces la informațiile din algoritm nu depind de poziția acestora (nu există
diferențe între prelucrarea diferitelor elemente dintr-un tablou)

În concluzie, timpul de execuție al unui algoritm se exprimă în numărul de operații


elemenate pe care algoritmul le execută. Sunt considerate operații elementare:
 Instrucțiunile simple de atribuire

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

 Evaluarea expresiilor logice sau de relatie din cadrul instrucțiunilor de decizie sau
repetitive
 Evaluarea expresiilor aritmetice din cadrul instrucțiunii repetitive cu număr cunoscut
de pași
Considerând că toate operațiile elementare au același cost de execuție (presupus, în general,
egal cu 1), timpul de execuție se obține prin însumarea costurilor prelucrărilor din algoritm.

Să exemplificăm operaţia de analiză pe următorul algoritm tipic:

Exemplul 2.13 Să se determine valoarea maximă a unui şir de numere, precum şi poziţia din
şir a valorii maxime. În cazul în care sunt mai multe valori maxime, să se determine ultima
valoare. Descrierea formală este următoarea:
Dându-se n elemente, x1, x2, ..., xn, să se determine m şi j astfel încât:
m=xj=max(x1, x2, ..., xn),
pentru care j este cel mai mare posibil.
Analiza problemei.
Se vor utiliza următoarele variabile de ieşire:
- m, pentru memorarea valorii maxime până la valoarea curentă care se testează;
- j, pentru memorarea indicelui valorii maxime.
Iniţial, valoarea maximă se consideră x1. Se vor parcurge pe rând elementele şirului de
numere; dacă elementul curent xi este mai mare decât valoarea maximă curentă, acesta va
deveni noua valoare maximă.

Descrierea algoritmului.

start
1 citeste n
2 pentru k  1 la n executa
2.1  citeste xk
฀
3 m  x1
4 j  1
5 pentru k  2 la n executa
5.1  daca xk>m atunci
5.1.1   m  xk
5.1.2   j  k
 ฀
฀
6 scrie m,j
sfarsit

Pentru a putea fi identificate, s-au notat instrucţiunile cu numere. Instrucţiunile interne unor
instrucţiuni compuse s-au notat cu mai multe numere. De exemplu, instrucţiunea 5.1 este
instrucţiunea de decizie internă instrucţiunii repetitive 5. În general, numărul de numere cu
care este etichetată o instrucţiune indică nivelul de indentare al acesteia (nivelul de
includere).

Analiza algoritmului.

A. Timpul de execuţie

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

Pentru analiza algoritmului, trebuie precizate câteva elemente privind timpul de execuţie al
instrucţiunilor limbajului algoritmic:
a) toate instrucţiunile simple au un timp egal de execuţie (presupus egal cu 1);
b) timpul de execuţie al instrucţiunii de decizie este egal cu timpul de execuţie al uneia
dintre secvenţele interne de instrucţiuni (acea care se va executa) plus timpul de
evaluare al expresiei logice (presupus egal cu 1);
c) timpul de execuţie al instrucţiunilor repetitive cu test iniţial şi final se calculează după
următoarea formulă:
t = n*(t1+1) ,
unde t1 reprezintă timpul de execuţie al instrucţiunilor din secvenţa internă, n numărul
de iteraţii al instrucţiunii; constanta 1 provine de la evaluarea expresiei logice la
fiecare iteraţie;
d) timpul de execuţie al instrucţiunii repetitive cu număr cunoscut de iteraţii se
calculează după următoarea formulă:
t = 1+n*(t1+2) ,
unde t1 reprezintă timpul de execuţie al instrucţiunilor din secvenţa internă, n numărul
de iteraţii al instrucţiunii; constanta 2 provine de la operaţia de determinare a valorii
curente a variabilei de control a instrucţiunii şi de la evaluarea expresiei logice la
fiecare iteraţie, iar constanta 1 de la operaţia de iniţializare a variabilei de control.

Se observă faptul că pentru determinarea timpului de execuţie al unei instrucţiuni compuse,


este necesar să se determine timpul de execuţie al unei secvenţe de instrucţiuni. Acesta este
egal cu suma timpilor de execuţie al instrucţiunilor ce compun secvenţa.

Se poate estima acum timpul de execuţie:


t = t1+t2+t3+t4+t5+t6,
unde:
t1 = t3 = t4 = t6 = 1,
t2 = 1+n*(t2.1+2) = 1+n*3, pentru că t2.1 = 1,
Rezultă:
t = 2+3*n+*t.
Estimarea timpului t depinde de estimarea timpului de execuţie a instrucţiunii 5.1. Aceasta
este o instrucţiune scurtă de decizie: din cele (n-1) apeluri ale sale, o parte execută
instrucţiunile 5.1.1 şi 5.1.2 (precum şi evaluarea expresiei logice), iar cealaltă doar evaluarea
expresiei logice. Notând cu a numărul de execuţii ale secvenţei interne, timpul de execuţie al
instrucțiunii 5 se poate scrie astfel:
t5 = 1 + 2*(n-1) + a*3 + (n-1-a)*1
Timpul total de execuție al algoritmului va fi:
t = 5+3*n+t5 = 3+6*n+2*a.
Singura valoare necunoscută este a, care reprezintă numărul de modificări ale valorii maxime
curente. Acest număr depinde de distribuţia valorilor din şir, deci de execuţia algoritmului şi
nu poate fi determinată exact în etapa de proiectare a acestuia.
În mod uzual, timpul de execuţie al unui algoritm nu poate fi determinat exact. Din
acest motiv, analiza unui algoritm presupune determinarea unuia dintre următorii timpi de
execuţie (sau mai mulţi dintre aceştia):
- timpul maxim de execuţie;
- timpul minim de execuţie;
- timpul mediu de execuţie.

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

În cazul algoritmului precedent, vor trebui determinate: valoarea minimă, valoarea maximă şi
cea media a lui a.

Valoarea minimă a lui a este zero. Aceasta se întâmplă când şirul este ordonat crescător:
x1<x2< ... <xn. În acest caz, timpul minim al algoritmului este:
tmin = 1+6*n.

Valoarea maximă este n-1, în czul în care sirul este ordonat descrecător: x1>x2> ... >xn. În
acest caz, timpul maxim al algoritmului este:
tmin = 1+8*n.

Valoarea medie a lui a este cuprinsă între 0 şi n-1, dar este mai greu de estimat. Pentru
determinarea valorii medii, vor trebui făcute anumite presupuneri asupra caracteristicilor
probabile pentru datele de intrare.
Pentru algoritmul precedent vom considera că elementele xk sunt distincte şi că
fiecare din cele n! permutări ale acestora sunt echiprobabile. Această presupunere este uzuală
pentru cele mai multe situaţii, dar analiza poate fi efectuată si pe baza altor presupuneri.
Pentru cazul particular n=3, de exemplu, presupunem că următoarele şase situaţii sunt
la fel de probabile (alăturat sunt specificate valorile lui a pentru cazul respectiv):
- x1<x2<x3, a=2;
- x1<x3<x2, a=1;
- x2<x1<x3, a=1;
- x2<x3<x1, a=1
- x3<x1<x2, a=0
- x3<x2<x1, a=0.
Valoarea medie a lui a pentru cazul n=3 este: (2+1+1+1+0+0)/6=5/6.
Se observă faptul că în cele şase situaţii contează doar ordinea relativă a numerelor,
ceea ce conduce la considerarea mulţimii indicilor elementelor în locul valorilor: 123, 132,
213, 231, 312, 321.
Folosind această observaţie, se poate defini probabilitatea ca a să aibă valoarea k
(notată cu pnk):
pnk = (numărul de permutări a n obiecte pentru care a=k) / (n!)

De exemplu, pentru cazul de mai sus: p32=1/6, p31=3/6=1/2, p30=2/6=1/3.


Valoarea medie a lui a se defineşte în mod uzual astfel:
n 1
(1) an = k * p
k 0
nk

Pentru determinarea lui an ar trebui determinate valorile probabilităţilor pnk, operaţie destul de
dificilă. O variantă constă în determinarea unei relaţii de recurenţă pentru probabilităţile pnk
şi utilizarea unei funcţii generatoare pentru aceste probabilităţi.

Determinarea unei relaţii de recurenţă se face pe baza următoarelor observaţii:


- se consideră permutările mulţimii x1, x2, ..., xn pe mulţimea {1, 2, ..., n};
- dacă xn=n, atunci valoarea lui a este cu unu mai mare decât valoarea obţinută
raportată la mulţimea x1, x2, ..., xn-1 (cazurile a şi c de mai sus);
- dacă xnn, atunci valoarea lui a este aceeaşi cu valoarea obţinută raportată la
mulţimea x1, x2, ..., xn-1 (cazurile b, d, e şi f de mai sus).
Considerând permutările mulţimii {x1, x2, ..., xn} pe mulţimea {1, 2, ..., n}, rezultă că
numărul total de cazuri în care ultimul element are valoarea i (adică xn = i) este ci = (n-1)!.

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

Deoarece c1 = c2 = ... =cn = (n-1)!, rezultă că:


- Probabilitatea ca xn să aiba valoarea n este
P(xn=n) = (n-1)! / n! = 1/n,
- Probabilitatea ca xn sa aiba o altă valoare decât n (adică 1, 2,..., sau n-1) este
P(xnn) = (n-1)*(n-1)! / n! = (n-1)/n,

Din aceste observații rezultă o relație de recutență pentru pnk:


(2) pnk = 1/n*p(n-1)k+(n-1)/n*p(n-1)(k-1)
În plus se pot determina valori iniţiale pentru acest şir de probabilităţi:
(3a) p1k = 0k (adică p10=1 şi p1k=0 pentru k0).
Alte valori limită sunt pentru cazul în care k<0 sau k>n:
(3b) pnk = 0, dacă k<0, sau dacă k>n.

Funcţiile generatoare sunt utilizate pentru a obţine informaţii despre cantităţile pnk.
Considerând prin extensie pnk=0 pentru k>n, conform relației (3b), se poate considera funcţia
generatoare ca o serie infinită:
(4) Gn(z) = pn0+pn1*z+pn2*z2+ ... = k(pnk*zk)
Folosind condiţiile (3a), se poate calcula G1(z):
G1(z) = p10+p11*z+ ... = p10 + 0 = 1.
Utilizând relaţiile de recurenţă (2), se poate determina şi o relaţie de recurenţă pentru funcţia
generatoare Gn:
(5) Gn(z) = k0(pnk*zk) = k0((1/n*p(n-1)k+(n-1)/n*p(n-1)(k-1)) * zk) =
= (1/n)*k0(p(n-1)k*zk) + (z*(n-1)/n)*k0(p(n-1)(k-1)*zk-1) =
= (1/n)*Gn-1(z) + (z*(n-1)/n)*Gn-1(z)
Prima derivată a funcţiei Gn se poate determina uşor din relația (4):
(6) Gn1(z) = k(k*pnk*zk-1)
Din relaţiile (1), (6) şi (3b) rezultă:
n 1
an = Gn1(1) = k * p
k 0
nk

În concluzie, pentru determinarea timpului mediu de execuție, trebuie determinată valoarea


Gn1(1). Pentru determinarea lui Gn1(1) se derivează şi relaţia (5):
Gn1(z) = 1/n* Gn-1(z)+z/n* Gn-11(z)+(n-1)/n* Gn-11(z)
Gn1(z) = 1/n* Gn-11(z) + (n-1)/n* Gn-1(z) + z*(n-1)/n* Gn-11(z)
Rezultă:
(7) Gn1(1) = 1/n* Gn-11(1) + (n-1)/n* Gn-1(1) + (n-1)/n* Gn-11(1) =
= Gn-11(1) + (n-1)/n* Gn-1(1).
Pe de altă parte, din relaţiile (3) avem:
G11(1) = p11+2*p12+3*p13 + ... = 0,
iar, pentru orice număr n, rezultă:
Gn(1) = pn0 + pn1 + pn2 + ... + pnn + pn(n+1) + ... = 1 + 0 = 1.
Calculul termenilor șirului definit de relația de recurență (7) se poate determina astfel:
G21(1) = G11(1) + 1/2*G1(1) = 0 + 1/2*1 = 1/2,
G31(1) = G21(1) + 2/3*G2(1) = 1/2 + 2/3*1 = 1/2 + 2/3,
G41(1) = G31(1) + 3/4*G3(1) = 1/2 + 2/3 + 3/4*1 = 1/2 + 2/3 + 3/4,
...
Gn1(1) = 1/2 + 2/3 + 3/4 + ... + (n-1)/n.
Rezultă în final:
an = Gn1(1) = 1/2 + 2/3 + 3/4 + ... + (n-1)/n
Notând cu Hn seria dată de relația

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

(8) Hn = 1/2 + 2/3 + 3/4 + ... + (n-1)/n,


rezultă că timpul mediu de execuţie al algoritmului este:
(9) tmed = 3+6*n+2*a = 3+6*n+2*(Hn-1) = 1 + 6*n + 2*Hn.

B. Notaţia asimptotică

O notaţie convenabilă pentru specificarea aproximaţiilor este notaţia O. Ea descrie pe scurt


conceptul de aproximare şi suprimă informaţia detaliată, care nu este în mod uzual
revelatoare.
Fie f şi g două funcţii reale de variabilă întreagă şi pozitivă:
f, g: NR+,
Se spune că f(n) aproximează g(n) şi se notează g(n)O(f(n)), dacă există o constantă
pozitivă M și un număr n0N, astfel încât: |g(n)|  M*|f(n)|, pentru orice n  n0.
În general, pentru o funcție g: NR+, O(g(n)) reprezintă mulțimea de funcții:
O(g(n)) = {f: NR+ | MR+, n0N, a.î. 0  f(n)  M*g(n), nn0}
Intuitiv, faptul că f(n)∈O(g(n)) înseamnă că f(n) crește asimptotic cel mult la fel de repede ca
g(n).
Prin abuz de limbaj, notația g(n)O(f(n)) se scrie g(n)=O(f(n)).

De exemplu, se poate scrie:


12+22+ ... +n2 = O(n3),
Într-adevăr, avem:
g(n) = 12+22+ ... +n2 = n*(n+1)*(2*n+1)/6 = n3/3+n2/2+n/6.
Considerând f(n)=n3, trebuie determinat M astfel încât |n3/3+n2/2+n/6|  M*n3. Dar M poate
fi ales astfel: M=1/3+1/2+1/6 și n0=1.
În general, dacă P(n) este un polinom de grad cel mult m, atunci:
(10) O(P(n)) = O(a0+a1*n+ ... +am*nm) = O(nm).

Câteva proprietăți ale notației O:


 f(n)O(f(n)) - reflexivitate
 dacă f(n)O(g(n)) și g(n)O(h(n)), atunci f(n)O(h(n)) – tranzitivitate
 O(f(n)+g(n)) = O(max{f(n),g(n)})
 O(loga(n)) = O(logb(n)), pentru orice valori reale pozitive diferite, a și b.

Primele două proprietăți permit notației O să definească clase de echivalență: f(n) și g(n)
sunt echivalente dacă f(n)O(g(n)). Clasele de echivalență corespunzătoare se numesc clase
de complexitate. Principalele clase de complexitate sunt următoarele:
 Complexitate logaritmică, O(lg(n)); de exemplu: căutarea binară
 Complexitate liniară, O(n); de exemplu: căutarea secvențială
 Complexitate pătraticică, O(lg(n2)); de exemplu: sortarea prin inserție
 Complexitate cubică, O(lg(n3)); de exemplu: produsul a două matrici
 Complexitate exponențială, O(2n); de exemplu: prelucrarea tuturor submulțimilor unei
mulțimi de n elemente
 Complexitate factorială, O(n!); de exemplu: prelucrarea tuturor permutărilor unei
mulțimi de n elemente

Cu ajutorul acestei notaţii, timpul minim și maxim de execuţie al algoritmului precedent


poate fi descris astfel:

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

tmin = 1+6*n = O(n),


tmax = 1+8*n = O(n).
Pentru exprimarea timpului mediu, se poate utiliza următoarea relaţie:
(11) 2*Hn = 2*(1 + 1/2 + ... + (n-1)/n) < 2*(n-1)
Deoarece timpul mediu de execuţie dat de relația (9) este:
tmed = 1+6*n+2*Hn,
rezultă din relația (11):
(12) tmed = 1+6*n+2*Hn  1+6*n+2*(n-1) = 8*n - 1.
Folosind notația asimptotică, din relațiile (9) și (12), rezultă că și timpul mediu de execuție al
algoritmului este:
tmed = O(n).

2.6 Probleme

2.1. Să se demonstreze matematic caracterul finit al algoritmului lui Euclid din exemplul
2.1.

2.2. Să se scrie algoritmul care determină valoarea: y = arcsin(x2+1), pentru un număr x


dat, folosind doar funcţiile trigonometrice uzuale: sin, cos şi arctg.

2.3. Pentru o valoare întragă n dată, să se scrie un algoritm care determină valorile
următoarelor expresii:
e1 = 2n+2-n
e2 = 1/2+2/3+ ... +n/(n+1)
e3 = (sin(1))/(n2+1)+(sin(2))/(n2+2)+ ... +(sin(n))/(n2+n)

2.4. Se consideră un punct în plan P(x0, y0) şi o dreaptă de ecuaţie: f(x, y) = a*x+b*y+c =
0. Să se scrie un algoritm care determină poziţia punctului P faţă de dreaptă:
a) pe dreaptă,
b) în semiplanul ce conţine originea O(0, 0),
c) în semiplanul ce nu conţine originea O(0, 0).

2.5. Să se scrie un algoritm care determină dacă un număr întreg n este prim.

2.6. Să se scrie un algoritm care determină valoarea y = n x , pentru un număr real pozitiv x
şi un număr întreg pozitiv n, efectuând un număr minim de operaţii de înmulţire şi
extragere a rădăcinii pătrate.
Indicaţie. Se vor determina cifrele numărului fracţionar 1/n în baza 2 şi se va utiliza
forma polinomială a numărului 1/n.

2.6. Se consideră că o mulţime este specificată prin numărul de elemente şi vectorul ce


conţine elementele sale. Să se scrie un algoritm care determină, intersecţia, reuniunea
şi diferenţa a două mulţimi de numere date.

2.7. Se consideră o mulţime finită A = {a1, a2, …, an} şi relaţie binară R  A  A. Relaţia
se poate reprezenta printr-o matrice M, astfel: mij = 1, dacă (aI, aj)  R şi mij = 0 altfel.
Pentru o asemenea relaţie binară, să se scrie un algoritm care determină dacă ea este:
- simetrică,

Downloaded by Mihaela Stan (miha_cio@yahoo.com)


lOMoARcPSD|12059127

- reflexivă,
- tranzitivă.

2.8. Să se scrie un algoritm care determină polinomul sumă şi polinomul produs a două
polinoame cu coeficienţi reali. Polinoamele sunt specificate prin gradele lor şi vectorii
coeficienţilor.

2.9. Se consideră două şiruri de numere: x1, …, xn şi y1, …, ym. Să se scrie un algoritm care
determină dacă şirul al doilea este un subşir al primului (adică este format din elemente
consecutive ale primului şir: există un indice k astfel încât xk+i = yi, pentru i=1, 2, …,
m).

2.10. Se consideră sistemul bielă-manivelă din figura alăturată. În lungul axei Ox se mişcă o
culisă, iar manivela OA se mişcă în sens trigonometric cu viteza unghiulară constantă .
Să se scrie un algoritm care determină poziţia şi viteza punctului C situat la jumătatea
distanţei AB (adică valorile x, y, vx, vy ale acestuia), în puncte succesive pentru intervalul
de timp [0, tmax], cu un pas de incrementare dt pentru variabila t. Se cunoaşte: tmax, , dt,
|OA| = r, |AB| = l.
y
A

O B

2.11. Se consideră în plan n puncte de coordonate: (x1, y1), (x2, y2), ..., (xn, yn). Să se scrie un
algoritm care determină dacă poligonul cu vârfurile în punctele date este convex sau
nu;

2.12. Să se determine timpul de execuţie al algoritmului din exemplul 2.7.

2.13. Să se determine timpul minim, maxim şi mediu de execuţie al algoritmului din


exemplul 2.6. Se va considera că şirul de intrare conţine n valori nenule.

2.14. Să se determine timpul minim, maxim şi mediu de execuţie al algoritmului din


problema 2.6.

2.15. Să se determine timpul minim, maxim şi mediu de execuţie al algoritmului din


problema 2.10.

Downloaded by Mihaela Stan (miha_cio@yahoo.com)

S-ar putea să vă placă și