Professional Documents
Culture Documents
CarteteoriePASCALsiC++GRADE Nou
CarteteoriePASCALsiC++GRADE Nou
Prof.Bogdan Constantin
1
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
3. Algoritmi
3.1 Noţiunea de algoritm şi caracteristici
ALGORITMI. DESCRIEREA ALGORITMILOR
Algoritmi
Orice activitate umană se desfăşoară, în general, pa baza unor principii logice sau, altfel spus,
a unui algoritm bine definit. Deşi nu se conştientizează acest lucru, omul acţionează conform unor
algoritmi, care reprezintă expresia regulilor impuse de parcurgerea logică a etapelor necesare pentru a
ajunge de la o situaţie iniţială la un anumit rezultat.
Funcţionarea calculatoarelor se aseamănă în mare măsură cu activitatea umană. În cazul
acestora, este obligatorie conştientizarea faptului că întreaga activitate a echipamentului de calcul se
bazează pe respectarea unor algoritmi, algoritmi ce sunt elaboraţi de factorul uman dotat cu raţiune şi
capacitate de analiză. Calculatorul nu dispune de calităţile omului, ca atare, în procesul de rezolvare a
unei probleme cu ajutorul echipamentului electronic de calcul este obligatorie parcurgerea unei etape
importante, şi anume elaborarea algoritmului de calcul. Succesul rezolvării problemei depinde de
2
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
calitatea algoritmului întocmit de către utilizator şi aplicat de echipamentul de calcul prin intermediul unui
program.
Calculatoarele numerice prelucrează informaţiile prin executarea unor operaţii simple. Deşi operaţiile
sunt elementare, prin înlănţuirea unei mulţimi de operaţii se poate ajunge la prelucrări deosebit de
complexe. Combinarea operaţiilor nu se face la întâmplare, ea supunându-se unor reguli bine
precizate. Studiul acestor reguli are la bază noţiunea de algoritm. Noţiunea de algoritm este strâns
legată de noţiunea de calcul.
Intuitiv un algoritm de calcul este o mulţime finită de operaţiuni cunoscute care executate într-o
ordine bine stabilită, pornind de la un set de valori, numite date de intrare, conduc într-un timp finit la un
set de valori, numite date de ieşire.
Algoritmul reprezintă o mulţime de asemenea calcule. Altfel spus, prin algoritm se înţelege
metoda de rezolvare a unei probleme într-un număr finit de paşi. Metoda de rezolvare este în esenţă un
şir de operaţii precise, care dacă sunt îndeplinite conduc la rezultatul dorit într-un număr finit de paşi.
Se poate spune că un algoritm constituie un sistem de reguli care, aplicat la o clasă de
probleme de acelaşi tip, conduce de la o situaţie iniţială la un rezultat final prin intermediul unor operaţii
succesiv ordonate, unic determinate.
O informaţie iniţială pentru care un algoritm de calcul este aplicabil, se numeşte informaţie admisibilă.
Totalitatea informaţiilor de acest gen constituie domeniul algoritmului.
Cunoscând faptul că orice algoritm conţine un anumit număr de etape numite şi paşii
algoritmului, se poate afirma că regulile algoritmului f aplicate asupra informaţiei iniţiale, care aparţine
domeniului D, determină întotdeauna obţinerea informaţiei finale corespunzătoare. Ca urmare, un
algoritm poate fi definit ca o funcţie:
f = D--> F unde: D= domeniul algoritmului (informaţiile iniţiale);
F= soluţia finală (informaţiile finale).
În general, un algoritm se caracterizează prin:
unicitatea. regulile algoritmului determinând unicitatea ordinii în care au loc toate
transformările intermediare, dar şi obţinerea informaţiei finale, după care activitatea
algoritmului se opreşte.
finalitate. Orice pas al algoritmului trebuie să se termine după un număr finit de paşi, şi
anume atunci când este obţinut rezultatul final, nu cel intermediar. Această proprietate se
mai numeşte şi realizabilitate potenţială.
claritate (să fie definit). Fiecare pas al algoritmului trebuie să fie precis definit. Operaţiile
ce trebuie efectuate în cadrul fiecărui pas trebuie să fie specificate în mod riguros, precis,
astfel încât să nu apară ambiguităţi în interpretare lui de către cel care îl execută.
Totodată, trebuie riguros precizate toate etapele de calcul ce trebuie urmate pentru a
obţine soluţia finală;
eficacitate. Orice algoritm trebuie să fie eficace. Aceasta înseamnă că toate operaţiile
algoritmului să poată fi efectuate de un individ cu creion şi hârtie într-un interval de timp
finit.
generalitate (universal) - adică să permită rezolvarea oricărei probleme dintr-o
anumită clasă de probleme pentru care a fost stabilit.
Ca exemple de algoritmi cunoscuţi din matematică amintim: algoritmul lui Newton pentru aflarea
rădăcinii pătrate aritmetice a unui număr, algoritmul lui Euclid pentru aflarea celui mai mare divizor
comun a două numere etc .
Descrierea algoritmilor.
Transcrierea algoritmului într-un limbaj de programare, în vederea rezolvării lui cu ajutorul
calculatorului numeric poartă numele de program. Programele transmise calculatorului, ca o
reprezentare fidelă a algoritmului de calcul sunt transcrise într-un limbaj “înţeles” de calculator, nu
conţine ambiguităţi şi specifică precis şi clar doar operaţiile pe care calculatorul le poate executa.
Scrierea unui algoritm poate fi făcută rareori direct într-un limbaj de programare. Ca atare
realizarea unui program comportă, uzual nişte etape intermediare.
În vederea întocmirii unui algoritm de calcul şi utilizării acestuia la calculator, este necesară
realizarea următoarelor activităţi:
definirea problemei;
formularea modelului matematic al problemei;
stabilirea algoritmului de rezolvare a problemei;
reprezentarea algoritmului;
3
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Exemple
4
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
6. Testarea programului.
Testarea se face pe mai multe seturi de date care să acopere cazurile posibile ce pot
apărea.
3.2 Structuri fundamentale( secvenţa, decizia, repetiţia)
5
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
6
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
START
CITESTE
i
EITES
SUBRUTINA X
TE
PRINT i
STOP
V=Vi
A
A
C
NU V=V+r
C
DA
A V>Vr
Exemplu:
Se cere algoritmul şi schema logică pentru calculul lui n!
Paşii algoritmului de calcul sunt :
1. citeşte valoarea lui n;
7
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
START
Citeşte
n
p: = 1
i: = 1
p: = p * i
i: = i + 1
Diagrama arborescentă
Diagrama arborescentă constituie o altă modalitate de reprezentare grafică a algoritmilor. Ca şi
în cazul schemelor logice, există mai multe convenţii de reprezentare a operaţiilor în cadrul algoritmilor.
IN PSEUDOCOD AVEM:
a) Secvenţa – este o structură realizată prin scrierea succesivă (în secvenţă) a comenzilor
componente.
Exemplu: citeşte A,B
atribuie C A + B
scrie A , B , C
stop
Efectul execuţiei unei comenzi depinde de poziţia comenzii în cadrul secvenţei .
b) Decizia – este o structură care asigură alegerea pentru execuţie a unei secvenţe din două
alternative posibile.
Structura comenzii: dacă condiţie atunci
secvenţa1
altfel
secvenţa 2
[]
Începutul comenzii de decizie este marcat de cuvântul cheie “dacă” iar sfârşitul său de semnul []
Execuţia acestei comenzi comportă următoarele etape:
se evaluează “ condiţia”;
dacă rezultatul evaluării este adevărat (condiţie îndeplinită) se execută secvenţa 1;
în caz contrar se execută secvenţa 2.
După executarea secvenţei 1 sau a secvenţei 2 se trece la următoarea comandă (cea după
semnul [] )
Observaţie: În cazul în care secvenţa care urmează după cuvântul cheie “altfel” lipseşte, se utilizează
forma simplificată a deciziei:
8
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Exemplul:
dacă A > B atunci
scrie A
altfel
scrie B
[]
Efectul execuţiei exemplului de mai sus este următorul:dacă valoarea variabilei A este mai
mare decât a variabilei B se scrie valoarea lui A în caz contrar se scrie valoarea variabilei B şi nu
valoarea variabilei A.
Exemplul: Decsrierea în Pseudocod a algoritmului de aflare a celui mai mare element
din 3 valori reale desemnate prin variabilele a,b,c.Variabila “x” va conţine cel mai mare element din cele
3 valori.Algoritmul de rezolvare a unei probleme nu este unic.Ca atare se dau două descrieri
Pseudocod pentru rezolvarea acestei probleme.
a) varianta 1
citeşte a,b,c
dacă a>b atunci
atribuie x a
altfel
atribuie x b
[]
dacă c > x atunci
atribuie x c
[]
scrie x
stop
b) varianta 2
citeşte a,b,c
atribuie x a
dacă x < b atunci
atribuie x b
[]
dacă x < c atunci
atribuie x c
[]
scrie x
stop
O variantă simplificată : citeşte a,b,c,
atribuie x a
dacă x < b atunci atribuie x b
9
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
c2 : secvenţa 2
.
.
cn : secvenţa n
rest : secvenţa n+1
[]
Unde c1 , c2 , ... cn sunt etichete şi se folosesc pentru identificarea secvenţelor.Sfârşitul comenzii este
marcat de _[] iar liniile textului selecţiei sunt marcate prin etichetele c.
Modul de execuţie al comenzii de selecţie este următorul:
se evaluează expresia
se identifică eticheta ci ce are aceeaşi valoare cu expresia ( în urma evaluării expresiei)şi
este selectată secvenţa corespunzătoare.Dacă nici o etichetă nu are valoarea expresiei
atunci este selectată secvenţa n+1, corespunzătoare etichetei rest.
se execută secvenţa selecctată şi se sare la sfârşitul comenzii de selecţie adică după
semnul [].
Exemplu: Să se adune valoarea întreagă v la una din variabilele s 0,s1,s2 ,s3, după cum
restul împărţirii valorii v la 4 este 0,1,2 sau 3 .Descrierea în Pseudocod arată astfel:
citeşte v,s0,s1,s2,s3
alege v – int ( v/4)*4 dintre
0: atribuie s0 s0 + v
1: atribuie s1 s1 + v
2: atribuie s2 s2 + v
3: atribuie s3 s3 + v
[]
scrie s0,s1,s2,s3
stop
STRUCTURI REPETITIVE IN PSEUDOCOD
În acest caz , eticheta “rest” şisecvenţa respectivă lipseşte ,deoarece domeniul de valori ale expresiei
este mulţimea (0,1,2,3).
a) Ciclul cu test final – În rezolvarea unei probleme , nu de puţine ori apare situaţia executării
repetate a unei secvenţe de operaţii.O astfel de combinaţie , în care execuţia unui grup de
operaţii se repetă se numeşte ciclu sau iteraţie.Pentru reprezentarea ei se utilizează o comandă
de ciclare care specifică atâtoperaţiile care se repetă cât şi condiţia de repetare.
Forma generală a comenzii de ciclare cu test final este următoarea:
repetă
secvenţa
până condiţia
10
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
[]
Modul de execuţie al comenzii de ciclare este următorul:
1-se execută secvenţa
2-se evaluează condiţia şi dacă rezultatul este fals(condiţie neîndeplinită)se continuă cu etapa 1 , altfel
execuţia comenzii se termină şi se trece la comanda următoare.
Exemplu: Se dă algoritmul lui Euclid pentru afişarea celui mai mare divizor comun a
două numere întregi m,n(m>=n>0).
1. citeşte valorile lui m şi n
2. atribuie lui c valoarea lui n ( în variabila c se reţine cel mai mare divizor
comun )
3. atribuie lui r restul împărţirii întregi a lui m la n
4. dacă r diferit de 0 atunci treci la 7
5. scrie valoarea lui c
6. stop
7. atribuie lui m valoarea lui n
8. atribuie lui n valoarea lui r
9. treci la pasul 2
Se observă că operaţiile care se realizează calculul restului şiactualizarea valorilor c, m şi n se
repetă.
Folosind Descrierea în Pseudocod a algoritmului şi ciclul cu test final vom avea:
citeşte m,n
repetă
atribuie c n , r m-int(m/n)*n
atribuie mn , n r
până r=0
_[]
scrie c
stop
Condiţia de terminare a ciclului poate fi orice expresie logică.Secvenţa de operaţii din ciclu
alcătuieşte corpul ciclului .Ea poate conţine oriceoperaţii, inclusiv iteraţii.
b) Ciclul cu test iniţial – În cazul ciclurilor sau iteraţiilor condiţia de
ciclare poate apare şi la începutul secvenţei de ciclare
Forma generală este :
cât timp condiţia execută
secvenţa
[]
Condiţia poate fi orice expresie logică , iar secvenţa poate conţine orice comenzi , inclusiv
comenzi de ciclare.
Modul de execuţie al ciclului cu test iniţial :
1-se evaluează condiţia;dacă rezultatul este fals(condiţie neîndeplinită) execuţia se termină,iar dacă
rezultatul este adevărat se continuă secvenţa(etapa 2)
2-se execută secvenţa,după care se continuă cu 1.
În cazul în care rezultatul evaluării condiţiei este fals încă de la început,secvenţa nu se
execută niciodată spre deosebire de ciclul cu test final,când secvenţa se executa cel puţin o dată.
Scrierea algoritmului lui Euclid în Pseudocod folosind ciclul cu test iniţial ne conduce la:
citeşte m,n
atribuie c n , r m-int(m/n)*n
cât timp r <> 0 execută
atribuie m n , n r, c n
atribuie r m-int(m/n)*n
[]
11
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
scrie c
stop
c) Ciclul de contor, cu forma generală:
pentru contor = val iniţială, val.finală,pas execută
secvenţa
[]
unde prin contor se înţelege o variabilă cu valori întregi:”valoarea iniţială, finală şi pas” pot fi expresii
aritmetice cu valori întregi.
Execuţia ciclului cu contor se explicitează astfel:
1) variabilei contor i se atribuie valoarea iniţială;
2) se verifică condiţia contor > val. Finală; dacă rezultatul este fals se continuă cu, astfel
execuţia ciclului se termină;
3) se execută secvenţa
4) se modifică valoarea contorului cu pasul p şi se continuă cu pasul 2)
Exemplu: aflarea lui n!
Observaţii: 1. Dacă pasul de ciclare este 1, se poate omite
2. Algoritmul a fost completat şi pentru cazul în care n = 0
citeşte n
atribuie p = 1
dacă n>0 atunci
pentru i=1,n execută
atribuie p=p*i
[]
[]
scrie p
stop
12
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Scheme logice
Schemele logice reprezintă scrierea algoritmilor de calcul cu ajutorul unor simboluri (forme)
geometrice, care evidenţiază diferite tipuri de acţiuni.
Realizarea schemei logice corespunzătoare unui algoritm este utilă fie la depanarea
programelor, fie la lucrul în echipă, fie la schimbul de informaţii dintre diverse grupuri de
programatori,întrucât ea specifică precis şi clar ordinea de parcurgere a blocurilor (simbolurilor
geometrice).
Simbolurile uzuale utilizate în realizarea schemelor sunt cuprinse în tabelul de mai jos:
13
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
START
CITESTE
i
EITES
SUBRUTINA X
TE
PRINT i
STOP
STA STA
RT RT I
I
CITESTE CITESTE
I
i DA i DA I
A2
EITES EITES I
TE TE
A1 A3
PRINT i PRINT i
STOP STOP ii
CASE - OF I
IF - THEEN
- STRUCTURA REPETITIVĂ (CICLICĂ) se bazează pe repetarea unei secvenţe din
algoritm, care poate să cuprindă una sau mai multe operaţii. Există următoarele tipuri de
operaţii repetitive:
- WHILE – DO presupune executarea unei anumite secvenţe din algoritm atâta timp cât
este îndeplinită condiţia C. Deoarece structura este condiţionată anterior, există
posibilitatea ca secvenţa respectivă să nu se execute niciodată.
- DO – UNTIL , condiţionare posterioară, secvenţa din program se execută cel puţin o dată,
întrucât decizia de reluare a secvenţei se ia după executarea acesteia.
- DO – FOR se execută atunci când se cunoaşte de câte ori trebuie repetată o anumită
secvenţă. Ea se caracterizează prin apariţia unei variabile numită contor, care evidenţiază
numărul de repetări a secvenţei.
14
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
V=Vi
A
A
C
NU V=V+r
C
DA
A V>Vr
WHILE - DO
DO - UNTIL DO - FOR
Exemplu:
Se cere algoritmul şi schema logică pentru calculul lui n!
Paşii algoritmului de calcul sunt :
9. citeşte valoarea lui n;
10. atribuie lui P valoarea 1;
11. atribuie lui I valoarea 1;
12. atribuie lui P valoarea expresiei P * I;
13. atribuie lui I valoarea expresiei I + 1;
14. dacă I<N atunci treci la pasul 4;
15. scrie valoare lui P;
16. stop.
Schema logică corespunzătoare algoritmului:
START
Citeşte
n
p: = 1
i: = 1
p: = p * i
i: = i + 1
Diagrama arborescentă
Diagrama arborescentă constituie o altă modalitate de reprezentare grafică a algoritmilor. Ca şi
în cazul schemelor logice, există mai multe convenţii de reprezentare a operaţiilor în cadrul algoritmilor.
Limbajul Pseudocod
15
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
16
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
h) Secvenţa – este o structură realizată prin scrierea succesivă (în secvenţă) a comenzilor
componente.
Exemplu: citeşte A,B
atribuie C A + B
scrie A , B , C
stop
Efectul execuţiei unei comenzi depinde de poziţia comenzii în cadrul secvenţei .
i) Decizia – este o structură care asigură alegerea pentru execuţie a unei secvenţe din două
alternative posibile.
Structura comenzii: dacă condiţie atunci
secvenţa1
altfel
secvenţa 2
[]
Începutul comenzii de decizie este marcat de cuvântul cheie “dacă” iar sfârşitul său de semnul []
Execuţia acestei comenzi comportă următoarele etape:
se evaluează “ condiţia”;
dacă rezultatul evaluării este adevărat (condiţie îndeplinită) se execută secvenţa 1;
în caz contrar se execută secvenţa 2.
După executarea secvenţei 1 sau a secvenţei 2 se trece la următoarea comandă (cea după
semnul [] )
Observaţie: În cazul în care secvenţa care urmează după cuvântul cheie “altfel” lipseşte, se utilizează
forma simplificată a deciziei:
dacă condiţie atunci
secvenţa1
[]
În cazul în care condiţia nu este îndeplinită se trece direct la comanda ce urmează deciziei
Exemplul:
dacă A > B atunci
scrie A
altfel
scrie B
[]
Efectul execuţiei exemplului de mai sus este următorul:dacă valoarea variabilei A este mai
mare decât a variabilei B se scrie valoarea lui A în caz contrar se scrie valoarea variabilei B şi nu
valoarea variabilei A.
Exemplul: Descrierea în Pseudocod a algoritmului de aflare a celui mai mare element
din 3 valori reale desemnate prin variabilele a,b,c.Variabila “x” va conţine cel mai mare element din cele
3 valori.Algoritmul de rezolvare a unei probleme nu este unic.Ca atare se dau două descrieri
Pseudocod pentru rezolvarea acestei probleme.
a) varianta 1
citeşte a,b,c
dacă a>b atunci
atribuie x a
altfel
atribuie x b
[]
dacă c > x atunci
17
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
atribuie x c
[]
scrie x
stop
b) varianta 2
citeşte a,b,c
atribuie x a
dacă x < b atunci
atribuie x b
[]
dacă x < c atunci
atribuie x c
[]
scrie x
stop
O variantă simplificată : citeşte a,b,c,
atribuie x a
dacă x < b atunci atribuie x b
dacă x < c atunci atribuie x c
scrie x
stop
Observaţie: Ultima variantă a algoritmului are avantajul că poate fi uşor generalizată pentru aflarea
maximului unui şir.
j) Selecţia reprezintă o extindere a operaţiei de decizie, ea permitând alegerea unei alternative din
mai multe posibile.Forma generală a comenzii de selecţie este următoarea :
alege expresia dintre
c1 : secvenţa 1
c2 : secvenţa 2
.
.
cn : secvenţa n
rest : secvenţa n+1
[]
Unde c1 , c2 , ... cn sunt etichete şi se folosesc pentru identificarea secvenţelor.Sfârşitul comenzii este
marcat de _[] iar liniile textului selecţiei sunt marcate prin etichetele c.
Modul de execuţie al comenzii de selecţie este următorul:
se evaluează expresia
se identifică eticheta ci ce are aceeaşi valoare cu expresia ( în urma evaluării expresiei)şi
este selectată secvenţa corespunzătoare.Dacă nici o etichetă nu are valoarea expresiei
atunci este selectată secvenţa n+1, corespunzătoare etichetei rest.
se execută secvenţa selecctată şi se sare la sfârşitul comenzii de selecţie adică după
semnul [].
Exemplu: Să se adune valoarea întreagă v la una din variabilele s 0,s1,s2 ,s3, după cum
restul împărţirii valorii v la 4 este 0,1,2 sau 3 .Descrierea în Pseudocod arată astfel:
citeşte v,s0,s1,s2,s3
alege v – int ( v/4)*4 dintre
0: atribuie s0 s0 + v
18
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
1: atribuie s1 s1 + v
2: atribuie s2 s2 + v
3: atribuie s3 s3 + v
[]
scrie s0,s1,s2,s3
stop
În acest caz , eticheta “rest” şisecvenţa respectivă lipseşte ,deoarece domeniul de valori ale
expresiei este mulţimea (0,1,2,3).
k) Ciclul cu test final – În rezolvarea unei probleme , nu de puţine ori apare situaţia executării
repetate a unei secvenţe de operaţii.O astfel de combinaţie , în care execuţia unui grup de
operaţii se repetă se numeşte ciclu sau iteraţie.Pentru reprezentarea ei se utilizează o comandă
de ciclare care specifică atâtoperaţiile care se repetă cât şi condiţia de repetare.
Forma generală a comenzii de ciclare cu test final este următoarea:
repetă
secvenţa
până condiţia
[]
Modul de execuţie al comenzii de ciclare este următorul:
1-se execută secvenţa
2-se evaluează condiţia şi dacă rezultatul este fals(condiţie neîndeplinită)se continuă cu etapa 1 , altfel
execuţia comenzii se termină şi se trece la comanda următoare.
Exemplu: Se dă algoritmul lui Euclid pentru afişarea celui mai mare divizor comun a
două numere întregi m,n(m>=n>0).
10. citeşte valorile lui m şi n
11. atribuie lui c valoarea lui n ( în variabila c se reţine cel mai mare divizor
comun )
12. atribuie lui r restul împărţirii întregi a lui m la n
13. dacă r diferit de 0 atunci treci la 7
14. scrie valoarea lui c
15. stop
16. atribuie lui m valoarea lui n
17. atribuie lui n valoarea lui r
18. treci la pasul 2
Se observă că operaţiile care se realizează calculul restului şiactualizarea valorilor c, m şi n se
repetă.
Folosind Descrierea în Pseudocod a algoritmului şi ciclul cu test final vom avea:
citeşte m,n
repetă
atribuie c n , r m-int(m/n)*n
atribuie mn , n r
până r=0
_[]
scrie c
stop
Condiţia de terminare a ciclului poate fi orice expresie logică.Secvenţa de operaţii din ciclu
alcătuieşte corpul ciclului .Ea poate conţine oriceoperaţii, inclusiv iteraţii.
l) Ciclul cu test iniţial – În cazul ciclurilor sau iteraţiilor condiţia de ciclare poate apare şi la
începutul secvenţei de ciclare
Forma generală este :
cât timp condiţia execută
19
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
secvenţa
[]
Condiţia poate fi orice expresie logică , iar secvenţa poate conţine orice comenzi , inclusiv
comenzi de ciclare.
Modul de execuţie al ciclului cu test iniţial :
1-se evaluează condiţia;dacă rezultatul este fals(condiţie neîndeplinită) execuţia se termină,iar dacă
rezultatul este adevărat se continuă secvenţa(etapa 2)
2-se execută secvenţa,după care se continuă cu 1.
În cazul în care rezultatul evaluării condiţiei este fals încă de la început,secvenţa nu se
execută niciodată spre deosebire de ciclul cu test final,când secvenţa se executa cel puţin o dată.
Scrierea algoritmului lui Euclid în Pseudocod folosindciclul cu test iniţial ne conduce la:
citeşte m,n
atribuie c n , r m-int(m/n)*n
cât timp r <> 0 execută
atribuie m n , n r, c n
atribuie r m-int(m/n)*n
[]
scrie c
stop
m) Ciclul de contor, cu forma generală:
pentru contor = val iniţială, val.finală,pas execută
secvenţa
[]
unde prin contor se înţelege o variabilă cu valori întregi:”valoarea iniţială, finală şi pas” pot fi expresii
aritmetice cu valori întregi.
Execuţia ciclului cu contor se explicitează astfel:
5) variabilei contor i se atribuie valoarea iniţială;
6) se verifică condiţia contor > val. Finală; dacă rezultatul este fals se continuă cu, astfel
execuţia ciclului se termină;
7) se execută secvenţa
8) se modifică valoarea contorului cu pasul p şi se continuă cu pasul 2)
Exemplu: aflarea lui n!
Observaţii: 1. Dacă pasul de ciclare este 1, se poate omite
2. Algoritmul a fost completat şi pentru cazul în care n = 0
citeşte n
atribuie p = 1
dacă n>0 atunci
pentru i=1,n execută
atribuie p=p*i
[]
[]
scrie p
stop
n) Proceduri şi funcţii
În rezolvarea unor probleme apar frecvent situaţii când un număr decomenzi se repetă
schimbându-se numai variabilele ce compun aceste comenzi,structura comenzilor rămânând aceeaşi.
Pentru a nu repeta acel număr de comenzi în mai multe locuri în cadrul descrierii algoritmului de
rezolvare a problemei se folosesc procedurile şi funcţiile.
Procedura – descrie în termeni generali un algoritm cu posibilitatea de a aplica acel algoritm în
diverse cazuri particulare concrete.
20
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
S=
Descrierea în Pseudocod a procedurii este :
Procedura norma (a, n; s) este :
atribuie s 0
pentru i=1,n,1 execută
atribuie s s + |ai|
[]
sfârşit norma
Numele procedurii este “norma”.Parametrii de intrare necesari pentru a se realiza calculele din
procedură sunt vectorul a şi numărul de elemente ale vectorului n, iar parametrul de ieşire este S,prin
el se obţine rezultatul calculelor- norma . Separarea parametrilor de ieşire de cel de intrare se face prin
punct şi virgulă . Parametrii de intrare şi cei de ieşire specificaţi la definirea procedurii se numesc
parametrii formali.
Exemplu: Să se folosească procedura definită pentru a determina dacă norma vectorului x de l
componente este mai mare decât norma vectorului w de m componente.
Descrierea în Pseudocod a algoritmului de aflare a celei mai mari dintre normele vectorilor x şi
w este următoarea :
citeşte l ,(xi , i = 1, 1)
citeşte m,(xi , i = 1,m)
execută norma (x ,l ; s1)
execută norma (w,m; s2)
dacă s1>s2 atunci
scrie ‘norma vectorului x este mai mare’
altfel
scrie ‘norma vectorului w este mai mare’
[]
stop
În apelulprocedurii norma , parametrii x,l,s1,respectiv w,m,s2 sunt parametrii actuali.
Comanda “execută” urmată de numele procedurii are ca efect execuţia operaţiilor care
constituie procedura cu numele specificat , în care valorile parametrilor formali sunt înlocuite cu
valorile parametrilor efectivi corespunzători,adică parametrii a,n,s din procedura sunt înlocuiţi cu x,l,s1
respectiv w,m,s2 din apelul procedurii.
21
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
= =
22
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
T - T atribuie S0,T+1
pentru i=1,n,1 execută i:=1
atribuie S S + T*(1 / (2*i-1) )
T -T
NU DA
[] i<=n
atribuie PI 4 * S S := S + T*(1 / (2*i-1) )
scrie PI T := - T
stop i:=i+1
Variabila T asigură însumarea corectă
a termenilor cu semne contrare. T:=-T
d)Programul Pascal
Program calcul_pi; Scrie PI
var
i,n:integer; STOP
s,pi,t:real;
BEGIN{main}
writeln(‘introduceti valoarea lui
n:intreg’);
readln(n);
s:=0;t:=1;
for i:=1 to n do
begin
s:=s + t / (2 * i - 1);
t:= - t ;
end;
pi := 4 * s ;
writeln(‘valoarea lui PI=’,PI:10,8);
END.
23
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Să se calculeze pentru un n dat , toţi termenii şirului lui Fibonacci, cunoscând relaţia de
recurenţă f k = f k-1+ f k-2 , pentru orice k >= 2 şi f0 =0, f1 = 1
a) Descrierea algoritmului în limbaj natural
Relaţia de recurenţă necesită două valori iniţiale f 0 şi f . Această relaţie va fi aplicată de n-2 ori ,
actualizând de fiecare dată pe f k-2 şi f k-1.Deci pentru calculul termenului curent f k sunt suficienţi 2
termeni consecutivi din şir. Vom nota cu “a” termenul f k-2 ,cu “b” f k-1 şi cu “c” termenul f k calculat.
b.) Descrierea algoritmului în pseudocod:
citeşte n
scrie n
{iniţializează primi 2 termeni ai şirului}
atribuie a 0, b 1
scrie a,b {primi doi termeni}
pentru k=3, n, 1 execută
atribuie c a+b {calculează termenul curent}
24
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
25
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
26
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
27
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
until n>0; 0.
i:=0; Exemplu:
repeat Pentru n=4523, m=2 se va afisa 2, iar pt.
inc(i); write ('Numarul',i,':'); n=123 si m=4 se va afisa 0.}
readln(nr); nr1:=abs(nr); var n,m,cifra,k:word;
repeat begin
s:=0; write('n='); readln(n);
repeat write('pozitia='); readln(m);
inc(s,nr1 mod 10); cifra:=0; k:=0;
nr1:=nr1 div 10 while n<>0 do begin
until nr1=0; k:=k+1;
nr1:=s if k=m then
until nr1<10; cifra:=n mod 10;
if not odd(nr1) then n:=n div 10;
writeln(nr,'are cifra de baza',nr1) end;
until i=n; writeln; writeln('cifra:',cifra);
end. end.
6) Sa se calculeze ultima cifra a numarului a^n, 9) Sa se verifice daca numarul natural n este
unde a si n sunt numere bine ordonat.(n are cifrele fie
naturale mai mici ca 10000. in ordine crescatoare, fie in ordine
Exemplu: descrescatoare).ex:123 este
2^1000 are ultima cifra 6.} Solutie;
var a,n,i,p,r:word; Se pune problema in ce ordine are n cifrele:
begin crescatoare sau descrescatoare?
write('a='); readln(a); Ne dam seama de acest lucru comparand
write('n='); readln(n); ultimele doua cifre ale lui n.Dar daca
r:=a mod 10; p:=1; aceste sunt egale?Pentru a rezolva aceasta
for i:=1 to n do problema am facut un 'while' ce
begin elimina ultimele cifre din n. Apoi am facut o
p:=p*r; p:=p mod 10; conventie: daca n are cifrele
end; in ordine descrescatoare , t=0, iar daca le are
writeln('ultima cifra:',p); in ordine crescatoare t=1.}
end. var n,c,t,r:word;
7) Sa se genereze toate numerele naturale de ok:boolean;
patru cifre (abcd), ale caror begin
cifre sunt consecutive (cifra miilor este cea mai ok:=true;
mica), iar a*d=(bc)/2.Sa se write('n='); readln(n);
precizeze numarul lor. c:=n mod 10; n:=n div 10;
Observatie: while c= n mod 10 do
un singur numar indeplineste conditiile:4567} n:=n div 10;
var a,b,c,d,n:0..9; if c<n mod 10 then t:=0
nr:word; else t:=1;
begin r:=n mod 10; n:=n div 10;
n:=0; while n<>0 do begin
for a:=1 to 6 do c:=r;
begin if (c> n mod 10) and (t=0) then ok:=false;
b:=a+1; c:=b+1; d:=c+1; if (c< n mod 10) and (t=1) then ok:=false;
if a*d=(10*b+c) div 2 then begin r:=n mod 10; n:=n div 10;
nr:=1000*a+100*b+10*c+d; end;
write(nr:5); inc(n); end; if ok then writeln('bine ordonat')
end; else writeln('nu e bine ordonat');
writeln; end.
writeln(' numar de numere:',n); 10) Se dau doua numar natural x si y cu cel
end. mult zece cifre.Se cere sa se
8) Se citesc de pe mediul standard de intrare afiseze suma dintre produsul cifrelor lui x si
doua numere naturale n si m. Sa produsul cifrelor lui y.}
se afiseze cifra de pe pozitia m din numarul n. var
(cifrele vor fi numerotate de la x, y, px, py:longint;
dreapta la stanga).Daca nu exista o cifra pe begin
pozitia respectiva, se va afisa write ('x='); readln(x);
28
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
3.5.2 Divizibilitate
1)Determinaţi toate numerele care sunt for i:=1 to n do begin
multipli de k, care depăşesc valoarea n. read(x);
program multipli2; if x mod 2 =0 then
var k,i,n:longint; nr_pare:=nr_pare+1;
begin end;
write('k=');readln(k) write(nr_pare);
; end.
write('n=');readln(n) 3) Se citeste un numar natural n Sa se numere
; divizorii sai (inclusiv 1 si
i:=k; el insusi)}
while i<=n do
begin var n,nr_div,i:integer;
write(i,' '); begin
inc(i,k); Write('n='); readln(n);
end; nr_div:=0;
end. for i:=1 to n do
2) Se citesc n numere naturale.Sa se numere if n mod i=0 then
cate din ele sunt pare. nr_div:=nr_div+1;
write(nr_div);
var n,i,x,nr_pare:integer; end.
begin 4) Sa se genereze toate numerele naturale de
Write('n='); readln(n); patru cifre de forma 1bcd care
nr_pare:=0;
29
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
indeplinesc simultan conditiile:d<c, b-c=1, iar b writeln('Cel mai mic numar natural cu
si d sunt divizibile cu 3 . exact',d,'divizori este',n);
Sa se precizeze numarul lor. write('Divizorii lui', n,' sunt:');
Exemplu: for i:=1 to n do
Sunt 6 numere:1320, 1650, 1653, 1980, 1983, if n mod i=0 then write(i:5);
1986} writeln;
var b,c,d,n:0..9; break end
nr:word; else inc(n)
begin until false;
n:=0; readln
for b:=3 to 9 do end.
for d:=0 to 6 do begin 7) SA se determine descompunerea in factori
c:=b-1; primi a unui numar natural n,
if (d<c) and (b mod 3=0) and (d mod 3=0) then citit de pe mediul standard de intrare.Afisarea
begin se va efectua ca in exemplul
nr:=1000+100*b+10*c+d; urmator.
write(nr:5); inc(n); Exemplu:
end; pentru n=12 avem:
end; 12|2
writeln; 6|2
writeln('sunt',n,'numere'); 3|3
end. 1|-}
5) Sa se verifice daca numarul natural n este var n,p:word;
perfect sau nu.( n este perfect begin
daca este egal cu suma divizorilor sai mai mici write('n='); read(n); p:=2;
ca el). while n>1 do
Exemplu: begin
n=6 este perfect deoarece 6=1+2+3.} while n mod p=0 do
var n,i,s:word; begin
begin writeln(n,'|',p);
write('n='); readln(n); n:=n div p;
s:=0; end;
for i:=1 to n div 2 do p:=p+1;
if n mod i=0 then s:=s+i; end;
if n=s then writeln(1,'|-');
writeln('numar perfect') end.
else 8) SA se determine suma numerelor naturale
writeln('numarul nu este perfect'); mai mici ca n, divizibile cu 5.}
end. var i,n,s:word;
begin
6) Sa se determine cel mai mic numar natural write('n='); readln(n);
nenul care are exact n divizori s:=0;
(inclusiv divizorii banali), d>=2 dat.Sa se for i:=5 to n do
afiseze acest numar impreuna cu if i mod 5=0 then s:=s+i;
divizorii sai. writeln('s=',s);
Exemplu: end.
d=10 : n=48 9) Sa se determine cifrele x si y astfel incat
Divizori: 1,2,3,4,6,8,12,16,24,48} numarul 1x2y sa fie divizibil
var d,nr:byte; cu 3.
n,i:word; Solutie:
begin Daca x si y sunt cifre atunci x,y apartin
repeat multimii{0,1,..,9) cu x<>0.Vom
write('d='); readln(d) verifica daca suma 1+x+2+y=3+x+y este
until d>=2; divizibila cu 3}
n:=2; var x,y:byte;
repeat begin
nr:=0; for x:=1 to 9 do
for i:=1 to n do for y:=0 to 9 do
if n mod i=0 then inc(nr); if (x+y+3) mod 3=0 then
if nr=d then begin writeln(1,x,2,y);
30
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
31
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
prim:boolean; t:=true;
begin for i:=2 to trunc(sqrt(x)) do
write('n='); readln(n); if x mod i=0 then t:=false;
prim:=true; if t then k:=k+1;
for i:=2 to trunc(sqrt(n)) do y:=x+2; t:=true;
if n mod i =0 then for i:=2 to trunc(sqrt(y)) do
prim:=false; if y mod i=0 then t:=false;
if prim then if t then k:=k+1;
write('Numarul este prim') if k=2 then write (x+1,' ');
else end;
write('Numarul nu este prim'); end.
end. 5) Se citeste un numar natural de cel mult 8 cifre.
2) Se citeste un numar natural n.Sa se afiseze Sa se afiseze cel
divizorii sai primi. mai apropiat numar prim fata de acesta.}
ex:n=9 VAR x,i,k,n1,n2: longint;
=>3} ok: boolean;
begin
var n,i,j:integer; writeln('dati numarul ');
prim:boolean; readln (x); n1:=x;
begin repeat
write('n='); read(n); inc(n1);
for i:=2 to n-1 do ok:=true;
if n mod i=0 then begin for i:=2 to trunc(sqrt(n1)) do
prim:=true; if n1 mod i =0 then ok:=false;
for j:=2 to trunc(sqrt(i)) do until ok;
if i mod j =0 then n2:=x+1;
prim:=false; repeat
if prim then write(i); dec(n2); ok:=true;
end; for i:=2 to trunc (sqrt(n2)) do
end. if n2 mod i=0 then ok:=false;
3) Sa se afiseze toate numerele prime mai mici sau until ok;
egale decat n, n>1 dat. if k-n2<n1-x then writeln (n2)
ex:n=10 else writeln(n1);
=>2 3 5 7} readln;
var n,i,j:byte; end.
prim:boolean; 6) Se da un numar natural n (0<n<1000000).Se cere
begin sa se afiseze toate
write('n='); readln(n); perechile de numere gemene (a,b), a,b<=n. Perechea
for i:=2 to n do begin (a,b) este o
prim:=true; pereche de numere gemene daca a si b sunt prime si
for j:=2 to trunc(sqrt(i)) do valoarea absoluta a
if i mod j=0 then begin diferenteia-b este 2.}
prim:=false; break; end; var
if prim then write(i:5); i,j,n,l:integer;
end; bec: boolean;
writeln; begin
end. write ('n='); readln(n);
4) Sa se afiseze toate numerele naturale x mai mici for i:=2 to n-2 do begin bec:=true;
decat n,natural, cu for j:=2 to trunc(sqrt(i)) do
proprietatea ca x-1 si x+1 sunt numere prime. if i mod j=0 then bec:= false;
Exemplu: if bec then begin
pentru n=15 se vor afisa: 4,6,12.} l:=trunc (sqrt(i+2));
var x,y,n,i,k:integer; for j:=2 to l do
t:boolean; if (i+2) mod j=0 then
begin bec:=false;
write('n='); readln(n); if bec then write ('(',i,',',i+2,') ');end;
for x:=2 to n-2 do end;
begin readln;
k:=0; end.
32
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
7) Dându-se un număr întreg N, să se afişeze toţi factorii primi ai acestuia precum şi ordinele lor de
multiplicitate.
a) Descrierea algoritmului în limbaj natural:
O soluţie posibilă ar fi aceea de a alege dintre numerele 2,3,4,5...d...[n/2] pe acelea care sunt
numere prime urmând a fi “extrase” din numărul n.Ordinul de multiplicare al fiecărui factor prim d va fi
egal cu numărul de împărţiri cu rest nul care se pot face succesiv cu el.Pentru a verifica că d este
număr prim trebuie cercetată divizibilitatea sa cu 2,3,4,...[sqrt(d)],ceea ce presupune un număr mare de
împărţiri.O serie de observaţii ce se vor face va conduce la reducerea numărului de calcule.Dintre toate
numerele pare, singurul număr prim este 2.Deci este suficient să căutăm factorii primi numai printre 2 şi
numerele impare ce satisfac condiţia 2k+1<=[n/2] (partea întreagă din n/2).
Dacă se scot din “n” divizorii săi în ordine crescătoare, un număr neprim nu va fi găsit divizor al
lui n, deoarece proprii săi factori primi au fost eliminaţi din n. De exemplu un număr nu se mai divide cu
25 după ce toţi divizorii 5 au fost eliminaţi. Deci nu este necesar să se verifice dacă un număr este prim.
Algoritmul ne asigură că dacă un număr este divizor al lui n atunci acesta este un divizor prim.
Căutarea divizorilor este o operaţie care se repetă ciclic necunoscându-se aprioric numărul de
repatări. Operaţia continuă până numărul mai admite divizori (n>1). Dacă n=1, el nu admite divizori, deci
ciclul nu se va efectua niciodată (se va folosi ciclu cu test iniţial).
Întrucât valoarea lui n se modifică prin extragerea divizorilor,este necesară afişarea sa înaintea
începerii procesului de căutare a acestora.
b) Descrierea şi semnificaţia structurilor de date folosite
n : numărul ce se descompune
d : divizorul (potenţial )
m : ordinul de multiplicare
c) Descrierea algoritmului în Pseudocod
O primă formă arată astfel:
citeşte n
scrie n
atribuie d 2
cât timp *n mai admite divizori execută
* determină multiplicitatea eventualului divizor şi extrage d din n
dacă *d a fost divizor atunci
afişează d şi ordinul de multiplicare
[]
trecere la următorul d
[]
stop
Acţiunea “*determină multiplicitatea eventualului divizor d şi îl extrage pe d din n” are un
caracter ciclic, necunoscându-se numărul de repetări ale ciclului.Această acţiune se poate realiza în
Pseudocod astfel:
atribuie m 0 {ordinul de multiplicitate}
cât timp *n estedivizibil cu d execută
*extrage d din n
atribuie m m+1
[]
Deoarece divizorii se caută printre numerele 2,3,5,7.... acţiunea”*trecere la următorul d” se
realizează în Pseudocod astfel :
dacă d=2 atunci
atribuie d 3
altfel
atribuie d d + 2
[]
Acţiunea “* îl extrage pe d in n” se cere realizează astfel:
33
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
atribuie n n div d
Pentru valaorea maximă a lui d nu trebuiesc impuse condiţii , d va căpăta noi valori atât timp
cât n mai admite divizori.El nu va putea avea o valoare mai mare decât [ n / 2 ].
Având în vedere faptul că un număr n este prim dacă nu se divide cu 2,3,4,...[sqrt(n)]
algoritmul poate fi inductabil. Deci, trebuie căutaţi divizori ai lui n până la [sqrt(n)] şi nu până la [n/2]. În
final n va conţine iltimul divizor prim (cel mai mare) dacă acesta are multiplicitatea 1. În caz contrar, n va
fi 1. Algoritmul trebuie să facă distincţie între cele 2 situaţii.
Deoarece funcţia sqrt(n) oferă un rezultat de tip real, care poate fi afectat de erorile interne
operării cu numere reale, de exemplu sqrt(16) are valoarea 3,99999E+00, iar trunc(sqrt(16))=3, va
trebui introdusă corecţia sqrt(n+0.5), pentru ca algoritmul să lucreze corect.
citeşte n STAR
atribuie d 2 T
cât timp d<=(sqrt(n+0.5)) execută Citeste
atribuie m0 n
cât timp n mod d =0 execută
d := 2
atribuie n n div d
mm+1 DA
d<=(sqrt(n+0.5))
[]
dacă m>0 atunci m:=0
scrie d , m
[] n mod d :=0
dacă d = 2 atunci
atribuie d 3 n :=n divd
altfel m := m + 1
atribuie d d + 2 NU
NU DA
[] m>0
[]
Scrie d,m
dacă n > 1 atunci
scrie n
NU DA
[] d: = 2
n>1
stop
d := 3 d:= d + 2
Scrie n
STOP
d)Programul Pascal
Program divizorii ;{descompunere în factori primi}
var n,d,m:integer;
BEGIN{main}
write (‘introduceti n:integer’);
readln(n);
writeln(n:4,’are urmatorii factori primi’);
writeln(‘factor’,’‘:5,’multiplicitate’);
d:=2;{cel mai mic numar prim}
while d<= trunc(sqrt(n+0.5)) do
begin
34
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
m:=0;
while(n mod d)= 0 do
begin
n:=n div d;
m:=m+1;
end;
if m>0 then
writeln(d:5,’ ‘:9,m:2);
if d = 2 then d:=3
else d:=d+2;
end;
if n>1 then writeln(n:5,’ ‘:10,’1’);
END.
3.5.3 Algoritmul lui Euclid
1)Să se calculeze c.m.m.d.c. şi c.m.m.m.c a două numere întregi aplicând algoritmul lui
Euclid.
a.) Descrierea algoritmului în limbaj natural:
Se ştie că c.m.m.m.c a două numere A şi B este egal cu raportul dintre produsul celor două numere
şi c.m.m.d.c. al celor două numere. Ca atare în variabila p se va reţine produsul celor două numere.
Variabila CMMMC va reţine c.m.m.m.c, iar variabila CMMDC va reţine c.m.m.d.c. Conform
algoritmului lui Euclid de aflare a c.m.m.d.c se împarte cel mai mare număr (A) la cel mai mic (B) şi se
calculează restul împărţirii întregi (R). Dacă restul împărţiirii este 0 atunci c.m.m.d.c. este B. În caz
contrar se fac atribuirile: lui A i se atribuie B iar lui B i se atribuie R şi procesul se continuă până R=0.
Dacă la introducerea datelor B>A, se schimbă între ele cele două valori.
Dacă cel mai mic număr este 0 se va tipări mesajul ‘unul dintre numere este 0’ şi nu se va calcula
c.m.m.m.c.
Pentru calculul restului împărţirii se va folosi operatorul PASCAL ,,mod”.
b.) Descrierea şi semnificaţia structurilor de date folosite:
A,B : cele două numere întregi
CMMDC, CMMMC : variabile întregi pentru calculul c.m.m.d.c. şi c.m.m.m.c.
c)Descrierea şi semnificaţia structurilor de date folosite
a,b : cele două numere întregi
cmmdc,cmmmc : variabile xîntregi pt.calculul cmmdc şi cmmmc
p : produsul celor două numere ( pentru calculul cmmmc)
x : variabilă auxiliară
d)Descrierea algoritmului în Pseudocod
citeşte a,b
atribuie p a * b { reţine produsul numerelor }
dacă a<b atunci
atribuie x a {schimbă cele două valori între ele}
ab
bx
[]
dacă b<>0 atunci
atribuie r a mod b {restul împărţirii întregi }
cât timp r<>0 execută
atribuie a b {pregăteşte o nouă reluare
35
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
a algoritmului }
br
r a mod b
[]
atribuie cmmdc b
cmmmc p / b
scrie cmmmc,cmmdc
altfel
scrie ‘ unul din termeni este zero’
[]
stop
c)Programul Pascal
Program Euclid;
var a,b,x,p,r,cmmdc,cmmmc:integer;
BEGIN{main}
write(‘introduceţi a si b : integer’);
readln(a,b);
p:=a*b;
if a<b then
begin
x:=a;
a:=b;
b:=x;
end;
if b<>0 then
begin
r:=a mod b;
while r<>0 do
begin
a:=b
b:=r;
r:=a mod b;
end;
cmmdc:=b;
cmmmc:=p div b;
writeln(‘cmmdc=’,cmmdc:8,
’cmmmc=’,cmmmc:9);
end
else writeln(‘unul din termeni este
zero’);
END.
2
36
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
citeşte n
scrie n
{iniţializează primi 2 termeni ai şirului}
atribuie a 0, b 1
scrie a,b {primi doi termeni}
pentru k=3, n, 1 execută
atribuie c a+b {calculează termenul curent}
a b {actualizarea ultimilor doi}
b c {termeni din şir}
scrie c
stop
d.) Programul PASCAL:
program fibonacii;
var
a,b,c,k,n:integer;
BEGIN{main}
write('Introduceti nr. de
termeni:');
readln(n);
a:=0; b:=1;
write(a:3);
for k:=3 to n do
begin
c:=a+b;
a:=b; b:=c;
write(c:3)
end;
END.
2) Calculul termenului de rang n din 3) Se citeste de la tastatura o
sirul Fibonacci, n>0 dat.Sirul lui valoare n intreaga, pozitiva. Sa se
Fibonacci este definit astfel: f(1)=0, verifice
f(2)=1, f(n)=f(n-1)+f(n-2). daca acest numar este un
Exemplu: termen in sirul lui Fibonacci. In caz
n=7 : 1, 1, 2, 3, 5, 8,13.} contrar, sa
var n,a,b,c,i,fibo:word;
begin
se descompuna intr-o suma de
write('n='); readln(n); termeni Fibonacci.
if n=0 then fibo:=0 ex:5=2+3}
else if n=1 then fibo:=1 Program Fibo;
else begin var n,x,y,z,nr,k:longint;
a:=0; b:=1; BEGIN
for i:=2 to n do begin write('Dati valoarea lui n ');
c:=a+b; a:=b; b:=c; end; readln(n);
fibo:=b; end; nr:=n;
writeln('Termenul de rangul',n,'din sirul lui k:=1;
Fibonacci:',fibo); repeat
end. x:=0;
37
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
38
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
begin inc(e,p);
write('n='); readln(n); end;
e:=1; p:=1; write('E=',e);
for i:=1 to n do begin end.
p:=p*(2*i+1);
3.5.6 Determinare maxim/minim
1)Sa se determine printr-o for j:=i+1 to n do
singura parcurgere a unui vector atit begin
distanta:=sqrt(sqr(x[i]-x[j])
elementul +sqr(ordonata[i]-ordonata[j]));
maxim cit si minim if distanta>max then max:=distanta;
ex:3 end;
123 writeln(' distanta maxima este ',max);
=>1 readln;
3 end.
}
program MAX_MIN; 3){Sa se determine maximul
uses crt; elementelor pare din vector.
type vector=array[1..100]of integer; ex:n=3
var v:vector; 124
max,min,n,i:integer; =>4}
var a:array[1..20] of integer;
begin i,n,k,max,j:integer;
clrscr; ok:boolean;
write('n=');readln(n); begin
for i:=1 to n do begin write write('n=');
('v[',i,']='); readln(n);
readln(v[i]); for i:=1 to n do
end; begin
max:=v[1];min:=v[1]; write('a[',i,']=');
for i:=1 to n do begin if max<v[i] readln(a[i]);
then max:=v[i]; end;
if min> v[i] then
min:=v[i]; i:=1;
end; ok:=false;
write('max=',max); while (i<=n) and (ok=false) do
write('min=',min); if a[i] mod 2=0 then ok:=true
readln else i:=i+1;
end. if ok=false then begin
writeln('nu sunt elemente pare');
2)Fie n puncte .Sa se determine distanta max:=-1;
maxima dintre acestea end
ex:2 else begin
11 max:=a[i];
22 for j:=i+1 to n do
=>dist 1.41 if (a[j] mod 2=0) and (a[j]>max) then
} max:=a[j];
var writeln('maximul elementelor pare
y,x,ordonata:array[1..50]of real; este',max);
i,n,j:byte; max,distanta:real;s,ma:real; end;
begin readln;
write('Numarul de end.
elemente:');readln(n); 4) Se numeste varf creasta un maxim
for i:=1 to n do begin care in stanga sa are elementele ordonate
write('abscisa x',i,' '); crescator iar in dreapta sa are
read(x[i]); elementele ordonate descrescator.
write('ordonata y',i,' '); ex:3
read(ordonata[i]);end; 132
max:=0; => da este}
for i:=1 to n-1 do
39
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
40
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
begin
for i:=2 to N do begin
{insereaza a[i] la locul potrivit in sirul a[1]...a[i]}
a[0]:=a[i]; j:=i-1;
{cauta locul de inserare}
while a[j].cheie > a[0].cheie do begin
a[j+1]:=a[j]; j:=j-1
end;
a[j+1]:=a[0]
end;
end; {Insertie}
In cazul sortarii prin insertie C si M sint de ordinul N*N, avind valori minime cind tabloul e
ordonat si maxime cind tabloul e ordonat descrescator.
Aceasta metoda este stabila.
Teoria 2):
Sortarea prin insertie binara
Principiu: reprezinta o varianta a sortarii prin insertie, in care cautarea locului de inserare se
face aplicind cautarea binara, stiind ca secventa a[1],...,a[i-1] este deja ordonata.
Implementarea algoritmului in Pascal:
procedure InsertieBinara;
VAR i,j,s,d,m : TipIndex; x : TipElement;
begin
for i:=2 to N do begin
x:=a[i]; s:=1; d:=i-1;
while s<=d do begin
m:=(s+d) div 2;
if a[m].cheie > x.cheie then d:=m-1
else s:=m+1
end;
for j:=i-1 downto s do a[j+1]:=a[j];
a[s]:=x
end
end; {InsertieBinara}
In cadrul acestei metode, C este de ordinul N*log N, iar M de N*N.
Se obtin valori minime ale lui C pentru tablouri ordonate invers si valori maxime pentru tablouri
ordonate.
APLICATIA:
41
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
42
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
a[k]:=a[i]; a[i]:=x
end
end; {Selectie}
In cazul sortarii prin selectie C este de ordinul N*N , iar M este de ordinul
N*ln N. Aceasta metoda este mai putin rapida pentru tablouri ordonate sau aproape
ordonate.
Teoria 2)
Sortarea prin selectie performanta
Principiu: reprezinta o varianta a sortarii prin selectie, in care determinarea elementului cu
cheia minima dintr-o portiune de tablou se reduce la determinarea pozitiei acestuia. In felul acesta se
poate renunta la asignarea x:=a[j] care apare in ciclul "for" controlat de j.
Implementarea algoritmului in Pascal:
procedure SelectiePerform;
VAR i,j,min : TipIndex; x : TipElement;
begin
for i:=1 to N-1 do begin
min:=i;
for j:=i+1 to N do if a[j].cheie<a[min].cheie then min:=j;
x:=a[min]; a[min]:=a[i]; a[i]:=x
end
end; {SelectiePerform}
APLICATIA:
Sa se sorteze un vector prin metoda selectiei (se interschimba numere care
sunt adiacente(cel mai mare merge catre ultima pozitie si la urmatoatea parcurgere
urmatorul catre penultima)
ex:3
213
=>1 2 3}
uses crt;
var t,i,j,n:integer;
a:array[1..20]of integer;
begin
clrscr;
write('n=');
readln(n);
for i:=1 to n do begin
write('a[',i,']=');
readln(a[i]);
end;
for i:=1 to n-1 do
for j:=i+1 to n do
if a[i]>a[j] then begin
t:=a[i];
a[i]:=a[j];
a[j]:=t;
end;
for i:=1 to n do
write(a[i]:4);
readln;
end.
4)Metoda bulelor
Teoria 1:
Sortarea prin interschimbare (bubblesort)
Principiu: se considera subtabloul a[i],...,a[N] care se parcurge de la dreapta spre stinga,
comparind si interschimbind perechile de elemente alaturate care nu satisfac relatia de ordine,
procedeul repetindu-se pentru i=2,N. Practic, la o parcurgere a subtabloului a[i],...,a[N] are loc
deplasarea elementului minim al acestui subtablou pina in pozitia a[i-1].
Implementarea algoritmului in Pascal:
43
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
procedure BubbleSort;
VAR i,j : TipIndex; x : TipElement;
begin
for i:=2 to N do
for j:=N downto i do
if a[j-1].cheie>a[j].cheie then begin
x:=a[j-1];
a[j-1]:=a[j];
a[j]:=x
end
end; {BubbleSort}
APLICATIA:
Sa se sorteze un vector prin metoda bulelor ( adica se compara permanent doi vecini
astfel incit in final cel mai mare merge spre dreapta)
ex:3
3 2 12
=>2 3 12
}
uses crt;
var t,i,q,n:integer;
a:array[1..20]of integer;
begin
clrscr;
write('n=');
readln(n);
for i:=1 to n do begin
write('a[',i,']=');
readln(a[i]);
end;
q:=0;
while q=0 do
begin
q:=1;
for i:=1 to n-1 do
if a[i]>a[i+1] then begin
t:=a[i];
a[i]:=a[i+1];
a[i+1]:=t;
q:=0;
end;
end;
for i:=1 to n do
write(a[i]:4);
readln;
end.
3.5.9 Metode de cautare
1)Metoda binara var i,n:byte;
Se da un vector cu n elemente ordonat a:array[1..20] of integer;
crescator si o valoare v.Sa se indice v,st,dr,m,k:integer;
daca aceasta valoare exista in sir ,daca ok:boolean;
da ,sa se precizeze pe ce pozitie se begin
afla ,folosind metoda cautarii binare . clrscr;
ex:3 write('n=');
123 readln(n);
p=2 for i:=1 to n do begin
=> pe pozitia a doua este} write('a[',i,']=');
program cautarebinara; readln(a[i]);
uses crt; end;
const Nmax=20; write('pe cine cautati');
44
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
3.5.8 Interclasarea
Sa se scrie un program pentru ordonarea prin interclasare a doua
siruri de
numere intregi a si b.
ex:n=3,a=(2,3,4),n=1 ,b=(1)}
program interclass;
var i,j,k,L,m,n:integer;
a,b,c:array[1..30] of integer;
BEGIN
write('n=');read(n);
write('m=');
readln(m);
for i:=1 to n do begin
write('a[',i,']=');readln(a[i]);
end;
for i:=1 to m do begin
write('b[',i,']=');readln(b[i]);
end;
i:=1;j:=1;k:=0;
while (i<=n) and (j<=m) do begin
if a[i]<b[j] then begin
k:=k+1;c[k]:=a[i];i:=i+1;end
else begin
k:=k+1;c[k]:=b[j];j:=j+1;end;
if i>n then for L:=j to m do begin
k:=k+1;c[k]:=b[L];end
45
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Vom dezvolta in acest capitol aparatul matematic necesar pentru analiza eficientei algoritmilor,
incercand ca aceasta incursiune matematica sa nu fie excesiv de formala. Apoi, vom arata, pe baza unor
exemple, cum poate fi analizat un algoritm. O atentie speciala o vom acorda tehnicilor de analiza a
algoritmilor recursivi.
Notatia asimptotica
In Capitolul 1 am dat un inteles intuitiv situatiei cand un algoritm necesita un timp in ordinul unei
anumite functii. Revenim acum cu o definitie riguroasa.
Fie N multimea numerelor naturale (pozitive sau zero) si R multimea numerelor reale. Notam prin N+
si R+ multimea numerelor naturale, respectiv reale, strict pozitive, si prin R multimea numerelor reale
nenegative. Multimea {true, false} de constante booleene o notam cu B. Fie f : N→R o functie
arbitrara. Definim multimea
Cu alte cuvinte, O( f ) (se citeste “ordinul lui f ”) este multimea tuturor functiilor t marginite superior de
un multiplu real pozitiv al lui f, pentru valori suficient de mari ale argumentului. Vom conveni sa
spunem ca t este in ordinul lui f (sau, echivalent, t este in O( f ), sau t Є O( f )) chiar si atunci cand
valoarea f (n) este negativa sau nedefinita pentru anumite valori n < n0. In mod similar, vom vorbi
despre ordinul lui f chiar si atunci cand valoarea t(n) este negativa sau nedefinita pentru un numar finit
de valori ale lui n; in acest caz, vom alege n0 suficient de mare, astfel incat, pentru n <= n0, acest lucru
sa nu mai apara. De exemplu, vom vorbi despre ordinul lui n/log n, chiar daca pentru n = 0 si n = 1
functia nu este definita. In loc de t Є O( f ), uneori este mai convenabil sa folosim notatia
t(n) Є O( f (n)), subintelegand aici ca t(n) si f (n) sunt functii.
Fie un algoritm dat si fie o functie t : N→R astfel incat o anumita implementare a algoritmului sa
necesite cel mult t(n) unitati de timp pentru a rezolva un caz de marime n, n Є N. Principiul invariantei
(mentionat in Capitolul 1) ne asigura ca orice implementare a algoritmului necesita un timp in ordinul
lui t. Mai mult, acest algoritm necesita un timp in ordinul lui f pentru orice functie f : N→R pentru
care t Є O( f ). In particular, t Є O(t). Vom cauta in general sa gasim cea mai simpla functie f, astfel
incat t Є O( f ).
Proprietatile de baza ale lui O( f ) sunt date ca exercitii (Exercitiile 5.1-5.7) si este recomandabil sa le
studiati inainte de a trece mai departe.
Notatia asimptotica defineste o relatie de ordine partiala intre functii si deci, intre eficienta relativa a
diferitilor algoritmi care rezolva o anumita problema. Vom da in continuare o interpretare algebrica a
notatiei asimptotice. Pentru oricare doua functii f , g : N→R, definim urmatoarea relatie binara: f <= g
46
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
daca O( f ) O(g). Relatia “<=” este o relatie de ordine partiala in multimea functiilor definite pe N si
cu valori in R (Exercitiul 5.6). Definim si o relatie de echivalenta: f g daca O( f ) = O(g).
Aceasta ierarhie corespunde unei clasificari a algoritmilor dupa un criteriu al performantei. Pentru o
problema data, dorim mereu sa obtinem un algoritm corespunzator unui ordin cat mai “la stanga”.
Astfel, este o mare realizare daca in locul unui algoritm exponential gasim un algoritm polinomial.
In Exercitiul 5.7 este data o metoda de simplificare a calculelor, in care apare notatia asimptotica. De
exemplu,
n33n2n8 Є O(n3(3n2n8)) = O(max(n3, 3n2n8)) = O(n3)
Ultima egalitate este adevarata, chiar daca max(n3, 3n2n8) n3 pentru 0 <= n <= 3, deoarece notatia
asimptotica se aplica doar pentru n suficient de mare. De asemenea,
chiar daca pentru 0 <= n <= 6 polinomul este negativ. Exercitiul 5.8 trateaza cazul unui polinom
oarecare.
Notatia O( f ) este folosita pentru a limita superior timpul necesar unui algoritm, masurand eficienta
algoritmului respectiv. Uneori este util sa estimam si o limita inferioara a acestui timp. In acest scop,
definim multimea
Exista o anumita dualitate intre notatiile O( f ) si Ω( f ). Si anume, pentru doua functii oarecare
f, g : N→R, avem: f Є O(g), daca si numai daca g Є Ω( f ).
O situatie fericita este atunci cand timpul de executie al unui algoritm este limitat, atat inferior cat si
superior, de cate un multiplu real pozitiv al aceleiasi functii. Introducem notatia
©( f ) = O( f ) Ω( f )
numita ordinul exact al lui f. Pentru a compara ordinele a doua functii, notatia © nu este insa mai
puternica decat notatia O, in sensul ca relatia O( f ) = O(g) este echivalenta cu ©( f ) = ©(g).
Se poate intampla ca timpul de executie al unui algoritm sa depinda simultan de mai multi parametri.
Aceasta situatie este tipica pentru anumiti algoritmi care opereaza cu grafuri si in care timpul depinde
atat de numarul de varfuri, cat si de numarul de muchii. Notatia asimptotica se generalizeaza in mod
natural si pentru functii cu mai multe variabile. Astfel, pentru o functie arbitrara f : N x N→R
definim
47
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Multi algoritmi sunt mai usor de analizat daca consideram initial cazuri a caror marime satisface
anumite conditii, de exemplu sa fie puteri ale lui 2. In astfel de situatii, folosim notatia asimptotica
conditionata. Fie f : N→R o functie arbitrara si fie P : N→B un predicat.
Notatia O( f ) este echivalenta cu O( f | P), unde P este predicatul a carui valoare este mereu true.
Similar, se obtin notatiile Ω( f | P) si ©( f | P).
O functie f : N→R este eventual nedescrescatoare, daca exista un n0, astfel incat pentru orice n <= n0
avem f (n) <= f (n1), ceea ce implica prin inductie ca, pentru orice n <= n0 si orice m <= n, avem
f (n) <= f (m). Fie b <= 2 un intreg oarecare. O functie eventual nedescrescatoare este b-neteda daca
f (bn) Є O( f (n)). Orice functie care este b-neteda pentru un anumit b <= 2 este, de asemenea, b-neteda
pentru orice b <= 2 (demonstrati acest lucru!); din aceasta cauza, vom spune pur si simplu ca aceste
functii sunt netede. Urmatoarea proprietate asambleaza aceste definitii, demonstrarea ei fiind lasata ca
exercitiu.
Proprietatea 5.1 Fie b <= 2 un intreg oarecare, f : N→R o functie neteda si t : N→R o functie
eventual nedescrescatoare, astfel incat
unde X poate fi O, Ω, sau ©. Atunci, t Є X( f ). Mai mult, daca t Є ©( f ), atunci si functia t este neteda.
unde a, b Є R+ sunt constante arbitrare. Este dificil sa analizam direct aceasta ecuatie. Daca consideram
doar cazurile cand n este o putere a lui 2, ecuatia devine
Prin tehnicile pe care le vom invata la sfarsitul acestui capitol, ajungem la relatia
Pentru a arata acum ca t Є ©(n log n), mai trebuie doar sa verificam daca t este eventual
nedescrescatoare si daca n log n este neteda.
t(1) = a <= 2(ab) = t(2)
t([n/2]) <= t([(n1)/2])
48
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
t([n/2]) <= t([(n1)/2])
Atunci,
t(n) = t([n/2])t([n/2])bn <= t([(n1)/2])t([(n1)/2])b(n1) = t(n1)
In fine, mai ramane sa aratam ca n log n este neteda. Functia n log n este eventual nedescrescatoare si
2n log(2n) = 2n(log 2 log n) = (2 log 2)n 2n log n
Є O(n n log n) = O(max(n, n log n)) = O(n log n)
De multe ori, timpul de executie al unui algoritm se exprima sub forma unor inegalitati de forma
si, simultan
pentru anumite constante c, d Є R+, n0 Є N si pentru doua functii t1, t2 : N→R+. Notatia asimptotica ne
permite sa scriem cele doua inegalitati astfel:
t(n) Є t([n/2]) t([n/2]) O(n)
respectiv
t(n) Є t([n/2]) t([n/2]) Ω(n)
t(n) Є t([n/2]) t([n/2]) ©(n)
Definim functia
Am vazut ca f Є ©(n log n). Ne intoarcem acum la functia t care satisface inegalitatile precedente. Prin
inductie, se demonstreaza ca exista constantele v <= d, u <= c, astfel incat
v <= t(n)/f (n) <= u
t Є ©( f ) = ©(n log n)
Aceasta tehnica de rezolvare a inegalitatilor initiale are doua avantaje. In primul rand, nu trebuie sa
demonstram independent ca t Є O(n log n) si t Є Ω(n log n). Apoi, mai important, ne permite sa
restrangem analiza la situatia cand n este o putere a lui 2, aplicand apoi Proprietatea 5.1. Deoarece nu
stim daca t este eventual nedescrescatoare, nu putem aplica Proprietatea 5.1 direct asupra inegalitatilor
initiale.
49
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Nu exista o formula generala pentru analiza eficientei unui algoritm. Este mai curand o chestiune de
rationament, intuitie si experienta. Vom arata, pe baza exemplelor, cum se poate efectua o astfel de
analiza.
Consideram algoritmul select din Sectiunea 1.3. Timpul pentru o singura executie a buclei interioare
poate fi marginit superior de o constanta a. In total, pentru un i dat, bucla interioara necesita un timp de
cel mult ba(ni) unitati, unde b este o constanta reprezentand timpul necesar pentru initializarea
buclei. O singura executie a buclei exterioare are loc in cel mult cba(ni) unitati de timp, unde c
este o alta constanta. Algoritmul dureaza in total cel mult
unitati de timp, d fiind din nou o constanta. Simplificam aceasta expresie si obtinem
(a/2)n2 (bca/2)n (dcb)
de unde deducem ca algoritmul necesita un timp in O(n2). O analiza similara asupra limitei inferioare
arata ca timpul este de fapt in ©(n2). Nu este necesar sa consideram cazul cel mai nefavorabil sau cazul
mediu, deoarece timpul de executie este independent de ordonarea prealabila a elementelor de sortat.
In acest prim exemplu am dat toate detaliile. De obicei, detalii ca initializarea buclei nu se vor
considera explicit. Pentru cele mai multe situatii, este suficient sa alegem ca barometru o anumita
instructiune din algoritm si sa numaram de cate ori se executa aceasta instructiune. In cazul nostru,
putem alege ca barometru testul din bucla interioara, acest test executandu-se de n(n1)/2 ori.
Exercitiul 5.23 ne sugereaza ca astfel de simplificari trebuie facute cu discernamant.
Timpul pentru algoritmul insert (Sectiunea1.3) este dependent de ordonarea prealabila a elementelor de
sortat. Vom folosi comparatia “x < T[ j]” ca barometru.
Sa presupunem ca i este fixat si fie x = T[i], ca in algoritm. Cel mai nefavorabil caz apare atunci cand
x < T[ j] pentru fiecare j intre 1 si i1, algoritmul facand in aceasta situatie i1 comparatii. Acest lucru
se intampla pentru fiecare valoare a lui i de la 2 la n, atunci cand tabloul T este initial ordonat
descrescator. Numarul total de comparatii pentru cazul cel mai nefavorabil este
Є ©(n2)
Vom estima acum timpul mediu necesar pentru un caz oarecare. Presupunem ca elementele tabloului T
sunt distincte si ca orice permutare a lor are aceeasi probabilitate de aparitie. Atunci, daca 1 <= k <= i,
probabilitatea ca T[i] sa fie cel de-al k-lea cel mai mare element dintre elementele T[1], T[2], …, T[i]
este 1/i. Pentru un i fixat, conditia T[i] < T[i1] este falsa cu probabilitatea 1/i, deci probabilitatea ca sa
se execute comparatia “x < T[ j]”, o singura data inainte de iesirea din bucla while, este 1/i. Comparatia
“x < T[ j]” se executa de exact doua ori tot cu probabilitatea 1/i etc. Probabilitatea ca sa se execute
comparatia de exact i1 ori este 2/i, deoarece aceasta se intampla atat cand x < T[1], cat si cand
T[1] <= x < T[2]. Pentru un i fixat, numarul mediu de comparatii este
50
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
ci = 1×1/i 2×1/i * (i2)*1/i (i1)*2/i = (i1)/2 1/i
(n23n)/4 Hn Є ©(n2)
unde prin Hn= Є ©(log n) am notat al n-lea element al seriei armonice (Exercitiul 5.17).
Se observa ca algoritmul insert efectueaza pentru cazul mediu de doua ori mai putine comparatii decat
pentru cazul cel mai nefavorabil. Totusi, in ambele situatii, numarul comparatiilor este in ©(n2).
Algoritmul necesita un timp in Ω(n2), atat pentru cazul mediu, cat si pentru cel mai nefavorabil. Cu
toate acestea, pentru cazul cel mai favorabil, cand initial tabloul este ordonat crescator, timpul este in
O(n). De fapt, in acest caz, timpul este si in Ω(n), deci este in ©(n).
5.2.3 Heapsort
Vom analiza, pentru inceput, algoritmul make-heap din Sectiunea3.4. Definim ca barometru
instructiunile din bucla repeat a algoritmului sift-down. Fie m numarul maxim de repetari al acestei
bucle, cauzat de apelul lui sift-down(T, i), unde i este fixat. Notam cu jt valoarea lui j dupa ce se
executa atribuirea “j := k” la a t-a repetare a buclei. Evident, j1 = i. Daca 1 < t <= m, la sfarsitul celei
de-a (t1)-a repetari a buclei, avem j := k si k <= 2j. In general, jt <= 2jt-1 pentru 1 < t <= m. Atunci,
n <= jm <= 2jm-1 <= 4jm-2 <= … <= 2m-1i
Numarul total de executari ale buclei repeat la formarea unui heap este marginit superior de
Demonstratia ultimei inegalitati rezulta din Exercitiul 5.26. Dar d = [lg(n/2)] implica d1 <= lg n si
d1 <= lg(n/8). Deci,
51
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Din () deducem ca [n/2]3n repetari ale buclei repeat sunt suficiente pentru a construi un heap, deci
make-heap necesita un timp t Є O(n). Pe de alta parte, deoarece orice algoritm pentru formarea unui
heap trebuie sa utilizeze fiecare element din tablou cel putin o data, t Є Ω(n). Deci, t Є ©(n). Puteti
compara acest timp cu timpul necesar algoritmului slow-make-heap (Exercitiul 5.28).
Pentru cel mai nefavorabil caz, sift-down(T[1 .. i1], 1) necesita un timp in O(log n) (Exercitiul 5.27).
Tinand cont si de faptul ca algoritmul make-heap este liniar, rezulta ca timpul pentru algoritmul
heapsort pentru cazul cel mai nefavorabil este in O(n log n). Mai mult, timpul de executie pentru
heapsort este de fapt in ©(n log n), atat pentru cazul cel mai nefavorabil, cat si pentru cazul mediu.
Algoritmii de sortare prezentati pana acum au o caracteristica comuna: se bazeaza numai pe comparatii
intre elementele tabloului T. Din aceasta cauza, ii vom numi algoritmi de sortare prin comparatie. Vom
cunoaste si alti algoritmi de acest tip: bubblesort, quicksort, mergesort. Sa observam ca, pentru cel mai
nefavorabil caz, orice algoritm de sortare prin comparatie necesita un timp in Ω(n log n) (Exercitiul
5.30). Pentru cel mai nefavorabil caz, algoritmul heapsort este deci optim (in limitele unei constante
multiplicative). Acelasi lucru se intampla si cu mergesort.
Matematicianul francez Éduard Lucas a propus in 1883 o problema care a devenit apoi celebra, mai
ales datorita faptului ca a prezentat-o sub forma unei legende. Se spune ca Brahma a fixat pe Pamant
trei tije de diamant si pe una din ele a pus in ordine crescatoare 64 de discuri de aur de dimensiuni
diferite, astfel incat discul cel mai mare era jos. Brahma a creat si o manastire, iar sarcina calugarilor
era sa mute toate discurile pe o alta tija. Singura operatiune permisa era mutarea a cate unui singur disc
de pe o tija pe alta, astfel incat niciodata sa nu se puna un disc mai mare peste unul mai mic. Legenda
spune ca sfarsitul lumii va fi atunci cand calugarii vor savarsi lucrarea. Aceasta se dovedeste a fi o
previziune extrem de optimista asupra sfarsitului lumii. Presupunand ca in fiecare secunda se muta un
disc si lucrand fara intrerupere, cele 64 de discuri nu pot fi mutate nici in 500 de miliarde de ani de la
inceputul actiunii!
Observam ca pentru a muta cele mai mici n discuri de pe tija i pe tija j (unde 1 <= i <= 3, 1 <= j <= 3,
i j, n <= 1), transferam cele mai mici n1 discuri de pe tija i pe tija 6ij, apoi transferam discul n
de pe tija i pe tija j, iar apoi retransferam cele n1 discuri de pe tija 6ij pe tija j. Cu alte cuvinte,
reducem problema mutarii a n discuri la problema mutarii a n1 discuri. Urmatoarea procedura descrie
acest algoritm recursiv.
procedure Hanoi(n, i, j)
{muta cele mai mici n discuri de pe tija i pe tija j}
if n > 0 then Hanoi(n1, i, 6ij)
write i “-->“ j
Hanoi(n1, 6ij, j)
Consideram instructiunea write ca barometru. Timpul necesar algoritmului este exprimat prin
urmatoarea recurenta:
Acest algoritm este optim, in sensul ca este imposibil sa mutam n discuri de pe o tija pe alta cu mai
putin de 2n1 operatii. Implementarea in oricare limbaj de programare care admite exprimarea
recursiva se poate face aproape in mod direct.
52
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Am vazut in exemplul precedent cat de puternica si, in acelasi timp, cat de eleganta este recursivitatea
in elaborarea unui algoritm. Nu vom face o introducere in recursivitate si nici o prezentare a metodelor
de eliminare a ei. Cel mai important castig al exprimarii recursive este faptul ca ea este naturala si
compacta, fara sa ascunda esenta algoritmului prin detaliile de implementare. Pe de alta parte, apelurile
recursive trebuie folosite cu discernamant, deoarece solicita si ele resursele calculatorului (timp si
memorie). Analiza unui algoritm recursiv implica rezolvarea unui sistem de recurente. Vom vedea in
continuare cum pot fi rezolvate astfel de recurente. Incepem cu tehnica cea mai banala.
5.3.1 Metoda iteratiei
Cu putina experienta si intuitie, putem rezolva de multe ori astfel de recurente prin metoda iteratiei: se
executa primii pasi, se intuieste forma generala, iar apoi se demonstreaza prin inductie matematica ca
forma este corecta. Sa consideram de exemplu recurenta problemei turnurilor din Hanoi. Pentru un
anumit n > 1 obtinem succesiv
t(n) = 2t(n1) +1 = 22t(n2) +2 +1 = …
= 2n-1t(1)
t
Rezulta t(n) = 2n1. Prin inductie matematica se demonstreaza acum cu usurinta ca aceasta forma
generala este corecta.
5.3.2 Inductia constructiva
Inductia matematica este folosita de obicei ca tehnica de demonstrare a unei asertiuni deja enuntate.
Vom vedea in aceasta sectiune ca inductia matematica poate fi utilizata cu succes si in descoperirea
enuntului asertiunii. Aplicand aceasta tehnica, putem simultan sa demonstram o asertiune doar partial
specificata si sa descoperim specificatiile care lipsesc si datorita carora asertiunea este corecta. Vom
vedea ca aceasta tehnica a inductiei constructive este utila pentru rezolvarea anumitor recurente care
apar in contextul analizei algoritmilor. Incepem cu un exemplu.
si deci, f (n) Є O(n2). Aceasta ne sugereaza sa formulam ipoteza inductiei specificate partial IISP(n)
conform careia f este de forma f (n) = an2bnc. Aceasta ipoteza este partiala, in sensul ca a, b si c nu
sunt inca cunoscute. Tehnica inductiei constructive consta in a demonstra prin inductie matematica
aceasta ipoteza incompleta si a determina in acelasi timp valorile constantelor necunoscute a, b si c.
f (n) = a(n1)2b(n1)cn = an2(1b2a)n(abc)
53
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Daca dorim sa aratam ca IISP(n) este adevarata, trebuie sa aratam ca f (n) = an2bnc. Prin
identificarea coeficientilor puterilor lui n, obtinem ecuatiile 1b2a = b si abc = c, cu solutia
a = b = 1/2, c putand fi oarecare. Avem acum o ipoteza mai completa, pe care o numim tot IISP(n):
f (n) = n2/2n/2c. Am aratat ca, daca IISP(n1) este adevarata pentru un anumit n <= 1, atunci este
adevarata si IISP(n). Ramane sa aratam ca este adevarata si IISP(0). Trebuie sa aratam ca
f (0) = a0b0c = c. Stim ca f (0) = 0, deci IISP(0) este adevarata pentru c = 0. In concluzie, am
demonstrat ca f (n) = n2/2n/2 pentru orice n.
Exista, din fericire, si tehnici care pot fi folosite aproape automat pentru a rezolva anumite clase de
recurente. Vom incepe prin a considera ecuatii recurente liniare omogene, adica de forma
a0tn a1tn-1 ¼ aktn-k = 0 ()
tn = xn
unde x este o constanta (deocamdata necunoscuta). Incercam aceasta solutie in () si obtinem
a0xn a1xn-1 ... akxn-k = 0
Solutiile acestei ecuatii sunt fie solutia triviala x = 0, care nu ne intereseaza, fie solutiile ecuatiei
a0xk a1xk-1 ... ak = 0
Presupunand deocamdata ca cele k radacini r1, r2, ..., rk ale acestei ecuatii caracteristice sunt distincte,
orice combinatie liniara
este o solutie a recurentei (), unde constantele c1, c2, ..., ck sunt determinate de conditiile initiale. Este
remarcabil ca () are numai solutii de aceasta forma.
Sa exemplificam prin recurenta care defineste sirul lui Fibonacci (din Sectiunea 1.6.4):
tn = tn-1 tn-2 n <= 2
tn +tn-1 +tn-2 = 0
x2 +x +1 = 0
54
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
de unde determinam
c1,2 =
(ỹn(ỹ)-n)
care este cunoscuta relatie a lui de Moivre, descoperita la inceputul secolului XVI. Nu prezinta nici o
dificultate sa aratam acum ca timpul pentru algoritmul fib1 (din Sectiunea 1.6.4) este in ©(ỹn).
Ce facem insa atunci cand radacinile ecuatiei caracteristice nu sunt distincte? Se poate arata ca, daca r
este o radacina de multiplicitate m a ecuatiei caracteristice, atunci tn = rn, tn = nrn, tn = n2rn, ..., tn = nm-1rn
sunt solutii pentru (). Solutia generala pentru o astfel de recurenta este atunci o combinatie liniara a
acestor termeni si a termenilor proveniti de la celelalte radacini ale ecuatiei caracteristice. Din nou, sunt
de determinat exact k constante din conditiile initiale.
tn = 5tn-1 +8tn-2 4tn-3 n <= 3
iar t0 = 0, t1 = 1, t2 = 2. Ecuatia caracteristica are radacinile 1 (de multiplicitate 1) si 2 (de multiplicitate
2). Solutia generala este:
tn = c11n c22n c3n2n
a0tn a1tn-1 ... aktn-k = bnp(n) ()
unde b este o constanta, iar p(n) este un polinom in n de grad d. Ideea generala este ca, prin manipulari
convenabile, sa reducem un astfel de caz la o forma omogena.
tn 2tn-1 = 3n
In acest caz, b = 3 si p(n) = 1, un polinom de grad 0. O simpla manipulare ne permite sa reducem acest
exemplu la forma (). Inmultim recurenta cu 3, obtinand
55
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
3tn +6tn-1 = 3n+1
tn+1 +2tn = 3n+1
tn+1 +5tn +6tn-1 = 0
x2 +5x+ 6 = 0
adica (x2)(x3) = 0.
Intuitiv, observam ca factorul (x2) corespunde partii stangi a recurentei initiale, in timp ce factorul
(x3) a aparut ca rezultat al manipularilor efectuate, pentru a scapa de parte dreapta.
Generalizand acest procedeu, se poate arata ca, pentru a rezolva (), este suficient sa luam
urmatoarea ecuatie caracteristica:
(a0xk a1xk-1 ¼ ak)(xb)d+1 = 0
tn = 2tn-1 1 n <= 1
tn 2tn-1 = 1
care este de forma () cu b = 1 si p(n) = 1, un polinom de grad 0. Ecuatia caracteristica este atunci
(x2)(x1) = 0, cu solutiile 1 si 2. Solutia generala a recurentei este:
tn = c11n c22n
Avem nevoie de doua conditii initiale. Stim ca t0 = 0; pentru a gasi cea de-a doua conditie calculam
t1 = 2t0 +1
tn = 2n +1
Daca ne intereseaza doar ordinul lui tn, nu este necesar sa calculam efectiv constantele in solutia
generala. Daca stim ca tn = c11n +c22n, rezulta tn Є O(2n). Din faptul ca numarul de mutari a unor
discuri nu poate fi negativ sau constant, deoarece avem in mod evident tn <= n, deducem ca c2 > 0.
Avem atunci tn Є Ω(2n) si deci, tn Є ©(2n). Putem obtine chiar ceva mai mult. Substituind solutia
generala inapoi in recurenta initiala, gasim
56
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
1 = tn 2tn-1 = c1 c22n2(c1 c22n-1) = c1
5.3.5 Schimbarea variabilei
Uneori, printr-o schimbare de variabila, putem rezolva recurente mult mai complicate. In exemplele
care urmeaza, vom nota cu T(n) termenul general al recurentei si cu tk termenul noii recurente obtinute
printr-o schimbare de variabila. Presupunem pentru inceput ca n este o putere a lui 2.
T(n) = 4T(n/2) n n > 1
tk = 4tk-1 2k
(x4)(x2) = 0
T(n) = c1n2 c2n
Rezulta
T(n) = 4T(n/2) n2 n > 1
tk = 4tk-1 4k
cu ecuatia caracteristica
(x4)2 = 0
T(n) = c1n2 c2n2lg n
si obtinem
57
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
T(n) = 3T(n/2) cn n > 1
T(2k) = 3T(2k-1) c2k
tk = 3tk-1 c2k
cu ecuatia caracteristica
(x3)(x2) = 0
tk = c13k c22k
T(n) = c13lg n c2n
si, deoarece
alg b = blg a
obtinem
T(n) = c1nlg 3 c2n
deci,
In toate aceste exemple am folosit notatia asimptotica conditionata. Pentru a arata ca rezultatele
obtinute sunt adevarate pentru orice n, este suficient sa adaugam conditia ca T(n) sa fie eventual
nedescrescatoare. Aceasta, datorita Proprietatii 5.1 si a faptului ca functiile n2, n log n si nlg 3 sunt
netede.
Putem enunta acum o proprietate care este utila ca reteta pentru analiza algoritmilor cu recursivitati de
forma celor din exemplele precedente. Proprietatea, a carei demonstrare o lasam ca exercitiu, ne va fi
foarte utila la analiza algoritmilor divide et impera din Capitolul 7.
T(n) = aT(n/b) cnk n > n0
unde: n0 <= 1, b <= 2 si k <= 0 sunt intregi; a si c sunt numere reale pozitive; n/n0 este o putere a lui b.
Atunci avem
58
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Unele probleme se pot rezolva, altele nu. De exemplu, o problemă notorie, a cărei imposibilitate este
riguros demonstrată în anii '30 de către matematicianul englez Alan Turing, este de a decide dacă un
program se va opri vreodată pentru o anumită instanţă a datelor de intrare.
Pe de altă parte, chiar între problemele care pot fi rezolvate, teoreticienii trag o linie imaginară între
problemele care au rezolvări ``rezonabil'' de rapide, şi restul problemelor, care se numesc ``intratabile''.
În mod arbitrar, dar nu ne-justificabil, o problemă se numeşte ``intratabilă'' dacă complexitatea ei este
exponenţială în mărimea datelor de intrare. (Nu uitaţi, este vorba de complexitate ``worst-case''
asimptotică.) O problemă este ``tratabilă'' dacă putem scrie complexitatea ei sub forma unui polinom,
de un grad oricît de mare.
Mulţimea tuturor problemelor de decizie (adică a problemelor la care răspunsul este da sau nu) cu
complexitate polinomială se notează cu P (de la polinom). De exemplu, problema de a găsi dacă o
valoare se află într-un vector este în clasa P; algoritmul exhibat mai sus este un algoritm în timp linear
(O(n)) pentru a răspunde la această întrebare.
(Ca o curiozitate: există şi probleme cu o complexitate ``ne-elementară'', care este mai mare decît
complexitatea oricărei probleme exponenţiale. O astfel de problemă este cea de decizie a adevărului
unei formule în teoria numită S1S, sau ``teoria monadică a succesorilor de ordinul 2''. Nu vă lăsaţi
intimidaţi de terminologie: aceasta este practic o teorie logică peste numerele naturale, în care avem
voie să scriem formule cu cuantificatori şi conectori logici, ca mai sus, dar avem şi dreptul să
cuantificăm peste mulţimi. Complexitatea deciziei unei formule logice într-o astfel de teorie este mai
Acest tip de algoritmi este surprinzător de bogat în consecinţe cu valoare teoretică. Aceşti algoritmi nu
sunt direct aplicabili, însă studiul lor dă naştere unor concepte foarte importante.
Surprinzătoare este şi definiţia corectitudinii unui astfel de algoritm. Un algoritm nedeterminist este
corect dacă există o posibilitate de executare a sa care găseşte răspunsul corect. Pe măsură ce un
59
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
algoritm nedeterminist se execută, la anumiţi paşi se confruntă cu alegeri nedeterministe. Ei bine, dacă
la fiecare pas există o alegere, care făcută să ducă la găsirea soluţiei, atunci algoritmul este numit
corect.
Astfel, un algoritm nedeterminist care caută ieşirea dintr-un labirint ar arăta cam aşa:
Pe scurt algoritmul se comportă aşa: dacă la nord nu e perete mergi încolo, sau, poate, dacă la sud e
liber, mergi încolo, sau la est, sau la vest. În care dintre direcţii, nu se precizează (este ne-determinat).
Este clar că dacă există o ieşire la care se poate ajunge, există şi o suită de aplicări ale acestor reguli
care duce la ieşire.
Utilitatea practică a unui astfel de algoritm nu este imediat aparentă: în definitiv pare să nu spună nimic
util: soluţia este fie spre sud, fie spre nord, fie spre este, fie spre vest. Ei şi? Este clar că aceşti algoritmi
nu sunt direct implementabili pe un calculator real.
În realitate existenţa un astfel de algoritm deja înseamnă destul de mult. Înseamnă în primul rînd că
problema se poate rezolva algoritmic; vă reamintesc că există probleme care nu se pot rezolva deloc.
În al doilea rînd, se poate arăta că fiecare algoritm nedeterminist se poate transforma într-unul
determinist într-un mod automat. Deci de îndată ce ştim să rezolvăm o problemă într-un mod
nedeterminist, putem să o rezolvăm şi determinist! Transformarea este relativ simplă: încercăm să
mergem pe toate drumurile posibile în paralel, pe fiecare cîte un pas. (O astfel de tehnică aplicată în
cazul labirintului se transformă în ceea ce se cheamă ``flood fill'': evoluez radial de la poziţia de plecare
în toate direcţiile).
Clasa tuturor problemelor care se pot rezolva cu algoritmi nedeterminişti într-un timp polinomial se
notează cu NP (Nedeterminist Polinomial). Este clar că orice problemă care se află în P se află şi în NP,
pentru că algoritmii determinişti sunt doar un caz extrem al celor determinişti: în fiecare moment au o
singură alegere posibilă.
Din păcate transformarea într-un algoritm determinist se face pierzînd din eficienţă. În general un
algoritm care operează în timp nedeterminist polinomial (NP) poate fi transformat cu uşurinţă într-un
algoritm care merge în timp exponenţial (EXP). Avem deci o incluziune de mulţimi între problemele
de decizie: P NP EXP.
Partea cea mai interesantă este următoarea: ştim cu certitudine că P EXP. Însă nu avem nici o idee
despre relaţia de egalitate între NP şi P sau între NP şi EXP. Nu există nici o demonstraţie care să
infirme că problemele din NP au algoritmi eficienţi, determinist polinomiali! Problema P=NP este cea
mai importantă problemă din teoria calculatoarelor, pentru că de soluţionarea ei se leagă o grămadă de
consecinţe importante.
60
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Problema aceasta este extrem de importantă pentru întreaga matematică, pentru că însăşi demonstrarea
teoremelor este un proces care încearcă să verifice algoritmic o formulă logică (cum am văzut mai sus
de pildă); teoremele la care există demonstraţii ``scurte'' pot fi asimilate cu problemele din mulţimea
NP (la fiecare pas dintr-o demonstraţie putem aplica mai multe metode de inferenţă, în mod
nedeterminist; un algoritm trebuie să ghicească înşiruirea de metode aplicate pentru demonstrarea
enunţului); dacă orice problemă din NP este şi în P, atunci putem automatiza o mare parte din
demonstrarea de teoreme în mod eficient!
Problema P=NP este foarte importantă pentru criptografie: decriptarea este o problemă din NP (cel care
ştie cheia ştie un algoritm determinist polinomial de decriptare, dar cel care nu o ştie are în faţa o
problemă pe care nedeterminist o poate rezolva în timp polinomial). Dacă s-ar demonstra că P=NP
acest lucru ar avea consecinţe extrem de importante, iar CIA si KGB ar fi într-o situaţie destul de
proastă, pentru că toate schemele lor de criptare ar putea fi sparte în timp polinomial (asta nu înseamnă
neapărat foarte repede, dar oricum, mult mai repede decît timp exponenţial)!
Mai mult, în 1971 Cook a demonstrat că există o problemă specială în NP (adică pentru care se poate
da un algoritm eficient nedeterminist), numită problema satisfiabilităţii (notată cu SAT). Problema este
foarte simplă: dacă se dă o formulă booleană care cuprinde mai multe variabile, poate fi formula făcută
De la Cook încoace s-au mai descoperit cîteva sute de probleme NP-complete. Unele probleme care se
ivesc foarte adesea în practică s-au dovedit NP-complete! Acesta este un alt motiv pentru care clasa atît
de abstractă NP a problemelor cu algoritmi nedeterminişti este atît de importantă: foarte multe
probleme practice au algoritmi polinomiali nedeterminişti, dar cei mai buni algoritmi determinişti iau
un timp exponenţial!
Problema comis-voiajorului (turneu Hamiltonian de cost minim): dîndu-se o reţea de oraşe, o reţea de
drumuri între oraşe şi o lungime k, există un traseu de cost mai mic decît k trecînd prin fiecare oraş o
singură dată şi revenind la punctul de plecare?
Dîndu-se o mulţime de numere naturale, se poate împărţi în două mulţimi de numere de sume egale 2?
``Clica'': dîndu-se un graf G şi un număr k, are G un subgraf complet cu k vîrfuri (adică o mulţime de k
vîrfuri unite fiecare cu fiecare)?
``Acoperire'': dîndu-se un graf G şi un număr k, pot alege k vîrfuri în aşa fel încît toate muchiile din G au
un capăt ales?
O cantitate enormă de efort şi ingeniozitate a fost risipită pentru a încerca să se demonstreze că P=NP
sau opusul acestei afirmaţii, dar nici un rezultat concret nu a fost obţinut. Credinţa cvasi-unanimă este
că P=NP, dar numai matematica poate oferi vreo certitudine...
Din cauză că foarte multe probleme practice sunt în NP, şi ca aparent nu putem avea algoritmi
determinişti eficace pentru ele, cercetătorii şi-au îndreptat atenţia asupra unor clase noi de algoritmi,
care vor face obiectul secţiunilor următoare.
Algoritmi aproximativi
În secţiunile care urmează folosim tot timpul premiza nedemonstrată că PNP. Dacă P=NP, atunci
problemele pe care ne batem capul să le rezolvăm prin metode ciudate pot fi de fapt rezolvate exact şi
eficient.
61
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Optim şi aproximare
Într-adevăr, această metodă se bucură de un oarecare succes, dar nu de unul general. Algoritmii care
rezolvă o problemă de optimizare în speranţa unui rezultat sub-optimal se numesc ``algoritmi
aproximativi''.
Teoria algoritmilor aproximativi este relativ recentă (deşi ideea există de multă vreme), iar unele
rezultate sunt extrem de complicate. Ne vom mulţumi să dăm nişte exemple pentru a ilustra algoritmi
aproximativi în acţiune, şi tipul de rezultate care se pot obţine.
Vom ilustra două rezultate diferite din teoria algoritmilor aproximativi: algoritmi de aproximare
relativă, algoritmi de aproximare absolută a soluţiei (lămurim terminologia imediat).
Să notăm o instanţă a unei probleme cu I. Fie OPT(I) valoarea soluţiei optime pentru acea instanţă
(care există, dar pe care nu ştim s-o calculăm eficient), şi fie A(I) valoarea calculată de algoritmul
nostru aproximativ. Numim aproximaţia absolută dacă există un număr K, independent de instanţa I,
care are proprietatea că |OPT(I) - A(I)| < K. Numim aproximaţia relativă dacă există un R (numit
``performanţă'') astfel ca pentru orice instanţă I avem (A(I) / OPT(I)) < R (dacă problema caută un
maximum, atunci fracţia din definiţie trebuie inversată).
Problema rucsacului
Iată o variantă a problemei rucsacului care este NP-completă , dar pentru care se poate obţine cu foarte
mare uşurinţă un algoritm aproximativ relativ eficient.
Se dau o mulţime (mare) de rucsaci de capacitate egală (cunoscută, un număr natural). Se mai dă o
mulţime finită de obiecte, fiecare de un volum cunoscut (număr natural). Întrebarea este: care este
numărul minim de rucsaci necesari pentru a împacheta toate obiectele?
Algoritmul este banal: metoda ``greedy'': pune de la stînga fiecare greutate în primul rucsac liber:
Initializari:
o, folositi := 1, 0
do o <= nrobiecte -> liber[o] := capacitate od
Algoritm:
62
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
o := 1
do o <= nrobiecte ->
r := 1
do (liber[r] < marime[o]) -> r := r+1
od
folositi, liber[r], o :=
max(r, folositi), liber[r] - marime[o], o+1
od
Vom folosi o altă problemă NP-completă, pentru care avem imediat un algoritm de aproximare relativă
de performanţă 2, dar pentru care vom demonstra că nu există nici un algoritm de aproximare absolută.
Problema este cea a acoperirii unui graf, enunţată mai sus. Ca problemă de optimizare, ea se enunţă
astfel: ``care este numărul minim de vîrfuri care trebuie ``acoperite'' astfel ca toate muchiile dintr-un
graf să fie atinse?''
Pentru această problemă algoritmul greedy nu face multe parale ca algoritm de aproximare. Există însă
un algoritm relativ simplu, cu performanţă 2, care se foloseşte însă de un alt algoritm clasic, cel al
``cuplării'' (matching). Fără a intra în detalii, există un algoritm polinomial relativ sofisticat pentru a
calcula cuplări maximale pe grafuri4. Calculăm o cuplare maximală, după care luăm capetele tuturor
muchiilor care o formează: astfel obţinem o acoperire (uşor de demonstrat) care e cel mult dublă ca
mărime faţă de optim (pentru că în optim trebuie să se găsească cel puţin cîte un vîrf pentru fiecare
muchie din cuplare, iar noi am luat cîte două).
Iată şi un rezultat negativ interesant: pentru orice K fixat, nu există nici un algoritm care să dea pentru
problema acoperirii o soluţie aproximativă absolută la distanţa K de cea optimă pentru orice instanţă.
Demonstraţia este foarte simplă, odată ce ai văzut ideea, şi se bazează pe ``tehnica amplificării''. Iată
cum se face, prin reducere la absurd:
Să presupunem că avem un algoritm A care calculează pentru orice graf o acoperire care este cu cel
mult K noduri mai mare ca cea optimă (K e fixat). Cu alte cuvinte |OPT(G) - A(G)| < K. Să luăm o
instanţă arbitrară a problemei cuplării, G. Formăm un nou graf G 1 din G, care nu este conex, şi care
constă din K+1 copii ale lui G, alăturate. Aceasta este o instanţă perfect corectă a problemei acoperirii,
aşa că rulăm pe ea algoritmul nostru A. Acesta va oferi o acoperire care are cel mult cu K noduri mai
mult decît acoperirea optimă. (Vă reamintesc notaţiile: OPT(G) este valoarea optimă: numărul minim
de noduri pentru a acoperi muchiile, iar A(G) este valoarea calculată de algoritmul nostru.
Datorită faptului că cele K+1 copii ale lui G sunt neconectate, optimumul pentru G 1 este reuniunea a
K+1 optimumuri pentru G. Din cauza asta avem relaţia OPT(G 1) = (K+1) OPT(G). Fie acum H copia
lui G pe care A a marcat cele mai multe vîrfuri; atunci A(G 1) <= (K+1) A(H). Dar din proprietăţile lui
A avem: |OPT(G1) - A(G1)| < K, sau |(K+1) OPT(H) - (K+1) A(H)| < K, ori |OPT(H) - A(H)| <
K/(K+1) < 1. Însă ştim că OPT(H) şi A(H) sunt numere naturale, deci am obţinut OPT(H) = A(H)!
63
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Asta înseamnă că dacă avem un algoritm aproximativ absolut pentru problema acoperirii, putem
imediat construi un algoritm exact la fel de rapid. Ori asta ar însemna că P=NP, ceea ce am presupus
fals.
Exemplele pe care le-am ales sunt în mod deliberat simple; teoria algoritmilor aproximativi este în
plină dezvoltare şi are rezultate foarte spectaculoase şi în general complicate. În orice caz,
aplicabilitatea ei este imediată, pentru că multe probleme practice care nu pot aştepta au numai
rezolvări aproximative.
O tehnică foarte spectaculoasă pentru rezolvarea problemelor este cea a folosiri numerelor
aleatoare. Practic algoritmii aleatori sunt identici cu cei obişnuiţi, dar folosesc în plus o nouă
instrucţiune, care s-ar putea chema ``dă cu banul''. Această instrucţiune generează un bit arbitrar ca
valoare.
Acest lucru este adevărat şi pentru alte clase de algoritmi; de pildă algoritmul quicksort are
pentru majoritatea vectorilor de intrare o comportare O(n log n). Dacă însă datele de intrare sunt prost
distribuite, atunci quicksort poate face n2 comparaţii. Pentru n=100 asta înseamnă de 10 ori mai mult!
Numărul de instanţe pentru care quicksort este slab este mult mai mic decît numărul de instanţe pentru
care merge bine. Ce te faci însă dacă într-un anumit context lui quicksort i se dau numai date rele?
(Datele preluate din măsurători reale sunt foarte rar complet uniform distribuite). O soluţie paradoxală
constă în a amesteca aleator vectorul înainte de a-l sorta.
Complexitatea medie (average case) a lui quicksort este O(n log n). Complexitatea în cazul cel
mai rău (worst case) este O(n 2). Dacă datele vin distribuite cu probabilitate mare în zona ``rea'', atunci
amestecîndu-le putem transforma instanţe care pică în zona ``worst-case'' în instanţe de tip ``average-
case''. Fireşte, asta nu înseamnă ca nu putem avea ghinion, şi ca amestecarea să producă tot o instanţă
``rea'', dar probabilitatea ca acest lucru să se întîmple este foarte mică, pentru că quicksort are puţine
instanţe rele5.
Acesta este un caz de folosire a aleatorului pentru a îmbunătăţi performanţa medie a unui algoritm.
Cîteodată cîştigul este şi mai mare, pentru că putem rezolva probleme NP-complete foarte rapid
folosind aleatorismul. De obicei avem însă un preţ de plătit. Cînd folosim algoritmi din clasa prezentată
mai jos, putem risca să nu primim răspunsul corect.
64
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Evoluţia unui algoritm care foloseşte numere aleatoare nu mai depinde numai de datele de intrare, ci şi
de numerele aleatoare pe care le generează. Dacă are ``noroc'' algoritmul poate termina repede şi bine;
dacă dă prost cu zarul, ar putea eventual chiar trage o concluzie greşită. (În cazul quicksort de mai sus
răspunsul este întotdeauna corect, dar cîteodată vine mai greu. Aceasta este diferenţa dintre algoritmii
Monte Carlo, mereu corecţi, şi cei Las Vegas, care pot uneori, rar, greşi.)
Vom defini acum algoritmii probabilişti pentru probleme de decizie (ţineţi minte, la care răspunsul este
Da sau Nu). Majoritatea problemelor pot fi exprimate în forma unor probleme de decizie, deci
simplificarea nu este prea drastică.
Există două clase de algoritmi probabilişti, dar ne vom concentra atenţia numai asupra uneia dintre ele,
pentru care vom da şi două exemple simple şi spectaculoase. Vom defini totodată clasa problemelor
care pot fi rezolvate probabilist în timp polinomial, numită RP (Random Polinomial).
Observaţi că dacă indicăm de la început care sunt numerele aleatoare care vor fi generate, evoluţia
algoritmului este perfect precizată.
Definiţie: O problemă de decizie este în RP dacă există un algoritm aleator A care rulează într-un timp
polinomial în lungimea instanţei (nc pentru un c oarecare), şi care are următoarele proprietăţi:
Dacă răspunsul la o instanţă I este ``Da'', atunci cu o probabilitate mai mare de 1/2 algoritmul va
răspunde ``Da''.
Dacă răspunsul la o instanţă I este ``Nu'', atunci cu probabilitate 1 algoritmul va răspunde ``Nu''.
De cine este dată ``probabilitatea'' de mai sus? De numărul de şiruri aleatoare. Cînd rulăm un
algoritm aleator pentru o instanţă I avem la dispoziţie 2 nc şiruri aleatoare de biţi; pentru unele dintre ele
algoritmul răspunde ``Da'', pentru celelalte răspunde ``Nu''. Ceea ce facem este să numărăm pentru cîte
şiruri algoritmul ar răspunde ``da'' şi să facem raportul cu 2nc. Aceasta este probabilitatea ca algoritmul
să răspundă ``da''. Opusul ei este probabilitatea să răspundă ``nu''.
O tehnică foarte simplă de amplificare poate creşte nedefinit această probabilitate: dacă
executăm algoritmul de 2 ori pe aceleaşi date de intrare, probabilitatea de a greşi pentru răspunsuri
``nu'' rămîne 0. Pe de altă parte, ajunge ca algoritmul să răspundă măcar odată ``da'' pentru a şti că
răspunsul este ``da'' cu siguranţă! Din cauza asta, dacă probabilitatea de eroare este p pentru algoritm,
executînd de k ori probabilitatea coboară la p k (nu uitaţi ca p este subunitar, ba chiar sub 1/2). Această
metodă se numeşte ``boost'' în engleză, şi face dintr-un algoritm probabilist slab ca discriminare o sculă
extrem de puternică!
Pentru a scădea probabilitatea de eroare a unui algoritm care poate greşi cu probabilitatea p
pînă sub o limită dorită siguranta, se procedează astfel:
Fie un polinom de mai multe variabile, x1, x2, ... xn. Acest polinom poate fi descris printr-o
formulă aritmetică, de pildă: (x1 + 1) (x2 + 1) ... (xn + 1). Întrebarea este: este acest polinom identic nul
sau nu?
65
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Pentru polinomul de mai sus gradul este n, şi putem alege pentru K de exemplu Z p, unde p este
un număr prim relativ mare în raport cu n (de două ori mai mare ajunge!).
Alegînd arbitrar numerele v1, v2, ..., vn în Zp şi evaluînd q(v1, v2, ..., vn) mod p, putem imediat
afirma cu probabilitate mare > 1 - n/p despre q dacă este nul sau nu! Observaţi că evaluarea
polinomului nu este prea costisitoare, putîndu-se face în timp polinomial în lungimea expresiei care
descrie polinomul.
Folosind metoda de ``boost'' putem creşte rapid siguranţa noastră despre rezultatul algoritmului.
Izomorfismul arborilor
Se dau doi arbori, cu rădăcina precizată. Sunt aceşti doi arbori ``izomorfi'' (identici prin re-ordonarea
fiilor)? Această problemă este surprinzător de dificilă pentru un algoritm determinist (am impresia
chiar că este NP-completă). Iată însă o soluţie aproape imediată: construim pentru fiecare arbore cîte un
polinom care nu depinde de ordinea fiilor unui nod, în aşa fel încît dacă şi numai dacă arborii sunt
izomorfi polinoamele sunt egale. Apoi pur şi simplu testăm ca mai sus dacă polinomul diferenţă este
nul.
O metodă de a asocia recursiv un polinom unui arbore este de pildă următoarea: fiecărui nod îi
asociem o variabilă xk, unde k este înălţimea nodului (distanţa pînă la cea mai depărtată frunză).
Frunzele vor avea toate asociate variabila x 0. Apoi asociem nodului v de înălţime k cu fii v 1, ... vl
polinomul fv = (xk - fv1) (xk - fv2) ... (xk - fvl). Se arată uşor că polinoamele sunt egale pentru arbori
izomorfi, bazîndu-ne pe unicitatea descompunerii în factori a unui polinom. Gradul polinomului asociat
unui nod este egal cu suma gradelor fiilor, care la rîndul ei este egală cu numărul de frunze care se află
sub acel nod (cum se demonstrează imediat prin inducţie după înălţime). Şi asta-i tot!
Algoritmi on-line
Adesea trebuie luate decizii cu informaţii incomplete. Un caz particular este luarea de decizii
pe măsură ce datele devin disponibile. Deciziile afectează viitorul, dar sunt luate fără a avea cunoştinţe
despre datele viitoare. Sa vedem în acţiune un exemplu foarte simplu:
66
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Problema schiorului
Se pune problema: ce este mai bine: să închiriezi sau să cumperi schiuri? (Vom presupune că preţul
schiurilor este constant de-a lungul timpului, ca să simplificăm problema). Dilema constă din faptul că
în fiecare sezon, nu ştii dacă te vei mai duce odată. Dacă le cumperi şi nu te mai duci, ai dat banii
degeaba. Dacă le tot închiriezi şi te duci des, s-ar putea să le plăteşti de mai multe ori. Totuşi, trebuie să
iei o decizie. Pe care?
Există un răspuns foarte simplu, care promite nu că dă rezultatul cel mai ieftin în orice circumstanţă, ci
doar că nu vei cheltui de două ori mai mult decît în cazul în care ai face decizia perfectă (decizia
perfectă este cea care ştie precis dacă te vei mai duce, şi de cîte ori; ea nu este accesibilă decît ``post-
factum'', deci este pur teoretică).
Algoritmul este: închiriezi schiuri pînă ai dat pe chirie costul schiurilor. După aceea dacă mai vrei să
mergi le cumperi. Voi demonstra rapid că în felul ăsta orice s-ar întîmpla nu pierzi mai mult de jumate
din banii pe care i-ai fi cheltuit în cazul ideal.
Avem 3 posibilităţi:
1. Te opreşti înainte de a le cumpăra: în cazul ăsta ai jucat perfect, pentru că ai schiat şi nu puteai ieşi mai
ieftin nicicum;
2. Te opreşti imediat după ce le-ai cumpărat. În cazul ăsta ai dat de două ori preţul (odată pe închirieri, şi
odată pe cumpărare), dar ai schiat cît ai fi putut schia dînd numai odată preţul (mai ieftin de odată nu
puteai ieşi);
3. Te opreşti mai tîrziu: în cazul ăsta cel mai ieftin era tot să le cumperi din prima zi, deci iar ai cheltuit
dublu.
Orice altă schemă foloseşti pentru a decide cumpărarea, există un scenariu în care poţi cheltui mai mult
de dublu faţă de optim.
Algoritmii on-line apar foarte natural într-o mulţime de situaţii: de exemplu în reţele de calculatoare,
algoritmii care decid traseul unui pachet cu informaţii sunt algoritmi on-line; dacă decid trasee proaste,
reţeaua poate deveni supra-aglomerată în viitor; astfel de algoritmi nu au idee despre cererile viitoare,
aşa că acţionează cu informaţie incompletă.
Un alt exemplu este în sistemele de operare: algoritmii după care cache-urile (sau sistemele de
memorie virtuală) aleg paginile care trebuie înlocuite. Alegerea aceasta nu poate fi optimă în absenţa
informaţiilor despre viitoarele cereri. Cu toate acestea, anumite alegeri sunt mai bune decît altele.
Un al treilea exemplu, tot din contextul sistemelor de operare, este al algoritmilor de planificare, care
trebuie să stabilească în ce moment se execută fiecare proces pe un calculator (paralel). Acolo unde
minutul de rulare costă o grămadă de bani, deciziile trebuie să risipească cît mai puţin timp. Însă job-uri
pentru prelucrare sosesc dinamic, aşa că algoritmii trebuie să facă faţă unui mediu în continuă
schimbare.
Algoritmii on-line sunt în general analizaţi comparîndu-i cu algoritmii off-line, care ar avea înainte de a
face deciziile informaţii perfecte despre toate cererile viitoare. Este clar că informaţia aceasta este un
mare avantaj, aşa că în general algoritmii on-line au performanţe mult mai proaste decît cei
corespunzători off-line.
Cercetările în acest domeniu sunt doar la început; se explorează şi variante de algoritmi hibrizi on/off-line, în care
algoritmul are o idee despre viitor, dar nu neapărat o vedere completă.
67
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
s := s + n MOD 10
n := n DIV 10
START
REPEAT
WRITE s;
STOP. Cit. s
S := 0
DA NU
Tip. S
S := S + n MOD 10
STOP
N := N DIV 10
Cit. n
68
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
În problema anterioară am văzut cum putem izola cifrele unui număr. De menţionat că algoritmul
propus anterior izola cifrele numărului n în ordine inversă.
Exemplu: pentru numărul 162 se izolau pe rând cifrele 2, 6, şi 1. Pe de altă parte, dacă cunoaştem cifrele
unui număr putem calcula numărul respectiv.
Exemplu: din cifrele 2, 6 şi 1 putem obţine numărul 261. Aici nu este vorba de alăturarea cifrelor, cum
am fi tentaţi să credem, ci de calculul numărului sub forma:
2 * 102 + 6 * 101 + 1 * 100,
aşa cum cunoaştem din teoria bazelor de numeraţie. Cum procedăm pentru rezolvarea acestei probleme?
Considerăm o variabilă (notată ninv., care iniţial va avea valoarea 0). Pentru fiecare cifră noua valoare a lui niv va
fi vechea valoare înmulţită cu 10 la care se va adăuga cifra:
niv : = 0 * 10 + 2;
niv : = 2 * 10 + 6;
niv : = 26 * 10 + 1 = 261.
În concluzie, izolăm pe rând cifrele în ordine inversă (aşa cum am arătat în problema anterioară) şi cu
fiecare nouă cifră construim numărul cerut.
În pseudocod, algoritmul arată astfel:
Integer n, ninv;
READ n
ninv := 0;
WHILE n < > 0
ninv := ninv * 10 + n MOD 10;
n .= n DIV 10
REPEAT
WRITE ninv
STOP.
START
Cit. N
NINV := 0
NU
N0 Tip. NINV
DA
STOP
NINV := NINV * 10 + N MOD 10
69
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
i := 2
WHILE (i < n) AND (n MOD i < > 0)
i := i +1
REPEAT
IF i := n THEN WRITE ’numarul este prim’
ELSE WRITE ’numarul nu este prim’
ENDIF
STOP.
READ nr
N := 1
J := 0;
DO
prim := true
FOR i := 2, ∂
IF n MOD i = 0 THEN prim := false
ENDIF
REPEAT
IF prim THEN
WRITE n
j := j + 1
ENDIF
n := n + 1
UNTIL j = nr
STOP.
70
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
- se împarte n la I;
dacă fm este diferit de 0 (deci s-a găsit divizor al lui n) se tipăresc I şi fm;
se adun 1 la i (se incrementează).
Să presupunem că am citit n = 12. Algoritmul decurge astfel:
se iniţializează I cu 2;
se iniţializează fm cu 0;
întrucât 2 divide pe 12, fm va lua valoarea 1 iar n valoarea 6;
întrucât 2 divide pe 6, fm va lua valoarea 2 şi n valoarea 3;
n nu divide pe 3, deci se trece mai departe;
fm este diferit de 0, se tipăreşte 2 la puterea 2;
se măreşte i cu 1;
n nu este 1, deci secvenţa se reia;
fm va lua valoarea 0;
3 divide pe 3 (i divide pe n) deci fm va lua valoarea 1 şi n va deveni 1;
3 nu divide 1, deci se trece mai departe;
fm este diferit de 0, deci se tiopăreşte 3 la pueterea 1;
i devine 4;
n este 1 şi algoritmul se încheie.
În continuare se prezintă schema logică şi algoritmul realizat în pseudocod:
INTEGER n, i, fm;
READ n
i := 2;
DO
fm := 0;
WHILE n MOD i = 0
fm := fm + 1;
n := n DIV i
REPEAT
IF fm < > 0 THEN
WRITE I, ’la puterea’ fm
ENDIF
i := i + 1
UNTIL n = 1
STOP.
71
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Pentru calculul acestor valori se utilizează se utilizează variabila p. din cele arătate rezultă
schema logică de mai jos:
START
Cit. n
S := 0
P := 1
i := 1
P := p * i
S := s + p
i := i + 1
DA NU
I<N Tip. S STOP
INTEGER n, i, s, p;
READ n
s := 0
p := 1
FOR i := 1, n
p := * i
s := s + p
REPEAT
WRITE s
STOP.
2) Se consideră şirul de numere naturale:
1, 4, 7, 10, 13, . . .
Să se calculeze suma primelor n termeni, cu n dat de la tastatură
72
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Program Problema_1;
73
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
o cerinţă a programelor, tot aşa cum pentru a fi campion mondial la alergări este
necesar să nu ai picioarele amputate. Cel mai greu este ca programul să execute
întocmai ce şi-a propus cel ce l-a realizat. Prin semantica unui limbaj se înţelege ce
anume realizează fiecare instrucţiune a sa.
Sintaxa este formalizată perfect din punct de vedere matematic dar nu acelaşi
lucru se întâmplă şi cu semantica. Sintaxa poate fi descrisă cu ajutorul diagramelor de
sintaxă. Aceasta nu reprezintă singura formă de descriere a sintaxei unui limbaj(mai
există de exemplu, forma BNF), dar se remarcă prin faptul că sunt sugestive. În ce
constă o descriere cu ajutorul diagramelor de sintaxă? Să presupunem că dorim să
descriem riguros cum arată un număr în baza 16. dacă folosim o descriere în genul un
număr în baza 16 are în componenţa sa cifre şi litere, cifrele pot fi de la 0 la 9 iar
literele a,b,c,d,e,f,A,B,C,D,E,F şi dăm câteve exemple, nu suntem suficient de riguroşi.
Imediat pot apărea întrebări de genul: A reprezintă un număr în baza 16? Mai mult
dacă dorim să facem un program care să recunoască dacă un număr citit este sau nu
în bază 16, situaţia se complică.
Se observă că o astfel de schemă are un nume(în cazul nostru cifra
hexazecimală). Pentru a putea obţine o cifră trebuie să urmez un drum prin acest
desen(în matematică se numeşte graf orientat), de la intrare(din dreptul numelui) până
la ieşire, urmând sensul săgeţilor. Problema se poate pune şi invers: fiind dat un
caracter oarecare să se precizeze dacă este sau nu cifră. Caracterul este cifră dacă
în diagrama prezentată există un drum care trece printr-un cerculeţ ce reprezintă
caracterul. Acum am definit riguros cifraÎn noua diagramă apare un dreptunghi în care
este scris cuvântul cifră. Dreptunghiul se utilizează atunci când se foloseşte o noţiune
ce a fost definită printr-o diagramă de sintaxă. Orice drum folosit în acest desen(de la
intrare la ieţire) obţinem sau o cifră sau una din literele care pot face parte din
structura unui număr hexa:
74
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Citiri, scrieri
Să analizăm programul de mai jos, care citeşte un număr întreg(pe care noi îl
introducem de la tastatură) şi îl tipăreşte:
program c1;
var a:integer;
begin
read(a);write(a)
end.
În cazul în care introducem numărul 10, calculatorul va tipării 10, dacă
introducem 16, calculatorul va tipării 16 ş.a.m.d.
Citirea datelor se face cu ajutorul procedurii READ şi READLN. În acest
paragraf sunt prezentate aceste proceduri într-o formă mult simplificată. Pentru
amănunte, vezi fişier text. Procedura READ are forma READ(var), unde var are
semnificaţia de variabilă(variabile de tip boolean şi enumerare nu se citesc). Se citeşte
de la tastatură o dată care se depune în variabila var. Procedura READLN se
foloseşte exact ca READ, cu deosebirea că, după citire, cursorul sare pe linia
următoare a ecranului.
Scrierea datelor se face cu ajutorul procedurii WRITE şi WRITELN. În ambele
cazuri se scrie începând cu poziţia curentă a cursorului pe ecran. Diferenţa între
WRITE şi WRITELN este aceea că, după scriere, prin utilizarea procedurii WRITE
cursorul rămâne după ultimul caracter scris, iar prin utilizarea procedurii WRITELN el
sare pe prima poziţie a liniei următoare.
Exemple:
WRITE (a), unde a este o variabilă care conţine numărul 3 - scrie 3 începând din
poziţia curentă a cursorului.
WRITE (a,b), unde a şi b sunt variabile întregi care au conţinuturile 2, respectiv 3
- va avea ca efect scrierea numărului 2 urmat de numărul 3 (apare 23).
WRITE (‘a=’,a) - are ca rezultat scrierea şirului de caractere ‘a=’urmat de data
reţinută de variabila întreagă a.
Presupunem că b este o variabilă reală (care reţine numere reale) şi conţine
numărul 3.25 WRITELN (b:4:2) va determina apariţia pe monitor a numărului 3.25.
75
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Cifra 4 are semnificaţia de număr total de poziţii pe care să se scrie numărul real, iar
cifra 2 numărul de poziţii pe care să se scrie partea zecimală (în absenţa acestor
parametri, data reală se va scrie într-o formă greu inteligibilă).În situaţia in care partea
întreagă a datei reale nu încape în formatul prestabilit, nu se mai ţine cont de acest
format.
O utilizare specială o au instrucţiunile readln şi writeln fără parametri. Să
analizăm programul de mai jos.Acesta tipăreşte numărul 6 (se poate tipări un număr în
acest mod). Observăm că programul se termină cu instrucţiunea readln. Ce rol are ea?
După ce un program îşi încheie execuţia, se revine în mod automat în mediul în care
se găseşte textul sursă. Rezultatele se pot vizualiza tastând ALT + F5. Pentru ca
revenirea să nu se facă automat (să avem timp să vedem rezultatul), vom utiliza
instrucţiunea readln fără parametri. Efectul? Se va aştepta să se tasteze Enter. În
acest timp, avem posibilitatea să vedem ce s-a tipărit.
program c2
begin
writeln(6)
readln;
end.
Programul de mai jos tipăreşte numerele 6 şi 7. Între cele două numere există un
rând liber. De ce? Pentru că am utilizat writeln. Instrucţiunea writeln fără parametri are
rolul de a determina saltul cursorului pe rândul următor.
program c3;
begin
writeln(6);
writeln; {se sare un rând}
writeln (7)
end.
4.2.3 Constante
Constante
Constantele Pascal reprezintă valori care pot fi conţinute de un program scris în
acest limbaj (nu sunt citite de program). Ele folosesc în cadrul diverselor expresii
(numerice, logice, şiruri de caractere) sau pentru scrierea unor mesaje. Exemplu: În
program trebuie realizată atribuirea y:=2*x+1. În acest caz, 2 şi 1 sunt constante.
Constantă întreagă
Constantă reală
Constantă
Sir caractere
Constantă simbolică
76
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Constante întregi. Sunt alcătuite dintr-o submulţime a numerelor întregi care pot
fi reprezentate în memoria calculatorului.
Observaţie: Nu se pot reprezenta în calculator numere oricât de mari sau oricât
de mici (orice număr ocupă un spaţiu în memoria internă a calculatorului). Prin
utilizarea limbajului Turbo Pascal se pot reprezenta numere întregi cuprinse în
intervalul [-2.147.483.648, 2.147.483.647].
Numerele se pot reprezenta în baza 10 sau în baza 16 (mai rar utilizată). Pentru
baza 16, numărul este precedat de caracterul special ‘$’.
Exemple: 32, -164, +131, $a1.
Cifră
Constantă
întreagă
Cifră
hexazecimală
Constante reale. Sunt alcătuite dintr-o submulţime a numerelor reale (mai precis
a numerelor raţionale) care pot fi reprezentate în calculator. Numerele se găsesc în
intervalul [3.4*10-4932, 1,1*104932]. În locul virgulei se foloseşte punctul Exemple: 2.34, -
45.26, 512E+23, -45.1E-3.
Ultimele două numere folosesc o scriere neîntâlnită în matematică. Ele
reprezintă numerele 512*10 23 şi -45.1*10-3.
Constantă
reală cifră cifră
cifră
Constante şir de caractere. După cum reiese şi din denumire, cu ajutorul lor se
reprezintă şiruri de caractere. Caracterele de şir pot fi specificate enumerându-le între
apostrofuri sau se pot preciza prin codul lor ASCII, precedat de caracterul #.
Exemplu: #1$2 sau, echivalent (în baza 16), #$1#$2
‘abc’
‘abc’#10#13
caracter
Sir
caracter
e Constantă
întreagă
77
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
const
identificator = expresie;
identificator = expresie;
Exemplu.
const NrMaxValori = 30;
Dim = NrMax Valori*2-1;
Mesaj = ‘Nu exista solutie’#10#13'
PI = 3.14;
În paragraful anterior am văzut faptul că o variabilă poate reţine date de un anumit tip. De
exemplu, anumite variabile pot reţine numere întregi, altele numere reale (la informatică asta
înseamnă numere cu zecimale). Se pune întrebarea: cum are programatorul posibilitatea să
stabilească natura datelor care pot fi memorate de variabile? Mecanismul este următorul: atunci
când se declară o variabilă se precizează tipul ei.
Prin tip de date se înţelege:
mulţime de valori;
regulă de codificare a lor (modul în care se reprezintă în memorie);
mulţime de operaţii definite pe mulţimea valorilor.
Spunem că variabilele au un tip standard dacă acesta este recunoscut de către compilator, fără a
fi definiti în prealabil de programator. Vom vedea ulterior că există posibilitatea ca programatorul
să-şi definească propriile tipuri, pentru ca apoi să declare variabile de tipul definit de el. Limbajul
Turbo Pascal conţine următoarele tipuri de standard:
1. tipuri întregi;
2. tipul caracter;
3. tipul logic;
4. tipuri reale.
Acestea vor fi studiate în continuare.
Tipuri întregi
Tipul shortint.
Mulţimea valorilor este dată de numerele întregi cuprinse între -128, 127. Pentru memorare, se
foloseşte un singur octet, iar un număr se memorează în cod complementar. Operaţiile sunt cele
de la tipul integer. Datele sunt memorate în cod complementar.
78
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Tipul integer.
Mulţimea valorilor este dată de numerele întregi cuprinse între - 32768, 32767. Pentru memorare,
se folosesc doi octeţi, iar un număr se memorează în cod complementar. Datele sunt memorate
în cod complementar.
Tipul longint (întreg lung).
Mulţimea valorilor este dată de numerele întregi cuprinse între -2l47483648 şi 2147483647.
Pentru memorare, se folosesc 4 octeţi iar un număr se memorează în cod complementar. Datele
sunt memorate în cod complementar.
Tipul byte.
Mulţimea valorilor este dată de numerele naturale cuprinse între 0 şi 255. Pentru memorare, se
foloseşte un octet, iar un număr se memorează în binar. Datele sunt memorate în binar.
Tipul word.
Mulţimea valorilor este dată de numerele naturale cuprinse între 0 şi 65535. Pentru memorare se
folosesc doi octeţi, iar un număr se memorează în binar. Datele sunt memorate în binar.
Declararea variabilelor de unul din tipurile întregi se face ca mai jos:
var a,b:integer;
c:word;
d,e,f:longint;
Variabilelor (operanzilor) de tip întreg li se pot aplica mai mulţi operatori.
Operanzilor de tip întreg li se pot aplica şi operatorii pe biţi (lucrează asupra biţilor din
reprezentarea internă a numărului). Aceştia sunt tot cei logici, dar acţionează de această dată
altfel.
Operatorul NOT.
Acţionează asupra variabilelor în felul următor:
toţi biţii care reţin 1, vor reţine 0;
toţi biţii care reţin 0, vor reţine 1.
Exemplu: O variabilă de tip byte a reţine valoarea 11110000. După atribuirea a:=not a; variabila a
va reţine valoarea 00001111.
Operatorul SHL.
Este binar (are doi operanzi).
Are rolul de a deplasa la stânga conţinutul biţilor primului operand cu un număr de poziţii dat de
al doilea operand. Conţinutul primilor biţi se pierde, iar ultimii biţi vor reţine 0.
Exemplu. O bariabilă de tip byte a reţine valoarea 10000110. După operaţia a shl 2; se obţine
00011000.
Observaţie. În cazul în care primul bit este 0, prin deplasare la stânga cu o poziţie (a shl 1)
valoarea se înmulţeşte cu 2.
Exemplu. O variabilă de tip byte a reţine valoarea 00000110(2)=6(10). După operaţia a shl 1; se
obţine valoarea 00001100(2) = 12(10).
Operatorul SHR.
Este binar şi are rolul de a deplasa la dreapta conţinutul biţilor primului operand cu un număr de
poziţii dat de al doilea operand. Conţinutul primilor biţi se pierde, iar ultimii biţi vor rămâne 0.
Exemplu. O variabilă de tip byte a reţine valoarea 10000110. După operaţia a shr 2; variabila a va
reţine valoarea 00100001.
Observaţie. Prin deplasare la dreapta cu o poziţie (a shr 1) se efectuează împărţirea întreagă la 2
(a div 2).
Exemplu. O variabilă de tip byte a reţine valoarea 00000110(2)=6(10). După atribuirea a:-a shr 1;
variabila a va reţine valoarea 00000011(2)=3(10).
Tipul caracter.
Calculatoarele nu lucrează numai cu numere. Ele reţin şi caractere. Din ce este alcătuită
mulţimea caracterelor?
Mulţimea caracterelor conţine:
literele mari şi mici ale alfabetului (a,b,...z, A,B,...Z);
cifrele sistemului zecimal (0,1,2,..9);
caractere speciale (!,$,%,?,. şi altele);
alte caractere.
În Turbo Pascal un caracter se notează între apostrofuri.
Exemple:’a’, ‘A’, ‘1’ (caracterul ‘1’ nu trebuie confundat cu numărul 1).
79
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
O variabilă de tip caracter reţine, la un moment dat, un singur caracter. Declaraţia unei variabile
de tip caracter se face ca în exemplul următor în care se declară două variabile a şi b de acest
tip:
Var a, b: char; (char înseamnă caracter).
Se citeşte variabila ch (de tip caracter) care, apoi, se tipăreşte. De asemenea se tipăreşte şi
caracterul 7. Cele două caractere sunt separate de un alt caracter şi anume caracterul spaţiu (şi
acesta este un caracter).
program c;
var ch: char;
begin
write(‘ch=’); readln (ch);
writeln (ch,’ ‘.’7')
end.
Tipuri reale
Variabilele de un tip real reţin numere cu zecimale. Exemple de astfel de numere: 6, 82, 9, 3, -8, 6.
În locul virgulei, în informatică se foloseşte punctul. Astfel, numerele de mai sus, vor fi
notate:6.82, 9.3, -8.6.
În Turbo Pascal există mai multe tipuri reale. O variabilă de un tip real reţine datele codificate în
virgulă mobilă (vezi anexa 2).
Tipul REAL.
Se reţin numerele reale care aparţin domeniului:
[-1,7*1038,-2,9*10-29] [2,9*10-29, 1,7*1038]
Tipul SINGLE.
Se reţin numere reale care aparţin domeniului:
[-3,4*1038,-1,5*10-45] [1.5*10-45, 3,4*1038]
80
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
begin
write (‘v’); readln (v);
writeln (‘v=’,v);
writeln (‘v=’,v:3:2);
end.
Să presupunem că citim numărul 3.35 (3,35 cum suntem obişnuiţi). Programul va tipări prima
dată 3.35000000000E+00 iar a doua oară 3.35. De fapt, de fiecare dată se tipăreşte acelaşi număr
însă înscris în forme diferite. Prima formă se numeşte formă normalizată sau formă ştiinţifică.
Pentru a regăsi numărul se procedează astfel: se înmulţeşte numărul aflat înaintea literei E cu 10
la puterea care este dată de numărul care urmează lui E (3.350...0x100 = 3.35).
Totuşi ne-am putea întreba care este logica faptului că există această formă (la prima vedere
chiar stupidă)? Trebuie ţinut seama de faptul că, în general, numerele reale nu se pot reţine
întotdeauna cu precizie în calculator (chiar numerele aflate între două valori). De exemplu, nu pot
fi reţinute cu precizie nici măcar numerele aflate între 1 şi 2. De ce? Fie numărul
1.6272625729383973235...9. Are prea multe zecimale. Există numere cu şirul zecimalelor infinit.
Atunci cum poate fi memorat un astfel de număr?
Se reţine o aproximaţie a sa. Acum putem răspunde la întrebare: forma normalizată tipăreşte
numărul cu precizia cu care a putut fi reţinut de calculator. Acesta este motivul existenţei sale.
Renunţând la ea, vom comanda calculatorului precizia cu care va fi tipărită valoarea respectivă.
Cum? Se poate utiliza formatul nr.:lg: zec, unde nr este numărul real pe care îl tipărim, lg este
numărul total de poziţii pe care se va tipări valoarea respectivă, iar zec reprezintă numărul de
zecimale care vor fi tipărite.
În program, am solicitat ca numărul să fie tipărit pe 3 poziţii din care ultimile două să fie
zecimale. S-a tipărit 3.35. Aţi observat, probabil, că numărul a fost tipărit pe 4 poziţii (şi punctul
ocupă o poziţie). Apare o neconcordanţă între cele afirmate. De ce?
Calculatorul va proceda astfel: va tipări întotdeauna numărul de zecimale cerut. În cazul în care
nu mai există poziţii care să permită tipărirea numărului întreg (ca în exemplu) nu se ţine cont de
lg. În cazul în care numărul poziţiilor pe care va fi tipărit numărul este mai mare decât cel
necesar, numărul va fi tipărit cu un număr de spaţii în faţă. Testaţi!
Tipul logic
Variabilele de acest tip pot reţine numai două valori: TRUE (adevărat) şi FALSE (fals). Pentru
declaraţie se foloseşte cuvântul boolean.
Reţinem următorul amănunt: conţinutul variabilelor de acest tip poate fi tipărit, dar nu poate fi
citit.
Tipuri ordinale
Am arătat că un tip de date conţine,în primul rând, o mulţime de valori(date).
Spunem că un tip de date este ordinal dacă:
datele pot fi ordonate (crescător);
fiecare dată din şirul ordonat al valorilor are:
o un succesor – valoarea care îl urează în şir (excepţie face ultima
dată din şir);
o un predecesor – valoarea aflată imediat înainte în şirul ordonat
(excepţie face prima dată din şir).
Tipurile întregi sunt tipuri ordinale. Fie tipul integer ‚. Să considerăm o valoare a
sa, numărul 123. succesorul acestuia este numărul 124, iar predecesorul său este
numărul 122. Evident, pentru fiecare valoare din şir putem face un astfel de
raţionament. De asemenea, pentru fiecare tip întreg (byte,longint etc.) se poate face
un astfel de raţionament.
81
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
82
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
pentru o valoare care aparţine tipului char, funcţia ord returnează codul
caracterului respectiv.
În cazul tipului boolean funcţia ord returnează următoarele valori:
o 0, pentru false;
o 1, pentru true.
Convingeţi-vă de cele prezentate rulând programul de mai jos:
program ordin;
var a:integer;
b:char;
begin
a:= -13;b;= ’a’;
writeln(ord(a));writeln(ord(b));
writeln(ord(false));writeln(ord(true));
end.
În programul următor definim tipul timp. Acesta este format din 4 valori numite:
dimineaţa, prânz, seara şi noaptea. Tot aici, am declarat o variabilă de tip timp, căreia
i-am atribuit o valoare.
program ordinal3;
type timp= (dimineaţa, prânz, seara, noaptea);
var a:timp;
begin
a:= dimineaţa;
end.
Observaţii:
Valorile unui tip enumerare nu se citesc şi nu se tipăresc.
Ordinul primei valori din şir este 0, următoarea valoare din şir are ordinul
1, următoarea are ordinul 2 ş.a.m.d.
Tipul subdomeniu. Fiind dat un tip ordinal – numit tip părinte, putem construi un
alt tip ordinal numit tip subdomeniu al părintelui. Tipul subdomeniu conţine o
83
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Tipul Lit este un tip subdomeniu al tipului Litere. Ordinul valorii b este 1(acesta
este ordinul ei din tipul Litere.
4.2.5 Variabile
Variabile. Declararea variabilelor
84
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
VA identificator : tip ;
R
:
85
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Aceasta nu înseamnă că este bine să procedăm astfel. Să ne imaginăm că avem în faţă un program
mare scris aşa. El poate fi rulat, dar care programator va mai înţelege ceva, dacă îl priveşte?
Observaţie 3. Versiunea Borland a limbajului permite ca secvenţa program nume să lipsească. De
exemplu putem scrie şi aşa:
begin
end.
Dacă suntem ordonaţi nu procedăm astfel. Un program scris în Pascal (oricât de complex ar fi) are
structura următoare:
program nume;
definiţii de constante;
definiţii de tipuri;
declaraţii de variabile;
declaraţii de subprograme;
begin
instrucţiuni
end.
Nu este obligatoriu ca într-un program să figureze toate acestea, dar dacă figurează, trebuie să apară în
această ordine.
4.2.8 Comentarii
Separatori şi comentarii. Cele mai simple elemente alcătuite din caractere cu
semnificaţie lingvistică poartă denumirea de unităţi lexicale. Acestea se repetă între
ele, după caz, prin unul sau mai multe blancuri, caracterul CR, sfârşit de linie sau
caracterul ’;’. Pentru ca un program să fie uşor de înţeles se folosesc comentariile.
Acestea se plasează oriunde în program. Un comentariu poate fi scris în două feluri:
între acolade, exemplu: {un comentariu}
între paranteze rotunde urmate de *, exemplu (*un comentariu*).
4.2.9 Expresii
Expresii
O expresie este fie o constanta, fie o variabila, fie un apel de functie, fie o combinatie
corecta (din punct de vedere sintactic) de expresii mai simple.
“Combinarea” se realizeaza cu ajutorul operatorilor. Elementele care se combina se
numesc operanzi. In general, se lucreaza cu expresii algebrice, in care regulile de formare sunt
aceleasi ca si in matematica, insa, dupa cum am mai spus, expresiile se scriu liniarizat. Pot
exista,de asemenea,si expresii nenumerice,cum ar fi de pilda:’Turbo’+’Pascal’,aici simbolul +
reprezentand alipirea (concatenarea) celor doua siruri de caractere.Rezultatul este sirul
‘TurboPascal’.
Prioritate Operator
86
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Atentie! O alta eroare ce poate surveni in scrierea unei expresii este urmatoarea: daca a, b
si c sunt valori intregi, de pilda, expresia (a>b) and (b<c) nu este echivalenta cu expresia a>b
and b<c, deoarece aceasta din urma este incorecta, fiindca mai intai se efectueaza operatia pe
biti: b and b si expresia isi pierde sensul!
expresie
+
termen
factor operator multiplicativ
factor
Un factor este fie un numar fara semn, fie o constanta sau o variabila, fie un identificator
de functie avand ca argument o alta expresie (intre paranteze), fie un alt factor precedat de
operatorul unar NOT.
4.2.10 Atribuirea
Sintaxa instructiunii de atribuire
LIMBAJUL PASCAL
id_variabila:=valoare/expresie;
Precizare: Tipul variabilei trebuie sa coincida
cu tipul valorii/expresiei.
Ajutati de profesor, editati un prim program in mediul Turbo/Borland Pascal, care se porneste
prin comanda turbo sau bp. In construirea unui program, tineti cont de cerintele prezentate in Anexa 2.
Fisierul executabil este, cel mai adesea:C:\BP\BIN\turbo.exe sau C:\BP\BIN\bp.exe. lansarea in
87
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
executie a programului editat si corectat se face prin actionarea simultana a tastelor Ctrl si F9. De fapt,
capitolul 7 din manual prezinta modul de lucru cu mediul limbajului.
Programul nostru va calcula aria unui cerc in functie de lungimea razei cercului:
program CalculArie;
const pi=3.1415926;
var raza, aria: Real;
begin
raza:=2;
aria:=pi*Sqr(raza;
end.
El are doua parti: primele trei randuri reprezinta zona declaratiilor, iar instructiunile dintre
begin si end. zona actiunilor, adica partea operativa.
Daca pornim in executie acest program (in mediul Turbo Pascal), vom observa ca palpaie
putin ecranul, dar nu se intampla nimic. E si normal. Calculatorul a atribuit valoarea 2 variabilei raza.
A calculat aria (obtinand o anumita valoare) si gata. Noi nu am precizat prin nimic sa ni se comunice
rezultatul. De aceea va trebui sa folosim o procedura de extragere a datelor, de scriere a lor pe ecran.
Dar, chiar daca am dispune de o asemenea procedura, rezultatul programului ar fi acelasi la
orice executare a sa. De aceea, ar fi bine sa putem introduce de la tastatura raze de diferite valorui; deci
am avea nevoie de o procedura de citire a datelor. Aceste proceduri exista in limbajul Pascal:
ReadLn (v1, v2, . . . , vn) – citeste variabilele v1, . . . , vn, introduse de la tastatura. Variabilele
pot fi de orice tip invatat pana acum, mai putin Boolean sau un tip enumerare (sau un subdomeniu
al unui astfel de tip). Introducerea mai multor variabile se poate face daca acestea se separa prin
spatii sau <Enter>. La sfarsit trebuie apasata tasta <Enter>. Cursorul trece pe randul urmator.
Procedura ReadLn va citi si sfarsitul de linie (caracterul Enter).
Read(v1, v2, . . . , vn) – la fel ca ReadLn, doar ca nu citeste sfarsitul de linie.
Atentie! Datele citite se depun, de fapt, intr-o zona tampon, inainte de a fi date variabilelor.
Aceasta zona tampon se goleste cand apare ReadLn. De aceea, un apel simplu ReadLn (fara
argumente) va avea drept efect golirea acestei zone tampon. Astfel, apelul ReadLn (x, y, . . . ) este
echivalent cu secventa Read (x, y, . . . ); ReadLn.
Daca variabilele ar fi avut alte valori inaintea apelului procedurii de citire, ele se pierd.
Valorile citite ale acestor variabile raman neschimbate pana la rpima atribuire sau (re)citire a lor.
Write(e1,e2, . . .,en) – evalueaza si apoi afiseaza valorile expresiilor e1, e2, . . ., en. Expresiile
pot fi inclusiv de tipul Boolean, caz in care se afiseaza unul din cele doua cuvinte (False sau True),
dar nu pot fi de tip enumerare. Dupa afisarea valorilor unor expresii, acestea nu se pierd si nici nu
se schimba.
WriteLn(e1,e2, . . .,en) – face acelasi lucru, dar la sfarsitul intregii afisari, muta cursorul pe
randul urmator. De exemplu, pentru a citi raza vom scrie: ReadLn(raza), iar, dupa calculul ariei,
aceasta se afiseaza prin: Write(aria). Putem scrie direct Write(pi*Sqr(raza)), efectul fiind acelasi.
Observatie
88
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Exemple:
Fie declaratiile de variabile: var a: Integer; s: String;. Fie urmatoarea secventa de program:
a:=20; ReadLn(a,s); WriteLn(a,s); Write(s+’s’); in cazul introducerii valorilor 3 si alfa, se realizeaza
urmatoarele: a primeste valoarea 20; dupa citire, a isi pierde valoarea initiala (20) si devine 3.
Erori frecvente:
Unii incepatori sau cunoscatori ai limbajului BASIC cred ca se poate face o citire in felul
urmator: ReadLn(‘Dati n=”,n); iar altii nu sesizeaza diferenta intre un sir si valoarea identificatorului
corespunzator: ReadLn(‘n’).
Sa rescriem programul nostru folosind noile proceduri invatate:
program CalculArie;
const pi=3.1415926;
var raza, aria: Real;
begin
ReadLn(raza);
aria:=pi*Sqr(raza;
WriteLn(aria)
end.
Atentie! Daca se afiseaza un numar intreg sau un sir de caractere, n trebuie sa lipseasca.
Cu aceasta inlocuire programul devine mai “bun”, dar tot nu satisface urmatoarele cerinte:
sa se ceara explicit sa introducem raza;
sa se spuna ca rezultatul pe care il afiseaza este aria cercului de raza data.
De aceea vom scrie programul de mai jos.
program CalculArie;
{ acest program calculeaza aria unui cerc in functie de raza sa }
const pi=3.1415926;
var raza, aria: Real;
begin
WriteLn(‘Program de calculat aria cercului’);
WriteLn(‘********************************’);
Write(‘Dati raza=’);ReadLn(raza);
aria:=pi*Sqr(raza);
WriteLn(‘Aria este=’, aria:7:3)
end.
Acum lucrurile stau mai bine, insa ne mai deranjeaza doua lucruri:
trebuie sa apasam Alt-F5 pentru a vedea rezultatul programului;
raman pe ecran “urme” care deranjeaza, de la executia programelor anterioare.
Pentru a solutiona prima problema se va folosi un apel al procedurii ReadLn fara parametri,
inainte de instructiunea end finala. Aceasta instructiune va astepta sa apasam Enter, apoi va reveni in
mediul Turbo Pascal.
Observatie
89
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Limbajul Pascal dispune de functia EoLn care testeaza daca s-a ajuns la citirea sfarsitului de
linie, caz in care returneaza True, sau nu, cind returneaza False. O astfel de functie se poate folosi
atunci cand se doreste prelucrarea de linii de caractere, cu dimensiuni variabile.
Program demonstrativ
Sa se citeasca mai multe linii de caractere de la tastatura si sa se afiseze fiecare linie, inlocuind
caracterele mici cu majusculele corespunzatoare. Prelucrarea se va incheia la aparitia caracterului ‘$’.
Pentru a transforma literele mici in litere mari se va folosi functia UpCase.
Program ConversieMinusculeMajuscule;
Var linie_vida,gata: Boolean; c:Char;
begin
Gata:=False;
While not gata do
begin
Write(‘Dati linia: ‘);
While not EoLn do
begin
Read(c);Write(UpCase(c));
linie_vida:=False;
if c=’$’ then gata:=True
end;
if linie_vida then WriteLn(‘Linia este vida!’)
else WriteLn
end.
Tipuri de constante
-intregi – numere intregi pozitive care nu pot -intregi – numere intregi pozitive cu valori
depasi valoarea 32767, valoare identificata de intre 0 si 4.294.967.295 si care sunt de trei
compilator sub numele de MAXINT;valorile tipuri:
intregi pot fi numere: -zecimale (baza 10);
-zecimale (baza 10); Exemple:43,152,7564.
Exemple:43,187,2001. -octale (baza 8),care sunt precedate de un
-hexazecimale (baza 16),care sunt zero nesemnificativ;
precedate de caracterul special $ Exemplu:0354→345(8)
Exemplu:$2F4 sau $2F4→ 2F4(16). -hexazecimale (baza 16),care sunt
-reale – numere reale cu valori absolute precedate de Ox sau OX.
cuprinse intre 5.9×10(la puterea -39) si 3.4×10(la Exemplu:0×2F4 sau 0X2F4 sau
puterea 38);atat partea intreaga,cat si cea 0×2f4-→2F4(16).
zecimala trebuie sa contina cel putin o -reale – orice valoare reala
cifra,chiar daca aceasta este 0. Exemple:32.45,0.5.
-caracter – orice caracter scris intre apostrofuri. -caracter- orice caracter scris intre
Exemplu:’A’ apostrofuri.
-siruri de caractere – o succesiune de Exemplu:’A’
caractere,delimitata tot prin apostrofuri. -siruri de caractere – o succesiune de
Exemple:true/false,MAXINT. caractere,delimitata tot prin ghilimele.
-constante definite prin cuvinte-cheie
Exemplu:NULL
90
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Tipuri de date
Tipul SINGLE.
Se reţin numere reale care aparţin domeniului:
[-3,4*1038,-1,5*10-45] [1.5*10-45, 3,4*1038]
91
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
92
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
variabile elementare de orice tip sau de variabile elementare de orice tip sau de
constante. constante.
La terminarea scrierii (afisarii),cu
procedura writeln,cursorul este adus pe
prima pozitie a randului urmator.
Functii matematice
LIMBAJUL PASCAL LIMBAJUL C/C++
93
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
EXEMPLU:
LIMBAJUL PASCAL LIMBAJUL C/C++
var a,b,selector:integer; #include<iostream.h>
begin void main()
write(’a=’);readln(a);write(’b=’);readln(b); {int a,b,selector;
writeln(’Tastati una din cifre’); cout<<’’a=’’;cin>>a;cout<<’’b=’’;cin>>b;
writeln(’1-suma/2-diferenta/3-produs/4-cat’); cout<<’’Tastati una dintre cifre’’<<end1;
write(’selector=’);readln(selector); cout<<’’1-suma/2-diferenta/3-produs/4-cat’’;
case selector of cout<<’’selector=’’;cin>>selector;
1:write(’suma = ’,a+b); switch(selector)
2:write(’diferenta = ’,a-b); {case 1:cout<<’’suma=’’<<a+b;break;
3:write(’produsul = ’,a*b); case2:cout<<’’produsul=’’<<a*b;break;
4:write(’catul impartirii intregi=’,a div b); case3:cout<<’’diferenta=’’<<a-b;break;
else write(’Ati tastat o optiune inexistenta’); case4:cout<<’’catul=’’<<a/b;break;
end; default:cout<<’’Ati tastat o optiune inexistenta’’;
end. }}
94
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Daca secventa contine mai multe Daca secventa contine mai multe
instructiuni,atunci acestea sunt cuprinse intre instructiuni,atunci acestea sunt cuprinse intre
begin si end. acolade {}.
Exemplu:
repeat do
S; {S;
until (cond_logica); }while(cond_logica);
Secventa (S) se executa pana cand conditia Secventa (S) se executa cat timp conditia logica
logica este adevarata (expresia genereaza este adevarata (expresia genereaza o valoare
valoarea logica true). nenula).
Secventa se executa cel putin o data,chiar Secventa se executa cel putin o data,chiar deca
daca conditia logica este indeplinita conditia logica nu este indeplinita.
(adevarata).
95
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
begin for(i=1;i<=n;i++)
write(’numarul=’);readln(x); {cout<<’’numarul=’’);cin>>x;
if(x=1) then prim:=false if(x==1)prim=0;
else else
begin {prim=1;j=2;
prim:=true;j:=2; while (prim && j<=sqrt(x))
while(prim and (j<=trunc(sqrt(x)))) do if(x%j==0)prim=0;
if(x mod j=0 ) then prim:=false else j++;
else inc(j); }
end; If(prim) cout<<x<<end1;
if(prim) then writeln(x) }
end;end. }
Compararea valorilor.Profesorul diriginte doreste sa afle cea mai mare medie a clasei
96
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
end. max=medii[i];
//se afiseaza cea mai mare medie
cout<<’’media este’’<<max;
}
Subprograme
Noţiunea de subprogram
Prin subprogram vom înţelege un ansamblu alcătuit din tipuri de date, variabile şi
instrucţiunii scrise în vederea unei anumite prelucrări (calcule, citiri, scrieri) şi care poate fi utilizat
(rulat) doar dacă este apelat de un program sau de alt subprogram.
■ de prelucrare a şirurilor de caractere:in Pascal avem pos,length …,iar in C++ strlen, strcpy, strncat.
În acest capitol învăţăm să le creăm. Pentru a înţelege noţiunea de subprogram, vom porni de
la două exemple:
97
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
□ Se citeşte n, număr natural. Să se scrie programele care tipăresc valoarea calculată a expresiilor:
E1=1+1/2+1/3+1/4+…+1/n
E2=(1+1/2+1/3+1/4+…+1/n)ⁿ
E₂=E₁ⁿ
Cerinţa este de a scrie programe separate. Cum procedăm? Prin utilizarea cunoştinţelor
dobândite până în prezent, scriem cele două programe separat, iar în al doilea program, secvenţa care
calculează prima expresie, se copiază din primul.
Oare nu se poate lucra mai eficient? Răspunsul este afirmativ. Se scrie un program care
calculează E₁ şi care este apelat de ambele programe. Primul program va tipări valoarea transmisă de
subprogram, al doilea va ridica la putere această valoare şi va afişa rezultatul.
Desigur, ştim să rezolvăm această problemă şi clasic, în mai multe feluri, pentru că am studiat
mai mulţi algoritmi de sortare. De această dată vom rezolva problema prin utilizarea subprogramelor.
Vom scrie un subprogram care citeşte un vector, unul care tipăreşte un vector şi un al treilea
care sortează vectorul, după una din metodele cunoscute.
Faţă de scrierea clasică, aici problema a fost descompusă în altele mai mici (citire, sortare,
tipărire). În general, o problemă complexă se rezolvă mai uşor dacă o descompunem în altele mai
simple. Apoi, şansele de a greşi la scrierea unui subprogram sunt cu mult mai mici decât acelea de a
greşi la scrierea unui program mare. Acesta din urmă rezultă din “asamblarea” subprogramelor la care
se adaugă, eventual, câteva linii scrise în programul principal. Putem acum enumera avantajele
utilizării subprogramelor:
■ reutilizarea codului –o dată scris, un subprogram poate fi utilizat de mai multe programe;
■ elaborarea algoritmilor prin descompunerea problemei în altele mai simple. În acest fel, rezolvăm cu
mult mai uşor problema;
■ depistarea cu uşurinţă a erorilor –verificăm la început subprogramele, apoi modul în care le-am
asamblat (le-am apelat din cadrul programului).
Parametrii care se găsesc în antetul funcţiei se numesc parametrii formali.
Atunci când scriem o funcţie nu cunoaştem valoarea propriu-zisă a parametrilor. Funcţia trebuie să
întoarcă rezultatul corect, oricare ar fi valoarea lor. Din acest punct de vedere ei se numesc formali.
98
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
La apel, lucrurile stau altfel: valorile acestora sunt cunoscute. Prin urmare aceştia se cunosc
parametrii efectivi.
În esenţă, o funcţie este alcătuită din:
Antet – acesta conţine mai multe informaţii importante necesare compilatorului, numele funcţiei,
lista parametrilor formali, tipul rezultatului.
O funcţie poate fi apelată de sine stătător (prin nume şi lista parametrilor efectivi), dar poate fi inclusă şi în cadrul
expresiilor, caz în care, la evaluarea expresiei este apelată.
Sistemul de operare alocă fiecărui program trei zone distincte în memoria internă în care se găsesc
memorate variabilele programului.
Segment de date
Segment de stivă
Heap
1. Clasa de memorare.
2. Vizibilitate.
3. Durata de viaţă.
4. Tipul variabilei, singurul pe care l-am studiat până în prezent.
1. Clasa de memorare – precizează locul unde este memorată variabila respectivă. O variabilă poate
fi memorată în segmentul de date, în cel de stivă, în heap sau într-un registru al microprocesorului.
2. Vizibilitatea – precizează liniile textului sursă din care variabila respectivă poate fi accesată. Astfel
avem:
b. Vizibilitatea la nivel de fişier – în cazul în care programul ocupă un singur fişier sursă,
singurul caz pe care îl tratăm acum.
3. Durata de viaţă – reprezintă timpul în care variabila respectivă are alocat spaţiu în memoria
internă. Astfel avem:
a. Durata statică – variabila are alocat spaţiu în tot timpul execuţiei programului.
b. Durata locală - variabila are alocat spaţiu în timpul în care se execută instrucţiunile
blocului respectiv.
Variabile globale
Acestea se declară în afara corpului oricărei funcţii
La declarare, variabilele globale sunt iniţializate cu 0.
99
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
2. Vizibilitatea – În cazul în care declaraţiile acestora sunt înaintea tuturor funcţiilor, acestea sunt
vizibile la nivelul întregului program (fişier). Dacă anumite funcţii se află plasate înaintea
declaraţiilor acestor variabile, atunci ele sunt vizibile doar pentru funcţiile care sunt plasate după
aceste declaraţii.
3. Durata de viaţă a variabilelor globale este statică. Ele au spaţiu rezervat în tot timpul execuţiei
programului.
Variabile locale
Acestea sunt declarate în corpul funcţiilor. Mai precis, pot fi declarate în orice bloc (instrucţiune
compusă) al acestora
1. Clasa de memorare a variabilelor locale este, implicit, segmentul de stivă. Există posibilitatea ca
acestea să fie alocate în registrele microprocesorului, caz în care declaraţia lor trebuie precedată de
cuvântul cheie register.
1. Variabilele locale nu sunt iniţializate implicit cu 0. În ipoteza în care acestea nu sunt iniţializate
explicit de programator, reţin o valoare oarecare, numită valoare reziduală.
Transmiterea parametrilor
Aşa cum am arătat, parametrii care se găsesc în antetul funcţiei se numesc parametrii formali,
iar cei care se găsesc în instrucţiunea de apel se numesc parametrii efectivi.
După fiecare apel al funcţiei se tipăreşte suma obţinută. Între parametrii formali şi cei efectivi trebuie
să existe o anumită concordanţă, care este descrisă prin regulile următoare:
Numărul parametrilor formali trebuie să coincidă cu numărul parametrilor efectivi. La această regulă
există o excepţie care va fi prezentată într-un paragraf separat.
Tipul parametrilor formali trebuie să coincidă cu tipul parametrilor efectivi sau tipul parametrilor efectivi
să poată fi convertit implicit către tipul parametrilor formali la fel ca în cazul atribuirii
Observaţie: Nu este obligatoriu ca numele parametrilor formali să coincidă cu numele parametrilor
efectivi.
Vom analiza modul în care sunt memoraţi parametrii transmişi, în momentul lansării în
execuţie a funcţiei.
Memorarea parametrilor transmişi se face în ordinea în care aceştia figurează în antet: de la stânga
la dreapta.
În cadrul subprogramului, parametrii transmişi şi memoraţi în stivă sunt variabile. Numele lor este
cel din lista parametrilor formali.
100
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
A. Transmiterea prin valoare se utilizează atunci când suntem interesaţi ca subprogramul să lucreze
cu acea valoare, dar, în prelucrare, nu ne interesează ca parametrul efectiv (cel din blocul apelant)
să reţină valoarea modificată în subprogram.
1. Valorile reţinute de variabile. În acest caz, parametrii efectivi trebuie să fie numele
variabilelor.
2. Parametrii efectivi sunt expresii, care mai întâi se evaluează.
Aşa cum am arătat, transmiterea parametrilor prin valoare se utilizează atunci când nu ne
interesează ca, la întoarcerea din subprogram, parametrul efectiv să reţină valoarea modificată
acolo. Întrebare: dacă n-ar exista decât transmiterea prin valoare, ar fi posibil să modificăm
valoarea anumitor variabile care sunt declarate în blocul aparent?
În cazul transmiterii prin referinţă, parametrii efectivi trebuie să fie referinţe la variabile (vezi
tipul referinţă prezentat în capitolul anterior).
În acest caz ne putem întreba care este mecanismul prin care, deşi pentru o variabilă transmisă se
reţine adresa ei, în subprogram putem adresa variabila normal (nu indirect)? La compilare, orice
referinţă la variabila respectivă, este “tradusă” ca adresare indirectă.
Programul următor utilizează o funcţie care interschimbă valorile reţinute de două variabile.
Acestea sunt transmise prin referinţă.
Definirea şi declararea unui subprogram
Deşi aparent asemănătoare, cele două noţiuni diferă. Buna înţelegere a lor ne ajută să evităm
anumite erori. Mai mult, aceste noţiuni sunt utilizate de orice limbaj de programare.
□ A defini un subprogram, înseamnă a-l scrie efectiv, după structura anterior prezentată. O problemă
importantă este locul unde se defineşte subprogramul.
FUNCTII
LIMBAJUL PASCAL LIMBAJUL C/C++
declaratiile
FUNCTION tip_returnat_de_functie
nume_functie(parametrii:tip):tip_returnat_de_functie; nume_functie(tip parametrii)
Var variabile_locale:tip; {
Begin tip variabile_locale;
exemplu
Var s,i,n:integer; #Include<iostream.h>
Function ss(n:integer):integer; int i,n;
101
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
}
Exemplu
LIMBAJUL PASCAL LIMBAJUL C/C++
declaratiile
Var s, i,n:integer; #Include<iostream.h>
procedure ss(n:integer;var s:integer); int s=0,i,n;
Begin void ss(int n, int& s)
S:=0; {
For i:=1 to n do for (i=0;i<n;i++)
S:=s+i; s=s+i;
End; }
Begin void main()
Readln(n); {
ss(n,s); cin>>n;
Write(s); ss(n,s);
End. cout<<s;
}
RECURSIVITATE
Introducere in recursivitate
Prezentare generala
Recursivitatea este una din notiunile fundamentale ale informaticii. Utilizarea frecventa a recursivitatii
s-a facut dupa anii 80.Multe din limbajele de programare evaluate si mai mult utilizate -Fortran, Cobol-
nu permiteau scrierea programelor recursive.
Recursivitatea a aparut din necesitati practice date de transcrierea directa a formulelor matematice
recursive.In timp. Acest mecanism a fost extins, fiind utilizat in elaborarea multor algoritmi.
Mecanismul recursivitatii
102
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
A) Pentru a scrie o functie recursiva care efectueaza acelasi calcul, vom porni de la o
definitie recursiva a lui n !. Aceasta este :
n !=fact(n)= 1, n=0
n€N
n * fact(n-1), astfel
Care este mecanismul prin care subprogramele se pot autoapela? Sa ne amintim modul in care
subprogramele memoreaza parametrii transmisi:
● Pentru memorarea parametrilor, subprogramele folosesc o zona de memorie numita stiva (mai
exact, aceasta zona se numeste segment de stiva).
● Pentru parametrii transmisi prin valoare, se memoreaza valoarea transmisa, iar pentru cei
transmisi prin referinta se memoreaza adresa variabilei.
● In cadrul subprogramului, parametrii transmisi si memorati in stiva sunt variabile.Numele lor este
cel di lista parametrilor formali.
In capitolul anterior am studiat proprietatile structurii numita stiva. Exact aceleasi proprietati le are si
segmental de stiva.Singura diferenta este data de faptul ca gestiunea segmentului de stiva este facuta
automat de catre calculator.Mai exact, codul in limbaj masina, obtinut in urma compilarii, contine
secvente prin care se gestioneaza segmentul de stiva.
● In cazul in care subprogramul se autoapeleaza pe un al doilea nivel se depun din nou parametrii
transmisi si se rezerva un nou spatiu pentru variabilele locale.
In continuare prezentam grafic modul in care functioneaza recursivitatea in cazul functiei fact a
programului anterior. Aceasta functie nu are variabile locale, deci in stiva se depune doar parametrul
n.
n→2
n→3 Functia se autoapeleaza. De aceasta data parametrul n ia valoarea 2
103
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Var n:integer;
Procedure fact( val:integer;var prod:integer); #include <iostream.h >
Begin void fact(int val, int n,int& prod)
If (val<=n) then { if (val<=n)
Begin { prod*=val;
Prod=prod*val; fact(val+1,n,prod);
fact(val+1,n,prod); }
} }
begin main( )
readln(n); { int val,n,p=1;
p=1; cout<<”n=”; cin>>n;
fact(1,n,p); fact(1,n,p) ;
write(p); cout<<p ;
end. }
104
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
1 3 Referinta catre
p
1
p val n prod
Pentru ca val este mai mic sau egal ca n se efectueaza : prod :=prod*val ;Intrucat
variabila p a fost transmisa prin referinta, programul lucreaza cu aceasta variabila, in
loc de prod.In concluzie, se efectueaza p :=p*val ;.Apoi, functia se autoapeleaza :
2 3 Referinta catre p
1 1 3 Referinta catre p
p val n prod
2
p val n prod
Pentru ca val este 3 –mai mic sau egal cu 3 – se efectueaza prod :=prod*val, deci p
ia valoarea 6, dupa care se revine pe nivelul 2, apoi 1, apoi in programul principal.
Observatii :
▫Dupa cum rezulta din aceste exemple, subprogramul lucreaza cu datele aflate pe un
anumit nivel al stivei pentru variabilele transmise prin valoare si variabilele locale
ale sale, dar si cu variabilele functiei main( ) , daca acesteav sunt transmise prin
referinta.
105
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
▫In cazul unui numar mare de autoapelari , exista posibilitatea ca segmentul de stiva
sa se ocupe total, in caz in care programul se va termina cu eroare.
▫Recursivitatea presupune mai multa memorie(ma refer la stiva), aceasta este oricum
rezervata.
1.Wirth.O camera de luat vederi are in obiectiv un televizor care transmite imaginile
primite de la camera.Evident, in televizor se va vedea un televizor, iar in acesta
un televizor...s.a.m.d
Pe scurt :
▪ in orice televizor, se vede un televizor.
3.Constatare. Intr-o tara cu nivel de trai scazut, orice partid care ajunge la putere
afirma:de vina nu suntem noi, sunt cei de la care am preluat puterea!.
4.Logica. Orice militar aflat in ciclu 2 de instruire afirma :cand eram in ciclu 1, cei
din ciclu 2 ‘m-au chinuit inutil’.Asa fac si eu cu cei din ciclu 1.
106
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Observatii
▪Pentru orice algoritm recursiv exista unul iterativ care rezolva aceeasi problema.
107
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
}
Recursiv indirect sa se calculeze sirurile date prin:a0:=a;b0=b;
an:=(A[n-1]+B[n-2])/2
si bn:=sqrt(a[n-1]*b[n-1])
LIMBAJUL PASCAL LIMBAJUL C/C++
sursele
var n,a0,b0:word; #include <iostream.h>
function a(n:word):real;forward; #include <math.h>
function b(n:word):real; double a,b;
begin int n;
if n=0 then b:=b0
else double bn (int n);
b:=sqrt(a(n-1)*b(n-1)); double an (int n);
end; { if (!n) return a;
function a; else return (an(n-1)+bn(n-1))/2;
begin }
if n=0 then a:=a0
else double bn (int n)
a:=(a(n-1)+b(n-1))/2; { if (!n) return b;
end; else return sqrt(an(n-1)*bn(n-
begin 1));
writeln('valoarea initiala a sirului a ');readln(a0); }
writeln('valoarea initiala a sirului b ');readln(b0);
write('rangul sirurilor ');readln(n); main( )
writeln('b= ',b(n):6:2,' a= ',a(n):6:3); { cout<<”a=”;cin>>a;
readln; cout<<”b=”;cin>>b;
end. cout<<”n=”;cin>>n;
cout<<an(n)<<’ ‘<<bn(n) ;
}
DIVIDE ET IMPERA
o Se citeste un vector cu n componente,numere naturale.Se cere sa se
tipareasca valoarea maxima.
Problema de mai sus este binecunoscuta.Cum o rezolvam utilizand metoda divide et
impera?
Trebuie tiparita valoarea maxima dintre numerele retinute in vector de la i la j(initial
i=1,j=n).Pt acesta procedam astfel:
Daca i=j,valoarea amxima va fi v[i];
Contrar vom imparti vectorul in doi vectori(primul vector va contine
componentele de la i la (i+j) div 2,al doilea va contine componentele de la
(i+j)div 2+1 la j),rezolvam subproblemele(aflam maximul pentru fiecare
dintre ele) iar solutia problemei va fi data de valoarea maxima dintre
rezultatele celor doua subprobleme.
108
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Conform strategiei generale Divide et impera,problema este descompusa in alte doua subprobleme de
acelasi tip si,dupa rezolvarea lor,rezultatele se combina(in particular se interclaseaza).Descompunerea
unui vector in alti doi vectori care urmeaza a fi sortati are loc pana cand avem de sortat vetori de una
sau doua componente.
In aplicatie,functia sort sorteaza un vector cu maximum doua elemente;interc interclaseaza
rezultatele ;divimp implementeaza strategia generala a metodei studiate
109
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Pentru rezolvare este necesara o functie poz care trateaza o portiune din vector
cuprinsa intre indicii dati de li (limita inferioara) si ls(limita superioara).Rolul acestei
functii este de a pozitiona prima componenta a[li] pe o pozitie k cuprinsa intre li si
ls,astfel incat toate componentele vectorului cuprinse intre li si k-1 sa fie mai mici sau
egale decat a[k] si toate componentele vectorului cuprinse intre k+1 si ls sa fie mai
mari sau egale decat a[k].
In aceasta functie exista doua moduri de lucru:
110
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
111
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
a[st]:=a[dr]; { cout<<”a[“<<i<<”]=”;cin>>a[i];}
while (st<dr) and (a[dr]>=x) do dec(dr);
quick(1,n);
a[st]:=a[dr]; for (i=1;i<=n;i++) cout <<a[i]<<endl;
while (st<dr) and (a[st]<x) do inc(st); }
a[dr]:=a[st];
end;
a[st]:=x;divide:=st;
end;
procedure rapida(p,q:indice);
var m:indice;
begin
m:=divide(p,q);
if m-1>p then rapida(p,m-1);
if m+1 <q then rapida(m+1,q);
end;
begin
citire;
rapida(1,n);
afisare;
readln;
end.
112
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
o Turnurile din Hanoi.Se dau 3 tije simbolizate prin a,b,c.Pe tija a se gasesc discuri de
diameter diferite,asezate in orine descrescatoare a diametrelor private de jos in sus.Se
cere sa se mute discurile de pe tija a pe tija b,utilizand ca tija intermediara tija
c,respectand urmatoarele reguli:
La fiecare pas se muta un singur disc;
Nu este permis sa se aseze un disc cu diametrul mai mare peste un disc cu diametrul mai mic.
Rezolvare:
Daca n=1 se face mutarea ab,adica se muta discul de pe tija a pe tija b.
Daca n=2 se fac mutarile ac,ab,cb.
In cazul in care n>2 problema se complica.Notam cu H(n,a,b,c) sirul mutarilor celor n discuri de pe tija a
pe tija b,utilizand ca tija intermediara,toja c.
Conform strategiei Divede et impera incercam sa descompunem problema in alte doua subprobleme
de acelasi tip,urmand apoi combinarea solutiilor.In acest sens,observam ca mutarea celor n discuri de
pe tija a pe tija b,utilizand ca tija intermediara tija c,este echivalenta cu:
Mutarea a n-1 discuri de pe tija a pe tija c,utilizand ca tija intermediara tija b;
Mutarea discului ramas pe tija b;
Mutarea a n-1 discuri de pe tija c pe tija b,utilizand ca tija intermediara tija a.
a b, daca n=1
H(n,a,b,c)=
H(n-1,a,c,b),ab,H(n-1,c,b,a), daca n>1
Pentru n=2 avem: H(2,a,b,c)=H(1,a,c,b),ab,H(1,c,b,a)=ac,ab,cb.
Pentru n=3 avem:
H(3,a,b,c)=H(2,a,c,b),ab,H(2,c,b,a)=H(1,a,b,c),ac,H(1,b,c,a),ab,H(1,c,a,b),cb,H(1,a,b,
c)=ab,ac,bc,ab,ca,cb,ab.
113
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
discurile(n-1,a,c,b); else
writeln(a,'-----se pune pe---> ',b); {
discurile(n-1,c,b,a); han(n-1,a,c,b);
end; cout<<a<<b<<endl;
end; han(n-1,c,b,a);
begin }
write('n=');readln(n); }
a:='mic';b:='mijlociu';c:='mare'; mian ( )
discurile(n,a,b,c); {
readln; cout<<”N=”;cin>>n;
end. a=’a’;b=’b’;c=’c’;
han(n,a,b,c);
}
Mentionam ca dreptunghiul de arie maxima fara gauri este retinut prin aceiasi
parametric ca si dreptunghiul cu gauri,in zonele XF,YF,LF,HF
114
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
TABLA DREPTUNGHIULARA
TABLA #include <iostream.h>
{SE DAU COORDONATELE COLTURILOR UNEI TABLE int 1,h,I,n,xf,yf,lf,hf,xv[10],yv[10];
DREPTUNGHIULARE SI N GAURI IN EA
Stiind ca se permit numai taieturi orizontale si verticale sa se void dimp(int x,int y,int l,int h,int&
decupeze xf,int&yf,int& lf,int& hf,int xv[10],int yv[10])
o bucata de arie maxima} { int gasit=0,i=1;
type vector=array[1..100] of integer; while (i<=n && !gasit)
var x,y:vector; if (xv[i]>x && xv[i]<l && yv[i]>y &&
n:integer; yv[i]<y+h)
function max(i,j:integer):integer; gasit=1;
begin else i++;
if i<j then max:=j if (gasit)
else { dimp(x,y,xv[i]-x,h,xf,yf,lf,hf,xv,yv);
max:=i; dimp(xv[i],y,l+x-xv[i],h,xf,yf,lf,hf,xv,yv);
end; dimp(x,y,l,yv[i]-y,xf,yf,lf,hf,xv,yv);
function arie(x1,y1,x2,y2:integer):integer; dimp(x,yv[i],l,h+y-yv[i],xf,yf,lf,hf,xv,yv);
var i:integer;nusereducelaunpunct:boolean; }
begin else
i:=1;nusereducelaunpunct:=false; if (l*h>lf*hf)
repeat { xf=x;yf=y;
nusereducelaunpunct:=(x1<x[i]) and(x[i]<x2) and(y1<y[i]) and lf=l;hf=h;
(y[i]<y2);i:=i+1; }
until nusereducelaunpunct or(i=n+1); }
i:=i-1; main ( )
if not nusereducelaunpunct then { cout<<”n=”;cin>>n;
arie:=(x2-x1)*(y2-y1) for(int i=1;i<=n;i++)
else { cout<<”x[“<<i<<”]=”;cin>>xv[i];
arie:=max( max(arie(x1,y1,x[i],y2),arie(x[i],y1,x2,y2)),max(arie(x1,y1,x cout<<”y[“<<i<<”]=”;cin>>yv[i];
2,y[i]),arie(x1,y[i],x2,y2))); }
end; cout<<”l=”;cin>>l;cout<<”h=”;cin>>h;
begin dimp(0,0,l,h,xf,yf,lf,hf,xv,yv);
n:=6; cout<<”x=”<<xf<<”y=”<<yf<<”l=”<<”h=”<<hf
x[1]:=5;x[2]:=7;x[3]:=10;x[4]:=12;x[5]:=13;x[6]:=17; ;
y[1]:=3;y[2]:=4;y[3]:=5;y[4]:=13;y[5]:=16;y[6]:=22; }
writeln(arie(0,0,20,20));readln;
end.
BACKTRACKING
Aspecte teoretice
Aceasta tehnica se foloseste in reezolvarea problemelor care indeplinesc simultan urmatoarele conditii:
solutia lor poate fi pusa sub forma unui vector S=x1,x2,..,xn,cu x1 apartine de de A1,x2
apartine de A2,…,xn apartine de An;
multimile A1,A2,…,An sunt multimi finite,iar elementele lor se considera ca se afla intr-o relatie
de ordine bine stabilita;
nu se dispune de o alta metoda de rezolvare,mai rapida.
Observatii:
nu pentru toate problemele n este cunoscut de la inceput;
x1,x2,…,xn pot fi la randul lor vectori;
in multe probleme,multimile A1,A2,…,An coincide.
Observatie: tehnica Backtracking are ca rezultat obtinerea tuturor solutiilor problemei.In cazul in care se
cere o singura solutie,se poate forta oprirea,atunci cand a fost gasita.
Pentru usurarea intelegerii metodei,vom prezenta o rutina unica(aplicabila oricarei
probleme),rutina care este elaborate folosind structura de stiva.Rutina va apela functii care au
intotdeauna acelasi nume si care,din punct de vedere al metodei,realizeaza acelasi
lucru.Sarcina rezolvitorului este sa scrie explicit,pentru fiecare problema in parte,functiile
apelate de rutina backtracking.
Evident o astfel de abordare conduce la programe lungi.Nimeni nun e opreste ca,dupa
intelegerea metodei,sa scriem programe scurte,specifice fiecarei probleme in parte(de
115
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
1 2 2 2 2
1 1 1 1 1 1
1 2 3
3 3 3 3 1
1 1 1 1 2 2
1 2 3 1
1 1 1 2 3 3
2 2 2 2 2 2
116
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Observam ca a treia daman u poate fi plasata in linia a 3-a.Incercam atunci plasarea celei de-a doua
dame in coloana a 4-a.
D
D
D
117
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
D
D
D
Acum este posibil sa plasam a patra dama in coloana a-3-a si astfel am obtinut o solutie a problemei.
D
D
D
D
Algoritmul continua in acest mod pana cand trebuie scoasa de pe tabla prima dama.
Pentru reprezentarea unei solutii putem folosi un vector cu n componente (avand in vedere ca pe
fiecare linie se gaseste o singura dama).Exemplu:pentru solutia gasita avem vectorul st ce poate fi
asimilat unei stive.
Doua dame se gasesc pe aceeasi diagonala daca si numai daca este indeplinita conditia:l st(i)-st(j) l=li-
jl: diferenta, in modul, intre linii si coloane este aceeasi).
ST(4)
ST(3)
ST(2)
ST(1)
sau situatia:
D st(1) = 3 i = 1
st(3) = 1 j=3
D | st(i) – st(j) l|= | 3-1 | = 2
| i-j | = |1-3 | = 2
Intrucat doua dame nu se pot gasi in aceeasi coloana, rezulta ca o solutie este sub forma de permutare.
O prima idee ne conduce la generarea tuturor permutarilor si la extragerea solutiilor pentru
3 problema ( ca doua dame sa nu fie plasate in aceeasi diagonala).A proceda astfel, inseamna
1 ca nu lucram conform strategiei backtracking.
4
2
LIMBAJUL PASCAL LIMBAJUL C/C++
GENERARE PERMUTARI
type sir =array[1..100] of integer; #include <iostream.h>
int st[10],n,k;
var x:sir;
p,i,j,k,n,k1:integer; void Init( )
118
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
as,ev:boolean; { st[k]=0;}
v:string[20];
int Am_Succesor( )
procedure succesor(var x:sir;k:integer;var { if st[k]<n)
as:boolean); { st[k]++;
begin return 1;
if (x[k]<n) then begin }
as:=true; x[k]:=x[k]+1; else return 0;
}
end int E_Valid( )
else { for (int i=1;i<k;i++)
as:=false; if (st[i]==st[k]) return 0;
end; return 1;
}
procedure valid(x:sir;k:integer;var ev:boolean);
var i:integer; int Solutie ( )
begin { return k==n;}
ev:=true;
for i:=1 to k-1 do void Tipar( )
if v[x[k]]=v[x[i]] then ev:=false; {
for (int i=1;i<=n;i++)
end; cout<<st[i];
cout<<ebdl;
}
procedure afis(x:sir;k:integer);
var i:integer; void back( )
begin {int AS;
for i:=1 to n do
k=1;
write(v[x[i]],' ');
Init( );
while (k>0)
writeln;
{ do {}
end;
while ((AS=Am_Succesor( ))
&& !E_Valid( ));
begin
if (AS)
READLN(N);
if (Solutie( ))
write('dati vectorul ');
Tipar( );
readln(v);
for i:=1 to n do else
read(v[i]; {
k:=1; k++;
x[k]:=0; Init( );
while(k>0) do }
begin else k--;
repeat }
succesor(x,k,as); }
if as then valid(x,k,ev) main ( )
until (as and ev) or (not as); { cout<<””n=;cin>>n;
if as then back( );
if (k=n) then }
afis(x,k)
else
begin
k:=k+1;
x[k]:=0;
end
else
k:=k-1 ;
end;
readln;
end.
119
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
begin main( )
{ cout<<”n=”; cin>>n;
write('dati numarul n= '); back( );
readln(n); }
k:=1; p:=1;
x[k]:=0;
while(k>0) do
begin
repeat
succesor(x,k,as);
if as then valid(x,k,ev)
until (as and ev) or (not as);
if as then
if k=n then begin
120
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
writeln('solutia
',p);writeln('==============');
afis(x,k);
end
else
begin
k:=k+1;
x[k]:=0;
end
else
k:=k-1 ;
end;
readln;
end.
cin>>v.camp1;
…
cin>>v.campN
}
121
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
GREEDY
122
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
{Dindu-se n spectacole fiecare avind ora de inceput si de sfirsit sa se stabileasca o #include <iostream.h>
ordine a lor ca sa aiba loc un numar maxim de spectacole int s[2][10],o[10],n,i,h1,m
Varianta 1:se dau n compozitori fiecare cu durata lui de viata void sortare( )
Se cere sa se scrie un numar maxim de compozitori contemporani {
VARIANTA 2:Fiind date n intervale sa se determine multimea maxima de intervale int gata,m,i;
disjuncte do{ gata=1;
VARIANTA 3:FIIND DATE DURATA DE INCEPUT SI SFIRSIT LA N MELODII for (i=1;i<=n-1;i++);
CUM LE ORGANIZEZ CIT MAI MULTE PE O BANDA if (s[i][o[i]] s[1][o[i+1]])
} {m=o[i];o[i]=o[i+1];
type spectacol=array[1..2,1..10] of integer; o[i+1]=m;
ordine=array[1..10] of integer; gata=0;
var s:spectacol; }
o:ordine; }
n,i,oradeinceputaspectacoluluicurent,siciteminutearespectacolulcurent, while (!gata)
oradesfirsitaspectacoluluiurmator,siciteminutearespectacolulurmator:integer; }
procedure sortare; main( )
var gata:boolean; { cout<<"n=";cin"n;
variabiladeschib,i:integer; for (i=1;i<=n;i+=)
begin {o[i]=i;
repeat cot<<"ora de inceput pen
gata:=true; spectacolul"<<i<<"( h h)
for i:=1 to n-1 do cin >>h1>m1;
if s[2,o[i]]>s[2,o[i+1]] then s[0][i]=h1*60+m1;
begin cout <<"oradesfarsit pen
variabiladeschib:=o[i]; "<<i<,"(hh mm)=";
o[i]:=o[i+1]; cin>>h2>>m2;
o[i+1]:= variabiladeschib; s[1][i]=h2*60+m2;
gata:=false; }
end; sortare( );
until gata; cout,<<ordinea spectaco
end; este"<<end1<<0[1]<<end
begin ora=s[1][o][1]];
write(' nr de spectacole n='); for (i=2;i<=n;i++)
readln(n); { if (s[0][o[i]]>=ora{cout<
for i:=1 to n do ora=s[1][o[i]];}
begin }
o[i]:=i; }
write ('ora de inceput pentru spectacolul ',i); readln(oradeinceputaspectacoluluicurent);
write ('si cite minute ',i); readln(siciteminutearespectacolulcurent);
write ('ora de sfirsit pentru spectacolul ',i); readln(oradesfirsitaspectacoluluiurmator);
write ('si cite minute ',i); readln(siciteminutearespectacolulurmator);
s[1,i]:=oradeinceputaspectacoluluicurent*60+siciteminutearespectacolulcurent;
s[2,i]:=oradesfirsitaspectacoluluiurmator*60+siciteminutearespectacolulurmator;
end;
sortare;
write('primul este ',o[1]);
for i:=2 to n do
if s[1,o[i]]>=s[2,o[i-1]] then
123
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
prima situatie,problema poarta numele de problema continua a rucsacului ,iar in a doua avem
problema discreta a rucsacului.Aceste doua probleme se rezova diferit,mpotiv pentru care ele
sunt prezentate separat .Varianta continua a probelmei rucsacului este tratata in acest
paragraf.Algoritmul este urmatorul:
-se calculeaza,pentru fiecare obiect in parte,eficienta de transport rezultata prin impartirea
castigului la greutate(de fapt,acesta reprezinta castigul optinut din transportul unitatii de
greutate);
-obiectele se sorteaza in ordine descrescatoare a eficintei de transport si se preiau in calcul in
aceasta ordine;
-castigul initial va fi 0 iar greutatea ramasa deincarcat va fi G
-atat timp cat nu a fost completata greuatatea maxima a rucsacului si nu a fost luate un
considerare toate obiectele se procedeaza astfel:
-dintre obiectele neincarcate se selecteaza acela cu cea mai mica eficienta de transport si
avem doua posibilitati:
-acesta incape in totalitate in rucsac.deci se scade din greutatea ramasa de incarcat
greutatea obictului,la castig se cumuleaza castigul datorat transportului acestui obiect;
-se tipareste 1 in sensul ca intregul obiect a fost incarcat;
-obiectul nu incape in totalitate in rucsac,caz in care se calculeaza ce parte din el poate fi
transportata se cumuleaza castigul obtinut cu transportul aceste plati din obiect iar greutatea
ramasa de incarcat devine 0.
PROBLEMA RUCSACULUI
{Dindu-se un rucsac de o anumita capacitate si n obiecte care au un cost #include<iostream.h>
si o greutate si stiind ca se poaate lua si double c[9],g[9],ef[9],gv,man,castig;
o parte din fiecare obiect sa se gaseasca o modalitate de cistig maxim int n,i,man1,inv,ordine[9];
transportat cu rucsacul} main( )
type vector=array[1..9] of real; {cout<<''Greutatea ce poate fi transportata='';cin
var i,n,auxiliara1:integer; ef,c,greutateaobiectului :vector; cout<<''Numar de obiecte='';cin>>n;
capacitatearucsacului,auxiliara,cistig:real; for(i=1;i<=n;i++)
inv:boolean; {
ordine:array[1..9] of integer; cout<<''c[''<<i<<'']='';cin>>c[i];
begin cout<<''g[''<<i<<''];cin>>g[i];
write('greutatea ce poate fi transportata in sac '); ordine[i]=i; ef[i]=c[i] /g[i];
readln(capacitatearucsacului); }
writeln(' cite obiecte sunt'); do
readln(n); {
for i:=1 to n do inv=0;
begin for(i=1;i<=n-1;i++)
write('costul obiectului ',i);readln(c[i]); if(ef[i]<ef[i+1])
write('greutatea obiectului ',i);readln(greutateaobiectului[i]); { man=ef[i];ef[i]=ef[i=1];ef[i=1]=man;
ordine[i]:=i; man=c[i]; c[i]=c[i=1]; c[i=1]=man;
ef[i]:=c[i]/greutateaobiectului[i]; man=g[i];g[i]=g[i+1]=man;
end; inv=1;
repeat man1=ordine[i];ordine[i]=ordine[i+1];ordine[i+1]
inv:=false; }
for i:=1 to n-1 do }
if ef[i]<ef[i+1] while (inv);
then i=1;
begin while(gv>o && i<=n)
auxiliara:=ef[i]; {
ef[i]:=ef[i+1]; if (gv>g[i])
ef[i+1]:=auxiliara; { cout <<''Obieclul ''<<ordine[i]<< ' '<<1<<endl;
auxiliara:=greutateaobiectului[i]; gv-=g[i];castig+=+c[i];
greutateaobiectului[i]:=greutateaobiectului[i+1]; }
greutateaobiectului[i+1]:=auxiliara; else
auxiliara:=c[i]; {cout<<''Obiectul ''<<ordine[i]<<' ' <<gv /g[i]<<en
124
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
end
else
begin
writeln('obiectul cu numarul de ordine ',ordine[i],' intra din el
',capacitatearucsacului/greutateaobiectului[i]:1:2);
cistig:=cistig+c[i]*capacitatearucsacului/greutateaobiectului[i];
capacitatearucsacului:=0;
end;
i:=i+1;
end;
writeln('cistigul maxim este ',cistig:3:2);
readln;
end.
PROGRAMARE DINAMICA
Alaturi de Greedy,programarea dinamica este o tehnica ce conduce, de cele mai
multe ori, la un timp de calcul polinomial.Mai mult, ea furnizeaza in totdeauna solutia
optima .Din nefericire, programarea dinamica nu se poate aplica tuturor problemelor, ci
numai care indeplinesc anumite conditii.
Se considera o problema in care rezultatul se obtine ca urmare a unui sir de decizii D1,
D2,......Dn. In urma decizei D1 sistemul evolueaza din starea S0 in starea S1,in urma
decizei D2 sistemul evolueaza din starea S1 in starea S2,....,in urma decizei Dn sistemul
evolueaza din starea Sn-1 in stareaSn.
Daca D1, D2,....Dn este un sir de decizii care comduce sistemul in mod optim din S0 in
Sn,atunci trebuie indeplinita una din conditiile urmatoare (principiul de optimalitate):
1)Dk...Dn este un sir de decizii ce conduce optim sistemul din starea Sk-1 in starea
Sn,Ak,1<=k<=n;
2)D1....Dk este un sir de decizii ce conduce optim sistemul din starea S0 in
stareaDk,Ak,1<=K<=;
3)Dk+1...Dn,D1...Dk sunt siruri de decizii care conduc optim sistemul starea Sk in starea
Sn, respectiv din starea D0 in starea Sk,Ak,1<=k<=n.
=>Daca principiulde optimalitate se verifica in forma 1,spunem ca se aplica programarea
dinamica metoda inainte.
=>Daca principul de oplimalitate se verifica in forma 2, spunem ca se aplica programarea
dinamica inapoi.
=>Daca primcipiul de optimalitate se verifica in forma 3, spunem ca se aplica programarea
dinamica metoda mixta.
125
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Programarea dinamica se poate aplica problemelor la care optimul general implica optimul
partial.
Faptulca optimul general determina optimul partial, nu inseamna ca optimul partial determina
optimul general.
cu toate acestea, faptul ca potimul general impune optimul partial ne este de mare
ajutor:cautam optimul general,intre optimele partiale, pe care le retinem la fiecare
pas.Oricum,cautarea se reduce considerabil.
Problema triunghiului.Se considera un triunghi de numere naturale format din n
linii.Prima linie contine un numar,a doua doua numere,........ultims n numere naturale.Cu
ajutorul acestuoi triunghi se pot forma sume ne numer naturale in felul urmator:
-se porneste cu numarul din linia unu;
-succesorul unui numar se afla pe linia urmatoare plasat sub el(acees coloana) sau pe
diagonala la dreapta(coloana creste cu 1).
Care este cea mai mare suma care se poate forma astfel si care sunt numerele care o
alcatuiesc:
Exemplu:n=4;
2
3 5
6 3 4
5 6 1 4
Se pot forma mai multe sume:
S1=2+3+6+5=16;
S2=2+5+4+1=12;
Sk=2+3+6+6=17 (care sete[i suma maxim').
Saq observam ca se pot forma 2 la puterea n-1 sume de acest fel.A le lua in considerare pe
toate pentru a gasi valoarea maxima nu este eficient.
Pentru etapa i se trateza linia i a triunghiului.Fie un sir de n numere care respecta conditile
problemei si care formeaza suma maxima.In acest sir,consideram numarul care a fost preluat
de pe linia i.Numerele intre i+1 si n,formeaza o suma maxima in raport cu sumele care se pot
forma incepand cu nu,marul preluat de pe linia i,contrar,se contrazice ipoteza.In aceasta
situatie se poate aplica programarea dinamica,metoda inainte.
Vom forma un triunghi,de la baza catre varf,cu sumele maxime care se pot forma cu fiecare
numar.Daca am citit triunghiul de numere intr-o matrice T si calculam sumele intr-o matrice C
vom avea relatiile urmatoare:
C[n][1]:=T[n][1];
C[n][2]:=T[n][2];
C[n][n]:=T[n][n];
Pentru linia i (i<n), cele i sume maxime care se obtin aqstfel:
C[i][j]=max{T[i][j]+C[i+1][j],T[i][j]+C[i+1][j+1]},i apatine multimii {1,2,....,n-1) iar j apartine multimii
{1,.....,i}.
Sa rezolvam problema propusa ca exemplu:
Linia 4 a matricei C va fi linia n a matricei T:5 6 1 4;
Linia 3 se calculeaza astfel:
C[3][1]=max{6+5,6+6}=12;
C[3][2]=max{3+6,3+1}=9;
C[3][3]=max{4+1,4+4}=8;
Linia 2:
C[2][1]=max{3+12,3+9}=15;
C[2][3]=max{5+9,5+8}=14;
Linia 1
C[1][1]=max{2+15,2+14}=17.
Aceasta este si cea mai mare suma care se poate forma.
126
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Pentru a tipari numerele luate in calcul se foloseste o matrice numita DRUM in care pentru
fiecare i apartinand multimii mai sus mentionate si j la fel apartinand multimii mentionate mai
sus se retine coloana in care se gaseste succesorul lui T[i][j].
celcareretinesumamaximademomentpelinie[i,j]:=celcareretinesumamaximademo
mentpelinie[i+1,j+1]+t[i,j] ;
end;
writeln('suma este ',celcareretinesumamaximademomentpelinie[1,1]);
d:=celcareretinepozitiadinliniepentrusumamaxima[1,1];
writeln(1);
for i:=1 to n-1 do
begin
writeln(celcareretinepozitiadinliniepentrusumamaxima[i,d]);
d:=celcareretinepozitiadinliniepentrusumamaxima[i,d];
end;
readln;
end.
127
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
128
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
129
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
0 100 x x
x 0 10 x
A= x x 0 100
x x x 0
In continuare calculam:
A(1,3)=min{A(1,k)
+A(k+1,3)+DIM(1)*DIM(k+1)*DIM(4)}=min{0+10+10*1*1,100+0+10*10*1}=20;
A(2,4)=min{A(2,k)
+A(k+1,4)+DIM(2)*DIM(k+1)*DIM(5)}=min{0+100+1*10*10,10+0+1*1*10}=20;
A(1,4)=min{A(1,k)
+A(k+1,4)+DIM(1)*DIM(K+1)*DIM(5)}=min{0+20+10*1*10,100+100+10*10,20+0+10*1*10}=12
0;
.
0 100 20 120
x 0 10 20
A= x x 0 100
x x x 0
In concluzie,pt. exemplul nostru, se fac minim 120 de inmultiri,rezultat luat din matricea A si anume
A(1,4).
LIMBAJUL PASCAL LIMBAJUL C/C++
Inmultiri optimale de matrice
#include<iostream.h>
{Prin programare dinamica sa se determine numarul minim de int i,n,dim[10]
inmultiri care sa se faca long a[10] [10];
cind se dau dimensiunile matricelor
ex:n=4 void costopt(int n,int dim[10],long
10 1 10 1 10} a[10] [10])
{int k,i,j,l;
program inm_optima; long m;
const nmax=20; for (i=1;i<=n;i++) a[i] [i]=0;
type vector=array[1..nmax] of word; for (k=1;k<=n-1;K++)
tabl=array[1..nmax,1..nmax] of word; for (i=1;i<=n-k;i++)
var p:vector; { j=i+k;
m:tabl;n,i,j,k,imin:integer;min,v:word; a[i] [j]=100000;
procedure paranteze(i,j:integer); for(l=i;l<=j;l++)
var k:integer; {m=a[i] [l] +a[l+1] [j]
begin +dim[i]*dim[l+1]*dim[j+1];
if i<j then begin if (a[i] [j]>m)
k:=m[j,i]; {
if i<>k then begin a[i] [j]=m;;
write('('); a[j] [i]=l;
130
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
paranteze(i,k); }
write(')'); }
end }
else paranteze(i,k); cout<<"cost optim:"<<a[1]
write('x'); [n]<<end1;
if k+1<>j then begin
write('('); }
paranteze(k+1,j); main()
write(')') {cout<<"n=";cin>>n;
end for (i=1;i<=n+1;i++)
else paranteze(k+1,j); { cout<<"d=";cin>>dim[i];}
end costopt(n,dim,a);
else write('A',i) }
end;
begin
write('Nr. de matrici:');
readln(n);
writeln('Dimensiuni matricelor:');
for i:=1 to n+1 do read(p[i]);
for i:=n downto 1 do
for j:=i+1 to n do
begin
min:=m[i,i]+m[i+1,j]+p[i]*p[i+1]*p[j+1];
imin:=i;
for k:=i+1 to j-1 do
begin
v:=m[i,k]+m[k+1,j]+p[i]*p[k+1]*p[j+1];
if min>v then begin
min:=v;
imin:=k
end;
end;
m[i,j]:=min;
m[j,i]:=imin;
end;
writeln('Numarul minim de inmultiri este:',m[1,n]);
writeln('Aceasta se obtine pentru urmatoarea ordine a
inmultirilor');
paranteze(1,n);
readln;
end.
131
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Alocare dinamica
Memoria interna poate fi privita ca o succesiune de octeti.Numarul de ordine
al unui octet se numeste adresa lui.Adresa unei variabile nu trebuie confundata cu
valoarea pe care aceasta o memoreaza.
Definitie: Adresa primului octet al variabilei se numeste adresa variabilei.
Adresele variabilelor se memoreaza cu ajutorul variabilelor de tip pointer.
LIMBAJUL PASCAL LIMBAJUL C/C++
Alocarea spatiului pentru variabila poiter p si elberarea lui
Procedure new(var p:pointer); P=new p;
Procedure dispose (var p :pointer); Delete p;
Ex: Ex:
Var adr1:^integer; Void main ()
New(adr1);adr^:=7; {
Writeln(adr1);dispose(adr1); int * adr1;
End; adr1=new int;
adr =7;cout<<*adr1;
delete adr1;
}
Tipul enumerare
LIMBAJUL PASCAL LIMBAJUL C/C++
union nume_enumerare
{
tip v0;
tip v1;
…
tip vn-1;
};
Exemplu:
#include< iostream.h>
132
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
union test
{ int a;
char b[10];
double c;
};
main()
{
test var;int I;
cin>>var.c;cout<<var.c<<endl;
cin>>var.c;cout<<var.c<<endl;
}
Siruri de caractere
LIMBAJUL PASCAL LIMBAJUL C/C++
SINTAXA: SINTAXA:
TYPE NUME=string[dimensiune]; Char nume[dimensiune] ;
Var variabila:nume; Char nume[dimensiune] =”sirul”;
Sau: Ex:
Var variabila:string[dimensiune]; #Include<iostream.h>;
Variabila[0] este lungimea sirului main()
Are maxim 255 de caractere {
Ex: char a[20];
Var a:string[3]; cin>>a;
Begin cout<<a;
A:=”cal”; }
Write(a); obs:
End. a[0] reprezinta prima componenta
a sirului
Functii care lucreaza cu siruri de caractere
LIMBAJUL PASCAL LIMBAJUL C/C++
LUNGIMEA UNUI SIR DE CARACTERE
Sintaxa: Sintaxa:
Variabila :=Length(sir); #include<string.h>
Ex: Variabila:= strlen (sir);
Var s: string; Ex:
Begin #include<iostream.h>
Readln(s); #include<string.h>
Writeln(length(s); main()
End. {
char a[100];
cin.get(a,100);
cout<<”sirul este de lungimea
“<<strlen (a);
}
133
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
134
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
135
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
main()
{
int s;
char a[100]=”11.2001”;
s=strtoi(a);
cout<<p;
}
#include<iostream.h>
#include<string.h>
main()
{
FLOAT s;
char a[100]=”11.2001”;
s=strtof(a);
cout<<p;
}
Stiva funcţionează pe principiul LIFO (Last In First Out) – “ultimul intrat, primul ieşit”.
Pentru a înţelege modul de lucru cu stiva, ne imaginăm un număr n de farfurii identice, aşezate
una peste alta (o “stivă” de farfurii). Adăugarea sau scoaterea unei farfurii se face, cu uşurinţă, numai în
vârful stivei. Oricât ar părea de simplu principiul stivei, el are consecinţe uriaşe în programare.
Stivele se pot aloca secvenţial (ca vectori). Fie ST[i] un vector. ST[1], ST[2], … , ST[n] pot reţine numai
litere sau numai cifre. O variabilă k indică în permanenţă vârful stivei, adică ultimul element introdus.
Observaţii:
În mod practic, la scoaterea unei variabile din stivă, valoarea variabilei ce indică vârful stivei scade cu 1, iar atunci
când scriem ceva în stivă, o eventuală valoare reziduală se pierde.
136
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Pe un anumit nivel se reţine, de regulă, o singură informaţie (literă sau cifră), însă este posibil, aşa cum va rezulta
din exemplele prezentate în lucrare, să avem mai multe informaţii, caz în care avem stive duble, triple, etc.
În cazul stivei, alocarea secvenţială nu prezintă mari dezavantaje, ca în cazul mai general, al listelor, pentru că nu
se fac operaţii de inserare sau ştergere în interiorul stivei. Singurul dezavantaj, în comparaţie cu alocarea dinamică
înlănţuită este dat de faptul că numărul de noduri care pot fi memorate la un moment dat este mai mic – depinde de
gradul de ocupare al segmentului de date.
În literatura de specialitate veţi întâlni termenul PUSH pentru operaţia de adăugare în stivă a unei înregistrări şi
POP, pentru extragere.
Exemple:
137
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Vom începe prin a studia modul de calcul al funcţiei pentru x=15 şi x=8.
f(15)=14;
f(8)=f(f(10))=f(f(f(12)))=f(f(11))=f(f(f(13)))=f(f(12))=f(11)=f(f(13))= f(12)=11.
Algoritmul va folosi o stivă ST şi o variabilă k, ce indică în permanenţă vârful stivei. Algoritmul se
bazează pe următoarele considerente:
■ la o nouă autoapelare a funcţiei f, se urcă în stivă (k se incrementează cu 1) şi se pune noua valoare.
■ în situaţia în care pentru valoarea aflată pe nivelul k se poate calcula funcţia, se coboară în stivă, punându-se pe
acest nivel noua valoare.
12 13
10 10 11 11
8 8
8 8 8
12 13
11 12
8 11
f=11
138
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
139
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
n,man:integer;
procedure push(var v:adresa;n:integer);
var c:adresa;
begin
if v=nil then
begin
new(v);
v^.info:=n;
v^.adr_inap:=nil;
end
else
begin
new(c);
c^.info:=n;
c^.adr_inap:=v;
v:=c;
end;
end;
procedure pop(var v:adresa);
var c:adresa;
begin
if v=nil then writeln('stiva este vida')
else
begin
c:=v;
v:=v^.adr_inap;
dispose(c)
end;
end;
procedure tipar(v:adresa);
var c:adresa;
begin
c:=v;
while c<> nil do
begin
writeln(c^.info);c:=c^.adr_inap;
end;
end;
begin
write('n=');
readln(n);
push(v,n);
while v<>nil do
if v^.info <12 then
begin
push(v,v^.info+2);
tipar(v); readln;
end
else
begin man:=v^.info;
pop(v);
tipar(v);
readln;
140
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
DINAMIC IN GENERAL
{Sa se creeze o stiva.
Scrieti doua proceduri diferite care
elimina elemente in stiva}
type ref=^inr;
inr=record
nr:integer;
urm:ref;
end;
var p:ref;
i,n:integer;
procedure b(var p:ref);
var c:ref;
begin
new(c);
writeln(' pe cine pui in stiva
');readln(c^.nr);
c^.urm:=p;
p:=c;
end;
procedure s(var p:ref);
var c:ref;
begin
if p=nil then
writeln(' goala ')
else
begin
writeln(' scot din stiva pe');
writeln(p^.nr);
c:=p;
p:=p^.urm;
dispose(c);
end;
end;
procedure s1(var p:ref);
var q:ref;
begin
q:=p;
p:=q^.urm;
dispose(q);
end;
begin
write('dati un numar n>=3 ');
readln(n);
for i:=1 to n do
b(p);
writeln('-----------elimin elementul din
virful stivei');
s1(p);
for i:=1 to n do
s(p);
readln;
end.
□ Funcţia lui Ackermann. Se dă funcţia următoare, definită pe produsul cartezian NXN.. Se citesc m şi
n. Să se calculeze Ack(m, n).
141
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
| n+1, m=0
Ack(m,n)= | Ack(m-1, 1), n=0
| Ack(m-1, Ack(m, n-1)), altfel
Pentru calculul acestei funcţii, folosim o stivă dublă, ST. Iniţial, valorile m şi n se reţin la nivelul 1. Pe
nivelul k al stivei se reţin valorile curente m şi n. În funcţie de valorile acestora se procedează astfel:
■ pentru m şi n diferite de 0, este necesar un nou calcul de funcţie, caz în care se urcă în stivă şi pe noul
nivel se pun argumente m şi n-1.
■ pentru cazul n=0, se rămâne pe acelaşi nivel în stivă, punând în locul lui m valoarea m-1, iar în locul
lui n valoarea 1.
■ în situaţia în care m=0, funcţia se poate calcula; se coboară în stivă şi se înlocuieşte valoarea lui m cu
m-1, valoarea lui n cu valoarea calculată anterior.
10 01
20 11 11 11
21 21 21 21 21
10
01 11 11
11
02 02 13 12 12
12
21 12
13 03
12 13 13
13 13 13 04
ack(2,1)=5.
142
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
else else
begin {
k:=k-1; k--;
if (k>0) if (k>0)
{ st[k,0] =st[k,0] – 1; { st[k] [0] =st[k[] [0] – 1;
st[k,1] =st[k+1,1] +1; st[k] [1] =st[k+1] [1] +1;
end; }
end; }
write(”ac(“m, n”) = ”,st[1,1] +1); cout<<”ac(“<<m<<’, ‘<<n<<”) =
end. ”<<st[1] [1] +1;
}
dinamic
#include <iostream.h>
struct Nod
{
int info;
Nod* adr_inap;
};
Nod* v;
int n;
void Pop(Nod*& v)
{
Nod* c;
If (!v) cout<<”stiva este vida”;
Else
{
c=v;
cout<<”am scos”<< c-
>info<<end1;
v=v->adr_inap;
delete c;
143
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
}
}
main( )
{ Push(v,1); Push(v,2); Push(v,3);
Pop(v); Pop(v); Pop(v); Pop(v);
}
Coada funcţionează pe principiul FIFO (First In First Out) – “primul intrat, primul ieşit”.
1 2 3 4
2 3 4 5
3 4 5 6
v sf
7 3 5 2
144
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
145
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
end;
close(f);close(g);
end;
procedure L;
var c:po;
begin
c:=p;
while(c<>nil) do
begin
write(c^.info, ' ');
c:=c^.leg;
end;
end;
procedure li;
var H:text;
var c:integer;
begin
assign(h,'ff.pas');rewrite(h);
d:=p;c:=0;
while d<>nil do
begin
writeln(d^.info);writeln(h,d^.info);
inc(c);d:=d^.leg;
end;
writeln(' am atitea inregistrari',c);
close(h);
end;
begin
o; {L;
writeln;}
Li;
readln;
end.
CU LISTE DUBLU INLANTUITE
{ Sa se creeze o structura de coada}
type ref=^inr;
inr=record
nr:integer;
as,ad:ref;
end;
var p,u:ref;i,n:integer;
procedure b(var u:ref);
var c:ref;
begin
new(c);
writeln(' pe cine pui in coada
');readln(c^.nr);
c^.ad:=nil;
c^.as:=nil;
if u<>nil then u^.ad:=c else
p:=c;
u:=c;
end;
procedure s(var p:ref);
var c:ref;
begin
if p=nil then writeln(' e goala ') else
begin
writeln(' pe cine scot ');
writeln(p^.nr);
146
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
c:=p;p:=p^.ad;
p^.as:=nil;
dispose(c);
end;
end;
begin
writeln(' cite elemente dai
n>=3');readln(n);
for i:=1 to n do
b(u);
for i:=1 to n do
s(p);
readln;
end.
Prezentarea structurii
O listă liniară este o colecţie de n≥0 noduri, X₁, X₂, … , Xn aflate într-o relaţie de ordine.
Astfel, X₁ este primul nod al listei, X₂ este al doilea nod al listei … Xn este ultimul nod.
Operaţiile permise sunt:
□ Accesul la oricare nod al listei în scopul citirii sau modificării informaţiei conţinute de acesta.
Există două metode de alocare a unei liste liniare: alocarea secvenţială şi alocarea
înlănţuită.
Nodurile listei ocupă poziţii succesive în memorie. Acest tip de alocare l-am întâlnit des,
de câte ori am utilizat vectori.
Exemplu: un vector are n componente de tip real. Se cere să se sorteze vectorul crescător.
Algoritmul are ca dată de intrare o listă liniară, cu n noduri de tip real. Ieşirea este tot o listă
liniară, cu aceleaşi noduri, dar în altă ordine. Să presupunem că utilizăm sortarea prin
147
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
■ v[i] v[i+1]; - accesez nodul i+1 în vederea citirii (operaţie permisă) şi accesez nodul i în vederea
modificării informaţiei reţinute (operaţie permisă).
■ v[i+1] = man; - accesez nodul i+1 în vederea modificării informaţiei reţinute de el.
În concluzie, sortarea se realizează prin utilizarea operaţiilor permise asupra unei liste
liniare.
Avantajul alocării secvenţiale este dat de faptul că programatorul are acces direct la oricare din
nodurile listei, la fel ca la componentele unui vector.
Dezavantajul alocării secvenţiale este dat de faptul că operaţiile de adăugare, eliminare sau
schimbare de poziţie a unui nod necesită un efort mare de calcul, ca în exemplul următor, în care
se elimină un nod:
■ in₁, in₂, in₃, … , inn reprezintă informaţiile conţinute de noduri, de altă natură decât cele de
adresă;
După cum observăm, fiecare nod, cu excepţia ultimului, reţine adresa nodului următor.
148
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
2. Alocarea dublu înlănţuită. Alocarea simplu înlănţuită permite parcurgerea listei într-un
singur sens (de la stânga la dreapta). În cazul în care se doreşte ca lista să poată fi parcursă
în ambele sensuri se utilizează alocarea dublu înlănţuită. Aici fiecare nod reţine adresele
predecesorului şi succesorului său, aşa cum se vede în figura următoare:
Avantajele alocării înlănţuite sunt date de faptul că operaţiile de adăugare sau eliminare a unui
nod se fac rapid. Exemplele sunt date pentru lista liniară simplu înlănţuită, dar bine înţelese, ne
permit să deducem singuri modul de efectuare a operaţiilor respective pentru liste dublu
înlănţuite.
Fie lista:
3 adr₂
7 adr₃ 9 nil
Etapele sunt:
3 adr₂
7 adr₃
9 nil
adrt
149
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
□ Se completează informaţiile pentru nodul creat – câmpul de adresă trebuie să conţină adresa
nodului care trebuie să-i urmeze în listă:
3 adr₂
7 adr₃
9 nil
5 adr₂
adrt
□ Se modifică adresa nodului care precede nodul nou creat. Adresa trebuie să fie a nodului nou
creat:
5 adr₂
adrt
b) Ştergerea unui nod. Pentru a exemplifica operaţiile efectuate în acest caz vom folosi a de mai
sus, la care ştergem al doilea nod (cel cu informaţia 5). Iată etapele:
150
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
□ Informaţia de adresă a nodului care îl precede trebuie să reţină adresa nodului următor:
3 adr₂ 9 nil
5 adr₂ 7 adr₃
adr₁ adrt adr₂ adrn
7 adr₃ 9 nil
3 adr₂
adr₁ adr₂ adrn
7 adr₃ 9 nil
3 adr₂
Observaţii:
În cazul alocării înlănţuite, adresele de memorare ale nodurilor consecutive nu sunt neapărat
consecutive. Pentru a realiza acest lucru este suficient să analizaţi cazul ştergerii unui nod (sau
acela al adăugării unui nod).
Prin alocarea memoriei pentru un nod înţelegem rezervarea spaţiului necesar memorării
informaţiilor conţinute de acesta. Evident, se poate aloca memorie doar dacă există memorie
disponibilă, adică nu este ocupată de alte variabile.
151
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Pentru eliberarea memoriei ocupate de un nod înţelegem că spaţiul ocupat de acesta devine
disponibil – este pus la dispoziţia programatorului, pentru ca, eventual, acesta să fie din nou
alocat.
Este important să folosim termenii corect. De exemplu, nu putem folosi în loc de “alocarea
memoriei” termenul “crearea memoriei”, tot aşa cum nu este corect să folosim în loc de
“eliberarea memoriei” termenul “ştergere a memoriei”.
Noţiunile care privesc alocarea şi eliberarea memoriei sunt prezentate în paragraful următor.
152
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
153
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
writeln(c^.nr:6); while(c)
c:=c^.urm;
{
end;
end; cout<<c->info<<endl;
begin c=c->adr_urm;
init(p); }
afisare(p);
readln;
}
end.
main( )
{
cout<<”numar=”; cin>>nr;
while(nr)
{
Adaug(v,nr);
cout<<”numar=”; cin>>nr;
};
Tip(v);
}
154
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
155
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
c:=c^.urm; Listare(v);
Sterg(v,sf,15);
if (c=nil) then potadauga:=false Sterg(v,sf,13);
else Sterg(v,sf,12);
begin Listare(v);
new(pecinepun); }
writeln(' pe cine vrei sa pui ');
readln(pecinepun^.nr);
pecinepun^.urm:=c^.urm;
c^.urm:=pecinepun ;
c:=c^.urm;
end;
end;end;
procedure pununadupamaimulte;
var cecaut:integer; pecinepun :ref;
begin
156
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
while (c<>u) do
begin
oretinpepenua :=c;
c:=c^.urm;
end;
desters :=c;
oretinpepenua^.urm :=nil;
u:=oretinpepenua ;
dispose( desters);
end;
procedure stergdupaunacareocaut;
var oretinpepenua,desters:ref;cecaut:integer;
begin
writeln('dupa a cit-a intergistrare vreti sa stergeti
');readln(cecaut);
c:=p;
for i:=1 to cecaut do
begin
oretinpepenua :=c;
c:=c^.urm;
end;
desters :=c;
oretinpepenua^.urm :=c^.urm;
dispose( desters);
end;
procedure sterguele;
var oretinpepenua,desters:ref;multe:integer;
begin
writeln('cite vreti sa stergeti incepind de la sfirsit spre inceput
');readln(multe);
for i:=1 to multe do
begin
c:=p;
while (c<>u) do
begin
oretinpepenua :=c;
c:=c^.urm;
end;
desters :=c;
oretinpepenua^.urm :=nil;
u:=oretinpepenua ;
dispose( desters);
end;
end;
procedure stergdelapamaimulte;
var desters:ref;multe:integer;
begin
writeln('cite vreti sa stergeti incepind de la pa ');readln(multe);
for i:=1 to multe do
begin
157
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
desters :=p;
p:=p^.urm;
dispose( desters);
end;
end;
procedure stergdupacecaut;
var osterg:ref;cecaut:integer;
begin
c:=p;
writeln(' dupa ce valoare vrei sa stergi');
readln(cecaut);
while (c<>nil) and (c^.nr<>cecaut) do
c:=c^.urm;
if c=nil then writeln(' nu este in lista ')
else
begin
osterg:=c^.urm;
c^.urm:=c^.urm^.urm;
{dispose(osterg); }
end;
end;
procedure stergcecaut;
var oretin,osterg:ref;cecaut:integer;
begin
c:=p;
writeln(' ce valoare vrei sa stergi');
readln(cecaut);
while (c<>nil) and (c^.nr<>cecaut) do
begin
oretin:=c;
c:=c^.urm;end;
if c=nil then writeln(' nu este in lista ')
else
begin
osterg:=c;
oretin^.urm:=c^.urm;
dispose(osterg);
end;
end;
procedure stergcecautdeciteoriapare;
var oretin,osterg:ref;cecaut:integer;potsterge:boolean;
begin
writeln(' ce valoare vrei sa stergi');
readln(cecaut);
potsterge:=true;
while potsterge do
begin
c:=p;
158
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
end;
procedure modificua;
begin
c:=u;
writeln('cu cine modifici pe ua');readln(c^.nr);
end;
procedure modificcepozitiecaut;
var cecaut:integer;
begin
c:=p;
writeln(' a cit-a inregistrare vrei sa o modifici');
readln(cecaut);
for i:=1 to cecaut-1 do
c:=c^.urm;
writeln(' cu cine o modifici');
readln(c^.nr);
end;
begin
init;
afisare;
inserareinaintedepa;
afisare;
inserareinaintedepamaimulte;
afisare;
adaugunlasfirsit;
afisare;
adaugunlasfirsitmaimulte;
afisare;
pununadupamaimulte;
afisare;
pununainaintedemaimulte;
afisare; writeln('o sterg pe pa ');
stergpa ;afisare;
stergdelapamaimulte; afisare;
159
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
stergua;
writeln('o sterg pe ua ');
afisare;
sterguele;afisare;
stergdupaunacareocaut;
afisare;
pununadupacecaut;afisare;
stergdupacecaut;
afisare;
stergcecaut;
afisare;
stergcecautdeciteoriapare; afisare;
modificpa;
afisare;
modificua; afisare;
modificcepozitiecaut; afisare;
readln;
end.
1) creare;
2) adaugare la dreapta;
3) adaugare la stanga;
4) adaugare in interiorul listei;
5) stergere din interiorul listei;
6) stergere la stanga listei;
7) stergere la dreapta listei;
8) listare de la stanga la dreapta;
9) listare de la dreapta la stanga.
1) Creare
2) Adaugare la dreapta
Functia add citeste informatia numerica, aloca spatiu pentru inregistrare, completeaza adresele,
modifica adresa la dreapta a inregistrarii din s cu adresa noii inregistrari si ii atribuie
lui s valoarea noii inregistrari.
3) Adaugare la stanga
160
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Functia includ parcurge lista pentru a gasi inregistrarea cu informatia m, in dreapta careia urmeaza sa
introducem noua inregistrare, citeste informatia, aloca spatiu, completeaza informatia, completeaza
adresa stanga a noii inregistrari cu valoarea adresei inregistrarii de informatie m, si completeaza adresa
dreapta a noii inregistrari cu valoarea adresei dreapta a inregistrarii cu informatia utila m.
Functia Sterg parcurge lista pentru a gasi informatia care va fi stearsa, atribuie inregistrarii precedente
campul de adresa dreapta al inregistrarii care va fi stearsa, iar inregistrarii care urmeaza celei care va fi
stearsa i se atribuie campul de adresa stanga al inregistrarii pe care o stergem, dupa care se elibereaza
spatiul de memorie rezervat inregistrarii care se sterge.
161
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
162
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
c^.ad^.as:=c^.as;
dispose(q)
end;
procedure ins1;
var i:integer;d,q:ref;
begin
writeln(' in fata cui inserati ');readln(i); writeln('------------------');
d:=p;
while(i<>d^.nr) and (d<>nil) do
d:=d^.ad;
if d= nil then writeln(' nu ')
else
begin
new(q);
writeln('informatia care o inserati ');
readln(q^.nr);
q^.ad:=d;
q^.as:=d^.as;
d^.as^.ad:=q;
d^.as:=q;
end;
end;
procedure listare;
var c:ref;
begin
c:=p;
while(c<>nil) do
begin
writeln(c^.nr,' ');
c:=c^.ad;
end;
end;
procedure listare1;
var c:ref;
begin
c:=u;
while(c<>nil) do
begin
writeln(c^.nr,' ');
c:=c^.as;
end;
end;
begin
creare;
writeln('------------------');
listare; writeln('sterg pe ultima ------------------');
stegultima;
writeln('o listez de la sfirsit spre inceput------------------');
listare1;
adauginaintedeprima;
writeln('------------------');
listare; writeln('------------------');
adugadupaultima; listare; writeln('------------------');
adaugadupaa_p1_acomponenta; listare; writeln(' sterg prima
------------------');
stegprima;listare; writeln('------------------');
stergA_p1_componenta; listare; writeln('------------------');
163
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
ins1; listare;
readln;
end.
Grafuri orientate
Notiuni introductive
_
Definitie.Se numeste graf orientat perechea ordonata G=(x,l ).
-Daca in acest graf [x,y] apartin multimii г, vom spune ca x si y sunt adiacente, iar
varfurile x si y sunt incidente cu muchia [x,y].
-Daca г(g)=multimea vida, acest graf se numeste graf nul si reprezentarea lui in
plan se reduce la puncte izolate.
Definitie.Un graf partial al unui graf orientat dat este un graf G1=(x,g1) unde g1este
inclus sau = cu g.
Definitie. Un subgraf al unui graf orientat G=(x,g) este un graf H=(y1,g1),unde y1-
inclus sau = cu x, iar muchiile din g1 sunt toate muchiile din g care au ambele
extremitati in multimea y.
-Gradul unui nod x(d(x)) este de doua feluri:
*grad exterior
*grad interior
Definitie.Un drum al unui graf orientat L=[x0,x1,x2,…xp] este o succesiune de
varfuri cu proprietatea ca [x0,x1]aparrtine de g, [x1,x2] la fel, s.a.
-x0 si xp = extremitatile drumului;
-p=lungimea drumului;
-daca x0,x1,…,xp sunt distincte doua cate doua drumul=elementar;
-daca x0=xp,drumul=circuit
-daca toate varfurile circuitului, cu exceptia primului si ultimului sunt distincte,
circuitul=elementar;
-un circuit elementar care trece prin toate nodurile grafului se numeste circuit
hamiltonian.
164
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
-parcurgem apoi toti descendentii sai – multimea nodurilor j pentru care exista
[I,j]apartin de g;
-parcurgem apoi toti descendentii nodurilor parcurse la pasul anterior.
Parcurgerea BF se efectueaza prin utilizarea structurii numita coada, avand grija ca un nod sa fie vizitat
o singura data. Coada va fi alocata prin utilizarea unui vector.
LIMBAJUL PASCAL LIMBAJUL C/C++
PARCURGEREA GRAFURILOR
165
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
IN ADANCIME IN ADANCIME
{Parcuregerea in adincime la grafuri neorientate -se face incapand de la un nod I
ex:n=5 -dupa parcurgerea unui nod se parcurge
m=4 primul dintre descendntii sai neparcursii inca
si anume (1 2),(1 5), ( 2 3),(2 4) EX:
nodul de pelecare este 1 => #include “grafuri.cpp”
12345 int s[50],A[50][50],n;
} void df_r9int nod)
uses crt; {
var a:array[1..20,1..20] of integer; int k;
vi:array[1..20] of integer; cout<<nod<<” “;
i,n,el,j,p,u,pl,m,x,y:integer; s[nod]=1;
for (k=1;k<=n;k++)
procedure pp(pl:integer); if ((A[nod][k]==1) && (s[k]==0))
166
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Un graf G este conex , daca oricare ar fi doua varfuri ale sale ,exista un lant care le
leaga.
Definitie:
Se numeste componenta conexa a grafului G=(X,U),un subgraf G1=(X1,U1) a lui
G ,conex , cu propietatea ca nu exista nici un lant care sa lege un nod din X1 cu un
nod din X-X1(pentru orice nod , nu exista un lant intre acel nod si nodurile care nu
fac parte din subgraf).
Graf tare conex .Componente tare conexe
Definitie:
Un graf orientat G=(X,U) este tare conex, daca pentru oricare doua noduri x si y
apartin de X, exista un drum de la x la y precum si un drum de la y la x.
Definitie
Fiind dat un graf orientat G=(X,U), se numeste componenta tare conexa a lui
G ,un subgraf G1=(X1,U1),tare conex, si maximal in raport cu aceasta propietate
(adica pentru orice nod x apartine de X-X1, subgraful indus de X1 U{x} nu mai este
tare conex).
167
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Consideram un graf orientat G=(X,U) cu n noduri, in care fiecarui arc ii este asociat un
numar intreg numit cost. Semnificatia
acestui cost poate fi foarte variata , in functie de domeniul pe care il descrie graful .
Matricea costurilor
168
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Pentru evidentierea costurilor tuturor arcelor unui graf cu n noduri se poate defini o
matrice a, cu n linii * n coloane.Exista doua forme ale acestei matrici:
Forma a): Fiecare element a[i,j] poate fi:
c , daca exista un arc de cost c>0 intre nodurile i si j;
0, daca i=j;
+∞ ,daca nu exista arc intre nodurile i si j .
Forma b): Este absolut similara,cu singura deosebire ca in loc de +∞ avem -∞.
Forma a) se foloseste pentru determinarea drumurilor de cost minim intre doua
noduri , iar forma b) este utilizata in aflarea drumurilor de cost maxim.
Daca dorim sa citim matrice costurilor ,evident ca nu putem introduce de la tastatura
“+”! In loc de + vom da un numar intreg foarte mare.
LIMBAJUL PASCAL LIMBAJUL C/C++
CAUTAREA UNUI SIR DE CARACTERE
{Fiind dat un graf neorientat G si doua varfuri x si y in acest graf, sa se Algoritmul lui ROY-FLOYD-vom aplica
determine un lant elementar de lungime minima, avand ca extremitati strategia generala Divide et
varfurile date. Datele de intrare se citesc din fisierul Graf.dat care are Impera(pentru lungimea minima):
urmatoarea componenta: #include “grafuri.cpp”
- pe prima linie se afla numarul de varfuri ale grafului(n); float A[50][50];
- pe a doua linie sunt inscrise cele doua extremitati ale lantului int n;
elementar separate prin spatii; void Drum(int I, int j)
- pe urmatoarele n linii se gasesc valorile matricei de adiacenta {
separate int k=1,gasit=0;
prin spatii. Datele de iesire se vor afrsa pe ecran si vor consta in: while ( (k<=n) && !gasit)
- mesajul "Nu exista lanl elementar Fntre cele doua varfuri" {
sau if ( (I!=) && (j!=k) && (A[I][j]==A[I]
- mesajul "Lantul minim are lungimea .... ", iar pe linia urmatoare [k]+A[k][I]) )
varfurile {
lantului Drum(I,k);Drum(k,j);
separate printr-un spatiu. Gasit=1;
K++;
Rezolvare }
Rezolvarea acestei probleme se bazeaza pe formarea matricei if (!gasit) cout<<j<<” “;
lanturilor. Un }
element al acestei matrici va contine Iungimea lantului minim dintre void Scriu_drum(int Nod_Initial, int
varfurile Nod_Final)
corespunzatoare liniei si coloanei.} {
program lant_elementar; if (A[Nod_Initial][Nod_Final]<Pinfinit)
const infinit=100; {
type matrice=array[1..20,1..20] of byte; cout<<”Drumul de la
var n,x,y:byte;a:matrice;f:text; “<<Nod_Initial<<” la “<<Nod_Final<<”
procedure citeste; are lungimea “<<A[Nod_Initial]
var i,j,p,q:byte; [Nod_Final]<<endl;
begin cout<<Nod_Initial<<” “;
assign(f,'in2.pas');reset(f); Drum(Nod_Initial,Nod_Final);
readln(f,n); }
else
for i:=1 to n do cout<<”Nu exista drum de la
for j:=1 to n do “<<Nod_Initial<<” la “<<Nod_Final;
if i=j then a[i,j]:=0 }
else a[i,j]:=infinit; void Lungime_Drumuri()
readln(f,x,y); {
while not eof(f) do int I,j,k;
begin for (k=1;k<=n;k++)
readln(f,p,q); for(I=1;I<=n;I++)
a[P,q]:=1; a[q,P]:=1; for (j=1;j<=n;j++)
end; if (A[I][j]>A[I][k]+A[k][j]
close(f) A[I][j]=A[I][k]+A[k][j];
}
169
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
end; main()
prOcedure mat_drumuri; {
var i,j,k:byte; Citire_cost(“Graf.txt”,A,n);
begin Lungime_Drumuri();
for k:=1 to n do Scriu_drum(4,2);
for i:=1 to n do }
for j:=1 to n do
if a[i,j]>a[i,k]+a[k,j] then *Algoritmul ROY-FLOYD pentru a gasi
begin drumuri de lungime maxima:
a[i,j]:=a[i,k]+a[k,j]; #include “grafuri.cpp”
a[j,i]:=a[i,j]; float A[50][50]
end; int n;
end; void Drum(int I,int j)
procedure drum(v1,v2:byte); {
var k:byte;gasit:boolean; int k=1,gasit=0;
begin while ( (k<=n) && !gasit)
k:=1;gasit:=false; {
while(k<=n)and not gasit do if ( (I!=k) && (j!=k) && (A[I][j]==A[I]
begin [k]+A[k][j]) )
if(v1<>k)and(v2<>k)and(a[v1,v2]=a[v1,k]+a[k,v2])then {
begin Drum(I,k0;Drum(k,j);
drum(v1,k);drum(k,v2); Gasit=1;}
gasit:=true; K++;
end; }
k:=k+1; if (!gasit) cout<<j<<” “;
end; }
if not gasit then write(v2,' '); void Scriu_drum(int
end; Nod_Initial,Nod_Final)
begin {
citeste; if (A[Nod_Initial][Nod_Final].Minfinit)
mat_drumuri; {
if a[x,y]=infinit then writeln('Nu exista lant elementar intre cele doua cout<<”Drumul de la “<<Nod_Initial<<”
varfuri') la “<<Nod_Final<<” are lungimea
else “<<A[Nod_Initial][Nod_Final]<<endl;
begin cout<<Nod_Initial<<” “;
writeln('Drumul minim are lungimea:',a[x,y]); Drum(Nod_Initial,Nod_Final);
write(x,' '); }
drum(x,y); else
end; cout<<”Nu exista drum de la
readln; “<<Nod_Initial<<” la “<<Nod_Final;
end. }
void Lungime_Drumuri()
{
int I,j,k;
for (k=1;k<=n;k++)
for (I=1;I<=n;I++)
for (j=1;j<=n;j++)
if (A[I][j]=A[I][k]+A[k][j];
}
main()
{
Citire_cost1(“Graf.txt”,A,n);
Lungime_Drumuri();
Scriu_drum(1,2);
}
ALGORITMUL
ALGORITMUL DIJKSTRA
{ Fie n localitati intre care exista o retea de drumuri. DIJKSTRA
Un turist care se gaseste in localitatea A doreste sa viziteze Fiind dat un graf memorat prin matricea
localitatea ponderilor, se cere sa se determine pentru
170
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
B cu cheltuieli minime. Cheltuielile turistului sunt direct proportionale orice x,y apartin de X lungimea minima a
cu distanta parcursa dintr-o localitate in alta. drumului de la nodul x la nodul y.Prin
Cunoscandu-se lungimea fiecarui drum dintre localitati, sa se lungimea unui drum intelegem suma
determine un ponderilor arcelor care-l alcatuiesc.
traseu pe care sa-l urmeze calatorul din localitatea A pana in Include “grafuri.cpp”
localitatea B Float A[50][50],D[50],min;
astfel incat costul calatoriei sa fie minim. Un drum intre doua localitali Int S[50],T[50],n,I,j,r,poz;
poate fi unidirectional sau bidirectional, pentru fiecare drum Void drum(int I)
cunosandu-se {
lungimea. if (T[I]) drum(T[I]);
cout<<I<<” “;
. Rezolvare }
Programul determina drumul minim intre doua varfuri ale unui graf main()
orientat {
folosind algoritmul Dijkstra. Citire+cost(“Graf.txt”,A,n);
n-numarul de localitati Cout<<”Introduceti nodul de pornire
a-matricea ponderilor asociata grafului; “<<endl;
d-vectorul care contine lungimea drumului minim dintre localitatea de Cout<<”r=”;cin>>r;S[r]=1;
plecare si o alta localitate; For (I=1;I<=n;I++)
{
p-vectorul care memoreaza varfurile prin care se trece pentru a D[I]=A[r][I];
obtine If (I!=r)
drumul minim.} If (D[I]<Pinfinit) T[I]=r;}
program drum_minim; For (I=1;I<=n;I++)
const infinit=1e38; {
type matrice=array[1..50,1..50] of real; min=Pinfinit;
multime=set of byte; for(j=1;j<=n;j++)
vect=array[1..50] of real; if (S[j]==0)
var n:byte;a:matrice;f:text;v1,v2:byte; if (D[j]<min)
d:vect;p:array[1..50] of byte; {
procedure citeste; min=D[j];
var i,x,y,j:byte;cost:real; poz=j;
begin }
assign(f,'in8.pas'); S[poz]=1;
reset(f); For (j=1;j<=n;j++)
readln(f,n); If (s[j]==0)
for i:=1 to n do If (D[j]>D[poz]+A[poz][j])
for j:=1 to n do {
if i=j then a[i,j]:=0 D[j]=D[poz]+A[poz][j];
else a[i,j]:=-1; T[j]=poz;
readln(f,v1,v2); }
while not eof(f) do for (I=1;I<=n;I++)
begin if (I!=r)
readln(f,x,y,cost); if(T[I])
a[x,y]:=cost; {
end; cout<<”distanta de la “<<r<<” la
close(f) “<<I<<” este “<<D[I]<<endl;
end; drum(I);
cout<<endl;
procedure Dijkstra; }
var varfuri:multime;i,j,k:byte;min:real; else
begin cout<<”nu exista drum de la “<<r<<” la
varfuri:=[1..n]-[v1]; “<<I<<endl;
for i:=1 to n do }
begin
d[i]:=a[v1,i];
P[i]:=v1
end;
for k:=1 to n-2 do
begin
171
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
min:=infinit;
for i:=1 to n do
if(i in varfuri) and (d[i]>0) and (d[i]<min) then
begin
min:=d[i];j:=i;
end;
varfuri:=varfuri-[j];
if j=v2 then break;
for i:=1 to n do
if(i in varfuri) and (d[j]<>-1) and (a[j,i]<>-1) then
if(d[i]=-1) or (d[i]>d[j]+a[j,i])then
begin
d[i]:=d[j]+a[j,i];
P[i]:=j;
end;
end;
end;
procedure scrie_drum(k:byte);
begin
if k<>v1 then scrie_drum(p[k]);
write(k,' ');
end;
begin
citeste;
Dijkstra;
if d[v2]=0 then write('Nu exista posibilitatea de deplasare de la ',v1,' la
',v2)
else
begin
writeln('Costul minim al deplasarii intre localitatile',v1,' si ',v2,' este
',d[v2]:7:2);
scrie_drum(v2)
end;
readln;
end.
Grafuri neorientate
Notiuni introductive
172
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Teorema:
Daca intr-un graf G=(X,U) cu n>=3 varfuri, gradul fiecarui varf x verifica conditia
d(x)>=n/2, atuncigraful este hamiltonian,
begin
173
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Grafuri euleriene
Definitie:
Se numeste ciclu eulerian intr-un graf, un ciclu care contine toate muchiile grafului.
Se numeste graf eulerian, un graf care contine un ciclu eulerian.
Teorema:
Un graf fara varfuri izolate este eulerian, daca si numai daca este conex, si
gradele tuturor varfurilor sunt numere pare
LIMBAJUL PASCAL LIMBAJUL C/C++
174
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
175
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
176
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
177
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
CUPRINS
Prefata…………………………..……………………………………………………………..1
Exemple de roboti………….………………………………………………………………….2
Structura robotilor…………………………………………………………………………..…5
Sistemul mecanic al robotului…….……………………….………………………………..…
33
Sistemul de actionare si comanda la roboti……………………………………………………
39
Senzori…………………………………………………………………………………………
48
Aplicatii roboti ficşi si mobili in
industrie……………………………………………………..62
Constructia electronica a unui robot……….………………………………………………...…
93
Cuprins……………………………………………………………………………………...…
117
178
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
179