Sunteți pe pagina 1din 13

Capitolul 3.

Elaborarea algoritmilor de rezolvare a


problemelor
3. 1. Cutare binar
Se numete cutare binar operaia de cutare a unei valori ntr-un vector ordonat.
La baza acesteia st metoda matematic a njumtirii intervalului de cutare.
Problem : Fie x un vector cu n numere, ordonat cresctor.
Exist n vector valoarea v ?
Principiul cutrii binare :
Iniial intervalul de cutare este definit de indicii 1,2,,n. Notm cu p
nceputul intervalului de cutare ( p=1 ) i cu q sfritul intervalului de cutare (
q=n )
Determinm mijlocul aproximativ al intervalului de cutare , m=(p+q)/2
Exist 3 cazuri :
o
Valoarea v se afl chiar pe rangul m : ntrerupem cutarea, cu succes
o
Valoarea v este mai mic dect cea de pe rangul m : intervalul se
restrnge prin deplasarea nceputului de interval n poziia m-1 iar cutarea
continu
o
Valoarea v este mai mare dect cea de pe rangul m : intervalul se
restrnge prin deplasarea sfritului de interval n poziia m+1 iar cutarea
continu
Operaia de cutare se ncheie dac valoarea v s-a semnalat sau dac intervalul de
cutare s-a restrns att de mult nct nu mai exist ( valoarea v nu s-a ntlnit ).
Algoritm de rezolvare :
Pasul 1: Iniializri : p=1, q=n ; s=0 ( semnaleaz apariia )
Atta timp ct exist interval de cutare se execut paii 2,3
Pasul 2: se determin mijlocul aproximativ al intervalului de cutare
Pasul 3: se stabilete dac valoarea s-a gsit i eventual se restrnge intervalul de
cutare
Implementare :
int s=0 , p=1 , q=n;
while ( p<=q ) {
m=(p+q)/2;
if ( x[m]==v ) { s=1; break; }
else if ( v<x[m] ) q=m-1; else

p=m+1;

Analiza eficienei algoritmului:


Fie n lungimea intervalului de cutare. Operaia elementar este comparaia.
Caz defavorabil : valoarea cutat nu exist. Considerm n=2k ( kN* ). Rezult

k=log2n. Numrul de operaii este cel mult egal cu 2*k deci cu 2*log2n. n
consecin, ordinul de complexitate al algoritmului este O(log2(n)).

3. 2. Inserare i tergere
Numim inserare operaia de introducere ntr-un vector a unei noi valori, pe o poziie
cunoscut, fr a pierde vreo valoare dintre cele deja existente.
Numim tergere operaia de eliminare din vector a unei valori a crei poziie este
cunoscut.
Inserare : n vectorul x cu n elemente s insereaz valoarea v, pe poziia p (1pn+1).

Exemplu :
Iniial : n=5, p=3, v=17
x
10 20 30 40 50
2
3
4
5
ranguri 1

ranguri

10

Final : n=6
20 17 30 40

50

Algoritm de rezolvare :
Pasul 1: se deplaseaz cu cte o poziie spre dreapta toate valorile ce ocup
rangurile : n,n-1,,p .
Astfel se suprascriu elementele x[n+1],x[n],,x[p+1]
Pasul 2: numrul de valori din vector se incrementeaz
Pasul 3: se suprascrie elementul x[p] atribuindu-i-se valoarea v
Implementare :
for(i=n; i>=p; i-- )
x[i+1]=x[i];
n++;
x[p]=v;

tergere: Din vectorul x cu n elemente, se elimin valoarea ce ocup poziia p


(1pn).

Exemplu :
x

10

ranguri

Iniial : n=5, p=3


20
30
40
2

50
5

x
ranguri

10
1

Final : n=4
20
40
2

50
4

Algoritm de rezolvare :
Pasul 1: se deplaseaz cu cte o poziie spre stnga toate valorile ce ocup
rangurile : p+1,p+2,,n.
Astfel se suprascriu elementele x[p],x[p+1],,x[n-1]
Pasul 2: numrul de valori din vector se decrementeaz

Implementare :
for(i=p+1; i<=n; i++ )
x[i-1]=x[i];
n--;

3. 3. Permutare circular
Permutare circular stnga cu o poziie
Exemplu :
10

Iniial
20
30
40

50

20

30

Final
40

50

10

ranguri

ranguri

Algoritm de rezolvare :
Pasul 1: se pstreaz ntr-o variabil auxiliar valoarea primului element
Pasul 2: se deplaseaz cu cte o poziie spre stnga toate valorile ce ocup
rangurile : 2,3,,n.
Astfel se suprascriu elementele x[1],x[2],,x[n-1]
Pasul 3: se suprascrie elementul x[n] cu valoarea variabilei auxiliare
Implementare :
aux=x[1];
for(i=2; i<=n; i++ )
x[n]=aux;

x[i-1]=x[i];

Permutare circular dreapta cu o poziie


Exemplu :
x

10

20

rangur
i

Iniial
30
40
3

50
5

50

10

Final
20

30

40

ranguri

Algoritm de rezolvare :
Pasul 1: se pstreaz ntr-o variabil auxiliar valoarea ultimului element
Pasul 2: se deplaseaz cu cte o poziie spre dreapta toate valorile ce ocup
rangurile : n-1,n-2,,1
Astfel se suprascriu elementele x[n],x[n-1],,x[2]
Pasul 3: se suprascrie elementul x[1] cu valoarea variabilei auxiliare

Implementare :
aux=x[n];
for(i=n-1; i>=1; i-- )
x[i+1]=x[i];
x[1]=aux;

3. 4. Interclasare
Numim interclasare operaia prin care valorile aflate n doi vectori ordonai se
reunesc ntr-o singur colecie de valori, direct ordonat.
Problem :
Considerm vectorul x cu n componente i vectorul y cu m componente,
ordonai cresctor. S se afieze pe ecran toate valorile aflate n cei doi vectori, n
ordine cresctoare.
Exemplu :
Intrare : n=6, x=( 1, 3, 4, 5, 5, 22 )
m=7, y=( 2, 3, 3, 7, 9, 10, 15 )
Ieire : 1 2 3 3 3 4 5 5 7 9 10 15

22

Algoritm de rezolvare :
Faza 1 : se parcurg n paralel cei doi vectori pn cnd unul dintre ei se termin
Pasul 1: se iniializeaz contorii i,j cu care se puncteaz pe cei doi vectori
(i=1,j=1). Cu contorul i se acceseaz rangurile vectorului x iar cu
contorul j se acceseaz rangurile vectorului y
Atta timp ct nici unul dintre vectori nu s-a parcurs n totalitate se execut pasul 2
Pasul 2: se compar x[i] cu y[j]. Exist 2 cazuri :
ox[i]y[j] : se scrie x[i] i se acceseaz rangul urmtor numai n x
o x[i]>y[j] : se scrie y[j] i se acceseaz rangul urmtor numai n y
Faza 2 : se vor afia toate valorile rmase nescrise din vectorul ce nu s-a terminat
Pasul 3: se parcurge vectorul x ncepnd din poziia i i fiecare element ntlnit se
afieaz
Pasul 4: se parcurge vectorul y ncepnd din poziia j i fiecare element ntlnit se
afieaz
Numai unul dintre paii 3,4 va avea ca avea ca efect afiarea, deoarece unul dintre
vectori s-a terminat ( ori i>n ori j>m ).
Implementare :

i=1; j=1;
while ( i<=n && j<=m )
if ( x[i]<=y[j] ) { cout<<x[i]<<" ";
i++ ;
}
else
{ cout<<y[j]<<" ";

j++; }
for(k=i;k<=n; k++ )
cout<<x[k]<<" ";
for(k=j;k<=m; k++ )
cout<<y[k]<<" ";

Analiza eficienei algoritmului:


Fie n i respectiv m lungimile celor dou secvene de interclasat. Operaia
elementar este comparaia. Caz defavorabil: n=m i colecia final va fi de forma
x1,y1,x2,y2,,xn,ym. Rezult n+m-1 operaii elementare. n consecin, ordinul de
complexitate al algoritmului de interclasare este O(n+m)- algoritm liniar.
Operaia de interclasare poate fi extins i la vectori ordonai diferit, respectiv
ansamblu ordonat descresctor.
De exemplu:
Vectorul x ordonat cresctor, vectorul y ordonat descresctor :
o ansamblul final ordonat cresctor : se acceseaz rangurile din y n ordine
descresctoare
o ansamblul final ordonat descresctor : se acceseaz rangurile din x n
ordine descresctoare
Vectorul x ordonat descresctor, vectorul y ordonat cresctor :
o ansamblul final ordonat descresctor : se acceseaz rangurile din y n
ordine descresctoare
o ansamblul final ordonat cresctor : se acceseaz rangurile din x n
ordine descresctoare
Vectorul x ordonat descresctor, vectorul y ordonat descresctor :
o ansamblul final ordonat descresctor : se acceseaz rangurile din x i y
n ordine cresctoare
o ansamblul final ordonat cresctor : se acceseaz rangurile din x i y n
ordine descresctoare
Problem :

Se dau dou mulimi n doi vectori ordonai cresctor. S se afieze reuniunea celor
dou mulimi, ca mulime ordonat descresctor.
Aceast problem reprezint o aplicaie a interclasrii.
Diferen : n situaia n care se ntlnesc dou valori egale se vor accesa rangurile ce
urmeaz att ntr-un vector ct i n cellalt.

Implementare :

i=n; j=m;
while ( i>=1 && j>=1 )
if ( x[i]==y[j] ) { cout<<x[i]<<" ";
i-- ; j--; }
else
if (x[i]>y[j] { cout<<x[i]<<" ";

i--; }
else { cout<<y[j]<<" ";
j--; }
for(k=i;k>=1; k-- )
cout<<x[k]<<" ";
for(k=j;k>=1; k-- )
cout<<y[k]<<" ";

3. 5. Sortare
Numim sortare operaia de ordonare cresctoare sau descresctoare a valorilor
memorate ntr-un vector.
Problem : Fie x un vector cu n componente. S se ordoneze acesta cresctor.
Exemplu :
x

30

20

Iniial
40 10

60

50

rangur
i

ranguri 1

10

20

Final
30 40

50

60

Metoda seleciei
Aceasta presupune selectarea la fiecare pas a minimului pe secvena nc nesortat
urmat de plasarea valorii minime pe prima poziie a secvenei respective.
Principiul se repet pe urmtoarea secven nesortat., pn la sortarea ntregului
vector.
Exemplificare :
Etapa 1: secvena nesortat ocup rangurile 1,2,3,4,5,6
se determin rangul minimului ( r ) din secvena x[1],x[2],,x[6]
Rezult r=4
se interschimb x[1] cu x[4] i astfel vectorul va fi :
x
10
ranguri 1

20

40

30

60

50

Etapa 2: secvena nesortat ocup rangurile 2,3,4,5,6


se determin rangul minimului ( r ) din secvena x[2],x[3],,x[6]
Rezult r=2
se interschimb x[2] cu x[2] i astfel vectorul va fi :
x

10

ranguri 1

20

40

30

60

50

Etapa 3: secvena nesortat ocup rangurile 3,4,5,6


se determin rangul minimului ( r ) din secvena x[3],x[4],,x[6]
Rezult r=4
se interschimb x[3] cu x[4] i astfel vectorul va fi :
x

10
ranguri 1

20

30

40

60

50

Etapa 4: secvena nesortat ocup rangurile 4,5,6


se determin rangul minimului ( r ) din secvena x[4],x[5],x[6]
Rezult r=4
se interschimb x[4] cu x[4] i astfel vectorul va fi :
x

10

ranguri 1

20

30

40

60

50

Etapa 5: secvena nesortat ocup rangurile 5,6


se determin rangul minimului ( r ) din secvena x[5],x[6]
Rezult r=6
se interschimb x[5] cu x[6] i astfel vectorul va fi :
x

10
ranguri 1

20

30

40

50

60

Se observ c, indiferent de configuraia vectorului dat, sunt necesare n-1 etape


similare. O etap i are dou faze :
Faza 1 : determinarea rangului minimului pe secvena ce ocup rangurile i,i+1,,n
Faza 2 : aducerea minimului n poziia i fr ca valoarea elementului x[i] s se
piard.
Implementare :

for ( i=1; i<=n-1; i++ ) {


r=i;
for ( j=i+1; j<=n; j++ )
if ( x[j]<x[r] ) r=j;
aux=x[r]; x[r]=x[i]; x[i]=aux;

Evident, pentru a ordona descresctor se va selecta la fiecare pas valoarea maxim.


Analiza eficienei algoritmului:
Fie n lungimea secvenei de sortat. Operaia elementar este comparaia.
Numrul total de comparaii este : (n-1)+(n-2)+ +1=(n-1)*n/2. Ordinul de
complexitate al algoritmului este O(n2)- algoritm ptratic.
Forma simplificat a metodei seleciei

La fiecare parcurgere a unei secvene nesortate se interschimb valoarea iniial din


secven cu orice valoare mai mic dect ea.
Implementare :
for ( i=1; i<=n-1; i++ )
for ( j=i+1; j<=n; j++ )
if ( x[j]<x[i] ) {
aux=x[i]; x[i]=x[j];

x[j]=aux;

Metoda bulelor ( bubble-sort)


Aceasta presupune parcurgerea fiecrei secvene nesortate cu interschimbarea
oricror dou valori aflate pe ranguri succesive, valori care nu respect criteriul de
ordonare propus.
Principiul se repet ct timp, de-a lungul parcurgerii unei secvene, s-a realizat cel
puin o interschimbare.
La fiecare parcurgere se va reine ntr-o variabil auxiliar (s) poziia ultimei
interschimbri, adic finalul secvenei nesortate.
Exemplificare :
x

30

rangur
i

20

Iniial
40 10

60

50

10
ranguri 1

20

Final
30 40

50

60

Prima parcurgere : secvena nesortat ocup rangurile 1,2,3,4,5,6


-

s=0 ( nu s-a realizat nc nicio interschimbare )


se interschimb x[1] cu x[2] , s=1 i astfel vectorul va fi :
x
20 30 40 10 60 50
2
3
4
5
6
ranguri 1
se interschimb x[3] cu x[4] , s=3 i astfel vectorul va fi :
x
20 30 10 40 50 60
2
3
4
5
6
ranguri 1

s-a produs cel puin o interschimbare, aadar se va realiza nc o parcurgere

Alt parcurgere : secvena nesortat ocup rangurile 1,2,3


-

s=0 ( nu s-a realizat nc nicio interschimbare )


se interschimb x[2] cu x[3] , s=2 i astfel vectorul va fi :
x
20 10 30 40 50 60
2
3
4
5
6
ranguri 1

s-a produs cel puin o interschimbare, aadar se va realiza nc o parcurgere

Alt parcurgere : secvena nesortat ocup rangurile 1,2


-

s=0 ( nu s-a realizat nc nicio interschimbare )


se interschimb x[1] cu x[2] , s=1 i astfel vectorul va fi :
x
10 20 30 40 50 60
2
3
4
5
6
ranguri 1

s-a produs cel puin o interschimbare, aadar se va realiza nc o parcurgere


Alt parcurgere : secvena nesortat ocup rangul 1
s=0 ( nu s-a realizat nc nicio interschimbare )
nu exist n secven cel puin dou elemente, aadar parcurgerea se ntrerupe
Nu s-a produs nicio intrerschimbare, aadar ntregul vector este sortat
x
10 20 30 40 50 60
2
3
4
5
6
ranguri 1

Se observ c numrul de parcurgeri similare depinde de configuraia


vectorului. O parcurgere se face pe rangurile 1,2,,u-1 i presupune comparaii
ntre elementele ce ocup ranguri succesive urmate de eventuale interschimbri.
Valoarea variabilei u reprezint finalul secvenei nesortate i se determin din
parcurgerea anterioar, ca ultim poziie pentru care x[i]>x[i+1].
Evident, pentru ordonarea descresctoare interschimbarea va avea loc atunci
cnd x[i]<x[i+1].
Implementare :
u=n;
do {

for ( s=0, i=1; i<u ; i++ )


if ( x[i]>x[i+1] ) {
aux=x[i]; x[i]=x[i+1]; x[i+1]=aux; s=i; }
u=s; }
while ( u>0 );

Analiza eficienei algoritmului:


Fie n lungimea secvenei de sortat. Operaia elementar este comparaia. Caz
defavorabil : vector ordonat descresctor. Se fac n-1 parcurgeri a cte : n-1
comparaii,n-2 comparaii,,o singur comparaie. Rezult (n-1)*n/2 operaii
elementare. Ordinul de complexitate al algoritmului este O(n2)-algoritm ptratic.
Avantaje i dezavantaje ale metodelor de sortare
Ambele metode de sotare genereaz un algoritm polinomial cu ordin de
complexitate O(n2). Metoda bulelor devine avantajoas n cazul n care n vector
valorile ocup poziii iniiale apropiate de cele din vectorul sortat. Metoda seleciei

prezint avantajul unei implementri simple ct i avantajul sortrii valorilor ce nu


ocup ranguri succesive.
Exemplu: ordonarea descresctoare a valorilor pare
Implementare :

for ( i=1; i<=n-1; i++ )


if ( x[i]%2==0 )
for ( j=i+1; j<=n; j++ )
if ( x[j]%2==0 && x[i]<x[j] ) {
aux=x[i]; x[i]=x[j]; x[j]=aux;
}

Aplicaie :
n fiierul text aplic.txt sunt scrise separate prin spaiu: pe prima linie
valorile naturale nenule n i m (0<n,m100, n<m), pe linia a doua cele n elemente ale
tabloului unidimensional a iar pe linia a treia cele m elemente ale tabloului
unidimensional b. Elementele tablourilor sunt numere ntregi cu maxim 4 cifre fiecare.
S se verifice dac exist n b o secven de lungime n n care s se regseasc toate
elementele lui a, nu neaprat n aceeai ordine. Dac nu exist o astfel de secven se
va afia pe ecran valoarea 0 iar dac exist se va afia pe ecran primul indice din b n
care ncepe aceasta.
Exemplu : dac fiierul aplic.txt are 3 7
2 4 1
coninutul alturat, pe ecran se afieaz : 4
3 4 8 4 2 1 9

Variabile suplimentare : rang - reine nceputul primei secvene ce respect


condiia din enun, vectorul x - reine temporar o secven curent de lungime n
Algoritm de rezolvare :
Pasul 1: Se citete coninutul fiierului
Pasul 2: Se ordoneaz cresctor vectorul a
Pasul 3: Se reine n variabila rang valoarea 0 ( nu s-a gsit nc nicio secven )
Oricare ar fi nceputul unei secvene de lungime n n b, se execut paii 4,5,6,7,8
Pasul 4: Se memoreaz secvena ntr-un vector auxiliar x
Pasul 5: Se ordoneaz cresctor vectorul x
Pasul 6: Se verific dac vectorii a i x sunt identici
Pasul 7: Daca s-a semnalat identitate dup pasul 6, se reine n variabila rang
valoarea nceputului secvenei i se ntrerupe cutarea
Pasul 8: Se scrie valoarea variabilei rang
Implementare :

#include <fstream.h>
#include <iostream.h>
int main() {
int n,m,a[101], b[101],i,j,k,aux,s, rang=0, x[101];
ifstream f("aplic.txt");
f>>n>>m; for(i=1;i<=n;i++) f>>a[i];

for(i=1;i<=m;i++) f>>b[i]; f.close();


for(i=1;i<=n-1;i++)
for(j=i+1;j<=n;j++)
if (a[i]>a[j]) {aux=a[i]; a[i]=a[j];a[j]=aux;}
for(i=1;i<=m-n+1; i++)
{
for(j=1;j<=n;j++) x[j]=b[j+i-1];
for(j=1;j<=n-1;j++) for(k=j+1;k<=n;k++)
if(x[j]>x[k]){aux=x[j];x[j]=x[k]; x[k]=aux;}
for(s=0, j=1; j<=n;j++) if (x[i]!=a[i]) {s=1; break;}
if (!s) { rang=i; break; }
}
cout<<rang;
return 0;
}

3. 6. Vector caracteristic
Problema 1 :
n fiierul text numere.in sunt scrise separate prin spaiu, pe mai multe
linii, cel mult 106 numere naturale cu maxim 8 cifre fiecare. S se afieze pe ecran,
separate prin spaiu i n ordine cresctoare, toate cifrele sistemului de numeraie
zecimal care s-au folosit la scrierea numerelor din fiier.
Intrare : numere.in
Ieire
1230123 345812
0 321 555

Numerele ce se citesc nu pot fi memorate n vector deoarece exist riscul


depirii capacitii de memorie RAM. Problema se va rezolva prin alocarea unui
vector auxiliar v, care va caracteriza mulimea cifrelor sistemului de numeraie
zecimal n sensul utilizrii sau neutilizrii fiecrei cifre n parte la scrierea numerelor
din fiier. Acesta se numete vector caracteristic i este un vector de valori logice.
Iniial, v[c]=0 oricare ar fi c{0,1,2,,9} adic nicio cifr nu s-a folosit nc. La
apariia unei cifre c, v[c] primete valoarea 1, adic cifra c s-a folosit la scrierea cel
puin a unui numr din fiier. Se parcurge vectorul pe indici cresctori i fiecare indice
se afieaz dac valoarea elementului ce ocup poziia respectiv este nenul.
Algoritm de rezolvare :
Atta timp ct s-a citit numr din fiier se execut pasul 1
Pasul 1: se extrag cifrele numrului citit. Se actualizeaz valoarea lui v[c] la
fiecare cifr c a numrului citit.
Pasul 2: Se parcurge vectorul caracteristic pe indici cresctori i pentru fiecare v[c]
nenul se afieaz poziia sa ( c )

Implementare :

#include <fstream.h>
#include <iostream.h>
int v[10]; /* compilatorul realizeaz iniializarea */
int main() {
long x; int c;

ifstream f("numere.in");
while ( f>>x )
do {
c=x%10;
v[c]=1; x=x/10; }
while (x);
f.close();
for(c=0;c<=9;c++) if ( v[c] ) cout<<c<<" ";
return 0;
}

Analiza eficienei algoritmului - construcia vectorului caracteristic :


Fie n numrul valorilor date. Operaia elementar este atribuirea. Caz
defavorabil : se dau doar numere cu 8 cifre. Rezult 8*n operaii elementare. Ordinul
de complexitate al algoritmului este O(n)-algoritm liniar.
Problema 2 :
n fiierul text intrare.txt este scris pe prima linie un text alctuit
doar din litere mari ale alfabetului englez. S se afieze textul n fiierul ieire.txt
dar cu literele rearanjate n ordine invers alfabetic.
intrare.txt
ABABGHTRESDFGHIH

ieire.txt
TSRIHHHGGFEDBBAA

Rezolvarea eficient presupune alocarea unui vector caracteristic v, ce va


caracteriza mulimea tuturor literelor mari din punctul de vedere al numrului de
utilizri pentru fiecare liter n scrierea textului dat. Un astfel de vector auxiliar poate
purta denumirea de vector al frecvenelor de apariie dar este tot un vector
caracteristic.
Iniial, v[i]=0 oricare ar fi i{1,2,,26} adic nici o liter nu s-a utilizat
nc. La apariia unei litere L, v[L-64] se incrementeaz, adic litera L s-a folosit
nc o dat la scrierea textului. Expresia L-64 se bazeaz pe faptul c :
Litera A are codul 65
Toate literele mari ocup n tabela ASCII coduri consecutive
Se parcurge vectorul pe indici cresctori i fiecare indice se afieaz de un numr
de ori egal cu valoarea elementului ce ocup poziia respectiv.
Algoritm de rezolvare :
Atta timp ct s-a citit liter din fiier ( n variabila L ) se execut pasul 1
Pasul 1: Se actualiz valoarea lui v[L-64]
Pasul 2: Se parcurge vectorul caracteristic pe indici descresctori i pentru fiecare v[i]
se afieaz de V[i] ori litera ce are codul i+64

Implementare :
#include <fstream.h>
#include <iostream.h>
int v[27];
int main() {
char L; int i,j;
ifstream f("intrare.txt");
while ( f.peek()!=EOF ) { L=f.get(); v[L-64]++; }
f.close();

ofstream g("iesire.txt");
for(i=26; i>=1; i--)
for(j=1;j<=v[i]; j++)
g.close();
return 0;
}

g<<(char)(i+64);

Analiza eficienei algoritmului - construcia vectorului caracteristic :


Fie n numrul literelor date. Operaia elementar este incrementarea. Rezult n
operaii elementare. Ordinul de complexitate al algoritmului este O(n)-algoritm liniar.
Analiza eficienei algoritmului -afiarea literelor:
Fie n numrul literelor date. Operaia elementar este afiarea. Rezult n
operaii elementare. Ordinul de complexitate al algoritmului este O(n)-algoritm liniar.