Você está na página 1de 17

5/13/2014

DIVIDE ET IMPERA
Metode de programare
MURARU STEFAN, CLASA A XII-A RA
INDRUMATOR : PROF. ACHIREI MARIAN
COLEGIUL NATIONAL STEFAN CEL MARE TARGU-NEAMT

DIVIDE ET IMPERA
Metode de programare
MURARU STEFAN, CLASA A XII-A RA
INDRUMATOR : PROF. ACHIREI MARIAN
COLEGIUL NATIONAL STEFAN CEL MARE TARGU-NEAMT



1


Cuprins
Introducere ...................................................................................................................................................... 2
Aplicaii ........................................................................................................................................................... 5
Cutare binar ............................................................................................................................................. 5
Turnurile din Hanoi ..................................................................................................................................... 7
Sortare Rapida (QuickSort) ......................................................................................................................... 9
Sortare prin interclasare (MergeSort) ........................................................................................................ 11
Sortare prin inserie binara ........................................................................................................................ 13
Concluzii ....................................................................................................................................................... 14
Bibliografie ................................................................................................................................................... 15






2


Introducere

n politic i sociologie, Divide et impera este o combinaie de tactici (politice,
militare sau economice) de ctigare i meninere a puterii prin divizarea unei populaii
n entiti mai mici care luate separat au putere mai mic dect cel care i impune
voina. Este deseori ntlnit ca o strategie n care grupuri de putere mic sunt
mpiedicate s se uneasc i s devin mai puternice.
Divide et impera se bazeaz pe principiul descompunerii problemei n dou sau
mai multe subprobleme (mai uoare), care se rezolv, iar soluia pentru problema
iniial se obine combinnd soluiile subproblemelor. De multe ori, subproblemele
sunt de acelai tip i pentru fiecare din ele se poate aplica aceeai tactic a
descompunerii n (alte) subprobleme, pn cnd (n urma descompunerilor repetate) se
ajunge la probleme care admit rezolvare imediat.
Metoda DIVIDE ET IMPERA se poate aplica in rezolvarea unei probleme care
ndeplinete urmtoarele condiii :
se poate descompune in ( doua sau mai multe) subprobleme ;
aceste subprobleme sunt independente una fata de alta (o subproblema nu
se rezolva pe baza alteia si nu se folosete rezultate celeilalte);
aceste subprobleme sunt similare cu problema iniial;
la rndul lor subproblemele se pot descompune (daca este necesar) in alte
subprobleme mai simple;
aceste subprobleme simple se pot soluiona imediat prin algoritmul
simplificat.
Deoarece puine probleme ndeplinesc condiiile de mai sus ,aplicarea metodei este
destul de rara. Dup cum sugereaz si numele "desparte si stpnete "etapele
rezolvrii unei probleme (numita problema iniial) in DIVIDE ET IMPERA sunt :


3

descompunerea problemei iniiale in subprobleme independente ,similare
problemei de baza ,de dimensiuni mai mici ;
descompunerea treptata a subproblemelor in alte subprobleme din ce in ce
mai simple ,pana cnd se pot rezolva imediata ,prin algoritmul simplificat ;
rezolvarea subproblemelor simple ;
combinarea soluiilor gsite pentru construirea soluiilor subproblemelor de
dimensiuni din ce in ce mai mari ;
combinarea ultimelor soluii determina obinerea soluiei problemei iniiale

Metoda DIVIDE ET IMPERA admite o implementare recursiva ,deoarece
subproblemele sunt similare problemei iniiale, dar de dimensiuni mai mici .
Principiul fundamental al recursivitii este autoapelarea unui subprogram cnd
acesta este activ; ceea ce se ntmpl la un nivel ,se ntmpl la orice nivel ,avnd grija
sa asiguram condiia de terminare ale apelurilor repetate .Asemntor se ntmpl si in
cazul metodei DIVITE ET IMPERA ; la un anumit nivel sunt doua posibiliti :
s-a ajuns la o (sub)problema simpla ce admite o rezolvare imediata caz in
care se rezolva (sub)problema si se revine din apel (la subproblema
anterioara, de dimensiuni mai mari);
s-a ajuns la o (sub)problema care nu admite o rezolvare imediata ,caz in
care o descompunem in doua sau mai multe subprobleme si pentru fiecare
din ele se continua apelurile recursive(ale procedurii sau funciei).
In etapa finala a metodei DIVIDE ET IMPERA se produce combinarea
subproblemelor (rezolvate deja) prin secvenele de revenire din apelurile recursive.
Etapele metodei DIVIDE ET IMPERA (prezentate anterior)se pot reprezenta prin
urmtorul subprogram general (procedura sau funcie )recursiv exprimat in limbaj
natural:

