Sunteți pe pagina 1din 14

UNIVERSITATEA BABEŞ-BOLYAI CLUJ-NAPOCA

FACULTATEA DE MATEMATICĂ ŞI INFORMATICĂ

Algoritmică
şi
programare

Vasile Prejmerean Vasile Cioban

Cluj-Napoca
2016
Cuprins
1. Descrierea algoritmilor, limbajul Pseudocod................................................ 2
1.1. Descrierea algoritmilor. ........................................................................................ 2
1.2. Limbajul Pseudocod. ............................................................................................ 4
2. Proceduri, funcţii. ............................................................................................. 8
2.1. Subalgoritmi. ......................................................................................................... 8
2.2. Funcţii. ................................................................................................................... 9

1
1. Descrierea algoritmilor, limbajul Pseudocod.

1.1. Descrierea algoritmilor.


Noţiunea de algoritm e destul de greu de definit formal, D.E.Kunth încearcă o astfel de
definiţie în [1]. Knuth defineşte algoritmul ca o funcţie de 4 variabile (intrarea, ieşirea, stările
procesărilor, regulile de procesare). Din considerente practice prin algoritm putem înţelege o
succesiune finită de operaţii sau procese. Acesta presupune executarea unor calcule (procesări) într-o
anumită ordineAlgoritmii pe care îi descriem ar trebui să fie:
- cât mai generali (să rezolve o clasă de probleme de acelaşi tip);
- să dea rezultate într-un anumit timp (finit, adică să se termine oricare ar fi datele de
intrare);
- şi de asemenea să asigure unicitatea rezulatelor ori de câte ori se dau aceleaşi date de
intrare.
Aceste trei caracteristici generalitate, finitudine şi unicitate trebuie să ne preocupe ori de câte ori
scriem un algoritm, indiferent de forma (scheme logice sau limbaj Pseudocod) în care este prezentat
acesta.
Schema logică este un mijloc de descriere a algoritmilor prin reprezentare grafică. Regulile
de procesare ale algoritmului sunt descrise prin blocuri (figuri geometrice) reprezentând operaţiile
(paşii) algoritmului, iar ordinea lor de aplicare (succesiunea operaţiilor) este indicată prin săgeţi.
Fiecărui tip de operaţie îi este consacrată o figură geometrică (un bloc tip) în interiorul căreia se va
înscrie operaţia din pasul respectiv.
În descrierea unui algoritm, intervin variabile care marchează atât datele cunoscute iniţial, cât şi
rezultatele dorite, precum şi alte rezultate intermediare necesare în rezolvarea problemei. Variabila
defineşte o mărime care îşi poate schimba valoarea. Valorile pe care le poate lua variabila aparţin
unei mulţimi D pe care o vom numi domeniul variabilei. La orice pas al algorimului variabilele care
intervin în procesare trebuie să aiba valori, deci o variabilă poate fi utilizată doar daca are o valoare
(iniţilă sau rezultată din alte procesări)
Prin variabilă vom înţelege tripletul (nume, domeniul D, valoare) .
Concluzionând datele utilizate într-un algoritm pot fi:
- variabile (îşi pot modifica valoarea);
- sau constante (nu îşi pot modifica valoarea pe parcursul procesărilor).

În continuare vor fi enumerate blocurile ce descriu în schema logică o anumită operaţie.

Blocurile delimitatoare (Start şi Stop) (figura 1.a şi 1.b) vor marca începutul respectiv
sfârşitul unui algoritm dat printr-o schemă logică. Descrierea unui algoritm prin schemă logică va
începe cu un singur bloc Start şi se va termina cu cel puţin un bloc Stop.

Blocurile de intrare/ieşire (Citeşte şi Afişează) (figura 1.c şi 1.d) indică introducerea unor
Date de intrare respectiv extragerea unor Rezultate finale. Ele permit precizarea datelor iniţiale
cunoscute în problemă şi tipărirea rezultatelor cerute de problemă.
Blocul Citeşte iniţializează variabilele din lista de intrare cu valori corespunzătoare, iar blocul
Afişează va preciza rezultatele obţinute (la execuţia pe calculator cere afişarea pe ecran a valorilor
expresiilor din lista de ieşire).

Blocurile de atribuire (calcul) se utilizează în descrierea operaţiilor de atribuire (). Printr-o


