14
UNIVERSITATEA BABEŞ-BOLYAI CLUJ-NAPOCA FACULTATEA DE MATEMATICĂ ŞI INFORMATICĂ Algoritmică şi programare Vasile Prejmerean Vasile Cioban Cluj-Napoca 2016

1. Descrierea algoritmilor, limbajul Pseudocod

Embed Size (px)

Citation preview

Page 1: 1. Descrierea algoritmilor, limbajul Pseudocod

UNIVERSITATEA BABEŞ-BOLYAI CLUJ-NAPOCA

FACULTATEA DE MATEMATICĂ ŞI INFORMATICĂ

Algoritmică

şi

programare

Vasile Prejmerean Vasile Cioban

Cluj-Napoca

2016

Page 2: 1. Descrierea algoritmilor, limbajul Pseudocod

1

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

Page 3: 1. Descrierea algoritmilor, limbajul Pseudocod

2

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

Page 4: 1. Descrierea algoritmilor, limbajul Pseudocod

3

î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).

Figura 1. Blocurile schemelor logice.

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

aX2+bX+c=0 (a,b,c R şi a 0).

Ecuaţia poate avea rădăcini

reale, respectiv complexe, în funcţie

de semnul discriminantului

= b2 - 4ac.

Algoritmul de rezolvare a

problemei va citi mai întâi datele

problemei, marcate prin variabilele a,

b şi c. Va calcula apoi discriminantul

şi va continua în funcţie de

valoarea lui , aşa cum se poate

vedea în figura 2.

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

b)

a) c) d)

Stop

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

e) f) g)

Nu Condiţie

Da Var

=0

Epr. aritm. <0 >0

i

h)

i

Start

Citeşte a, b, c

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

Stop

Re-b / 2a

Im-/2a

<0 Nu Da

Nu

b2-4ac

Mesaj „a=0”

1

Da

x2

-b-

2a

x1

-b+ 2a

a=0

Page 5: 1. Descrierea algoritmilor, limbajul Pseudocod

4

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 :

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

- efectuarea de calcule (prelucrarea datelor),

- afişarea rezultatelor (extragerea datelor de ieşire).

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.

Prelucrare

Date de intrare

Date de iesire

Page 6: 1. Descrierea algoritmilor, limbajul Pseudocod

5

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 Minima

Altfel Altfel

Secvenţa2 Minimb

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).

Page 7: 1. Descrierea algoritmilor, limbajul Pseudocod

6

- 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.

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:=PQ }

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.

Secvenţă

Secvenţă Nu

Condiţie

Da Nu

Condiţie Da

Page 8: 1. Descrierea algoritmilor, limbajul Pseudocod

7

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:=n1;

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.

Page 9: 1. Descrierea algoritmilor, limbajul Pseudocod

8

Subalgoritm Parametri de Intrare Parametri de iesire

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.

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).

Page 10: 1. Descrierea algoritmilor, limbajul Pseudocod

9

R:=X

Y

X , Y R

Dacă de exemplu pentru trei mulţimi date A, B şi C dorim să calculăm AB, AC şi BC,

atunci vom apela un subalgoritm care construieşte reuniunea a două mulţimi de trei ori.

Acest subprogram va calcula reuniunea R :=XY,

pentru orice mulţimi X, Y date.

Subprogramul va avea doi parametri (formali) de intrare X şi Y şi un parametru de ieşire

R. El va fi apelat pentru a calcula succesiv reuniunile AB, AC şi BC.

Algoritmul Reuniuni Este :

Date A,B,C;

Cheamă Reuniune (A,B,R1);

Cheamă Reuniune (A,C,R2);

Cheamă Reuniune (B,C,R3);

Rezultate R1;

Rezultate R2;

Rezultate R3;

Sf_Algoritm.

Subalgoritmul Reuniune ( X,Y, R ) Este :

R:=X;

Pentru fiecare yY Execută

Dacă yX Atunci R:=R{y}

Sf_Dacă

Sf_Pentru

Sf_Reuniune.

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ă bA. 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.

Page 11: 1. Descrierea algoritmilor, limbajul Pseudocod

10

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 (yX).

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ă yX 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 * (n1)! .

Page 12: 1. Descrierea algoritmilor, limbajul Pseudocod

11

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! =

Subalgoritmul corespunzător este următorul:

Funcţia Factorial(n) Este:

Dacă n<2

Atunci Factorial:=1

Altfel Factorial:= n*Factorial(n1)

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.

1 dacă n<2

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

Page 13: 1. Descrierea algoritmilor, limbajul Pseudocod

12

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ă bA

sau bA.

Page 14: 1. Descrierea algoritmilor, limbajul Pseudocod

13

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.