Sunteți pe pagina 1din 14

Divide et Impera este o metod folosit la muli algoritmi importani n limbajele de programare.

Termenul provine din limba latin, nsemnnd "divide i conduce", dup ideea de a putea conduce mai uor o mulime de oameni care nu sunt aliai ntre ei. 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. Nu toate problemele pot fi rezolvate prin utilizarea acestei tehnici. Se poate afirma c numrul celor rezolvabile prin "divide et impera" este relativ mic, tocmai datorit cerinei ca problema s admit o descompunere repetat. Divide et impera este o tehnic ce admite o implementare recursiv. Principiul general prin care se elaboreaz algoritmi recursivi este: "ce se ntmpl la un nivel, se ntmpl la orice nivel" (avnd grij s asigurm condiiile de terminare). Aadar, un algoritm prin divide et impera se elaboreaz astfel: la un anumit nivel avem dou posibiliti: s-a ajuns la o problem care admite o rezolvare imediat (condiia de terminare), caz n care se rezolv i se revine din apel; nu s-a ajuns n situaia de la punctul 1, caz n care problema curent este descompus n (dou sau mai multe) subprobleme, pentru fiecare din ele urmeaz un apel recursiv al funciei, dup care combinarea rezultatelor are loc fie pentru fiecare subproblem, fie la final, naintea revenirii din apel.

01/04/2013

n prim instan, o abordare a acestei metode este implementat n algoritmul de sortare Merge Sort. Astfel, fiind un vector nesortat de n elemente, n loc s l sortm prin interschimbare a fiecrei valori prin metoda Bubble Sort sau "Metoda bulelor" (complexitate O(n2) ), mjumtim repetat vectorul, sortnd jumtile separat, dup care le interclasm, obinnd n final vectorul sortat (complexitatea metodei Merge Sort este O(n * log n) ). O alt utilizare a aceste metode este n cadrul algoritmului de cutare binar. Amintesc c acest algoritm este folosit pentru a gsi poziia unui element cu o anumit proprietate fiind dat un vector de n elemente nesortat. Pentru a folosi cutarea binar, trebuie nti s sortm vectorul. Acesta fiind sortat, algoritmul de cutare binar njumtete repetat vectorul, verificnd la fiecare njumtire dac elementul cutat este "nainte" sau "dup" jumtate. n mod evident, este mult mai rapid s gseti poziia unui element njumtind vectorul repetat (O(n * log n) ) dect s-l parcurgi pas cu pas, poziie cu poziie ( O(n) ).

01/04/2013

Ca n imaginea de mai sus, dorim s gsim poziia lui x n cel mai scurt mod. n loc s parcurgem pas cu pas vectorul de la nceput pn la x (care poate fi chiar i ultimul element al vectorului), mprim vectorul n 2 i verificm n care din jumti se afl x-ul nostru. n acest exemplu, dup prima njumtire, tim c x-ul nostru se afl la stnga fa de n/2. Lsm ce este la dreapta de n/2, i njumtim din nou. Ajungem la n/4, verificm unde este x-ul i tim c x-ul este la stnga de n/4. Din nou, lsm ce se afl la dreapta de n/4 i iar njumtim. Astfel ajungem la n/8 i tim c x-ul se afl la dreapta de n/8. Lsm ce este la stnga de n/8 i njumtim ce este la dreapta de n/8, ajungnd la n/16, .a.m.d.

01/04/2013

Maximul dintr-un sir:

#include<iostream.h> #include<conio.h> int x[20], n, i; int div_imp(int p, int q) { int mij, max1, max2; if(p==q) return x[p]; else { mij=(p+q)/2; max1=div_imp(p, mij); max2=div_imp(mij+1, q);

if(max1>max2)
return max1; else return max2; } } void main() { cout<<endl<<"n="; cin>>n; for(i=0; i<=n-1; i++) { cout<<"x["<<i<<"]="; cin>>x[i]; } cout<<endl<<"valoarea maxima este: "<< div_imp(0, n-1); } 01/04/2013

Turnurile din hanoi:


Se dau 3 tije simbolizate prin a,b,c. Pe tija a se gsesc discuri de diametre diferite, asezate n ordine descresctoare a diametrelor privite de jos n sus. Se cere s se mute de pe tija a pe b, utiliznd ca tija intermediar tija c, respectnd urmtoarele reguli:

la fiecare pas se mut un singur disc ; nu este permis s se aseze un disc cu diametrul mai mare peste un disc cu diametrul mai mic. Rezolvare:

Dac n=1 se face mutarea ab, adic se mut discul de pe tija a pe tija b. Dac n=2 se fac mutrile ac,ab,cb. n cazul n care n>2 problema se complic. Notm cu H(n,a,b,c) sirul mutrilor celor n discuri de pe tija a pe tija b , utiliznd ca tij intermediar, tija c. Conform strategiei Divide et impera ncercm s descompunem problema n alte dou subprobleme de acelasi tip, urmnd apoi combinarea solutiilor. n acest sens, observm c mutarea celor n discuri de pe tija a pe tija b,utiliznd ca tij intermediar tija c, este echivalent cu: muatrea a n-1 discuri de pe tija a pe tija c , utiliznd ca tij intermediar tija b; mutarea discului rmas pe tija b;