astfel de operaţie, unei variabile var i se atribuie valoarea calculată a unei expresii expr (figura
1.e).
Blocurile de decizie marchează punctele de ramificaţie ale algoritmului în derularea paşilor
săi. Ramificarea poate fi dublă (blocul logic, figura 1.f) sau triplă (blocul aritmetic, figura 1.g).
Blocul de decizie logic indică ramura pe care se va continua execuţia algoritmului în functie de
2
îndeplinirea (ramura Da) sau neîndeplinirea (ramura Nu) unei condiţii. Condiţia care se va înscrie în
blocul de decizie logic va fi o expresie logică a cărei valoare poate fi una dintre valorile "adevărat"
sau "fals". Blocul de decizie aritmetic va hotarî ramura de continuare a algoritmului în funcţie de
semnul valorii expresiei aritmetice înscrise în acest bloc, care poate fi negativă, nulă sau pozitivă.
Blocurile de conectare marchează întreruperile săgeţilor de legătură dintre blocuri, dacă din
diverse motive s-au efectuat astfel de întreruperi (figura 1.h).

Start
Citeşte listă_var_intrare Afişează listă_expr.ieşire
Stop

a) c) d)
b)

Da Nu <0 >0
Var  Condiţie Epr. aritm.

=0

e) f) g)
i
i
h)
Figura 1. Blocurile schemelor logice.

Vom da în continuare o schemă logică, pentru rezolvarea ecuaţiei de gradul doi


aX +bX+c=0 (a,b,c  R şi a  0).
2
Start
Ecuaţia poate avea rădăcini
reale, respectiv complexe, în funcţie
de semnul discriminantului Citeşte a, b, c
 = b - 4ac.
2

Algoritmul de rezolvare a Da
problemei va citi mai întâi datele a=0 Mesaj „a=0”
problemei, marcate prin variabilele a, Nu
b şi c. Va calcula apoi discriminantul 1
 şi va continua în funcţie de b2-4ac
valoarea lui , aşa cum se poate
Da Nu -b+
vedea în figura 2. Re-b / 2a <0 x1
2a

Im-/2a -b-
x2
2a

Afişează Re,Im 1 Afişează x1,x2

Stop

Figura 2. Algoritm pentru rezolvarea ecuaţiei de gradul doi.

3
1.2. Limbajul Pseudocod.

Pentru că schemele logice reprezintă o modalitate de reprezentare mare consumatoare de


spaţiu grafic s-a definit o altă modalitate de reprezentare a algoritmilor. Totuşi schema logică are
avantajul unei înţelegeri vizuale a procesărilor.
Putem considera, dintr-o altă perspectivă că un algoritm este o secvenţă finită de propoziţii ale unui
limbaj de descriere a algoritmilor. Fiecare propoziţie a limbajului precizează o anumită regulă de
calcul, aşa cum se intâmplă când folsim altă modalitate de descriere a algoritmilor (limbajul
Pseudocod).

Limbajul Pseudocod a fost conceput pentru descrierea algoritmilor. Limbajul Pseudocod are două
tipuri de propoziţii:
- standard (care au o structură fixă şi este formată cu ajutorul unor cuvinte cheie);
- propoziţii nestandard (care descriu părţi ale algoritmului încă incomplet elaborate,
nefinisate, asupra cărora urmează să se revină) şi
- comentarii (texte scrise între acolade sau alte semne distinctive utilizate pentru
documentarea algoritmului).
Propoziţiile limbajului Pseudocod se vor executa în ordinea întâlnirii lor în text, asemenea oricărui
text al limbii române.
În descrierea algoritmilor se recomandă o scriere structurată prin utilizarea următoarelor
structuri:
-secvenţială (formată dintr-o succesiune de propoziţii simple);
-alternativă (permite executarea anumitor ramuri în funcţie de anumite condiţii);
-repetitivă (prin care putem executa aceleaşi propoziţii de mai multe ori).

Structura generală a unui algoritm descris în Pseudocod este :

Algoritmul Nume Este : { Antetul algoritmului }


. . . { Corpul algoritmului }
Sfarşit_Algoritm. { Sfarşitul algoritmului }

Un algoritm (în general) se desfăşoară în trei etape : Date de intrare

- citirea datelor de intrare (iniţializarea datelor), Prelucrare


