Documente Academic
Documente Profesional
Documente Cultură
In mod natural metoda divide et impera se implementeaz recursiv, dar este posibil
s eliminm recursivitatea printr-un ciclu iterativ.
1
7.2 Exemple de implementare a metodei:
1. Dndu-se un ir ordonat cresctor de n numere ntregi i un numr ntreg x, s se
determine dac numrul x aparine irului i poziia pe care se gsete n ir.
Descrierea algoritmului:
Se citete irul ntr-un tablou unidimensional a. Notm cu li limita inferioar a irului
(indicele cel mai din stnga), cu ls limita superioar a irului (indicele cel mai din dreapta)
i cu m indicele din mijlocul irului.
Dac li <= ls nseamn c n ir mai sunt elemente printre care trebuie sa-l cutm pe
x. Determinm m=(li+ls)/2, indicele din mijlocul irului.
Verificm daca elementul de pe poziia m este chiar x.
dac da, funcia se termin returnnd poziia m pe care se gsete x
altfel, se verific dac x<a[m]
atunci se reapeleaz funcia pentru subsirul cuprins ntre li i ls=m 1
altfel se reapeleaz funcia pentru subsirul cuprins ntre li=m + 1 i ls.
Dac li>ls nseamn c x nu se gsete n ir iar funcia returneaz 1.
2
Implementarea iterativ a funciei cauta:
int cauta(int li,int ls,int x) // li-limita inferioara a irului, ls-limita superioar a irului
{int m;
while (li<=ls) //atta timp cr li <= ls nseamn c n ir mai sunt elemente
{ //printre care trebuie sa-l cutm pe x.
m=(li+ls)/2; // m-indicele din mijlocul irului
if(x==v[m]) //se compar x cu elementul din mijlocul irului
return m; //returneaz indicele elementului de tablou, unde se gsete x
if(x<v[m])
ls=m-1; //dc x este mai mic dect elementul din mijloc, se modifica ls
else
li=m+1; //n caz contrar se modific li
}
return -1; //dac x nu a fost gsit, funcia returneaz -1
}
Vom aplica metoda divide et impera astfel: irul iniial l mprim n dou
subiruri, apoi le mprit pe acestea n alte dou subiruri i aa mai departe, pn
cnd ajungem la un singur element.Cu siguran, dac un ir conine un singur
element, este foarte simplu s spunem care este cel mai mare element al irului.
Iat c mprind irul am ajuns la probleme suficient de simple pe care s le
rezolvm cu mare uurin.
Dup ce determinm maximul pe fiecare subir, recompunem soluiile pentru a
determina n final maximul irului iniial.
3 7 5 9 8 4 6
3 7 5 9 8 4 6
3 7 5 9 8 4 6
7 5 9 8 4 6
7 9 6
7 9
3
Descrierea algoritmului:
Notm cu li indicele reprezentnd limita inferioar a subsirului i cu ls indicele
reprezentnd limita superioar a irului.
Determinm indicele m din mijlocul irului.
Folosim dou variabile a n care vom pstra maximul subsirului stng (de la li la
m) i b n care vom pstra maximul subirului drept (de la m+1 la ls).
Funcia se reapeleaz pn cnd fiecare subir va conine un singur element.
Acest element l considerm ca fiind maximul pentru subirul respectiv.
Comparm maximele astfel obinute pntru fiecare subir, reinndu-se cel mai
mare dintre ele.
#include<iostream.h> //MAXIM
const MAX=20;
int v[20],n;
void main()
{int i;
cout<<"n=";cin>>n;
for(i=0;i<n;i++)
{cout<<"v["<<i<<"]=";cin>>v[i];}
cout<<"elem. maxim="<<maxim(0,n-1);
}
4
Exemplu: pentru n= 4
5
4 0
3 8 2
2 7 9 6
5
#include <iostream.h> //SUMA MAXIMA
#define MAX 101
int t[MAX][MAX],n; //n-nr. linii, t-memoreaz elementele triunghiului
void citire();
void afisare();
int sumamax(int i,int j);
void main()
{citire();
afisare();
cout<<"suma maxima="<<sumamax(1,1);
}
6
4. Turnurile din Hanoi
Fie trei tije i n discuri cu diametre distincte. Notm tijele cu literele A, B, C.
Cele n discuri se afl toate pe tija A, aezate n ordinea descresctoare a diametrelor.
Se cere s se mute cele n discuri de pe tija A pe tija B, folosind drept tij de manevr,
tija C, astfel:
- la un moment dat se mut un singur disc;
- niciodat un disc de diametru mai mare nu se afl peste un disc de diametru
mai mic.
exemplu:
pentru n=1 A B
pentru n=2 A C
A B
C B
.........................................................................................................................................
pentru n discuri:
- se muta n-1 discuri de pe A pe C folosind ca manevra tija B, la fel ca
mai sus
- se mut discul n de pe A pe B
- se aduc cele n-1 discuri de pe C pe B folosind ca manevr tija A, la fel
ca mai sus
#include<iostream.h> //HANOI
void hanoi(int n,char a,char b,char c);
void main()
{int n;
cout<<"n="; cin>>n; //n-numrul de discuri
hanoi(n,'A','B','C'); //apelul funciei hanoi nu parametri nr. discuri i cele 3 tije
}
7
5. S se determine cel mai mare divizor comun al unui ir de n numere naturale.
Vom mpri irul n dou subiruri, apoi fiecare subir n alte dou subiruri mai
mici, pn cnd subirurile astfel obinute vor conine cel mult dou elemente.
Pentru aceste elmente vom aplica algoritmul lui Euclid de determinare a celui
mai mare divizor comun.
Recompunem apoi soluiile astfel obinute pentru a determina cel mai mare
divizor comun al tuturor elementelor din irul iniial.
#include<iostream.h> //CMMDC
const MAX=20;
unsigned v[MAX],n;
unsigned cmmdc(unsigned li,unsigned ls);
unsigned euclid(unsigned a,unsigned b);
void main()
{int i;
cout<<"n=";cin>>n; //n-numrul de elemente ale irului
for(i=0;i<n;i++) //se citesc elementele irului
{cout<<"v["<<i<<"]=";cin>>v[i];}
cout<<"cmmdc="<<cmmdc(0,n-1);
}
8
Pentru cele dou subiruri se reapeleaz funcia recursiv relundu-se astfel
algoritmul pn cnd n subirurile astfel obinute nu mai exist nici un element.
9
Problema noastr conine doar un ir neordonat.
Conform metodei divide et impera, vom mpri problema n subprobleme de
acelai tip pn cnd devin suficient de simple pentru a le rezolva. Rezolvm aceste
probleme apoi recompunem soluiile lor.
Pentru a ordona vectorul l vom mpri n doi vectori, vom mpri aceti doi
vectori fiecare n cte doi vectori i aa mai departe pn cnd vectorii obinui vor
avea cel mult dou elemente. Pentru astfel de vectori ordonarea este foarte simpl,
vom interschimba elementele lor dac este cazul. Apoi vom interclasa rnd pe rnd
vectorii n ordinea invers obinerii lor.
#include <iostream.h> //SORTARE PRIN INTERCLSARE
#define MAX 20
int a[MAX], n;
void div_imp(int li, int ls);
void sortare(int li, int ls);
void interclasare(int li, int ls, int m);
void citire();
void afisare();
void main()
{int i;
citire();
afisare();
div_imp(0,n-1);
afisare();
}
void citire() // citete n i elementele irului
{int i;
cout<<"n=";cin>>n;
for(i=0;i<n;i++)
{cout<<"a["<<i<<"]="; cin>>a[i]; }
}
void afisare() //afieaza elementele irului
{int i;
for(i=0;i<n;i++) cout<<a[i]<<" ";
cout<<endl;
}
void div_imp(int li, int ls) //gsete mijlocul i mparte irul n subiruri pn cnd
{int m; // se ajunge la cel mult dou elemente n fiecare subir
if((ls-li)<=1)
sortare(li,ls); //ordoneaz ubirurile formate din cel mult dou elemente
else
{m=(li+ls)/2; //mijlocul irului
div_imp(li,m); //reapelarea funciei pe subirul stng
div_imp(m+1,ls); //reapelarea funciei pe subirul drept
interclasare(li,ls,m);} //terclaseaz subirurile ordonate
}
void sortare(int li, int ls)
{int aux;
if(a[li]>a[ls]) //interschimb elementele irului dac nu sunt n ordinea dorit
{aux=a[li];
a[li]=a[ls];
a[ls]=aux; }
}
10
8. Sortarea rapid1 (Ouick Sort).
void citire();
void afisare();
void qsort(int s,int d);
void main()
{citire();
qsort(0,n-1);
afisare();
}
void qsort(int s,int d) //s-indicele din stnga intervalului, d-indicele din dreapta intervalului
{int aux,m,i,j; //aux-variabil auxiliar pentru interschimbarea elementelor, ind. de mijloc
if (s<d) //dac mai exist elemente n ir
{ m=a[(s+d)/2]; //determinm elementul din mijlocul irului
i=s; j=d; //i-indice, parcurge subirul stng de la stnga la dreapta
do // j-indice, parcurge subirul drept de la dreapta la stnga
{while ((i<=d) && (a[i]<m)) //ct timp elementele din stg. sunt n ordinea dorit
i++; // crete i
while ((j>=s) && (a[j]>m)) //ct timp elementele din dr. sunt n ordinea dorit
j--; // scade j
if (i<=j) //dac mai sunt elemente n subsiruri, ele nu sunt n orinea dorit
{aux=a[i]; //le inversm
a[i]=a[j];
a[j]=aux;
i++; j--; //crete i i scade j
}
}
while (i<=j); //se repet algoritmul ct timp mai sunt elemente ntre i i j
qsort(s,j); // se reia algoritmul pe subirul stng
qsort(i,d); // se reia algoritmul pe subirul drept
}
}
1
Funcia qsort(), este implementare metodei de sortare rapid i se afl n biblioteca limbajului de programare C+
+.
11
void citire() //tire datelor
{int i;
cout<<"n="; cin>>n;
for (i=0;i<n;i++)
{cout<<"a["<<i<<"]=";cin>>a[i];}
}
7.3. Evaluare
TESTUL 1
1. Descriei n ce const metoda divide et impera i etapele ei.
int a[10];
int f(int i,int j)
{int m,x,y;
if(i<=j)
{x=f(i, (i+j)/2);
y=f((i+j)/2, j);
return a[(i+j)/2]*x*y;}
else
return 0;}
}
12
TESTUL 2
TESTUL 3
13
7.4. Probleme propuse
2. S se numere elementele prime ale unui vector care conine n numere ntregi,
folosind metoda divide et impera.
6. S se calculeze:
an/2*an/2 pentru n par i n0
an={ a*an-1 pentru n impar i n0
1 pentru n=0
unde a i n sunt numere ntregi pozitive.
7. Ghicii numrul. Realizai un joc astfel nct calculatorul s poat ghici un numr
cuprins ntre 1 i 1000 , evident din ct mai puine ntrebri, la care dumneavoastr
s rspundei prin da sau nu. Intrebrile pot fi doar de forma:
- numrul este egal cu X?
- numrul este mai mare dect X?
- numrul este mai mic dect X?
14