Sunteți pe pagina 1din 37

+

Algoritmi i tehnici de
programare
Cursul 3

+
Cuprins

Cutare secvenial i binar

Divide et Impera

Interclasare

Sortare prin interclasare

Sortare rapid

Sortarea Shell

Sortare prin numrare

+
Cutare secvenial
Presupunem

c dorim s determinm dac un


element aparine sau nu unui vector de elemente.

Dac

nu se tie nimic despre elementele vectorului


avem soluia cutrii secveniale, pn gsim
elementul cutat sau pn testm toate elementele.

+
Cutare secvenial
#include<stdio.h>
int cautare(int x[100],
int n, int a)
{
int gasit=0,i;
for(i=0;i<n;i++)
if(a==x[i]) gasit=1;
return gasit;
}

void main()
{
int x[100],n,a,i,g;
printf("n="); scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("x[%d]=",i);
scanf("%d",&x[i]);
}
printf("valoarea cautata=");
scanf("%d",&a);
g=cautare(x,n,a);
if(g==1)
printf("valoarea %d se gaseste in sir",a);
else
printf("valoarea %d nu se gaseste in sir",a);
}

+
Cutare secvenial
Cautarea secvenial rapid
bool cautare(int x[100],int n, int a)
{
bool gasit=false,
int i=0;
while ( ( v[i]!=x ) && ( i<n ) )
i++;
if(i<n) gasit=true;

return gasit;
}

+
Cutare binar
Dac

elementele vectorului sunt ordonate cresctor,


putem s ne dm seama dac elementul nu exist n
vector fr a fi nevoie s parcurgem toate elementele
vectorului.

Unul

dintre algoritmii folosii n acest caz este algoritmul


de cutare binar.

Acest

algoritm are la baz principiul njumtirii repetate


a intervalului sau domeniului n care se caut elementul,
prin mprirea vectorului n doi subvectori.

+
Cutare binar
Notm

cu p primul indice al vectorului i cu u ultimul


indice al vectorului, iar m este indicele elementului din
mijloc al vectorului m=(p+u)/2.

Se

compar valoarea cutat k cu valoarea elementului


din mijloc v[m] .

Dac

cele dou valori sunt egale nseamn c s-a gsit


elementul.

Dac

nu sunt egale vectorul o s fi mprit n doi


subvectori.

+
Cutare binar
int cautare(int v[], int n, int k)
{
int u, p, gasit=-1,m;
p = 0;
u = n - 1;
while(p <= u)
{ m = (p + u) / 2;
if (k == v[m])
{
gasit=m;
p = u + 1;
}
else
if (k < v[m]) u = m - 1;
else p = m + 1;
}
return gasit;
}

+
Cutare binar - recursiv
int cauta(int v[], int p, int u, int k)
{ if (p > u) return -1;
else
{
int m = (p + u) / 2;
if(k < v[m])
return cauta(v, p, m-1, k);
else
if(k > v[m])
return cauta(v, m+1, u, k);
else
return m;
}
}

+
Metoda Divide et Impera

Divide et Impera este o tehnic special prin care se pot


rezolva o serie de probleme.

Principiul care st la baza acestei tehnici este


urmtorul:
se descompune problema n dou sau mai multe
subprobleme mai simple
se rezolv subproblemele
se combin soluiile problemelor n care a fost
descompus i se obine soluia problemei iniiale

+
Metoda Divide et Impera
Probleme
Cautarea

clasice

binar
Maximul dintr-un vector
Turnurile din Hanoi
Sortarea prin interclasare
Sortarea rapid

+
Metoda Divide et Impera

Cautarea binar

int cauta(int v[], int p, int u, int k)


{
if (p > u)
return -1;
else
{
int m = (p + u) / 2;
if(k < v[m])
return cauta(v, p, m-1, k);
else
if(k > v[m])
return cauta(v, m+1, u, k);
else
return m;
}
}

+
Metoda Divide et Impera

Maximul dintr-un vector

Apel:

int max1(int a[100], int s, int d)


{
int x1,x2;
if (s==d) return a[s];
else
{
x1 = max1(a,s,(s+d)/2);
x2 = max1(a,(s+d)/2+1,d);
if (x1>x2)
return x1;
else
return x2;
}
}
int m;
m = max1(a,0,n-1);

+
Metoda Divide et Impera
Turnurile

din Hanoi

void hanoi(unsigned n, unsigned a, unsigned b, unsigned c)


{
if (n==1) printf("de pe tija %u pe tija %u\n", a,b);
else
{
hanoi(n-1,a,c,b);
printf("de pe tija %u pe tija %u\n", a,b);
hanoi(n-1,c,b,a);
}
}

Apel:

unsigned a, b, c, n;
hanoi(n,a,b,c);

+
Interclasare

Fiind dati doi vectori ordonai se obine un al treilea


vector ordonat care va conine elementele din cei doi
vectori.

