Sunteți pe pagina 1din 13

?? ?

?
Metoda divide et impera

Algoritmi i tehnici de
programare

Divide et impera

Determinarea
elementului
maxim
dintr-ocomplexe
mulime
Metod
de rezolvare
a unor
probleme
Maxim(a, n)

Caracteristici probleme

x =

max

Maxim(a, p, u)

Maxim(a,
n-1)
x1 = cu
Maxim(a,
p, (p+u)/2)
pot fi descompuse
n probleme
complexitate
mai mic
= x>a[n-1] ? x : a[n-1] x2 = Maxim(a, (p+u)/2+1, u)
de acelai tip / cu soluie cunoscut (probleme primitive)
max = x1>x2 ? x1 : x2

descompunerea este finit problem primitiv / condiie de terminare


cte probleme?
cum se face mprirea?
Metoda biseciei

rezolvarea noilor probleme este mai uoar


soluiile combinate soluia problemei iniiale

Descompunere propriu-zis / reducere

Divide et impera

Algoritm recursiv
Implementarea este de obicei recursiv
Forma general
S=
determin o modalitate de descompunere a problemei P =>
P1, P2, Pn
pentru fiecare i=1:n
aplic recursiv algoritmul, pentru rezolvarea problemei Pi
=> Si
S=S Si

Divide et impera

Exemple
Probleme de parcurgere
Problema turnurilor din Hanoi
Problema tieturilor
Probleme de cutare
secvenial / binar

Probleme de sortare

prin interclasare
prin inserare
rapid (quick sort)
metoda micorrii incrementului (Shell sort)

Divide et impera

Probleme de parcurgere

o mulime a, cu n elemente => P(a, 0, n)


Problema primitiv: i==n
P(a, i, n) se descompune n
prelucrare a[i]
P(a, i+1, n)

void parcurge(float *v, int i, int n)


{ if( i!=n )
{ printf("%7.2f ",v[i]); //prelucrare v[i]
parc(v,i+1,n);
}
}

Divide et impera

Problema turnurilor din Hanoi

H(n, S, D, I)
H(n-1, S, I, D)
mut un disc de pe S pe D
H(n-1, I, D, S)

void hanoi(int n, char s, char d, char i)


{ if(n>0)
{ hanoi(n-1,s,i,d);
Surs
Destinaie
Intermediar
printf("\nMuta un disc de pe %c pe %c",s,d);
hanoi(n-1,i,d,s);
}
}
hanoi( 5, a, b, c);

Divide et impera

1
3
4
2

void taietura(int **c, int x, int y, int a, int b,


int *xm,
int *ym, intx,*am,
Problema
tieturilor
a,int
b *bm)
,y,
c[2,n]
{ int i,gasit;
1:x,c[1,i]a,y+b-c[1,i]
for( i=gasit=0; (i<n)&&!gasit;
)
a
if((c[0][i]>x)&&(c[0][i]<x+a) && (c[1][i]>y)&&(c[1][i]<y+b))
y+b
2:x,ya,c[1,i]-y
gasit=1;
else
3:x,yc[0,i]-x,b
i++;
if(gasit)
4:c[0,i],yx+a-c[0,i],b
c[1,i] { taietura(c, x,c[1][i], a,b-c[1][i]+y, xm,ym,am,bm);
taietura(c, x,y,
a,c[1][i]-y,
xm,ym,am,bm);
taietura(c, x,y,
c[0][i]-x,b,
xm,ym,am,bm);
taietura(c, c[0][i],y, a-c[0][i]+x,b, xm,ym,am,bm);
xmax,ymax
y}
amax=0,bmax=0
else
if(a*b>(*am)*(*bm))
{ *am=a;
*bm=b;
x
c[0,i]
x+a
*xm=x; *ym=y;
}
}

Divide et impera

Probleme de cutare
Secvenial problem de parcurgere (mulimi sortate

sau nesortate)
Mulime
nesortat

Binar (mulimi sortate)

Mulime sortat

C(x,a,a,p,i,u,n,poz)
poz)
C(x, a, i, n, poz)
C(x,
dacp>u
i==n
dac i==n || a[i]>x
dac
poz=-1
poz=-1
poz=-1
altfel
altfel
altfel
dac x==a[i]
dac x==a[i]
m=(p+u)/2
poz=i
dacpoz=i
x==a[m]
altfel
altfel
poz=m
C(x, a, i+1, n,
C(x, a, i+1, n, poz)
altfel
poz)
daca x<a[m]
C(x, a, p, m-1, poz)
Nualtfel
exist riscul s se obin poziia -1 chiar dac
C(x, a, m+1, u, poz)

elementul cutat se afl n mulime, deoarece n


momentul gsirii lui, nu se mai face nici un apel recursiv i

Divide et impera

Sortare prin interclasare

S(a, n) => S(a, 0, n-1) S(0,14)


15 7dac
13p<u
5 11
3
1
8 14
6 12
4 10
9
m=(p+u)/2
S(0,7)
S(8,14)
S(a, p, m)
15
7 S(a,
13 m+1,
5 u)
11
3
1
8 14
6 12
4 10
2
9 interclaseaz a[p:m] cu a[m+1:u]

1
12
1
14

3
14
2
15

11

13

15

10

10

11

12

13

Divide et impera

Sortare rapid
Q(0,n-1)

Q(x,
x[0]
x[1]p,u)
x[2] x[k-2] x[k-1] x[k] x[k+1] x[k+2]
dac p<u
x[n-1]
Q(0,k-1)
Q(k+1,n-1)
poziionare(x,
p, u, k)
Q(x, p, k-1)
x[0] x[1]
Q(x,x[2]
k+1,
u) x[k-2] x[k-1] x[k] x[k+1] x[k+2]

x[n-1]

10

0 1

19

15

17

-1

Divide et impera

Sortare prin micorarea incrementului (Shell sort)


generalizare a sortrii prin inserie
vector k-sortat
secven de pai : valori descresctoare, ultima este 1
Algoritm

pentru fiecare pas din secven


pentru fiecare i=pas..n-1
j=i-pas
ct timp j>0 i v[j]>v[j+pas]
v[j] <->v[j+pas]
j-=pas

Divide et impera

Sortare prin micorarea incrementului (Shell sort)

indici
n=15
Initial:
Dupa pasul
7:
Dupa pasul
3:
Dupa pasul
1:

0
38
3
3
3

1
13
13
5
5

2
85
71
9
9

3
98
40
10
10

4
5
5
13
13

5
70
9
44
38

6
45
10
40
40

7
44
38
38
44

8
68
68
44
44

void sort_shell(double v[], int l)


{ 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;
}
}

9
71
85
70
45

10
40
98
45
68

11
44
44
68
70

12
9
70
85
71

13
10
45
98
85

14
3
44
71
98

Spor la nvat!