Recursivitate Informatica

  • Uploaded by: AlexJohn
  • 0
  • 0
  • January 2021
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Recursivitate Informatica as PDF for free.

More details

  • Words: 3,319
  • Pages: 11
Loading documents preview...
Informatică clasa a XI-a

RECURSIVITATE

1

1. Mecanism general Recursivitatea este o metodă de elaborare a algoritmilor. Noţiunea se regăseşte şi în matematică, unde este o modalitate de definiţie a conceptelor. Numită şi definiţia prin inducţie, este principiul care corespunde demonstraţiei prin inducţie matematică. Scrierea recursivă a programelor este un caz particular de dezvoltare descendentă, şi anume problema de rezolvat este redusă la probleme din ce în ce mai simple, însă identice ca structură cu problema iniţială. Un obiect (algoritm, concept etc.) este recursiv dacă el este descris prin intermediul unor obiecte de acelaşi tip cu obiectul însuşi. Paradoxal şi în aparenţă, un obiect recursiv conţine, în definiţia sa, obiectul- dar nu identic, ci unul asemănător- care tocmai se defineşte. O definiţie recursivă implică, deci, referiri la însuşi obiectul definit. În programare, recursivitatea este implementată cu ajutorul subprogramelor. Un subprogram este recursiv dacă el se autoapelează (când subprogramul este lansat în execuţie, se fac apeluri la el insuşi). Dacă autoapelul apare în instrucţiunea compusă a subprogramului (notat P), recursivitatea se numeşte directă. tip P(....) { o functie} {..... ..... P(....); {apel P } ..... } Dacă apelul apare în instrucţiunea compusă a unui alt subprogram (notat Q), care se apelează din primul subprogram (notat P), recursivitatea se numeşte indirectă, iar subprogramele P şi Q se numesc mutual recursive. tip Q(....); { prototipul functiei Q } tip P(...) { definitia functiei P } { ... ... Q(...); { apel Q } ..... } tip Q { nu se mai scrie lista parametrilor formali } { .... ..... P(...); { apel P } .... } Dacă un subprogram nu se autoapelează, spunem că el este iterativ. Exemplul1: Factorialul unui număr. Fie n număr natural. Prin definiţie: n!=1*2*3*....*n , pentru n>0 şi 0!=1 . Definim recursiv n! astfel : 1 , n=0 n!= n*(n-1)! , n>=1 Factorialul lui n este definit tot prin intermediul unui factorial, şi anume al factorialului lui n-1. Deci factorialul care se defineşte este redus la factorialul unui număr mai mic cu o unitate. Evident, după un număr de paşi, vom ajunge la calcului lui 0!, care este definit direct ca egal cu 1. Deci 3!=3*2!=3*(2*1!)=3*(2*(1*0!))=3*(2*(1*1))=6 Funcţia C transcrie fidel definiţia matematică şi parcurge, în execuţie, etapele calculului de mai sus. #include using namespace std; unsigned long fact(unsigned long x) { if(x==1) return 1; return x*fact(x-1); }

Informatică clasa a XI-a

}

RECURSIVITATE

2

