Sunteți pe pagina 1din 24

Recursivitatea (1)

Iteraia presupune execuia repetat a unei poriuni de program, pn n momentul cnd se ndeplinete o anumit condiie. Fiecare execuie se duce pn la capt, se verific ndeplinirea condiiei, i, la un rspuns nesatisfctor se reia execuia de la nceput (while, do-while, for). Recursivitatea presupune de asemenea execuia repetat a unei poriuni de program. In contrast cu iteraia ns, n cadrul recursivitii condiia este verificat n decursul execuiei portiunii de program (nu la sfiritul ei ca la iteraie) i, n caz de rezultat satisfctor, ntreaga poriune de program este apelat din nou ca subprogram a ei nsi, n particular ca procedur a poriunii de program originale care ns nu i-a terminat execuia. In momentul satisfacerii condiiei de revenire, se reia execuia programului apelant exact din punctul din care s-a apelat pe el nsui. Acest lucru este valabil pentru toate apelurile anterioare satisfacerii condiiei.

Recursivitatea (2)
Structurile de program necesare i suficiente n exprimarea recursivitii sunt subrutinele (funciile) care pot fi apelate prin nume. Dac o subrutina P conine o referin direct la ea nsi se spune c este direct recursiv; dac P conine o referin cu o alt subrutina Q, care la rndul ei conine o referin (direct sau indirect) la P, se spune c P este indirect recursiv

Recursivitatea (3)
unei subrutine i se asociaz un set de obiecte ale subrutinei (variabile, constante, tipuri, parametri), care sunt definite local n subrutina i care nu exist sau nu au neles n afara acesteia. de fiecare dat cnd o astfel de subrutina este apelat recursiv, se creeaz un nou set de astfel de obiecte locale, specifice apelului. dei aceste obiecte au acelai nume ca i cele corespunztoare lor din instana anterioar a subrutinei (n calitate de program apelant), ele au valori distincte i orice conflict de nume este evitat prin regulile care stabilesc domeniul identificatorilor: identificatorii se refer ntotdeauna la setul cel cel mai recent creat de obiecte. Aceleai reguli sunt valabile si in cazul parametrilor subrutinei, asociai prin definiie cu setul de variabile.

Recursivitatea (4)
procedurile recursive necesit evaluarea unei condiii de terminare, fr de care un program recursiv duce la o bucl de program infinit. aplicaiile practice au demonstrat c, dei teoretic recursivitatea poate fi infinit, practic ea nu numai c este finit, dar adncimea sa este relativ mic: fiecare apel recursiv al unei subrutine necesit alocarea unui volum de memorie destinat obiectelor (variabilelor) sale curente; in plus, alturi de acestea mai trebuie memorat i starea curent a programului, cu scopul de a fi refcut atunci cnd noua activitate a subrutinei se termin i urmeaz ca cea veche s fie reluat

Mecanismul recursivitatii
int fact(int n) { int rez; if(n==1) return 1; else rez = n*fact(n-1); cout << Gata functia fatorial de ! << n; return rez; } void main() { int i; for(i=1; i<12; i++) cout<<"Factorial de "<< i <<" este: "<< fact(i)<<"\n"; }

Algoritmi de divizare
Algoritmi pentru aflarea extremelor valorilor componentelor unui vector.
include <stdio.h> #include <stdlib.h> #define n 8 typedef struct { int inf, sup; } limite; div_t y; int a[n+1]; limite *domeniu(int i,int j) { int mijloc; limite *l1, *l2, *l; l1=(limite*)malloc(sizeof(limite)); l2=(limite*)malloc(sizeof(limite)); l=(limite*)malloc(sizeof(limite)); if (j<=i+1) { if (a[i]<a[j]) { l->inf=a[i]; l->sup=a[j]; } else { l->inf=a[j]; l->sup=a[i]; } } else { mijloc=(i+j)/2; l1=domeniu(i,mijloc); l2=domeniu(mijloc+1,j); if (l1->sup>l2->sup) l->sup=l1->sup; else l->sup=l2->sup; if (l1->inf<l2->inf) l->inf=l1->inf; else l->inf=l2->inf; } return l; } void main() { int m,k; limite *lim; for (k=1;k<=n;k++) { printf("a[%d]=",k); scanf("%d", &a[k]); } lim=domeniu(1,n); printf("valoarea minima este %d iar maxima %d", lim->inf, lim->sup); }

Algoritmi de divizare
Algoritm pentru determinarea permutrilor primelor n numere naturale
#include <stdio.h> #include <stdlib.h> #define n 5 int a[n]; else { for (i=0;i<=k;i++) { x=a[i];a[i]=a[k];a[k]=x; permut(k-1); x=a[i];a[i]=a[k];a[k]=x; } } } void main() { int i; for (i=0;i<=n-1;i++) a[i]=i+1; printf("rezultatul este "); permut(n-1); }