- efectuarea de calcule (prelucrarea datelor),
- afişarea rezultatelor (extragerea datelor de ieşire).
Date de iesire

Citirea datelor se face prin propoziţia


Date (sau Citeşte) Listă_variabile_de_intrare;

Afişarea rezultatelor prin:


Rezultate (sau Afişare) Listă_expresii_de_ieşire;
O propoziţie des utilizată în efectuarea calculelor este aceea prin care unei variabile i se
atribuie valoarea unei expresii. Aceasta este de forma:
[Fie] Variabilă  Expresie;
în care cuvântul Fie poate lipsi. Expresia din dreapta semnului de atribuire poate fi o expresie
construită cu operaţiile aritmetice, alte operaţii inclusiv atribuirea simplă. Prin această instrucţiune
o variabilă primeşte (i se asignează, i se atribuie, sau este iniţializată) valoarea (calculată a) unei
expresii.
4
Pentru descrierea unei structuri alternative avem trei posibilităţi :

- structura alternativă cu o ramură :


Dacă Condiţie Atunci Dacă a<0 Atunci
Secvenţă Fie a  a*a

Sf_Dacă; Sf_Dacă;

interpretată astfel: dacă este îndeplinită această Condiţie atunci se execută secvenţa de propoziţii
care urmează până la sfârşitul structurii, iar în caz contrar se trece direct la urmatoarea structură;

- structura alternativă cu două ramuri :


Dacă Condiţie Atunci Dacă a<b Atunci
Secvenţă1 Minima
Altfel Altfel
Secvenţa2 Minimb
Sf_Dacă; Sf_Dacă

aceasta se interpretează astfel: dacă această Condiţie este îndeplinită se execută prima secvenţă, dacă
nu, a doua.

- structura alternativă cu mai multe ramuri :

Selectează Expresie Dintre Selectează Luna Dintre


Listă_Valori1 : Secvenţă1; 4, 6, 9, 11: Nr_Zile:=30;
Listă_Valori2 : Secvenţă2; 2: Nr_Zile:=28+Dif_Bisect
. . . Altfel Nr_Zile:=31
Listă_Valorin : Secvenţăn Sf_Selectează;
[ Altfel Secvenţăn+1 ]
Sf_Selectează;

care se poate “traduce” astfel : se caută valoarea expresiei în listele de valori şi se execută secvenţa
corespunzătoare. Dacă valoarea calculată nu se regăseste în nici o listă (şi apare alternativa Altfel
care este opţională, atunci se execută ultima secvenţă notată cu n+1).

Structurile repetitive permit executarea unei secvenţe de propoziţii de mai multe ori (de un
anumit număr de ori, sau câtă vreme este îndeplinită o anumită condiţie, sau până când este
îndeplinită o anumită condiţie). Pentru descrierea structurilor repetitive există trei variante pe care le
putem alege în funcţie de problema concretă pe care dorim să o rezolvăm.
Structura Pentru este o structură repetitivă cu un număr bine determinat de paşi, în schimb
structura Cât_Timp (cu test iniţial) şi structura Repetă (cu test final) sunt structuri repetitive cu un
număr necunoscut de paşi (lucru pe care îl vom vedea imediat).
- structura repetitivă Pentru se descrie prin propoziţia :
Pentru Varc := Li , Lf [ , Pas ] Execută
Secvenţă
Sf_Pentru;
având următoarea semnificaţie : se execută secvenţa (corpul structurii) dând succesiv valori
variabilei contor (Varc ) începând de la limita iniţială (Li) până la limita finală (Lf) cu pasul precizat
(implicit este 1, adică dacă lipseşte Pas, atunci se consideră egal cu 1).
5
- structura repetitivă Cât_Timp are format general :
Cât_Timp Condiţie Execută
Secvenţă
Sf_Cât_Timp;

şi se interpretează astfel : dacă această condiţie este îndeplinită atunci se execută secvenţa şi din nou
se verifică condiţia, şi asa mai departe. În momentul în care condiţia nu este îndeplinită se termină
structura repetitivă şi se continuă cu urmatoarea structură.

- structura repetitivă Repetă se va scrie

Repetă
Secvenţă
Până_Când Condiţie ;