int main() { unsigned long n; cout<<"n= "; cin>>n; cout<
Exemplul 2: Suma cifrelor unui număr natural. Fie n natural şi S(n) suma cifrelor numărului n. Definim S(n) recursiv astfel: 0 , n=0 S(n)= n %10 +S(n/10) , n>=1 Se observă că S(n) este definită tot prin intermediul sumei cifrelor unui număr, şi anume n/10, număr obţinut din n prin eliminarea ultimei sale cifre, n%10. Deci, calculul sumei cifrelor unui număr este redus la calculul sumei cifrelor unui număr care are cu o cifră mai puţin. După un număr de paşi, evident se va ajunge la calculul sumei cifrelor unui număr cu 0 cifre, adică numărul 0. S(0)=0, valoare definită direct, şi calculul se opreşte aici. Astfel, pentru n=473, conform definiţiei avem : S(473)=3+S(47)=3+(7+S(4))=3+(7+(4+S(0)))=3+(7+(4+0))=14 #include using namespace std; long int n; int s(long int n) { if(n==0)return 0; else return ( n%10+s(n/10) ); } int main() { cout<<"n=";cin>>n; cout<<"suma cifrelor este "<<s(n); return 0; } Exemplul 3: Calculul celui mai mare divizor comun a două numere. Fie a,b numere naturale. Definim recursiv cmmdc(a,b), conform teoremei lui Euclid astfel: cmmdc(a,b)= a

, b=0

cmmdc(b,a%b)

, b<>0

cmmdc(a,b)=

Definiţia reduce deci calculul lui cmmdc(a,b) la calculul unui alt cmmdc şi anume cmmdc(b,a mod b). Din teorema împărţirii cu rest a=(a/b)*b+(a%b) avem inegalităţile : 0<=a%b <=b După un număr finit de paşi, se va ajunge la valoarea zero a restului, situaţie în care cmmdc este definit direct ca fiind egal cu ultimul împărţitor, restul de la pasul precedent. Pentru a=17 şi b=12 avem: cmmdc(17,12)=cmmdc(12,5)=cmmdc(5,2)=cmmdc(2,1)=cmmdc(1,0)=1 #include<stdio.h> int a,b; int cmmdc(int a,int b) { if(!b) return a;

Informatică clasa a XI-a

RECURSIVITATE

3

else return cmmdc(b,a%b); } void main() { printf(“a,b=”); scanf(“%d %d”, &a, &b); printf(“cmmdc(%d,%d)=%d”, a, b, cmmdc(a,b)); } Exemplul 4: Recursivitate indirectă. Fie funcţiile f,g :R->R , unde: f(x)=

g(x)+1 , x<=3 x2 , x>3

g(x)=

5 , x<0 f(x+1)+2*x , x>=0

Iată aici o situaţie aparte, în care funcţiile sunt recursive, însă, de data aceasta , una prin intermediul celeilalte. Calculul, de exemplu, a lui f(2) decurge astfel : f(2)=g(2)+1=(f(3)+2*2)+1=f(3)+5=(g(3)+1)+5=g(3)+6=(f(4)+2*3)+6= f(4)+12=42+12=16+12=28 Ne propunem să scriem funcţiile C care calculează valorile lui f şi g. Analizând definiţiile celor două funcţii, constatăm că f este definită prin intermediul lui g, deci declaraţia lui g trebuie făcută înaintea declaraţiei lui f, iar g este definită prin intermediul lui f, deci declaraţia lui f trebuie făcută înaintea declaraţiei lui g. #include<stdio.h> int g(int x); int f(int x) { if x>3 return x*x; else return g(x)+1; } int g(int x) { if( x<0) return 5; else return f(x+1)+2*x; } void main() { int x; printf(“x=”); scanf(“%d”, &x); printf(“f(%d)=%d”, x, f(x)); printf(“g(%d)=%d”,x, g(x)) }

2. Conceperea algoritmilor recursivi Definiţiile recursive date în exemplele anterioare au toate aceeaşi structură, în sensul că fiecare din ele conţine două părţi. Prima ramură a definiţiei recursive cuprinde una sau mai multe definiţii directe. Altfel spus, pentru anumite date de intrare, valorile funcţiei sunt date direct şi nu prin intermediul unor alte valori ale acesteia. Această parte din definiţiile recursive este esenţială şi face ca procesul de calcul să se oprească după un număr finit de paşi. Ea se numeşte condiţie de oprire. În implementarea C++ a algoritmilor, acestă parte de definiţie corespunde cel puţin unei execuţii fără autoapel. A doua ramură a definiţiei recursive cuprinde descrierea operaţiilor care se fac la un pas oarecare al algoritmului. La funcţiile matematice scrise anterior, constă într-un proces inductiv de calcul al unor noi valori ale funcţiei pe baza unor valori deja cunoscute ale ei. Reguli pentru scrierea corectă a subprogramelor recursive: a) Orice subprogram recursiv trebuie să se execute, cel puţin o dată, fără a se autoapela. Condiţia de oprire se va scrie pentru valori extreme ale mulţimii valorilor de testat. b) Autoapelurile trebuie să conducă spre situaţia (situaţiile) în care subprogramul se execută direct (fără autoapel).