void permut(int k) { int x,i; if (k==0) { for (i=0;i<=n-1;i++) printf("%d", a[i]); printf("\n"); }

Algoritmi recursivi pentru determinarea tuturor soluiilor unor probleme


Algoritm pentru evidenierea tuturor posibilitatilor de secionare a unui fir, de lungime ntreag dat (N) n parti de lungime 1 sau 2

#include <stdio.h> #include <stdlib.h> #include <conio.h> #define n 8 char z[n+2]; int i,k,x; void p(int m) { if (m>1) { k=k+1; z[k]='.';p(m-1); z[k]='_';p(m-2); k=k-1; }

else { printf(" "); for (i=1;i<=k;i++) printf("%c",z[i]); if (m==1) printf("."); printf("\n"); } } void main() { int x; for (x=1;x<=n;x++) { k=0; printf("\n"); p(x); getch(); } }

Algoritmi recursivi pentru determinarea tuturor soluiilor unor probleme


Algoritm pentru determinarea tuturor soluiilor de ieire dintr-un labirint include <stdio.h> #include <stdlib.h> #include <conio.h> #define n 5 char m[n+1][n+1]; int i,j; div_t a,b; void tipar() { for (i=0;i<=n;i++) { printf(" "); for (j=0;j<=n;j++) printf("%c",m[i][j]); printf("\n"); } printf("\n"); }

void p(int x,int y) { if (m[x][y]==' ') { m[x][y]='+'; a=div(x,n); b=div(y,n); if ((a.rem==0) || (b.rem==0)) tipar(); else { p(x+1,y); p(x,y+1); p(x-1,y); p(x,y-1); } m[x][y]=' '; } }

Algoritmi recursivi pentru determinarea tuturor soluiilor unor probleme


void main() { for (i=0;i<=n;i++) for (j=0;j<=n;j++) m[i][j]='*'; for (j=2;j<=5;j++) m[1][j]=' '; m[2][1]=' '; m[2][2]=' '; m[2][4]=' '; m[3][2]=' '; m[3][3]=' '; m[3][4]=' '; m[4][2]=' '; m[5][2]=' '; tipar(); a=div(n,2); p(a.quot,a.quot); }

Algoritmi de backtracking
Problema turneului calului pe o tabla de sah (1)
function incearca; { se initializeaza selecia micrilor; se selecteaz candidatul urmtor din lista micrilor urmtoare; if este acceptabil then { nregistreaz micarea; if solutia nu e completa then { ncearc micarea urmtoare; if not reuita then terge nregistrarea anterioar } } until (micare reuit) or (nu mai exist candidai) };

Problema turneului calului pe o tabla de sah (2)


function incearca(int i; indice x,y; bool q); int u,v; bool q1; { initializeaza selectia miscarilor; repeat if (1<=u<=n)and(1<=v<=n)and(t[u,v]=0) then { t[u,v]:=i; if i<n*n then { incearca(i+1,u,v,q1); if not q1 then t[u,v]:=0 } else q1:= true } until q1 or nu mai exista candidati; q:=q1 }

Problema turneului calului pe o tabla de sah (3)


#include <stdio.h> #include <conio.h> #define TRUE 1 #define FALSE 0 #define n 5 int i,j, a[9], b[9], t[n+1][n+1],q; int incearca(int i, int x, int y) { int k,u,v,q1; k=0; do { k=k+1; q1=FALSE; u=x+a[k];v=y+b[k]; if ((1<=u) && (u<=n) && (1<=v) && (v<=n)) { if (t[u][v]==0) { t[u][v]=i; if (i<n*n) { q1=incearca(i+1,u,v); if (q1==FALSE) t[u][v]=0; } else q1=TRUE; } } } while ((q1==FALSE) && (k<8)); return q1; }

Problema turneului calului pe o tabla de sah (4)


void main() { a[1]=2; b[1]=1; a[2]=1;b[2]=2; a[3]=-1; b[3]=2; a[4]=-2;b[4]=1; a[5]=-2; b[5]=-1; a[6]=-1;b[6]=-2; a[7]=1; b[7]=-2; a[8]=2;b[8]=-1; for (i=1;i<=n;i++) for (j=1;j<=n;j++) t[i][j]=0; t[1][1]=1; q=incearca(2,1,1); if (q==TRUE) { printf("\n"); for (i=1;i<=n;i++) { for (j=1;j<=n;j++) printf("%d\t",t[i][j]); printf("\n"); } } else printf("nu exista solutie"); }

Modelul principal al unui algoritm cu revenire (backtracking) 1


function incearca; { initializeaza selectia candidatilor; repeat selecteaza urmatorul candidat; if acceptabil then { inregistreaza-l; if solutie incompleta then { incearca pasul urmator; if nu este reusit then sterge inregistrarea } } until (pas reusit) or (nu mai sunt candidati) }

Modelul principal al unui algoritm cu revenire (backtracking) 2