având semnificaţia : se execută secvenţa descrisă apoi se verifică dacă este îndeplinită condiţia
precizată. Dacă aceasta este îndeplinită se termină structura repetitivă, iar dacă nu este îndeplinită,
atunci de execută din nou secvenţa şi se reevaluează condiţia.

Secvenţă

Da Nu
Condiţie Secvenţă Condiţie
Nu Da
Structura Cât_Timp Structura Repetă
Figura 3.

Se observă şi în figura 3 că spre deosebire de structura Cât_Timp care poate să nu execute


niciodată secvenţa sa, structura Repetă va permite executarea corpului său cel puţin o dată. Pentru
ambele structuri trebuie să fim atenţi să modificăm în secvenţele lor, variabile care fac parte din
condiţie pentru ca aceasta să se modifice. În caz contrar algoritmul nu se va termina, va intra într-o
buclă infinită.

Exemplul următor calculează produsul a două polinoame P şi Q , date prin şirurile


coeficienţilor.

Algoritmul Produs Este : { R:=PQ }


Date m,(Pi, i=0,m), n,(Qj, j=0,n); { m=gradul lui P, n=gradul lui Q }
Pentru k:=0,m+n Execută { m+n=gradul lui R }
Rk:=0
Sf_Pentru;
Pentru i:=0,m Execută
Pentru j:=0,n Execută
Ri+j:=Ri+j+Pi*Qj
Sf_Pentru;
Sf_Pentru;
Rezultate (Rk, k=0,m+n)
Sf_Algoritm.

6
Algoritmul următor, dat ca exemplu, determină primele n (n dat) numere prime.

Algoritmul Prime Este : { Primele n numere Prime }


Date n; { primele n numere prime p =2,3,5, ... }
p:=2; i:=0;
Cât_Timp i<n Execută { i reprezintă al câtelea număr prim a fost găsit }
d:=2; { p este prim ?( se divide cu 2,3, ... )}
Cât_Timp (d<Sqrt(p)) şi (p Mod d > 0) Execută
d:=d+1 {se caută divizori d =2,3,... p}
Sf_Cât_Timp;
Dacă d>Sqrt(p) Atunci { dacă am trecut cu d de p atunci p este prim ! }
Rezultate p; i:=i+1
Sf_Dacă;
Dacă p=2 Atunci p:=p+1 { Se verifică doar pentru }
Altfel p:=p+2 { numerele impare de la 3,... }
Sf_Dacă;
Sf_Cât_Timp
Sf_Algoritm.

Ca exemplu de folosire a structurii Repetă vom scrie următorul algoritm care determină cel
mai mare numar n de patru cifre pentru care este îndeplinită condiţia :

Oglindit (n) + Suma_Cifrelor(n) = n + 99 (Oglinditul lui 123 este 321).

De exemplu pentru n = 4014, egalitatea este adevarată pentru că

4104 + 9 = 4014 + 99 (4+0+1+4=9).

Algoritmul Număr Este : { Cel mai mare număr n de patru cifre : }


n:=9999; { Ogl (n) + Sc (n) = n + 99 }
Repetă
n:=n1;
Cât:=n; Sc:=0; Ogl:=0; { Primul Cât este n }
Repetă
Uc :=Cât Mod 10; { Determin Ultima cifră a numărului }
Sc :=Sc + Uc; { Adun Ultima cifră la Suma cifrelor }
Ogl :=Ogl *10+ Uc; { Adaug Ultima cifră la Oglindit }
Cât :=[Cât / 10] { Sterg Ultima cifră din număr }
Până_Când Cât=0;
Până_Când (Ogl+Sc=n+99) Sau (n=999);
Dacă n>999 Atunci Rezultate n
Altfel Rezultate ‘Nu există’
Sf_Dacă
Sf_Algoritm.

7
2. Proceduri, funcţii.

Este foarte bine ca atunci când rezolvăm o problemă (mai ales dacă aceasta este mai
complexă) să o împărţim în subprobleme pe care apoi să le rezolvăm pe rând, eventual dacă aceste
subprobleme nu sunt simple, pot la rândul lor să fie împarţite, pâna când aceste subprobleme sunt
elementare (simple). Aceasta înseamnă că o problemă complexă P se poate descompune în mai
multe subprobleme mai simple Si . Algoritmul de rezolvare al unei subprobleme Si devine în acest
caz un subalgoritm pentru algoritmul de rezolvare al problemei P.