Informatică clasa a XI-a

RECURSIVITATE

4

Exemplu: Să se scrie o funcţie recursivă care verifică dacă o valoare întreagă x se află printre componentele unui vector a=(a0,a2,......,an-1) cu elemente întregi. Pentru x număr întreg şi 0<=i<=n-1 , definim funcţia găsit astfel: găsit(x,i)=

1

, x apartine vectorului

0 , x nu apartine vectorului Definim recursiv funcţia în două moduri echivalente : gasit(x,i)= (x==aI

x==a1 ) || gasit(x,i-1)

, i=1 , 1<=n

gasit(x,i)= (x==ai

x==an ) || gasit(x,i+1)

, i=n , 1<=i
#include<stdio.h> int n,i; int x; int a[100] ; int gasit1(int x, int i) { if( i==1) return (x==a[1]) else return ( x==a[i] || gasit1(x,i-1)); } int gasit2(int x, int i) { if( i==n) return (x==a[n]) else return ( x==a[i] || gasit2(x,i+1)); } void main() { printf(“n=”); scanf(“%d”, &n); for(i=1;i<=n;i++) scanf(“%d”, &a[i]); printf(“x=”); scanf(“%d”, &x); printf(“%d\n”, gasit1(x,n)); printf(“%d\n”, gasit2(x,1)); } Ambele funcţii au condiţii de oprire, acestea fiind îndeplinite pentru i=1, respectiv i=n. Partea inductivă a funcţiilor este scrisă astfel încât calculele să conducă spre execuţia fără autoapel : - în primul caz, funcţia este apelată din programul principal pentru i=n-1, iar valoarea lui i se decrementează - în al doilea caz, funcţia este apelată pentru i=0, iar valoarea lui i se incrementează

3. Execuţia programelor recursive La activarea unui subprogram, se salvează pe segmentul de stivă : valorile parametrilor transmişi prin valoare valorile variabilelor locale modulului apelator (instanţa) adresa de revenire din subprogram În cazul subprogramelor recursive mecanismul este acelaşi. La fiecare apel al subprogramului, se va aloca în stivă un nou nivel unde se va salva setul de valori (parametri, variabile locale, adresa de revenire) corespunzătoare stării curente a execuţiei subprogramului. Subliniem că, deşi parametrii şi -

Informatică clasa a XI-a

RECURSIVITATE

5

variabilele locale au, pentru toate apelurile aceiaşi identificatori, valorile lor diferă de la o execuţie la alta. În referirile la identificatori, valorile acestora corespund întotdeauna ultimului set de valori salvate. La terminarea execuţiei unui apel recursiv, se reia ultima execuţie întreruptă, în stivă fiind activ setul de valori corespunzătoare acesteia. Să analizăm în continuare execuţia funcţiei recursive care inversează un şir de caractere citit de la tastatură şi încheiat cu caracterul ‘.’ . Funcţia foloseşte pentru citire o singură variabilă de tip caracter. #include using namespace std; void oglinda(); int main() { oglinda(); return 0; } void oglinda() { char a; {I} cin.get(a); {II} if(a!='.') oglinda(); {III} cout<
revenire

I

a=’c’

I

a=’i’

I a=’p’

I

a=’.’

II [C-true]

II [C-true]

II [C-true]

II [C-false]

III scrie ‘c’

III scrie ‘i’

III scrie ‘p’

III se scrie ‘.’

primul apel

