Sunteți pe pagina 1din 10

6. Algoritmi elementari 6.2 Divizibilitate. Numere prime. Algoritmul lui Euclid.

6.2.1 Divizibilitate
6.1 Probleme care operează asupra cifrelor unui număr cel mai mare divizor comun şi cel mai mic multiplu comun a
două numere
6.1.1 Problemă care calculează suma cifrelor unui număr program cmmdc_cmmmc;
program suma_nr; var a,b:integer;
var n,s,r: longint; p:real;
begin begin
readln(n); writeln('Dati numerele');
s:=0; readln(a,b);
r:=0; p:=a*b;
repeat while a<>b do
r:=n mod 10; if a>b then
s:=s+r; a:=a-b
n:=n div 10; else
until n<=0; b:=b-a;
writeln(s); writeln('cmmdc este',a);
end. writeln('cmmmc este',p/a:4:2);
readln;
end.
6.1.2 Problemă care inversează cifrele unui număr
Program inversare_cifre;
var n,nr:longint; 6.2.2 Numere prime
begin -program care testează dacă un număr este prim
readln(n); Program nrprim;
nr:=0; var n,mij,i:longint;
repeat este:boolean;
nr:=nr*10+ n mod 10; begin
n:=n div 10; readln(n);
until n<=0; mij:=round(sqrt(n));
write(nr);end. este:=false;
for i:=2 to mij do
if n mod i=0 then este:=true;
if este then writeln('nr ',n,'nu este prim')
else writeln( 'nr ',n,' este prim');
end.

25
6.2.3 Algoritmul lui Euclid 6.3.2.1 Suma cifrelor unui număr
-program care calculează cel mai mare divizor
Program cmmdc; program care_calculeaza_suma_cifrelor_unui_numar;
var n1,n2,r:longint; var n,s,i:integer;
begin begin
readln(n1,n2); readln(n);
repeat s:=0;
r:=n1 mod n2; repeat
n1:=n2; s:=s+(n mod 10);
n2:=r; n:=n div 10;
until r=0; until n=0;
writeln(n1); write(s);
end. end.

6.3.2.2* Program care verifică dacă un număr este


palindrom (verifică dacă un număr este egal cu răsturnatul
6.3 Şirul lui Fibonacci. Calculul unor sume cu termenul său)
general dat program palindrom;
var n,m,i,x:integer;
begin
6.3.1 Şirul lui Fibonacci readln(n);
Program fibonacci; m:=n;
var n,i,a1,a2,a3:longint; x:=0;
begin repeat
readln(n); x:=x*10+m mod 10;
a1:=1; m:=m div 10;
a2:=1; until m=0;
for i:=3 to n do if x=n then write(‘numărul este palindrom ’)
begin else write(‘numarul nu e palindrom’);
a3:=a1+a2; end.
a1:=a2;
a2:=a3;
end;
writeln(a2);
end.

6.3.2 Calculul unor sume cu termenul general dat 6.4 Determinare minim/maxim

26
6.4.1 Determinarea minimului dintr-un şir if max<x[i] then max:=x[i];{dacă elementul este
program minim_sir; mai mare decât max atunci max ia valoarea
var x:array[1..100] of integer; elementului}
n,i,min:integer writeln(‘maximul este:‘,max);
begin end;
write(‘n=’) {se citeşte numărul de elemente al
şirului} Metode de ordonare (metoda bulelor, inserŃie,
readln(n); selecŃie, numărare)
for i:=1 to n do
readln(x[i]) {se citesc elementele şirului} 6.4.1 Metoda bulelor
min:=x[1];{presupunem că minimul este primul program sortare;
element din şir} var x:array[1..100] of integer;
for i:=2 to n do{parcurgem şirul pornind de la al n,i,min,aux:integer
doilea element} f:boolean;{fanion care are valoarea true dacă şirul
if min>x[i] then min:=x[i];{dacă elementul este e ordonat, altfel e false}
mai mare decât min atunci min ia valoarea begin
elementului} write(‘n=’) {se citeşte numărul de elemente al
writeln(‘minimul este:‘,min); şirului}
end;
readln(n);
for i:=1 to n do
6.4.2 Determinarea maximului dintr-un şir readln(x[i]) {se citesc elementele şirului}
program maximul_din_sir; repeat
var i,n,max:integer; f:=true;{presupunem că şirul este ordonat}
x:array[1..100] of integer; for i:=1 to n-1 do{parcurgem vectorul}
begin {comparăm două elemente consecutive}
write(‘n=’) {se citeşte numărul de elemente al if x[i]>x[i+1] then begin
şirului} aux:=x[i]; {facem
readln(n); interschimbarea}
for i:=1 to n do x[i]:=x[i+1];
readln(x[i]) {se citesc elementele şirului} x[i+1]:=aux;
f:=false; {dacă am făcut o
max:=x[1];{presupunem că maximul este primul schimbare şirul nu este ordonat}
element din şir} end;
for i:=2 to n do{parcurgem şirul pornind de la al until f;{toate aceste operaŃii se efectuează până
doilea element} când şirul este ordonat}
for i:=1 to n do
write(x[i]:2) {se afişează vectorul sortat}