Subprogram DIVIMP (PROB);
Daca PROBLEMA PROB este simpla


4

Atunci se rezolva si se obine soluia SOL
Altfel pentru i=1,k
executa DIVIMP(PROB) si se obine SOL1;
Se combina soluiile SOL 1,... ,SOL K si se obine SOL;
Sfrit _subprogram;

De obicei problema iniial se descompune in doua subprobleme mai simple. In
acest caz etapele generale ale metodei DIVIDE ET IMPERA se pot reprezenta concret,
n limbaj pseudocod ,printr-o procedura recursiva astfel :
Procedura DIVIMP(li,ls,sol);
Daca ((ls-li)<=eps)
Atunci REZOLVA (li,ls,sol);
Altfel
DIVIDE (li,m,ls);
DIVIMP(li,msol1);
DIVIMP(m,ls,sol2);
COMBINA(sol1,sol2,sol)
Sfrit_ procedura;

Procedura DIVIMP se apeleaz pentru problema iniial care are dimensiunea
intre limita inferioara (li) si limita inferioara(ls);daca (sub)problema este simpla (ls-
li<=eps),atunci procedura REZOLVA ii afla soluia imediat si se produce ntoarcerea
din apelul recursiv; dac (sub)problema este (nc) complexa ,atunci procedura
DIVIDE o mparte in doua subprobleme ,alegnd poziia m intre limitele li si ls
;pentru fiecare din cele doua subprobleme se reapeleaz recursiv procedura DIVIMP;
in final ,la ntoarcerile din apeluri se produce combinarea celor doua soluii sol1 si sol2
prin apelul procedurii COMBINA.



5


Aplicaii

Cutare binar

Se citete un vector cu n componente numere ntregi (numerele se presupun
ordonate cresctor) i o valoare ntreag ("nr"). S se decid dac nr se gsete sau nu
printre numerele citite, iar n caz afirmativ s se tipreasc indicele componentei care
conine aceast valoare.
O rezolvare n care nr se compar pe rnd cu toate cele n componente reprezint o
pierdere de performan (nu exploateaz faptul c cele n valori sunt n secven
cresctoare). Algoritmul care va fi propus este optim i se poate spune c face parte
dintre algoritmii "clasici".
Funcia care va fi implementat va decide dac valoarea cutat se gsete printre
numerele aflate pe poziii de indice cuprins ntre i i j (iniial, i=1, j=n). Pentru aceasta,
se va proceda astfel:
dac nr coincide cu valoarea de la mijloc, aflat pe poziia de indice (i+j)/2, se
tiprete indicele i se revine din apel (problema a fost rezolvat).
n caz contrar, dac mai sunt i alte elemente de analizat (adic i<j, deci nu au
fost verificate toate poziiile necesare), problema se descompune astfel:
dac nr este mai mic dect valoarea testat (din mijloc), nseamn c nu se
poate afla pe poziiile din partea dreapt, ntruct acestea sunt cel puin mai
mari dect valoarea testat. Nr se poate gsi doar printre componentele cu
indice ntre i i (i+j)/2 - 1, caz n care se reapeleaz funcia cu aceti
parametri;
dac nr este mai mare dect valoarea testat (din mijloc), nseamn c nu se
poate afla n stnga; se poate gsi doar printre componentele cu indicele ntre
(i+j)/2 + 1 i j, caz n care se reapeleaz funcia cu aceti parametri.


6

dac nu mai sunt alte elemente de analizat (pentru c i=j i valoarea din
mijloc, v[i], nu coincide cu nr), se concluzioneaz c nr nu apare n cadrul
vectorului.
Aceast problem nu mai necesit analiza tuturor subproblemelor n care se
descompune, ea se reduce la o singur subproblem, iar partea de combinare a
soluiilor dispare. n linii mari, aceast rezolvare este tot de tip "divide et impera".

#include <iostream>
using namespace std;