al doilea apel

al apel

treilea

al patrulea apel

Funcţia conţine o singură variabilă locală şi nu are parametri, deci pe stivă se vor salva, la fiecare autoapel: - adresa de revenire, care este adresa instrucţiunii putch(a) ; ea rămâne de fiecare dată aceeaşi la fiecare apel, de aceea nu va mai apărea în imaginea de mai jos - valorile variabilei locale a

4. Avantajele şi dezavantajele recursivităţii S-a demonstrat că pentru orice algoritm recursiv există unul iterativ echivalent şi, reciproc, pentru unul iterativ există unul recursiv echivalent. Pentru care optăm ? Algoritmii recursivi, deoarece realizează la fiecare autoapel salvări pe stivă necesită mai mult spaţiu de memorie şi, implicit, timp de execuţie mai îndelungat. Dacă numărul de autoapeluri (adâncimea stivei sau a recursivităţii) este mare, spaţiul de memorie alocat stivei poate fi insuficient; compilatorul transmite, în aceste situaţii mesajul “stack overflow” (depăşire stivă) şi programul nu poate fi executat. Să comparăm în continuare soluţia recursivă şi cea iterativă pentru o problemă nostimă: câte perechi de iepuri se pot obţine în n luni dintr-o pereche ştiind că: - la momentul iniţial, iepurii din prima pereche sunt nou-născuţi - fiecare pereche de iepuri devine fertilă la o lună

Informatică clasa a XI-a

RECURSIVITATE

6

- fiecare pereche produce o pereche de descendenţi în fiecare lună - nici-un iepure nu moare Numărul perechilor de iepuri din fiecare lună este descris de şirul : Luna 0 1 2 3 4 Nr.perechi 1 1 2 3 5 Notăm cu u(n) numărul perechilor din luna n. Atunci avem : 1, n=0 u(n)= 1, n=1 u(n-1)+u(n-2) , n rel="nofollow">=2

5 8

6 13

7 21

… ….

Acest şir este cunoscut ca şirul lui Fibonacci. Varianta recursivă de calcul este : #include<stdio.h> int n; int fib(int n) { if (n==0) return 1; else if(n==1) return 1; else return (fib(n-1)+fib(n-2)); } void main() { printf(“n=”); scanf(“%”, &n); printf(“fib(%d)=%d”, n, fib(n)); } Algoritmul recursiv decurge astfel : pentru calculul lui fib(n) sunt calculaţi fib(n-1) şi fib(n-2), ai căror parametri sunt depuşi pe stivă. Deoarece metoda implică determinarea, cu salvările pe stivă aferente, a aceloraşi valori în mod repetat, este de preferant, evident, varianta iterativă, mult mai naturală în această situaţie. Pentru a calcula, spre exemplu, fib(5) , se fac următoarele apeluri : fib(5) fib(4) fib(3) fib(2) fib(1)

fib(1)

fib(3) fib(2)

fib(1)

fib(2) fib(0)

fib(1)

fib(1) fib(0)

fib(0)

Marele avantaj pe care îl au algoritmii recursivi este cel al conciziei şi clarităţii. Textele sursă ale programelor recursive sunt mult mai scurte şi mai uşor de înţeles. În plus, în situaţiile în care obiectele care intervin în problema de rezolvat sunt definite recursiv, este mult mai natural să concepem un algoritm recursiv. Există unele probleme pentru care este realmente dificil să punem la punct o rezolvare iterativă.

5. Aplicaţii recursivitate 1. Fie n natural şi a,b,c numere reale , a diferit de zero. Presupunând că ecuaţia de gradul al II-lea ax2+bx+c=0 are rădăcinile reale x1, x2 , se cere să se calculeze valoarea sumei Cn=xn1+x2n , pentru n>=1, fără a rezolva ecuaţia. Avem : ax12+bx1+c=0 |*x1n-2 ax22+bx2+c=0 |*x2n-2