27
end; while x[j] > x[0] do begin
x[j+1]:=x[j]; j:=j-1
end;
6.4.2 Sortare prin inserŃie x[j+1]:=x[0]
end;
Principiu: tabloul este văzut ca fiind format din
două subtablouri a[1], a[2],..., a[i-1] şi for i:=1 to n do
respectiv a[i], a[i+1],...,a[N] (i=2,N). SecvenŃa write(x[i]:2) {se afişează vectorul sortat}
a[1],...,a[i-1] este ordonată şi urmează ca a[i] să end.
fie inserat în această secvenŃă la locul potrivit,
astfel încât secvenŃa a[1],...,a[i-1],a[i] să 6.4.3 Sortare prin selecŃie
devină ordonată, urmând ca în pasul următor cele Principiu: se consideră subtabloul
două subtablouri considerate să fie a[1],...,a[i] a[i],...,a[n], se caută elementul cu valoarea
şi a[i+1],...,a[N]. minimă din acest subtablou şi apoi se interschimbă
Pentru a găsi locul în care trebuie să fie acest element cu elementul a[i], repetându-se
inserat a[i] se parcurge şirul a[1],...,a[i-1] de procedeul pentru valori ale lui i de la 1 la N-1.
la dreapta spre stânga, pâna când fie se găseşte un Implementarea algoritmului în Pascal:
element cu valoarea <= cu valoarea elementului
a[i], fie s-a atins capătul şirului. Aici se poate program sortare_prin _selectie;
utiliza metoda fanionului, extinzând tabloul spre var x:array [1..100] of integer;
stânga cu elementul a[0] care se asignează iniŃial n,i,j,k,a:integer;
cu a[i] begin
Implementarea algoritmului în Pascal: write(‘n=’) {se citeşte numărul de elemente al
şirului}
Program inserŃie; readln(n);
var x:array[0..100] of integer; for i:=1 to n do
n,i,j,min,aux:integer readln(x[i]) {se citesc elementele şirului}
begin for i:=1 to n-1 do begin
write(‘n=’) {se citeşte numărul de elemente al k:=i; a:=x[i];
şirului} for j:=i+1 to n do if x[j]<a then begin
readln(n); a:=x[j];
for i:=1 to n do k:=j;
readln(x[i]) {se citesc elementele şirului} end;
for i:=2 to N do begin x[k]:=x[i]; x[i]:=a;
{inserează x[i] la locul potrivit în şirul end
x[1]...x[i]} for i:=1 to n do
x[0]:=x[i]; j:=i-1; write(x[i]:2) {se afişează vectorul sortat}
{caută locul de inserare} end.

28
*sortare prin selecŃie directă for i:=1 to n-1 do
program sort_sel_dir; for j:=i+1 to n do
var x:array[1..100] of integer; if x[i]<x[j]then v[j]:=v[j]+1
i,j,n,aux:integer; else v[i]:=v[i]+1;
begin for i:=1 to n do
readln(n); y[v[i]+1]:=x[i];
for i:=1 to n do for i:=1 to n do
readln(x[i]);{se citesc elementele vectorului x} write(y[i]:2);
for i:=1 to n-1 do end.
for j:=i+1 to n do 6.5 Interclasare
if x[j]<x[i] then
begin program interclasare;
aux:=x[i]; var x,y,z:array[1..100] of integer;
x[i]:=x[j]; nx,ny,nz,i,j,m:integer;
x[j]:=aux; {se interclasează vectorul x cu vectorul y şi
end; rezultatul îl punem în vectorul z}
for i:=1 to n do begin
write(x[i]:2) readln(nx) {se citeşte numărul de elemente al
end. vectorului x}
readln(ny) {se citeşte numărul de elemente al
vectorului y}
6.4.4 Sortare prin numărare for i:=1 to n do
Principiul metodei:pentru fiecare element existent readln(x[i]);{se citesc elementele vectorului x}
într-un vector se numără câte elemente mai mici for i:=1 to n do
decât acesta sunt în vector. Pentru a şti acest readln(y[i]); {se citesc elementele vectorului y}
număr de elemente, se va folosi un vector j:=1;
suplimentar. Rezultatul sortării se va depune într- i:=1;
un alt vector. k:=0;
while (i<=nx) and (j<=ny) do
Program sortare_prin _numarare; if x[i]<=y[j]then
Var x,v,y:array[1..100] of integer; begin
n,i,j:integer; inc(k);
begin z[k]:=x[i];
readln(n); inc(i);
for i:=1 to n do end
readln(x[i]);{se citesc elementele vectorului x} else
for i:=1 to n do v[i]:=0; begin

