22
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

Atestat Divide et Impera

Embed Size (px)

Citation preview

Page 1: Atestat Divide et Impera

5/13/2014

DIVIDE ET IMPERA

Metode de programare

MURARU STEFAN, CLASA A XII-A RAINDRUMATOR : PROF. ACHIREI MARIANCOLEGIUL NATIONAL „STEFAN CEL MARE” TARGU-NEAMT

Page 2: Atestat Divide et Impera

DIVIDE ET IMPERA

Metode de programare

MURARU STEFAN, CLASA A XII-A RAINDRUMATOR : PROF. ACHIREI MARIANCOLEGIUL NATIONAL „STEFAN CEL MARE” TARGU-NEAMT

Page 3: Atestat Divide et Impera

CuprinsIntroducere......................................................................................................................................................2

Aplicații...........................................................................................................................................................5

Căutare binară.............................................................................................................................................5

Turnurile din Hanoi.....................................................................................................................................7

Sortare Rapida (QuickSort).........................................................................................................................9

Sortare prin interclasare (MergeSort)........................................................................................................11

Sortare prin inserție binara........................................................................................................................13

Concluzii.......................................................................................................................................................14

Bibliografie...................................................................................................................................................15

1

Page 4: Atestat Divide et Impera

Introducere

În politică și sociologie, „Divide et impera” este o combinație de tactici (politice,

militare sau economice) de câștigare și menținere a puterii prin divizarea unei populații

în entități mai mici care luate separat au putere mai mică decât cel care își impune

voința. Este deseori întâlnită 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 ușoare), care se rezolvă, iar soluția pentru problema

inițială se obține combinând soluțiile subproblemelor. De multe ori, subproblemele

sunt de același tip și pentru fiecare din ele se poate aplica aceeași tactică a

descompunerii în (alte) subprobleme, până când (în urma descompunerilor repetate) se

ajunge la probleme care admit rezolvare imediată.

Metoda DIVIDE ET IMPERA se poate aplica in rezolvarea unei probleme care

îndeplinește următoarele condiții :

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 folosește rezultate celeilalte);

aceste subprobleme sunt similare cu problema inițială;

la rândul lor subproblemele se pot descompune (daca este necesar) in alte

subprobleme mai simple;

aceste subprobleme simple se pot soluționa imediat prin algoritmul

simplificat.

Deoarece puține probleme îndeplinesc condițiile de mai sus ,aplicarea metodei este

destul de rara. După cum sugerează si numele "desparte si stăpânește "etapele

rezolvării unei probleme (numita problema inițială) in DIVIDE ET IMPERA sunt :

2

Page 5: Atestat Divide et Impera

descompunerea problemei inițiale 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 când se pot rezolva imediata ,prin algoritmul simplificat ;

rezolvarea subproblemelor simple ;

combinarea soluțiilor găsite pentru construirea soluțiilor subproblemelor de

dimensiuni din ce in ce mai mari ;

combinarea ultimelor soluții determina obținerea soluției problemei inițiale

Metoda DIVIDE ET IMPERA admite o implementare recursiva ,deoarece

subproblemele sunt similare problemei inițiale, dar de dimensiuni mai mici .

Principiul fundamental al recursivității este autoapelarea unui subprogram când

acesta este activ; ceea ce se întâmplă la un nivel ,se întâmplă la orice nivel ,având grija

sa asiguram condiția de terminare ale apelurilor repetate .Asemănător se întâmplă si in

cazul metodei DIVITE ET IMPERA ; la un anumit nivel sunt doua posibilități :

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 funcției).

In etapa finala a metodei DIVIDE ET IMPERA se produce combinarea

subproblemelor (rezolvate deja) prin secvențele de revenire din apelurile recursive.

Etapele metodei DIVIDE ET IMPERA (prezentate anterior)se pot reprezenta prin

următorul subprogram general (procedura sau funcție )recursiv exprimat in limbaj

natural:

Subprogram DIVIMP (PROB);Daca PROBLEMA PROB este simpla

3

Page 6: Atestat Divide et Impera

Atunci se rezolva si se obține soluția SOLAltfel pentru i=1,k

executa DIVIMP(PROB) si se obține SOL1;Se combina soluțiile SOL 1,... ,SOL K si se obține SOL;

Sfârșit _subprogram;

De obicei problema inițială 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)Sfârșit_ procedura;

Procedura DIVIMP se apelează pentru problema inițială care are dimensiunea intre

limita inferioara (li) si limita inferioara(ls);daca (sub)problema este simpla (ls-

li<=eps),atunci procedura REZOLVA ii afla soluția imediat si se produce întoarcerea

din apelul recursiv; dacă (sub)problema este (încă) complexa ,atunci procedura

DIVIDE o împarte in doua subprobleme ,alegând poziția 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 soluții

sol1 si sol2 prin apelul procedurii COMBINA.

4

Page 7: Atestat Divide et Impera

Aplicații

Căutare binară

Se citește un vector cu n componente numere întregi (numerele se presupun

ordonate crescător) și o valoare întreagă ("nr"). Să se decidă dacă nr se găsește sau nu

printre numerele citite, iar în caz afirmativ să se tipărească indicele componentei care

conține această valoare.

O rezolvare în care nr se compară pe rând cu toate cele n componente reprezintă o

pierdere de performanță (nu exploatează faptul că cele n valori sunt în secvență

crescătoare). Algoritmul care va fi propus este optim și se poate spune că face parte

dintre algoritmii "clasici".

Funcția care va fi implementată va decide dacă valoarea căutată se găsește printre

numerele aflate pe poziții de indice cuprins între i și j (inițial, i=1, j=n). Pentru aceasta,

se va proceda astfel:

dacă nr coincide cu valoarea de la mijloc, aflată pe poziția de indice (i+j)/2, se

tipărește 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 pozițiile necesare), problema se descompune astfel:

dacă nr este mai mic decât valoarea testată (din mijloc), înseamnă că nu se

poate afla pe pozițiile din partea dreaptă, întrucât acestea sunt cel puțin mai

mari decât valoarea testată. Nr se poate găsi doar printre componentele cu

indice între i și (i+j)/2 - 1, caz în care se reapelează funcția cu acești

parametri;

dacă nr este mai mare decât valoarea testată (din mijloc), înseamnă că nu se

poate afla în stânga; se poate găsi doar printre componentele cu indicele între

(i+j)/2 + 1 și j, caz în care se reapelează funcția cu acești parametri.

5

Page 8: Atestat Divide et Impera

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

soluțiilor 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<<"găsit, indice="<<m; else if (i<j) if (nr<v[m]) caut(i, m-1); else caut(m+1, j); else cout<<"nu a fost găsit."; } 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; }

6

Page 9: Atestat Divide et Impera

Turnurile din Hanoi

Se dau 3 tije simbolizate prin a,b,c. Pe tija a se găsesc n discuri de diametre

diferite, așezate in ordine descrescătoare a diametrelor. Se cere sa se mute de pe tija a

pe b, utilizând ca tija intermediara tija c, toate cele n discuri, respectând următoarele

reguli:

la fiecare pas se muta un singur disc ;

nu este permis sa se așeze 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 mutările ac,ab,cb.

Daca n>2 . Notam cu H(n,a,b,c) șirul mutărilor celor n discuri de pe tija a pe

tija b , utilizând ca tija intermediara, tija c.

Conform strategiei Divide et impera încercăm sa descompunem problema in alte

doua subprobleme de același tip, urmând apoi combinarea soluțiilor. Deci: mutarea

celor n discuri de pe tija a pe tija b, utilizând ca tijă intermediara tija c, este echivalenta

cu:

mutarea a n-1 discuri de pe tija a pe tija c , utilizând ca tijă intermediară tija b;

mutarea discului rămas de pe tija a pe tija b;