Se întâmplă frecvent ca într-o problemă să ne confruntăm de mai multe ori cu aceeaşi


subproblemă (eventual pentru alte date). În această situaţie subalgoritmul va trebui conceput cât mai
general astfel încât să rezolve subproblema (solicitată de mai multe ori) chiar dacă datele
subproblemei se schimbă. Subalgoritmul astfel conceput se va descrie o singură dată şi va fi utilizat
ori de câte ori este necesar.

De asemenea este posibil ca o subproblemă, la rândul său, să fie descompusă în mai multe
subprobleme mai simple, şi aşa mai departe. Aceasta înseamnă că un subalgoritm poate să apleleze la
rândul său unul sau mai mulţi subalgoritmi. Acest lucru chiar este recomandat pentru a amâna
detaliile nesemnificative. Aceste detalii se vor descrie în subalgoritmii apelaţi.

Uneori o subproblemă se poate rezolva mai simplu aplelând o funcţie, care desigur va trebui
să fie definită. Modul de utilizare şi de descriere a funcţiilor va fi prezentată în paragraful 2.2.

2.1. Proceduri.

Putem spune că, în general, un subalgoritm rezolvă o anumită subproblemă în funcţie de


anumite date de intrare şi de nişte rezultate (date de ieşire) care vor fi folosite în problema care
apelează (cheamă) acest subalgoritm.

Parametri de Intrare Parametri de iesire


Subalgoritm
Folosirea unui subalgoritm în cadrul unui algoritm se face apelând acest subalgoritm prin :

Cheamă Nume_Subalgoritm (Lista_parametri_actuali);

Lista parametrilor actuali conţine toate datele de intrare (cele cunoscute în subproblema
corespunzătoare care pot fi anumite expresii) şi toate rezultatele (datele de ieşire, deci variabile)
obţinute în subalgoritm.

Definirea unui subalgoritm este asemănătoare descrierii unui algoritm :

Subalgoritmul Nume_Subalgoritm (Lista_parametri_formali) Este : {Antet}


... { Corp subalgoritm }
Sf_Subalgoritm. { sau Sf_Nume_Subalgoritm. }

Parametrii formali marchează datele de intrare (cele presupuse cunoscute) şi datele de ieşire
(rezultatele obţinute de subalgoritm).
Între lista parametrilor formali din definiţia subalgoritmului şi lista parametrilor actuali din
propoziţia de apel trebuie să existe o corespondenţă biunivoca (ca număr, tip, ordine, etc).
8
Dacă de exemplu pentru trei mulţimi date A, B şi C dorim să calculăm AB, AC şi BC,
atunci vom apela un subalgoritm care construieşte reuniunea a două mulţimi de trei ori.
Acest subprogram va calcula reuniunea R :=XY, X , Y R:=X R
pentru orice mulţimi X, Y date.
Subprogramul va avea doi parametri (formali) de intrare X şiYY şi un parametru de ieşire
R. El va fi apelat pentru a calcula succesiv reuniunile AB, AC şi BC.

Algoritmul Reuniuni Este : Subalgoritmul Reuniune ( X,Y, R ) Este :


Date A,B,C; R:=X;
Cheamă Reuniune (A,B,R1); Pentru fiecare yY Execută
Cheamă Reuniune (A,C,R2); Dacă yX Atunci R:=R{y}
Cheamă Reuniune (B,C,R3); Sf_Dacă
Rezultate R1; Sf_Pentru
Rezultate R2; Sf_Reuniune.
Rezultate R3;
Sf_Algoritm.

Subalgoritmul Reuninune determină mulţimea R = X  Y astfel :


R := X  (Y \ X), adică depune în reuniune mai întâi elementele din mulţimea X, la care apoi
mai adaugă acele elemente din Y care nu aparţin lui Y. Se observă că nu toate propoziţiile din
subalgoritm sunt cele standard, deci va trebui în continuare să rafinăm acest subalgoritm până se
ajunge la o formă finală. În primul rând vom considera că o mulţime este reprezentată sub forma
unui şir care va conţine elementele mulţimii, iar pentru relaţia de apartenenţă vom utiliza o funcţie
booleană Apart(b,A) care va preciza dacă bA. Despre funcţii vom discuta în paragraful următor, aşa
că forma finală a subalgoritmului o vom vedea imediat.