int v[100], n, nr;
void caut(int i, int j)
{
int m = (i+j)/2;
if (nr==v[m]) cout<<"gsit, indice="<<m;
else
if (i<j)
if (nr<v[m])
caut(i, m-1);
else caut(m+1, j);
else cout<<"nu a fost gsit.";
}

int main( )
{
cout<<"n="; cin>>n;
for (int i=1; i<=n; i++)
{
cout<<"v["<<i<<"]="; cin>>v[i];
}
cout<<"nr="; cin>>nr;
caut (0,n);
return 0;
}



7

Turnurile din Hanoi


Se dau 3 tije simbolizate prin a,b,c. Pe tija a se gsesc n discuri de diametre
diferite, aezate in ordine descresctoare a diametrelor. Se cere sa se mute de pe tija a
pe b, utiliznd ca tija intermediara tija c, toate cele n discuri, respectnd urmtoarele
reguli:
la fiecare pas se muta un singur disc ;
nu este permis sa se aeze un disc cu diametrul mai mare peste un disc cu
diametrul mai mic.
Rezolvare:
Daca n=1 se face mutarea ab, adic se muta discul de pe tija a pe tija b.
Daca n=2 se fac mutrile ac,ab,cb.
Daca n>2 . Notam cu H(n,a,b,c) irul mutrilor celor n discuri de pe tija a pe
tija b , utiliznd ca tija intermediara, tija c.
Conform strategiei Divide et impera ncercm sa descompunem problema in alte
doua subprobleme de acelai tip, urmnd apoi combinarea soluiilor. Deci: mutarea
celor n discuri de pe tija a pe tija b, utiliznd ca tij intermediara tija c, este echivalenta
cu:
mutarea a n-1 discuri de pe tija a pe tija c , utiliznd ca tij intermediar tija b;
mutarea discului rmas de pe tija a pe tija b;
mutarea a n-1 discuri de pe tija c pe tija b , utiliznd ca tij intermediar tija a.


#include <iostream>
using namespace std;

char a, b, c;
int n;

void han(int n, char a, char b, char c)
{


8


if (n == 1) cout << a << b << endl;
else
{
han(n - 1, a, c, b);
cout << a << b << endl;
han(n - 1, c, b, a);
}
}

int main(void)
{
cout << "n = "; cin >> n;
a = 'a'; b = 'b'; c = 'c';
han(n, a, b, c);
return 0;
}






9

Sortare Rapida (QuickSort)


Un tablou V se completeaz cu n elemente numere reale .S se ordoneze cresctor
folosind metoda de sortare rapida .
Soluia problemei se bazeaz pe urmtoarele etape implementate in
programul principal:
se apeleaz procedura quick cu limita inferioara li=1 si limita superioara
ls=n;
functiapoz realizeaz mutarea elementului v[i] exact pe
poziia ce o va ocupa acesta in vectorul final ordonat ; functiapoz
ntoarce (in k ) poziia ocupata de acest element;
in acest fel ,vectorul V se mparte in doua pri : li k-1 si k+1ls;
pentru fiecare din aceste pri se reapeleaz procedura quick, cu limitele
modificate corespunztor ;
in acest fel ,primul element din fiecare parte va fi poziionat exact pe
poziia finala ce o va ocupa in vectorul final ordonat (functiapoz);
fiecare din cele doua pri va fi ,astfel ,mprit in alte doua pri ;procesul
continua pana cnd limitele prilor ajung sa se suprapun ,ceea ce indica ca
toate elementele vectorului au fost mutate exact pe poziiile ce le vor ocupa
in vectorul final ;deci vectorul este ordonat ;
in acest moment se produc ntoarcerile din apelurile recursive si programul
i termina execuia .


#include<iostream.h>
int v[100],n,k;

void poz(int li,int ls,int & k,int v[100])
{


10

int i=li,j=ls,c,i1=0,j1=-1;
while(i<j)
{
if(v[i]>v[j])
{
c=v[j];v[j]=v[i];v[i]=c;
c=i1;i1=-j1;j1=-c;
}
i=i+i1;
j=j+j1;
}
k=i;
}

void quick(int li,int ls)
{
if(li<ls)
{
poz(li,ls,k,v);
quick(li,k-1);
quick(k+1,ls);
}
}
void main()
{
int i;
cout<<"n=";cin>>n;
for(i=1;i<=n;i++)
{
cout<<"v["<<i<<"]=";
cin>>v[i];
}
quick(1,n);
for(i=1;i<=n;i++) cout<<v[i]<<" ";
}