+
Interclasare
void interclasare(int x[10], int y[10], int
z[10],int n, int m, int *k)
{
int i,j;
i=0;j=0;*k=0;
while((i<m)&&(j<n))
{
if (x[i]<y[j])
{
z[(*k)]=x[i];
i++;
(*k)++;
}
else
{
z[(*k)]=y[j];
j++;
(*k)++;
}
}

if (i<m)
for( int l=i;l<m;l++)
{
z[(*k)]=x[l];
(*k)++;
}

else
for (int p=j;p<n;p++)
{
z[*k]=y[p];
(*k)++;
}
}

+
Sortare prin interclasare Merge sort

Aceasta metod de ordonare are la baz interclasarea a


doi vectori.

n cazul sortrii prin interclasare, vectorii care se


interclaseaz sunt dou secvene ordonate din acelai
vector.

Sortarea prin interclasare utilizeaz metoda Divide et


Impera.

+
Sortare prin interclasare Merge sort

Algoritm:
se mparte vectorul n secvene din ce in ce mai mici, astfel
nct fiecare secven sa fie ordonat la un moment dat i
interclasat cu o alt secven din vector corespunztoare.

Se urmresc cei trei pai:

se descompune problema n dou sau mai multe


subprobleme mai simple
se rezolv subproblemele
se combin soluiile problemelor n care a fost descompus i
se obine soluia problemei iniiale

+
Sortare prin interclasare Merge sort
34
34
34
34
25

25

25

41

84

41

34

41

41
25

34
6

41

25
25

78

41
9

25

34

41

84

84
84

9
78

78

78
78
84

84

78
78
84

+
Sortare prin interclasare Merge sort
#include<stdio.h>
void interclasare(int x[10],int p, int m, int u)
{int i,j,k,l;int z[10];
i=p; j=m+1; k=0;
while((i<=m)&&(j<=u))

if (x[i]<x[j])
{z[k]=x[i]; i++; k++;
}
else
{z[k]=x[j]; j++; k++;
}

if (i<=m)
for( int l=i;l<=m;l++)
{ z[k]=x[l];
k++;
}
if (j<=u)
for (int l=j;l<=u;l++)
{ z[k]=x[l];
k++;
}
int t=p;
for (k=0;k<(u-p)+1;k++)
x[t++]=z[k];
}

+
Sortare prin interclasare Merge sort
void divimp(int x[10],int p,int u)

{
if (p<u)
{
int m=(p+u)/2;

divimp(x,p,m);
divimp(x,m+1,u);
interclasare(x,p,m,u);
}
}

void main()
{
int n,m,i,j,k;
int x[10];
printf("n=");
scanf("%d", &n);
for(i=0; i<n;i++)
{printf("x[%d]=",i+1);
scanf("%d",&x[i]);
}
divimp(x,0,n-1);
printf("\nvect rez. este \n");
for(i=0;i<n;i++)
printf("x[%d]=%d\n",i,x[i]);
}

+
Sortarea rapid

Metoda Divide et Impera este utilizat n sortarea rapid.

Algoritmului:

1. Se alege o valoare pivot. Se ia valoarea elementului din


mijloc ca valoare pivot, dar poate fi oricare alt valoare, care este
n intervalul valorilor sortate, chiar dac nu este prezent n
tablou.

2. Partiionare. Se rearanjeaz elementele n aa fel nct, toate


elementele care sunt mai mari dect pivotul merg n partea
dreapt a tabloului. Valorile egale cu pivotul pot sta n orice parte
a tabloului. n plus, tabloul poate fi mprit n pri care nu au
aceeai dimensiune (nu sunt egale).

3. Se sorteaz amndou prile. Se aplic recursiv algoritmul


de sortare rapid n partea stng i n partea dreapt.

+
Sortarea rapid
Exemplu

dorim s sortm irul

{4, 6, 1, 3, 5, 2, 7} folosind sortarea rapid.

+
Sortarea rapid
Nesortat
4

+
Sortarea rapid
Valoarea pivot = mijloc=3; i=0; j=5
4

+
Sortarea rapid
v[0]>mijloc i nu crete (i=0)
v[6]>mijloc j scade (j=5)
i<=j
V[0]>mijloc>v[5] interschimbm 4 cu 2

crete i (i=1), scade j (j=4)


4

+
Sortarea rapid
v[1]>mijloc i nu crete (i=1)
v[4]>mijloc j scade (j=3)
i<=j
v[1]>mijloc>=v[3] interschimbm 6 cu 3

crete i (i=2), scade j (j=2)


2

+
Sortarea rapid
v[2]<mijloc i crete (i=3), v[2]<mijloc j nu scade (j=2)
i nu este mai mic dect j (3>2)
i>j se oprete partiionarea
2

+
Sortarea rapid
Vector sortat
1