2.2. Funcţii.

Destul de frecvent în cadrul unor algoritmi este necesar calculul valorilor unei funcţii în
diferite puncte. În această situaţie este de preferat sa definim funcţia printr-un subalgoritm de tip
funcţie după care putem să o referim pentru calculele în care aceasta intervine.
Definirea unui subalgoritm de tip funcţie se aseamănă cu descrierea anterioară (pentru
subalgoritmi de tip procedură) având un antet (care precizează numele funcţiei şi argumentele
acesteia), un corp (prin care este descris subalgoritmul) şi o marcă de sfârşit de funcţie :

Funcţia Nume_Funcţie (Listă_parametri_formali) Este : { Antetul funcţiei }


...
Nume_Funcţie := Expresie; { Corpul funcţiei }
...
Sf_Funcţie. { sau Sf_Nume_funcţie.}

În corpul funcţiei trebuie să existe cel puţin o atribuire prin care funcţia primeşte o
valoare.

Apelul unei funcţii se face scriind într-o expresie numele funcţiei urmat de lista parametrilor
actuali. Trebuie să existe o corespondenţa biunivoca între parametrii actuali si cei formali folosiţi în
definiţia funcţiei. Deşi denumirile variabilelor din cele două liste pot să difere, rolul variabilelor care
se corespund este acelaşi. Mai exact, parametrul formal si parametrul actual corespunzător trebuie să
se refere la aceeaşi entitate, trebuie să aiba aceeaşi semnificaţie, să reprezinte aceeaşi structură de
date.

9
Este permis ca un subprogram de tip funcţie să aibă chiar şi parametrii de ieşire, deci din
acest punct de vedere putem considera că o funcţie este mai “generoasă” pentru că va returna o
valoare în plus prin valoarea funcţiei.
De exemplu funcţia Există (b,A,n,p) de tip boolean ne va returna valoarea True dacă b se
află în şirul A (cu n componente) şi False în caz contrar. Însă este posibil ca în primul caz (în care
există un element ap pentru care b=ap) să obţinem şi indicele (prima poziţie) pe care se află acel
element. Atunci funcţia se poate apela astfel :
. . .
Dacă Există (b,A,n, p) Atunci Tipareşte p, ap
Altfel Tipareşte ‘ Nu există.’
Sf_Dacă;
. . .

Funcţia Există descrisă în continuare se poate uşor simplifica pentru a obţine o funcţie Apart
(b,A) utilă în exemplul anterior (yX).

Funcţia Există ( b, A, n, p ) Este :


p:=1;
Cât_Timp (p<=n) şi (b<>ap) Execută p:=p+1 Sf_Cât_Timp;
Există := (p<=n)
Sf_Există.

În subalgoritmul Reuniune, secvenţa

Dacă yX Atunci R:=R{y} Sf_Dacă;

se poate înlocui cu secvenţa

Dacă Not Apart (y,X) Atunci R:=R{y} Sf_Dacă;

iar funcţia Apart poate avea o primă formă :

Funcţia Apart (b,A) Este :


p:=1; {Card(A)=|A|}
Cât_Timp (p<=Card(A)) şi (b<>A[p]) Execută p:=p+1 Sf_Cât_Timp;
Apart := (p<=Card(A))
Sf_Apart.

Dacă elementele mulţimii A le reţinem în şirul a1,a2,...,an , atunci putem să reţinem şi


dimensiunea şirului (n) pe pozitia 0 a şirului (a0=n), aşa cum vom vedea că se obişnuieşte şi la unele
structuri de date chiar în Pascal. În acest caz funcţia Card este :

Funcţia Card (A) Este :


Card := a0
Sf_Card.

Există numeroase probleme în care soluţia (rezolvarea) recursivă este mult mai simplă. Este
posibil ca un subalgoritm să se apeleze pe el însuşi. Într-un astfel de caz spunem că apelul este
recursiv, iar subalgoritmul respectiv este definit recursiv. Un exemplu bine cunoscut este funcţia
factorial definită astfel:

n! = n * (n1)! .