Informatică clasa a XI-a

RECURSIVITATE

7

Aplificând prima ecuaţie cu x1n-2 , iar pe cea de-a doua cu x2n-2 şi apoi adunându-le , obţinem: a(x1n+x2n)+b(x1n-1+x2n-1)+c(x1n-2+x2n-2)=0 Deci: a*Cn+b*Cn-1+c*Cn-2=0 => Cn=-(b/a)*Cn-1-(c/a)*Cn-2 Ştiind că S=x1+x2=-b/a şi P=x1*x2=c/a obţinem : Cn=S*Cn-1-P*Cn-2 Scriind prin calcul direct valorile C0 şi C1 , obţinem formula de recurenţă completă : C0=x10+x20=2 C1=x1+x2=S Cn=S*Cn-1-P*Cn-2 Programul transcrie formula de recurenţă obţinută mai sus. Scrieţi varianta iterativă echivalentă, net mai avantajoasă în această situaţie. #include<stdio.h> double a,b,c,S,P; int n; double calcul(int n) { if (!n)return 2; else if(n==1) return S; else return (S*calcul(n-1)-P*calcul(n-2)); } void main() { printf(“a=”); scanf(“%lf”, &a); printf(“b=”); scanf(“%lf”, &b); printf(“c=”); scanf(“%lf”, &c); S=-b/a; P=c/a; printf(“n=”); scanf(“%d”, &n); printf(“C(%d)=%10.2lf”, n, calcul(n)); } 2. Transformarea unui număr din baza 10 în baza b. Fie b,n numere naturale, 2<=b<10. Se cere să se scrie numărul n în baza b. A scrie un număr în baza b (b<10) înseamnă a reprezenta numărul folosind cifrele de la 1 la b-1. Dacă n=b, scriem teorema împărţirii cu rest a lui n la b; restul împărţirii va fi ultima cifră a numărului scrie în baza b; dacă n div b>=b, împărţim n div b la b; restul acestei împărţiri este penultima cifră a reprezentării lui n în baza b; continuăm împărţirile până când obţinem un cât mai mic strict decât b – aceasta va fi ultima cifră din reprezentarea lui n în baza b. De exemplu, fie n=25 şi b=2. Avem : 12>=2 6>=2 3>=2 1<2

25=12*2+1 12=6*2+0 6=3*2+0 3=1*2+1 1=0*2+1

Deci numărul în baza 2 este 11001. #include<stdio.h> int n,b; void transform(int n, int b) { int rest; rest=n%b; if( n>=b) transform(n/b,b); printf(“%d”, rest); } void main() { printf(“n=”); scanf(“%d”, &n); printf(“b=”); scanf(“%d”, &b);

n

rest

Informatică clasa a XI-a

RECURSIVITATE

8

