?? ? Divide et impera ? Divide et impera maxim dintr-o mulțime MetodăDeterminarea de rezolvareelementului a unor probleme Maxim(a, n) Maxim(a, p, u) Caracteristici probleme x = Maxim(a, n-1) x1 = Maxim(a,
Download
Report
Transcript ?? ? Divide et impera ? Divide et impera maxim dintr-o mulțime MetodăDeterminarea de rezolvareelementului a unor probleme Maxim(a, n) Maxim(a, p, u) Caracteristici probleme x = Maxim(a, n-1) x1 = Maxim(a,
?? ?
Divide et impera
?
Divide et impera
maxim dintr-o mulțime
MetodăDeterminarea
de rezolvareelementului
a unor probleme
Maxim(a, n)
Maxim(a, p, u)
Caracteristici probleme
x = Maxim(a, n-1)
x1 = Maxim(a, p, (p+u)/2)
fi descompuse
probleme cu
mică
max =pot
x>a[n-1]
? x : îna[n-1]
x2complexitate
= Maxim(a,mai
(p+u)/2+1,
u)
▪ de același tip / cu soluție cunoscută max = x1>x2 ? x1 : x2
▪ descompunerea este finită – problemă primitivă / condiție de terminare
▪ cîte probleme?
▪ cum se face împărțirea? Metoda bisecției
rezolvarea noilor probleme este mai ușoară
soluțiile combinate soluția problemei inițiale
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 tăieturilor
Probleme de căutare
▪ secvențială / binară
Probleme de sortare
▪
▪
▪
▪
prin interclasare
prin inserare
rapidă (quick sort)
metoda micșorării incrementului (Shell sort)
Divide et impera
Probleme de parcurgere
o mulțime a, cu n elemente => P(a, 0, 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]);
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ă
Destinație
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
b
void taietura(int **c, int x, int y, int a, int b,
int *xm,
int *ym, int
int *bm)
Problema
tăieturilor
x, y,*am,
a, b, 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, y
a, c[1,i]-y
gasit=1;
else
3: x, y
c[0,i]-x, b
i++;
if(gasit)
x+a-c[0,i], b
c[1,i] { taietura(c, x,c[1][i], a,b-c[1][i]+y, xm,ym,am,bm);4: c[0,i], y
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;
x *bm=b;
c[0,i]
x+a
*xm=x; *ym=y;
}
}
Divide et impera
Probleme de căutare
Secvențială problemă de parcurgere (mulțimi sortate sau nesortate)
Mulțime
Binarănesortată
(mulțimi sortate)
Mulțime sortată
C(x, a, p, u, poz)
dacă
C(x, p>u
a, i, n, poz)
C(x, a, i, n, poz)
poz=-1
dacă i==n
dacă i==n || a[i]>x
altfel
poz=-1
poz=-1
m=(p+u)/2
altfel
altfel
dacă
x==a[m]
dacă
x==a[i]
dacă x==a[i]
poz=m
poz=i
poz=i
altfel
altfel
altfel
daca
x<a[m]
C(x,
a, i+1, n, poz)
C(x, a, i+1, n, poz)
C(x, a, p, m-1, poz)
altfel
Nu există
să se
C(x, riscul
a, m+1,
u,obțină
poz) poziția -1 chiar dacă elementul căutat se
află în mulțime, deoarece în momentul găsirii lui, nu se mai face nici un
apel recursiv și nu se mai modifică valoarea lui poz
Divide et impera
Sortare prin interclasare
S(0, 14)
S(a, n) => S(a, 0, n-1)
15 ▪ 7dacă
13p<u5 11
3
1
8 14
6 12
4 10
▪ 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
▪ interclasează a[p:m] cu a[m+1:u]
2
9
2
9
…
1
3
5
7
8
11
13
15
2
4
6
9
10
12
14
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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] … x[n-1]
▪ dacă p<u
Q(0, p,
k-1)
Q(k+1, n-1)
▪ poziționare(x,
u, k)
▪ Q(x, p, k-1)
x[0] x[1] x[2] … x[k-2] x[k-1] x[k] x[k+1] x[k+2] … x[n-1]
▪ Q(x, k+1, u)
10
0 1
9
19
15
3
17
4
1
-1
0
Divide et impera
Sortare prin micșorarea incrementului (Shell sort)
generalizare a sortării prin inserție
vector k-sortat
secvență de pași : valori descrescătoare, ultima este 1
Algoritm
pentru fiecare pas din secvență
▪ pentru fiecare i=pas..n-1
▪ j=i-pas
▪ cît timp j>0 și v[j]<v[j+pas]
v[j] <->v[j+pas]
j-=pas
Divide et impera
Sortare prin micșorarea 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