10
Este însă foarte important ca acestă funcţie (formulă) să fie completă, adică să capete
consistenţă. Aceasta înseamnă că trebuie definită o astfel de funcţie şi direct (nerecursiv), pentru
anumite valori. În acest exemplu va trebui să dăm consistenţa formulei pentru n=1 sau n=0 , adică
să precizăm că 0!=1 sau 1! =1.
În final putem să spunem că funcţia factorial poate fi definită astfel :

n! = 1 dacă n<2

n * (n-1)! dacă n>1


Subalgoritmul corespunzător este următorul:
Funcţia Factorial(n) Este:
Dacă n<2
Atunci Factorial:=1
Altfel Factorial:= n*Factorial(n1)
Sf_Dacă
Sf_Factorial.
Un alt exemplu de funcţie recursivă descrisă în continuare determină maximul a n numere
x1,x2 , ... ,xn (dintr-un şir X cu n componente).
Dacă reuşim să scriem o funcţie Max(X,k), care determină maximul pentru primele k
elemente din şir, atunci o vom apela pentru calculul primelor n (adică pentru toate elementele şirului,
Max(X,n) şi am rezolvat problema.
Pentru a determina maximul primelor k elemente se observă că
- dacă k=1 (aici se defineste direct şi dam consistenţa) atunci problema este simplă pentru că având
un singur element, maximul este acel element (x1),
- dacă k>1 atunci putem rezolva problema pentru primele k dacă am cunoaşte rezultatul pentru
primele k-1 , (adică în funcţie de Max(X,k-1) şi putem vorbi de primele k-1 deoarece k>1). Dacă
maximul primelor k-1 este mai mic decât xk, atunci maximul dintre primele k elemente este xk, altfel
maximul primelor k este egal cu maximul primelor k-1.

11
De aici rezultă că funcţia care determină maximul dintr-un şir X cu n componente poate fi
scrisă astfel :

Funcţia Max (X,k) Este :


Dacă k=1 Atunci Max:=x1 {Consistenţa}
Altfel Dacă Max(X,k-1) < xk Atunci Max:= xk
Altfel Max:= Max(X,k-1)
Sf_Dacă
Sf_Dacă
Sf_Max.

Funcţia Apart (b,A,k) prin care putem decide dacă b aparţine primelor k elemente din şirul A,
poate fi scrisă recursiv astfel :
Funcţia Apart (b,A,k) Este :
Apart := (k>0) şi ( Apart(b,A,k-1) Sau (b=ak) )
Sf_Apart.
( b aparţine primelor k dacă şirul are cel puţin un element (k>0) şi b aparţine sau subşirului primelor
k-1 elemente sau este egal cu elementul ak. Prin apelul Apart(b,A,Card(A)) putem decide dacă bA
sau bA.

12
Bibliografie

1. D.E.Knuth - Tratat de programarea calculatoarelor, vol.1 Algoritmi


fundamentali, Editura tehnică, 1974.
2. L. Livovschi si H. Georgescu, Sinteza şi analiza algoritmilor, Editura
şt. şi Enciclopedică, Bucuresti, 1986.
3. D. Lucanu, Proiectarea algoritmilor. Tehnici elementare, Editura Univ.
Al.I.Cuza, Iaşi, 1993.
4. R. Andonie, I. Gârbacea - Algoritmi fundamentali. O perspectivă C++,
Ed. Libris, Cluj-Napoca, 1995.
5. M.Frenţiu în colaborare cu un colectiv al catedrei de informatică -
Programare Pascal, Editura Promedia Plus Computers, Cluj-Napoca, 1995
6. M. Frenţiu şi V. Prejmerean, Algoritmică şi programare, Litografia
Universităţii "Babeş-Bolyai", 1995.
7. M. Frenţiu, S. Motogna, I. Lazăr si V. Prejmerean. Elaborarea
algoritmilor, Litografia Universităţii "Babeş-Bolyai", 1998.
8. M. Frenţiu, S. Motogna, I. Lazăr si V. Prejmerean, Programare Pascal,
Litografia Universităţii "Babeş-Bolyai", 1998.
9. I.Odăgescu, F.Furtună - Metode şi tehnici de programare, Ed.
Computer Press Agora, Cluj-Napoca, 1998.
10.S. Motogna, V.Prejmerean - Algoritmică şi programare, Centrul de
formare continuă şi învăţământ la distanţă, Cluj-Napoca, 2003.

13

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