transform(n,b); } Figurăm valorile din stivă pentru parametrul n şi pentru variabila locală rest, pentru fiecare autoapel, în cazul apelului transform(25,2). 3. Fiind dat n natural, n>=1, se cere să se genereze recursiv permutările de n elemente, adică se se enumere valorile 1,2,…..,n în toate ordinile posibile. Vom folosi următorul algoritm: - generăm permutarea de 1 element , şi anume (1) - având generată o permutare (a1,a2,……,an-1) a mulţimii 1,2,…..,n-1 , obţinem prin intermediul ei n permutări ale mulţimii 1,2,….,n astfel: - atribuim lui an valoarea n - interschimbăm pe rând an cu valorile a1,a2,……,an-1 şi obţinem: n a2 ……an-1 a1 1 a1=1 a1 n ……an-1 a2 1 2 a2=2 a1 a2 …. n an-1 2 1 se schimba a2=2 cu a1 a1 a2 ……an-1 n 2 1 3 a3=3 #include<stdio.h> 3 1 2 se schimba a3=3 cu a1 , scrie (3,1,2) int n; 2 3 1 se schimba a3=3 cu a2 , scrie (2,3,1) int p[50]; 2 1 3 se schimba a3=3 cu a3 , scrie (2,1,3) void tipar() 1 2 se revine si se schima a2=2 cu a2 { 1 2 3 a3=3 int i; 3 2 1 se schimba a3=3 cu a1 , scrie (3,2,1) printf(“\n”); 1 3 2 se schimba a3=3 cu a2 , scrie (1,3,2) for(i=1; i<=n; i++) 1 2 3 se schimba a3=3 cu a3 , scrie (1,2,3) printf(“%2d”, p[i]); } void permut(int i) { int k,aux; if(i==n+1) tipar(); else { p[i]=i; for(k=1;k<=i;k++) { aux=p[i]; p[i]=p[k]; p[k]=aux; permut(i+1); aux=p[i]; p[i]=p[k]; p[k]=aux; } } } void main() { printf(“n=”); scanf(“%d”, &n); permut(1); } 4. Algoritmul de haşurare a unei suprafeţe închise (FILL). Se dă o matrice binară. Valorile 1 delimitează anumite suprafeţe închise în cadrul matricei (elementele din interiorul acestor suprafeţe sunt marcate cu 0). Fiind date coordonatele x şi y ale unui element al matricei, semnificând un punct în interiorul uneia dintre suprafeţe, se cere să se haşureze suprafaţa care conţine acest element. Pentru a înţelege mai bine cerinţele acestei probleme, privim figura de mai jos. În partea stângă avem o figură în interiorul căreia există două zone, S1 şi S2. De asemenea, în interiorul figurii se mai află un punct, P1. Dorim haşurarea suprafeţei care conţine acest punct, fără a trece limita care o separă pe aceasta de oricare altă zonă a figurii. Se observă că suprafaţa care conţine punctul P1 este S1. De aceea, după haşurare, desenul va arăta ca în partea dreaptă.

S1

S1

S2

P1

S2

Informatică clasa a XI-a

RECURSIVITATE

9

Se consideră acum că “figura” este reprezentată printr-o matrice, în care “zonele” sunt delimitate de elemente egale cu 1, restul elementelor fiind 0. În acestă situaţie, selectând un punct din interiorul matricei, vom “haşura” suprafaţa care-l conţine prin transformarea tuturor elementelor egale cu 0 din cadrul acestei suprafeţe, în elemente egale cu 1. Pentru rezolvarea problemei, se foloseşte funcţia recursivă fill, care se execută astfel: - testează dacă elementul matricii ale cărei coordonate i-au fost transmise are valoarea 0 - dacă acest lucru este adevărat, atunci elementul respectiv va căpăta valoarea 1, iar funcţia se va autoapela pe rând pentru fiecare din vecinii acestui element (sus,jos,stânga,dreapta) - dacă elementul este deja 1, atunci apelul curent se încheie Pentru a nu mai fi nevoie să testăm la fiecare pas în parte dacă s-a ajuns la marginea matricei, este suficient să bordăm matricea cu câte un rând de elemente egale cu 1. Vom folosi pentru bordare liniile 0 şi m+1, respectiv coloanele 0 şi n+1, valorile citite fiind memorate în liniile şi coloanele numerotate de la 1 la m, respectiv 1 la n. #include<stdio.h> int a[50][50]; int m,n,x,y,i,j; void fill(int x, int y) { if(a[x][y]==0) { a[x][y]=1; fill(x,y+1); fill(x,y-1); fill(x-1,y); fill(x+1,y) } } void tipar() { int i,j; for( i=1; i<=m; i++) { for(j=1; j<=n; j++) printf(“%3d”, a[i][j]); printf(“\n”); } } void main() { printf(“m=); scanf(“%d”, &m); printf(“n=”); scanf(“d”, &n); // dimensiunile matricei for(i=1 ;i<=m;i++) for(j=1 ;j<=n; j++) { printf(“a[%d,%d]=”,i,j); scanf(“%d”, &a[i][j]); } // citirea matricei // bordarea matricei cu elemente 1 for (j=0;j<=n+1; j++) { a[0][j]=1; // linia 0 a[m+1][j]=1; // linia m+1 } for(i=0; i<=m+1; i++) { a[i][0]=1; // coloana 0 a[i][n+1]=1; // coloana n+1 } printf(“x=”); scanf(“%d”, &x);