mutarea a n-1 discuri de pe tija c pe tija b , utiliznd ca tij intermediar tija a.

01/04/2013

#include <iostream.h> char a,b.,c,int n; void h(int n,char a,char b,char c) {if(n==1) cout <<b<<,; else if(n>1) {h(n-1,a,c,b); cout<<a<<b<<,; h(n-1,c,b,a) } } Main() {int n; Cout<<n=; Cin>>n; a=a; b=b; c=c; h(n,a,b,c) }

01/04/2013

Cautare binar

Se citeste un vector cu n componente numere intregi, unde nemerele se presupun ordonate crescator si o valoare intreaga (nr). Sa se decida daca nr se gaseste sau nu printre numerele citite, iar in caz afirmativ sa se tipareasca indicele componentei care contine acea valoare . O rezolvare n care nr se compar pe rnd cu cele n valori, este lipsit de valoare (nu exploateaz faptul c cele n valori sunt n secvent cresctoare). Algoritmul care va fi propus este mult mai performant si face parte, asa cum am nvtat, dintre algoritmii clasici. Problema este de a decide dac valoarea cutat se gseste printre numerele de indice cuprins ntre i si j (intial i=1, j=n ). Pentru aceasta vom proceda astfel: dac nr coincide cu vloarea de indice (i+j)/2 ( valoarea de la mijloc ) , se tipeste indicele si se revine din apel (problema a fost rezolvat). Contrar, dac i<j (nu s-a cutat peste tot) problema se descompune astfel:

dac numul este mai mic dect valoarea testat (din mijloc), nseamn c avem sanse s-l gsim ntre componentele cu indicele ntre i si (i+j)/2-1 , caz n care reapelm functia cu acesti parametri
dac numrul este mai mare dect valoarea testat (din mijloc), nseamn c avem sanse s-l gsim ntre componentele cu indicele ntre (i + j)/2+1 si j , caz n care reapelm functia cu acesti parametri. Problema nu se descompune n altele care se rezolv, dup care nu se compar solutia, ci se reduce la o subproblem. n linii mari , acest rationament este de tip Divide et impera.

01/04/2013

#include<iostream.h> int v[100],n,nr; void caut(int i, int j) { if (nr==v[(i+j)/2]) cout<<gasit<< <<indice<<(i+j)/2; else if (i<j) if (nr<v[(i+j)/2]) caut (i , (i+j)/2-1; else caut ((i+j)/2+1,j); }; main ( ) { cout<<n=;cin>>n; for (int i=1;i<=n;i++) { cout<<v[<<i<<]=;cin>>v[i];} cout<<nr=;cin>>nr; caut (1,n); }

01/04/2013

Maximul dintr-un vector

Se citeste un vector cu n componente, numere naturale. Se cere sa se tipareasca valoare maxima. Trebuie tiparita valoarea maxima dintre numerele retinute in vector de la i la j(initial i= 1, j=n). Pentru aceasta procedam astfel : daca i=j, valoare maxima va fi v[i] ; contrar vom imparti vectorul in doi vectori (primul vector va contine componentele de la i la (i+j) div 2, al doilea va contine componentele de la ((i+j) div 2 +1 la j ) , rezolvam subproblemele (aflam maximul pentru fiecare din ele) iar solutia problemei va fi data de valoarea maxima dintre rezultatele celor doua subprobleme.

01/04/2013

10

Algoritm:

#include<iostream.h> int v[10],n; int max(int i ,int j) { int a,b; if (i==j) return v[i] ; else { a=max(i, (i+j)/2); b=max((i+j)/2+1,j); if (a>b) return a; else return b; } } main( ) { cout<<n=;cin>>n; for (int i=1;i<=n;i++) {cout<<v[<<i<<]=;cin>>v[i]; } cout<<max=<<max(1,n); }

01/04/2013

11

Sortare rapida(quicksort)

Un tablou V se completeaza cu n elemente numere reale .Sa se ordoneze crescator folosind metoda de sortare rapida. Solutia problemei se bazeaza pe urmatoarele etape implementate in programul principal: se apeleaza procedura quick cu limita inferioara li=1 si limita superioara ls=n; functiapoz realizeaza mutarea elementului v[i] exact pe pozitia ce o va ocupa acesta in vectorul final ordonat ; functiapoz intoarce (in k ) pozitia ocupata de acest element; in acest fel ,vectorul V se imparte in doua parti : li k-1 si k+1ls; pentru fiecare din aceste parti se reapeleaza proceduraquick,cu limitele modificate corespunzator ; in acest fel ,primul element din fiecare parte va fi pozitionat exact pe pozitia finala ce o va ocupa in vectorul final ordonat (functiapoz); fiecare din cele doua parti va fi ,astfel ,inpartita in alte doua parti ;procesul continua pana cand limitele partilor ajung sa se suprapuna ,ceea ce indica ca toate elementele vectorului au fost mutate exact pe pozitiile ce le vor ocupa in vectorul final ;deci vectorul este ordonat ; in acest moment se produc intoarcerile din apelurile recursive si programul isi termina executia .

01/04/2013

12

www.google.ro www.wikipedia.org/ www.ereferate.ro

01/04/2013

13

01/04/2013

14

S-ar putea să vă placă și