mutarea a n-1 discuri de pe tija c pe tija b , utilizând 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){

7

Page 10: Atestat Divide et Impera

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;

}

8

Page 11: Atestat Divide et Impera

Sortare Rapida (QuickSort)

Un tablou V se completează cu n elemente numere reale .Să se ordoneze crescător

folosind metoda de sortare rapida .

Soluția problemei se bazează pe următoarele etape implementate in

programul principal:

se apelează procedura “quick” cu limita inferioara li=1 si limita superioara

ls=n;

functia”poz” realizează mutarea elementului v[i] exact pe

poziția ce o va ocupa acesta in vectorul final ordonat ; functia”poz”

întoarce (in k ) poziția ocupata de acest element;

in acest fel ,vectorul V se împarte in doua părți : li …k-1 si k+1…ls;

pentru fiecare din aceste părți se reapelează procedura “quick”, cu limitele

modificate corespunzător ;

in acest fel ,primul element din fiecare parte va fi poziționat exact pe poziția

finala ce o va ocupa in vectorul final ordonat (functia“poz”);

fiecare din cele doua părți va fi ,astfel ,împărțită in alte doua părți ;procesul

continua pana când limitele părților ajung sa se suprapună ,ceea ce indica ca

toate elementele vectorului au fost mutate exact pe pozițiile ce le vor ocupa

in vectorul final ;deci vectorul este ordonat ;

in acest moment se produc întoarcerile din apelurile recursive si programul

își termina execuția .

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

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

9

Page 12: Atestat Divide et Impera

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]<<" ";

}

10

Page 13: Atestat Divide et Impera

Sortare prin interclasare (MergeSort)

Tabloul unidimensional V se completează cu n numere reale. Sa se ordoneze

crescător folosind sortare prin interclasare.

Sortarea prin interclasare se bazează pe următoarea logica : vectorul V se

împarte ,prin înjumătățiri succesive ,in vectori din ce in ce mai mici ;când se ating

vectorii de maxim doua elemente ,fiecare dintre aceștia se ordonează printr-o simpla

comparare a elementelor ;cate doi astfel de mini- vectori ordonați 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)

11

Page 14: Atestat Divide et Impera

{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 găsește implementat in

procedura “divimp” ;o astfel de abordare a problemei sortării unii vector conduce la economie de timp

de calcul ,deoarece operația de interclasare a doi vectori deja ordonați este foarte rapida ,iar ordonarea independenta celor doua jumătăți(mini- vectori) consuma in total aproximativ a doua parte din timpul care ar fi necesar ordonării vectorului luat ca întreg .

12

Page 15: Atestat Divide et Impera

Sortare prin inserție binara

Sa se ordoneze crescător un tablou unidimensional V de n numere reale ,folosind sortarea prin inserție binara .

Pentru fiecare element v[i] se procedează in patru pași:

se considera ordonate elementele v[1],v[2],….,v[i-1]; se caută poziția k pe care urmează s-o ocupe v[i] intre elementele v[1],v[2],

…,v[i-1](procedura “poz” prin căutare binara); se deplasează spre dreapta elementele din pozițiile k,k+1,…,n(procedura

“deplasare”); inserează elementul v[i] in poziția k (procedura „deplasare”);

Se obține o succesiune de k+1 elemente ordonate crescător.

#include<iostream.h>void main ( ){ int i,j,n,aux,a[50]; cout<<" introduceți dimensiunea șirului: "<<endl;cin>>n; cout<<"Dați 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;}

13

Page 16: Atestat Divide et Impera

Concluzii(analiza a complexității timp pentru algoritmii Divide et Impera)

Algoritmii de tip Divide et Impera au buna comportare in timp ,daca se îndeplinesc următoarele condiții:

dimensiunile subprogramelor(in care se împarte problema inițială) sunt aproximativ egale(“principiul balansării”);

lipsesc fazele de combinare a soluțiilor subproblemelor (căutare binara).

14

Page 17: Atestat Divide et Impera

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

15