Informatică clasa a XI-a

}

RECURSIVITATE

10

printf(“y=”); scanf(“%d”, &y); printf(“\n Matricea initiala: \n”); tipar(); fill(x,y); printf(“\n Matricea dupa hasurare : \n”'); tipar();

5. Problema fotografiei. Se dă o fotografie alb-negru, sub forma unei matrici binare. Aceasta înfăţişează unul sau mai multe obiecte. Elementele dinmatrice care aparţin unui obiect au valoarea 1. Se cere să se determine câte obiecte conţine matricea şi să se “coloreze” fiecare obiect cu o culoare diferită (elementele fiecărui obiect vor căpăta aceeaşi valoare şi nu vor exista două obiecte care să fie colorate la fel). Pentru colorarea efectivă a unui obiect, se foloseşte funcţia obiect, care funcţionează aproape la fel cu funcţia fill din algoritmul precedent. Prima deosebire între ele este că în acest caz funcţia va căuta pe toate cele 8 direcţii posibile, deoarece şi marginile unui obiect fac parte din acesta, iar cea de a doua este că haşura nu se face tot în cadrul matricei iniţiale, ci în cadrul unei matrici b, auxiliare. Astfel, în momentul întâlnirii unui punct care aparţine obiectului curent, funcţia îl va şterge pe acesta din matricea iniţială şi îl va adăuga, “colorat”, în matricea auxiliară b. În plus, acestă funcţie mai primeşte ca argument şi numărul cu care se “umple” un anumit obiect. Ca şi mai înainte, pentru a evita testul de depăşire a marginilor matricei, acesta se va borda cu elemente egale cu 0, care nu aparţin nici unui obiect. #include<stdio.h> int a[50][50],b[50][50]; int i,j,m,n,nr; void obiect(int x, int y, int nr) { if(a[x][y]==1) { a[x][y]=0; b[x][y]=nr; obiect(x,y+1,nr); obiect(x+1,y+1,nr); obiect(x,y-1,nr); obiect(x-1,y-1,nr); obiect(x-1,y,nr); obiect(x-1,y+1,nr); obiect(x+1,y,nr); obiect(x+1,y-1,nr); } } void main() { printf(“m=”); scanf(“%d”, &m); printf(“n=”); scanf(“%d”, &n); // dimensiunile matricei for( i=1; i<=m; i++) for(j=1; j<=n; j++) { printf(“a[%d,%d]=”,i,j); scanf(“%d”, &a[i][j]); } // citirea matricei // bordarea matricei for(j=0; j<=n+1; j++) { a[0][j]=0; // linia 0 a[m+1][j]=0; // linia m+1 } for(i=0; i<=m+1; i++) { a[i][0]=0; // coloana 0 a[i][n+1]=0; // coloana n+1 } printf(“\n Matricea initiala:\n”); for(i=1 ;i<=m;i++) { for(j=1;j<=n; j++) printf(“%3d”, a[i][j]); printf(“\n”);

Informatică clasa a XI-a

}

RECURSIVITATE

} for(i=1; i<=m; i++) for(j=1; j<=n; j++) if(a[i][j]==1) { nr++; obiect(i,j,nr); } printf(“\n\n Matricea cu obiectele hasurate :\n”); for(i=1; i<=m; i++) { for(j=1; j<=n; j++) printf(“%3d”, b[i][j]); printf(“\n”); }

11

Related Documents


More Documents from "Srikanth Gogikar"

Recursivitate Informatica
January 2021 2