+
Sortarea rapid
void quicksort(int v[100], int stanga, int dreapta)
{
int i, j, mijloc, aux;
i=stanga;
j=dreapta;
mijloc=v[(stanga+dreapta)/2];
while(i<=j)
{
while(v[i]<mijloc)
i=i+1;
while(v[j]>mijloc)
j=j-1;
if(i<=j)
{
aux=v[i]; v[i]=v[j]; v[j]=aux;
i=i+1; j=j-1;
}
}
if(stanga<j)
quicksort(v, stanga, j);
if(i<dreapta) quicksort(v, i, dreapta);
}

+
Sortarea Shell
n 1959 D.L. Shell a propus un algoritm de ordonare bazat
pe metoda de sortare prin inserie direct.

Este un algoritm cu o performan mbuntit deoarece


face comparaii ntre elemente distanate din vector.

Algoritmul sorteaz mai nti prin inserie subvectori


obinui din vectorul iniial prin extragerea componentelor
aflate la o distan inc una de cealalt, distan care se
numete increment.

Repetnd procedeul pentru incremeni din ce n ce mai


mici i, n final, pentru incrementul 1, se obine vectorul
sortat.

+
Sortarea Shell
Se consider un ir descresctor de numere naturale, numite incremeni
dintre care ultimul, incn, este 1:

inc1 > inc2 > > inci > inci+1 > > incn = 1.

(1) Se pornete cu incrementul inc1. Acesta poate s fie iniial jumatate


din lungimea vectorului. (Ulterior fiecare increment se njumtete.)
(2) La pasul iterativ m se consider incrementul incm . Se sorteaz prin
inserie direct subvectorii obinui din vectorul inial lund elemente aflate
la distana incm, adic subvectorii:

v[1], v[incm+1],
v[2], v[incm+2],
v[incm], v[2incm].

Apoi se reia pasul (2) pentru incrementul incm+1.


Deoarece ultimul increment este incn=1, ultimul pas iterativ n se reduce
la sortarea prin inserie direct, deci vectorul va fi sortat.

+
Sortarea Shell

Fie vectorul:

32 95 16 82 24 66 35 19 75 54 40

Prima iteraie se face cu salt 5.


Pentru a putea face deplasri spre stnga cu cte 5 poziii vom porni de
la elementul al 6-lea din ir, adic 66.
ncercm s l deplasm pe 66 cu 5 poziii spre stnga, dar vedem c
acolo este 32, un numr mai mic.

Trecem la 35.
ncercm s l deplasm cu 5 poziii spre stnga i vedem c acolo se
afl 95, un numr mai mare.
Ca urmare facem efectiv deplasarea, iar 95 trece n locul lui 35.
Obinem:

32 35 16 82 24 66 95 19 75 54 40

+
Sortarea Shell
void sort_shell(double v[],int l)
{
inc2 =inc1/2 ; inc3 =inc2/2..
int i, j, inc;
double a;
for(inc=l/2;inc>0;inc=inc/2)
for(i=inc; i<l;i++)
for(j=i-inc;(j>=0)&&(v[j]>v[j+inc]);j=j-inc)
{
a=v[j];
v[j]=v[j+inc];
v[j+inc]=a;
}
}
Apel:
int n;
double x[100]
sort_shell(x,n);

+
Sortare prin numrare

Metoda sortrii prin numrare pentru un vector v const n:

gsirea pentru fiecare element v[i], a numrului de elemente


din vector, mai mici ca el;
numerele obinute sunt memorate ntr-un vector num;
elementele vectorului de sortat v, sunt iniial atribuite vectorului
temp.
pe baza vectorului num, elementele lui temp vor fi aranjate n
vectorul v.

+
Sortare prin numrare

Vrem s sortm urmatorul ir:

Elementele lui v le atribuim lui temp:

v= (8, 1, 3, 15, 5)

temp= (8, 1, 3, 15, 5)

Pentru fiecare element v[i] numrm cte elemente sunt mai mici
ca el, aceste numere reinndu-le n vectorul num:

num=(3, 0, 1, 4, 2) se reconstitue vect V astfel:

v[num[0]]=temp[0]; v[num[1]]=temp[1]...

obinndu-se vectorul v sortat (1, 3, 5, 8, 15)

Dezavantajul metodei const n utilizarea a doi vectori de lucru,


deci utilizarea unui spaiu de memorie suplimentar

+
Sortare prin numrare
void sort_numarare(double v[],int l)
{
int i,j,*num;
double *temp;
temp=(double*)malloc(l*sizeof(double));
num=(int*)malloc(l*sizeof(int));
for(i=0;i<l; i++)
num[i]=0;
for(i=0;i<l; i++)
temp[i]=v[i];
for(i=0;i<l-1;i++)
for(j=i+1;j<l; j++)
if(v[j]<v[i])
num[i]=num[i]+1;
else num[j]=num[j]+1;
for(i=0;i<l;i++)
v[num[i]]=temp[i];
free(temp);
free(num);
}

Apel:
int n;
double x[100];
sort_numarare(x,n);