function incearca (i:integer); int k; { k:=0; repeat k:=k+1;{selecteaza al k-lea candidat} if acceptabil then { inregistreaza-l; if i<n*n then { incearca(i+1); if nereusita then sterge inregistrarea } } until reusita or (k=m) }

Problema celor opt regine


function incearca(i:integer); { repeat selecteaza pozitia urmatoare; if sigura then { pune regina if i<8 then { incearca(i+1); if nereusita then ia regina } } until reusita or nu mai sunt candidati; }

Reprezentarea amenintarilor
int x[1..8]; bool a[1..8]; bool b[b1 = 2..b2 = 16]; bool c[c1 = 0..c2 = 14];
unde: - x[i] precizeaza pozitia reginei in coloana i - a[j] = true precizeaza ca nici o regina nu ameninta rindul j - b[k] = true precizeaza ca nici o regina nu ameninta diagonala K - c[k] = true precizeaza ca nici o regina nu ameninta diagonala K

Conditia sigura este indeplinita daca cimpul (i,j) destinatie apartine unui rind si unor diagonale care sunt libere (true), astfel:
if a[j] and b[i+j] and c[i-j+7]

Problema celor 8 regine (1)


#include <stdio.h> #include <conio.h> #define TRUE 1 #define FALSE 0 int i, q, a[9], b[17], c[15], x[9]; int incearca(int i) { int j, q; j=0; do { j=j+1; q=FALSE; if ((a[j]==TRUE) && (b[i+j]==TRUE) && (c[i-j+7]==TRUE)) } { x[i]=j; a[j]=FALSE; b[i+j]=FALSE; c[i-j+7]=FALSE; if (i<8) { q=incearca(i+1); if (q==FALSE) { a[j]=TRUE; b[i+j]=TRUE; c[i-j+7]=TRUE; } } else q=TRUE; } } while ((q==FALSE) && (j<8)); return q;

Problema celor 8 regine (2)


void main() { for (i=1;i<=8;i++) a[i]=TRUE; for (i=2;i<=16;i++) b[i]=TRUE; for (i=0;i<=14;i++) c[i]=TRUE; q=incearca(1); if (q==TRUE) for (i=1;i<=8;i++) printf("%d\t",x[i]); printf("\n"); }

Problema celor 8 regine (3)


int incearca(int i) //determina toate solutiile {int j; for (j=1;j<=8;j++) { if ((a[j]==TRUE) && (b[i+j]==TRUE) && (c[i-j+7]==TRUE)) { x[i]=j; a[j]=FALSE; b[i+j]=FALSE; c[i-j+7]=FALSE; if (i<8) incearca(i+1); else { for (i=1;i<=8;i++) printf("%d ",x[i]); printf("\n"); } a[j]=TRUE; b[i+j]=TRUE; c[i-j+7]=TRUE; } } }

Problema selectiei optime algoritmul general


function incearca(i:integer); //incearca includerea /excluderea celui de-al i-lea obiect { if incluziunea este acceptabila then { include cel de-al i-lea obiect; if i<n then incearca (i+1) else verifica optimalitatea; elimina cel de-al i-lea obiect; } if excluzimea este acceptabila then if i<n then incearca(i+1) else verifica optimalitatea }

Problema selectiei optime (1)


#define TRUE 1 #define FALSE 0 # define n 5 typedef struct { int g,v; }obiect; int i, j, limg, vtot, vmax, g1, g2, ratia, b; obiect a[n+1]; int s[n+1], sopt[n+1]; void incearca(int i, int gt, int vp) { int vp1; if (gt+a[i].g<limg) { s[i]=TRUE; if (i<n) incearca(i+1,gt+a[i].g,vp); else if (vp>vmax) { vmax=vp; for (j=1;j<=n;j++) sopt[j]=s[j]; } s[i]=FALSE; } vp1=vp-a[i].v; if (vp1>vmax) { if (i<n) incearca(i+1,gt,vp1); else { vmax=vp1; for (j=1;j<=n;j++) sopt[j]=s[j]; } } }

Problema selectiei optime (2)


void main() { vtot=0; for (i=1;i<=n;i++) { printf("\ng[%d].g=",i); scanf("%d",&a[i].g); printf("\ng[%d].v=",i); scanf("%d",&a[i].v); vtot=vtot+a[i].v; } printf("\n"); printf("limita inferioara g1 = "); scanf("%d",&g1); printf("limita superioara g2 = "); scanf("%d",&g2); printf("ratia = "); scanf("%d",&ratia); do { limg=g1; vmax=0; for (i=1;i<=n;i++) { s[i]=FALSE; sopt[i]=FALSE; } incearca(1,0,vtot); printf("limita de greutate limg = %d ",limg); for (i=1;i<=n;i++) if (sopt[i]==TRUE) printf(" %d ",i); printf("\n"); g1=g1+ratia; } while (g1<=g2); }

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