11

Sortare prin interclasare (MergeSort)


Tabloul unidimensional V se completeaz cu n numere reale. Sa se ordoneze
cresctor folosind sortare prin interclasare.
Sortarea prin interclasare se bazeaz pe urmtoarea logica : vectorul V se mparte
,prin njumtiri succesive ,in vectori din ce in ce mai mici ;cnd se ating vectorii de
maxim doua elemente ,fiecare dintre acetia se ordoneaz printr-o simpla comparare a
elementelor ;cate doi astfel de mini- vectori ordonai se interclaseaz succesiv pana se
ajunge iar la vectorul V.


#include <iostream>
using namespace std;
int a[1000],n;

void interclas(int i,int m,int j)
{
int b[1000];
int x=i;
int k=1;
int y=m+1;
while(x<=m && y<=j)
if (a[x]<a[y])
b[k++]=a[x++];
else
b[k++]=a[y++];

while (x<=m)
b[k++]=a[x++];
while (y<=j)
b[k++]=a[y++];

int t=i;
for (k=1;k<=(j-i)+1;k++)
a[t++]=b[k];
}

void divimp(int i,int j)


12

{
if (i<j)
{
int m=(i+j)/2;
divimp(i,m);
divimp(m+1,j);
interclas(i,m,j);
}
}


void main()
{
clrscr();
cout<<"n=";
cin>>n;
for(int i=1;i<=n;i++)
{
cout<<"a["<<i<<"]=";
cin>>a[i];
}
divimp(1,n);
for(i=1;i<=n;i++)
cout<<a[i]<<' ';
}

OBSERVATII
o mecanismul general de tip Divide et Impera se gsete implementat in
procedura divimp ;
o astfel de abordare a problemei sortrii unii vector conduce la economie de timp
de calcul ,deoarece operaia de interclasare a doi vectori deja ordonai este
foarte rapida ,iar ordonarea independenta celor doua jumti(mini- vectori)
consuma in total aproximativ a doua parte din timpul care ar fi necesar
ordonrii vectorului luat ca ntreg .




13

Sortare prin inserie binara


Sa se ordoneze cresctor un tablou unidimensional V de n numere reale ,folosind
sortarea prin inserie binara .
Pentru fiecare element v[i] se procedeaz in patru pai:
se considera ordonate elementele v[1],v[2],.,v[i-1];
se caut poziia k pe care urmeaz s-o ocupe v[i] intre elementele
v[1],v[2],,v[i-1](procedura poz prin cutare binara);
se deplaseaz spre dreapta elementele din poziiile k,k+1,,n(procedura
deplasare);
insereaz elementul v[i] in poziia k (procedura deplasare);
Se obine o succesiune de k+1 elemente ordonate cresctor.

#include<iostream.h>
void main ( )
{
int i,j,n,aux,a[50];
cout<<" introducei dimensiunea irului: "<<endl;cin>>n;
cout<<"Dai elementele irului:"<<endl;
for(i=0;i<n;i++) {
cout<<"a["<<i<<"]=";cin>>a[i];
}
for(j=1;j<n;j++)
{ aux=a[j];
i=j-1;
while (aux<a[i] && i>=0)
{ a[i+1]=a[i];
i=i-1;
}
a[i+1]=aux;
}
cout <<"Sirul ordonat este:";
for(i=0;i<n;i++)
cout<<a[i]<<" ";
cout<<endl;
}


14

Concluzii
(analiza a complexitii timp pentru algoritmii Divide et Impera)


Algoritmii de tip Divide et Impera au buna comportare in timp ,daca se
ndeplinesc urmtoarele condiii:
dimensiunile subprogramelor(in care se mparte problema iniial)
sunt aproximativ egale(principiul balansrii);
lipsesc fazele de combinare a soluiilor subproblemelor (cutare
binara).



15

Bibliografie

Livia Toca, Cristian Opincaru, AdrianSindile , MANUAL DE
INFORMATICA PENTRU CLS.a-X a, Editura Niculescu ;
Radu Visinescu, BAZELE PROGRAMARII , Editura Petrion ;
Cristian Udrea, TEORIE SI APLICATII, Editura Arves ;
Kris Jamsa, Lars Klander, TOTUL DESPRE C si C++, Editura Teora

Webografie

www.scribd.com
www.infoarena.com

Você também pode gostar