29
inc(k); readln(n) {se citeşte numărul de elemente al
z[k]:=y[j]; vectorului x}
inc(j); for i:=1 to n do
end; readln(x[i]);{se citesc elementele vectorului x}
if i<=m then readln(c);{se citeşte elementul căutat}
while i<=m do poz:=0;{presupunem că nu am găsit elementul}
begin for i:=1 to n do{parcurgem vectorul}
inc(k); if x[i]=c then poz:=i;{dacă am găsit elementul
z[k]:=x[i]; căutat atunci memorăm poziŃia acestuia}
inc(i); write(poz);{afişăm poziŃia din vector a elementului
end căutat}
else end;
while j<=n do
begin 6.6.2 Căutarea binară
inc(k);
z[k]:=y[j]; program cautare_binara;
inc(j); var x:array[1..100] of integer;
for i:=1 to k do s,d,m,poz,n,i,j:integer;{căutarea elementului
write(z[k]:2); se face în intervalul s{capătul din stânga},
end. d{dreapta}
begin
readln(n) {se citeşte numărul de elemente al
vectorului x}
6.6 Metode de căutare (secvenŃială, binară) for i:=1 to n do
6.6.1 Căutarea secvenŃială (căutarea liniară) readln(x[i]);{se citesc elementele vectorului x}
readln(c);{se citeşte elementul căutat}
{Se caută liniar un element c în vectorul x de n poz:=0;{presupunem că nu am găsit elementul}
elemente şi se returnează poziŃia(poz) acestuia s:=1;d:=n;{la început s=1 şi d=n}
dacă îl gaseşte, altfel returnează 0} {cât timp în intervalul [s,d] există elemente şi
{Obs. În cazul în care elementul căutat apare de nu am găsit elementul căutat}
mai multe ori în şir se returnează ultima poziŃie while (s<=d)and(poz=0) do
la care a fost găsit} begin
m:=(s+d) div 2;{calculăm mijlocul şirului}
program cautare_liniara; if x[m]=c then poz:=m{dacă elementul căutat
var x:array[1..100] of integer; este egal cu elementul din mijlocul şirului atunci
i,poz,c,n:integer; memorăm pozitia lui}
begin else {altfel}

30
if c<x[m] then d:=m-1{dacă elementul este Timpul de rulare al unui program depinde de următorii
mai mic decît elementul din mijloc îl cautam în factori:
jumătatea din stînga, adică
limita din dreapta(d) o poziŃionăm în - datele de intrare
stînga mijlocului(m) } - calitatea codului generat de compilator
else s:=m+1;{dacă nu îl căutăm în - natura şi viteza de execuŃie a instrucŃiunilor
jumătatea din dreapta} programului
end;
write(poz) {se afişează poziŃia ocupată de
- complexitatea algoritmului care stă la baza
element în vector} programului.
end; Deci timpul de rulare e în funcŃie de intrarea sa, de cele mai
multe ori, nedepinzând de valorile de la intrare, ci de numărul
6.8 Analiza complexităŃii unui algoritm (considerând de date.
criteriile de eficienŃă durata de executare şi spaŃiu de Se notează cu T(n) timpul de rulare al unui program, ale
memorie utilizat) cărui date de intrare au dimensiunea n. De exemplu T(n) poate
De multe ori, pentru rezolvarea unei probleme, trebuie ales un fi c*n2, unde c este o constantă.
algoritm dintre mai mulŃi posibili, două criterii principale de Dacă timpul de rulare depinde de valorile datelor de la
alegere fiind contradictorii: intrare, în calculul lui T(n) se va lua în considerare situaŃia cea
1. algoritmul să fie simplu de înŃeles, de codificat şi de mai defavorabilă, cea care duce la timpul cel mai mare.
depanat; Cum timpul de rulare depinde nu numai de intrare (n) şi de
2. algoritmul să folosească eficient resursele calculatorului, să algoritm, ci şi de performanŃele calculatorului pe care se
aibă un timp de execuŃie redus. execută programul, T(n) se apreciază ca fiind proporŃional cu o
Dacă programul care se scrie trebuie rulat de un număr mic anumită funcŃie de n şi nu se exprimă în unităŃi reale de timp,
de ori, prima cerinŃă este mai importantă; în aceasta situaŃie, deci T(n)=c*f(n).
timpul de punere la punct a programului e mai important decât Timpul T(n) de rulare al unui program, poate fi apreciat
timpul lui de rulare, deci trebuie aleasă varianta cea mai simplă printr-o funcŃie O(f(n)), dacă exista constantele pozitive c şi n0,
a programului. astfel încît T(n)<=c*f(n), oricare ar fi n>=n0. FuncŃia O(f(n))
Dacă programul urmează a fi rulat de un număr mare de reprezintă aproximarea limitei superioare a lui T(n) şi se spune
ori, având şi un număr mare de date de prelucrat, trebuie ales că T(n) este O(f(n)), iar f(n) se numeşte limita superioară a
algoritmul care duce la o execuŃie mai rapidă. Chiar în această ratei de creştere a lui T(n).
situaŃie, ar trebui implementat mai înainte algoritmul mai
simplu şi calculată reducerea de timp de execuŃie pe care ar Exemplul 1.1
aduce-o implementarea algoritmului complex.

31
T(n)=3n3+2n2 este O(n3), pentru ca 3n3+2n2<=5n3, pentru orice Înainte de a prezenta câteva reguli pentru determinarea
n>=0. timpului de execuŃie al unui program, se dau cele referitoare la
Pentru specificarea limitei inferioare a ratei de creştere a lui suma şi produsul funcŃiei O:
T(n), se foloseşte funcŃia @(g(n)) şi se spune T(n) este 1. Dacă T1(n) şi T2(n) sunt timpii de execuŃie a două secvenŃe
@(g(n)), însemnând că există constanta pozitiva c, astfel încât de program P1 şi P2, T1(n) fiind O(f(n)), iar T2(n) fiind
T(n)>=c*g(n), pentru o infinitate de valori ale lui n. O(g(n)), atunci timpul de execuŃie T1(n)+T2(n), al secvenŃei
P1 urmată de P2, va fi O(max(f(n),g(n))).
Exemplul 1.2 DemonstraŃie:
T(n)=n +2n2 este @(n3), pentru că pentru c=1,
3
Exista c1 şi n1 astfel încît T1(n)<=c1*f(n), pentru orice
T(n)=n3+2n2>=n3, pentru o infinitate de valori ale lui n, cele n>=n1 şi exista c2 şi n2 astfel încît T2(n)<=c2*g(n), pentru orice
n>=0. n>=n2.
În comparaŃia între timpii de rulare ai diferitelor Notând n0=max(n1,n2), pentru n>=n0
programe (sau a diferitelor variante ale aceluiaşi program), T1(n)+T2(n)<=c1*f(n)+c2*g(n)<=(c1+c2)*max(f(n),g(n)).
constantele de proporŃionalitate nu pot fi întotdeauna neglijate.
Spre exemplu, s-ar putea spune că un program având O(n2) este
mai rapid decât unul cu O(n3), dar, în cazul când constantele ar Exemplul 1.3
fi 100, respectiv 5, al doilea program este mai rapid pentru Având trei secvenŃe de program cu timpii O(n3),O(n2) şi
n<20. O(n*log n),conform regulii anterior prezentate, timpul total de
Există următoarele cazuri când rata de creştere a timpului de execuŃie a celor trei secvenŃe va fi O(max(max(n3,n2),n*log
execuŃie, nu e cel mai bun criteriu de apreciere a n))= O(max(n3,n*log n))=O(n3).
performanŃelor unui algoritm:
- dacă un program se rulează de puŃine ori, se alege algoritmul 2. Dacă T1(n) este O(f(n)) şi T2(n) este O(g(n)),atunci
cel mai uşor de implementat; T1(n)*T2(n) este O(f(n)*g(n)).
- dacă întreŃinerea trebuie făcută de o altă persoană decât cea Câteva reguli generale pentru evaluarea timpului de execuŃie,
care l-a scris, un algoritm simplu, chiar mai puŃin eficient, e de funcŃie de mărimea n a datelor de intrare, sunt:
preferat unuia performant, dar foarte complex şi greu de • timpul de execuŃie a unei instrucŃiuni de asignare,
înŃeles; citire sau scriere, este O(1);
- există algoritmi foarte eficienŃi, dar care necesită un spaŃiu de • timpul de rulare a unei secvenŃe de instrucŃiuni e
memorie foarte mare, astfel încât folosirea memoriei externe, le determinat de regula de însumare, fiind proporŃional
diminuează foarte mult performantele. cu cel mai lung timp din cei ai instrucŃiunilor
secvenŃei;

32
• timpul de execuŃie a unei instrucŃiuni if-then-else (4) temp:=a[j-1];
este suma dintre timpul de evaluare a condiŃiei (5) a[j-1]:=a[j];
(O(1)) şi cel mai mare dintre timpii de execuŃie ai (6) a[j]:=temp
instrucŃiunilor pentru condiŃie adevărată sau falsă; end
• timpul de execuŃie a unei instrucŃiuni de ciclare este end; {bubble}
suma, pentru toate iteraŃiile, dintre timpul de Timpii de rulare pentru instrucŃiunile de asignare (4),(5)
execuŃie a corpului instrucŃiunii şi cel de evaluare a şi (6) sunt O(1), deci pentru secvenŃa (4)-(6), timpul este
condiŃiei de terminare (O(1)); O(max(1,1,1))=O(1).
• pentru evaluarea timpului de execuŃie a unei Pentru instrucŃiunea if-then (3), timpul este suma dintre
proceduri recursive, se asociază fiecărei proceduri cel pentru evaluarea condiŃiei, O(1) şi cel al secvenŃei ce se
recursive un timp necunoscut T(n), unde n măsoară execută la condiŃie adevărată, tot O(1), calculat mai sus, deci
argumentele procedurii; se poate obŃine o relaŃie O(1), acesta fiind deci şi timpul pentru o iteraŃie a instrucŃiunii
recurentă pentru T(n), adică o ecuaŃie pentru T(n), for (2).
în termeni T(k), pentru diferite valori ale lui k; Pentru cele n-i iteraŃii ale lui for (2), timpul de execuŃie
• timpul de execuŃie poate fi analizat chiar pentru este O((n-i)*1)=O(n-i).
programele scrise în pseudocod; se pot alege câteva Pentru instrucŃiunea for (1), având n-1 iteraŃii, timpul de
implementări şi astfel se poate face comparaŃie între execuŃie este:
performanŃele implementărilor, în contextul S(i=1,n-1)(n-i)=(n-1)+(n-2)+...+(n-n+1)=n^2/2-n/2,
aplicaŃiei respective. deci este O(n^2).

Exemplul 1.4 Exemplul 1.5


Mai jos se prezintă modul de evaluare a timpului de execuŃie a Modalitatea de evaluare a timpului de execuŃie al unei
procedurii de sortare a elementelor unui tablou de dimensiune n proceduri recursive, este ilustrată prin cea a funcŃiei de calcul al
prin metoda "bubble": factorialului:
type int_array=array[1..n] of integer; function factorial(n:integer):integer;
procedure bubble(var a:int_array); {sortare crescătoare} begin
var i,j,temp:integer; (1) if n<=1 then
begin (2) factorial:=1
(1) for i:=1 to n-1 do else
(2) for j:=n downto i+1 do (3) factorial:=n*factorial(n-1)
(3) if a[j-1]>a[j] then begin end; {factorial}

33
Dimensiunea intrării este aici n, valoarea numărului al
cărui factorial se calculează şi se notează cu T(n), timpul de
rulare al funcŃiei factorial(n).
Timpul de rulare pentru liniile (1) şi (2) este O(1), iar
pentru linia (3) este O(1)+T(n-1), deci cu constantele c şi d
neprecizate:
T(n)=c+T(n-1), pentru n>1 sau T(n)=d , pentru n<=1.
Pentru n>2, expandînd pe T(n-1), se obŃine T(n)=2*c+T(n-2),
pentru n>2.
Pentru n>3, expandînd pe T(n-2), se obŃine T(n)=3*n+T(n-3),
pentru n>3.
Deci, în general T(n)=i*c+T(n-i), pentru n>i.
În final, când=n-1, se obŃine T(n)=(n-1)*c+T(1)=(n-1)*c+d.
Deci T(n) este O(n).

34

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