Sunteți pe pagina 1din 12

Subprograme recursive.

Metoda Divide et Impera - exemple

Enunțuri:

1. Să se scrie subprogramul recursiv care determină numărul de elemente negative dintr-un


vector. Se va scrie și programul apelator.
2. Să se scrie subprogramul recursiv care determină produsul scalar dintre doi vectori. Se va
scrie și programul apelator.
3. Să se scrie subprogramul recursiv care determină cmmdc dintre două numere naturale. Se va
oferi și un exemplu de apel.
4. Să se scrie subprogramul recursiv care determină CMMDC dintr-un sir de numere naturale.
Se va oferi și un exemplu de apel.
5. Să se scrie subprogramul recursiv care determină suma elementelor impare dintr-un vector.
Se va oferi un exemplu de apel.
6. Să se scrie subprogramul recursiv care determină produsul primelor n numere impare. Se va
oferi un exemplu de apel.
7. Să se scrie subprogramul recursiv care determină suma cifrelor unui numar intreg. Se va oferi
un exemplu de apel.
8. Scrieți un subprogram recursiv pentru implementarea metodei bisectiei. Se va oferi un
exemplu de apel.
9. Să se scrie subprogramul recursiv care determină un număr la o putere (x n), precum și
programul apelator.
10. Să se scrie subprogramul recursiv care calculează valoarea unui polinom într-un punct dat,
precum și programul apelator.

11. Scrieți un subprogram recursiv care calculează (aranjamente de n luate câte k), precum și
programul apelator.
12. Să se scrie subprogramul recursiv care determină rezultatul ridicării unei matrice la o putere
dată, precum și programul apelator.
13. Scrieți un subprogram recursiv care rezolvă problema turnurilor din Hanoi. Se va oferi un
exemplu de apel.

Se vor studia ambele metode de scriere a unui subprogram recursiv (metoda reducerii și metoda
descompunerii).

1
1. Să se scrie subprogramul recursiv care determină numărul de elemente negative dintr-
un vector. Se va scrie și programul apelator.

a) Metoda reducerii unei probleme de grad n la o problema de grad n-1 și o problema primitiva
(verificarea unui element din vector)

#include<stdio.h>
int numara(float v[], int n)
{ int nr;
if( n == 0) nr = 0;
else {
nr=numara(v,n-1);nr+=(v[n-1]<0)?1:0;
}
return nr;
}

void main()
{ int n,i, rez; float x[100];
printf("n="); scanf("%d", &n);
for(i=0;i<n;i++)
{printf("x[%d]=", i);scanf("%f", &x[i]);}
rez=numara(x,n);
printf("numarul de elemente negative este %d ", rez);
}

b) Metoda descompunerii unei probleme în două subprobleme (doi vectori) cu rezolvare similară
(până la probleme primitive – cu rezolvare imediată, anume vectori cu un singur element)

#include<stdio.h>
int numara(float v[], int ls, int ld)
{ int nr;
if( ls==ld) nr = (v[ls]<0)?1:0;
else {
nr=numara(v,ls, (ls+ld)/2)+numara(v,(ls+ld)/2+1, ld);
}
return nr;
}

void main()
{ int n,i, rez; float x[100];
printf("n="); scanf("%d", &n);
for(i=0;i<n;i++)
{printf("x[%d]=", i);scanf("%f", &x[i]);}
rez=numara(x,0, n-1);
printf("numarul de elemente negative este %d ", rez);
2
}

2. Să se scrie subprogramul recursiv care determină produsul scalar dintre doi vectori. Se
va scrie și programul apelator.

#include<stdio.h>

//metoda reducerii
float ps(float *x, float *y, int n)
{ float s;
if (n==0) s=0;
else s= ps(x,y,n-1)+x[n-1]*y[n-1];
return s;
}

//metoda de descompunere
float ps1(float *x, float *y, int ls, int ld)
{ float s;
if( ls==ld) s= x[ls]*y[ls];
else {
s=ps1(x,y,ls, (ls+ld)/2)+ps1(x,y,(ls+ld)/2+1, ld);
}
return s;
}

void main()
{ int n,i; float x[100], y[100], rez;
printf("n="); scanf("%d", &n);
for(i=0;i<n;i++)
{printf("x[%d]=", i);scanf("%f", &x[i]);}
for(i=0;i<n;i++)
{printf("y[%d]=", i);scanf("%f", &y[i]);}
rez=ps(x,y,n);
printf("produsul scalar este %5.2f \n", rez);
rez=ps1(x,y,0, n-1);
printf("produsul scalar in varianta doi este %5.2f ", rez);
}

3
3. Să se scrie subprogramul recursiv care determină cmmdc dintre două numere naturale.
Se va oferi și un exemplu de apel.

#include<stdio.h>
int cmmdc_2(int a, int b)
{
int rez;
if (a%b==0) rez= b;
else rez= cmmdc_2(b,a%b);
return rez;
}

void main()

{
int a,b, cmmdc;
printf("a="); scanf("%d", &a);
printf("b="); scanf("%d", &b);
cmmdc=cmmdc_2(a,b);
printf("cmmdc=%d", cmmdc);
}

4. Să se scrie subprogramul recursiv care determină CMMDC dintr-un șir de numere


naturale. Se va oferi și un exemplu de apel.

#include<stdio.h>
unsigned int cmmdc_2(unsigned int a, unsigned int b)
{
unsigned int rez;
if (a%b==0) rez= b;
else rez= cmmdc_2(b,a%b);
return rez;
}

unsigned int cmmdc_n(unsigned int x[], int n)


{
unsigned int rez;
if (n==1) rez=x[0];
else rez= cmmdc_2(cmmdc_n(x,n-1),x[n-1]);
return rez;
}

void main()
{
unsigned int x[100], cmmdc;
int n,i;
printf("n="); scanf("%d", &n);
for(i=0;i<n;i++)

4
{printf("x[%d]=", i);scanf("%u", &x[i]);}
cmmdc=cmmdc_n(x,n);
printf("cmmdc=%u", cmmdc);
}

5. Să se scrie subprogramul recursiv care determină suma elementelor impare dintr-un


vector. Se va oferi un exemplu de apel.

#include<stdio.h>

//metoda reducerii
int suma(int *v, int n)
{ int s;
if (n==0) s=0;
else s= suma(v,n-1) + (v[n-1]%2==1)*v[n-1];
return s;
}

//metoda descompunerii
int suma2(int *v, int ls, int ld)
{ int s;
if (ls==ld) s=(v[ls]%2==1)*v[ls];
else s= suma2(v,ls, (ls+ld)/2) + suma2(v, (ls+ld)/2+1, ld);
return s;
}

void main()
{
int x[100], s;
int n,i;
printf("n="); scanf("%d", &n);
for(i=0;i<n;i++)
{printf("x[%d]=", i);scanf("%d", &x[i]);}
s=suma(x,n);
printf("suma numerelor impare este=%d\n", s);
s=suma2(x,0,n-1);
printf("suma numerelor impare in varianta doi este=%d", s);
}

5
6. Să se scrie subprogramul recursiv care determină produsul primelor n numere impare.

#include<stdio.h>

int produs(int n)
{
int rez;
if(n==1) rez=1;
else
rez=(2*n-1)*produs(n-1);
return rez;
}

void main()
{
int n;
printf("n="); scanf("%d", &n);
printf("produsul primelor %d numere impare=%d", n, produs(n));
}

7. Să se scrie subprogramul recursiv care determină suma cifrelor unui numar intreg.

#include<stdio.h>

int suma(int n)
{ int rez;
if(!n) rez=0;
else rez= n%10+suma(n/10);
return rez;
}

void main()
{
int n;
printf("n="); scanf("%d", &n);
printf("suma cifrelor este=%d", suma(n));
}

8. Metoda bisectiei
Funcţia are ca parametri de intrare capetele intervalului în care se caută soluţia (x0 şi x1),
numărul maxim de iteraţii (n), precizia dorită (eps), funcţia asociată ecuaţiei (f) şi adresa unde se
va înscrie soluţia. Prin numele funcţiei se returnează un cod de eroare cu următoarea
semnificaţie: 0 – nu s-a găsit soluţie datorită numărului prea mic de iteraţii sau preciziei prea

6
mari cerute; 1 – s-a obţinut soluţia exactă; 2 – s-a obţinut o soluţia aproximativă; 3 – intervalul
dat nu conţine nici o soluţie.

#include <stdio.h>
#include<math.h>

float f(float x)
{ return (pow(x,2)-5*pow(x,1)+6);
}

int bisectie(float x0,float x1,unsigned n,float eps,float (*f)(float),float *sol)


{ int cod;
if ((*f)(x0)*(*f)(x1)>0) cod=3;
else if (n==0) cod=0;
else {*sol=(x0+x1)/2;
if((*f)(*sol)==0) cod=1;
else if(fabs(x0-x1)<=eps) cod=2;
else if((*f)(*sol)*(*f)(x0)<0)
cod=bisectie(x0,*sol,n-1,eps,f,sol);
else cod=bisectie(*sol,x1,n-1,eps,f,sol);
}
return cod;
}
int main()
{ float eps,x0,x1,x2;
int n;
printf("x0= ");
scanf("%f",&x0);
printf("x1= ");
scanf("%f",&x1);
printf("n= ");
scanf("%d",&n);
printf("epsilon= ");
scanf("%f",&eps);
int cod=bisectie(x0,x1,n,eps,f,&x2);
switch (cod)
{case 0:printf("Nu s-a gasit nici o solutie !"); break;
case 1:printf("Solutia exacta: %f",x2); break;
case 2:printf("Solutia aproximativa: %f",x2); break;
case 3:printf("Nu exista solutie in intervalul dat"); break;
}
return 0;
}

7
9. Să se scrie subprogramul recursiv care determină un număr la o putere (x n), precum și
programul apelator.

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<conio.h>

float putere(float x, int n)


{
float rez;
if (n == 0) rez = 1;
else
rez = putere(x, n - 1) * x;
return rez;
}

void main()
{
float x, rez; int n;
printf("n=");
scanf("%d", &n);
printf("x=");
scanf("%f", &x);
rez = putere(x, n);
printf("rezultatul este %5.2f", rez);

10. Să se scrie subprogramul recursiv care calculează valoarea unui polinom într-un punct
dat, precum și programul apelator.

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<conio.h>

float putere(float x, int n)


{
float rez;
if (n == 0) rez = 1;
else
rez = putere(x, n - 1) * x;
return rez;
}

float polinom(float coef[], int n, float x)


{
float rez;
if (n == 0) rez = coef[0];
else
rez = polinom(coef, n - 1, x) + coef[n] * putere(x, n);
return rez;
}
void main()
8
{
int n,i;
float coef[100], x, val;
printf("Introduceti gradul polinomului, n="); scanf("%d", &n);
printf("Coeficientii polinomului: \n");
for (i = 0; i <= n; i++) {
printf("coeficientul lui x la puterea %d =", i);
scanf("%f", &coef[i]);
}
printf("Punctul pentru care se va calcula valoarea:");
scanf("%f", &x);
val = polinom(coef, n, x);
printf("Valoarea pol. in punctul %5.2f este %5.2f", x, val);
}

11. Scrieți un subprogram recursiv care calculează (aranjamente de n luate câte k),
precum și programul apelator.

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<conio.h>

long aranjamente(unsigned n, unsigned k)


{
long a;
if (k > n) a = 0;
else if (k == 0) a = 1;
else a = aranjamente(n - 1, k-1) *n;
return a;
}

void main()
{
int n,k;
printf("n="); scanf("%d", &n);
printf("k="); scanf("%d", &k);
int rez = aranjamente(n, k);
printf("aranjamete =%d", rez);
}

9
12. Să se scrie subprogramul recursiv care determină rezultatul ridicării unei matrice la o
putere dată, precum și programul apelator.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

void inmultire(float a[][10], float b[][10], float c[][10], int m)


{
int i, j, k;
for (i = 0; i < m; i++)
for (j = 0; j < m; j++)
{
c[i][j] = 0;
for (k = 0; k < m; k++)
c[i][j] = c[i][j] + b[i][k] * a[k][j];
}

void matrice_putere(float a[][10], float b[][10], int m, int p)


{
int i, j; float c[10][10];
if (p == 0)
{
for (i = 0; i < m; i++)
for (j = 0; j < m; j++)
if (i==j)
b[i][j] = 1;
else b[i][j] = 0;
}
else
{
matrice_putere(a, b, m, p - 1);
inmultire(a, b, c, m);
for (i = 0; i < m; i++)
for (j = 0; j < m; j++)
b[i][j] = c[i][j];

}
void main()
{
int m, p, j, i; float a[10][10], b[10][10];
printf("\n Matricea 1");
printf("\nNr de linii/coloane= "); scanf("%d", &m);
for (i = 0; i < m; i++)
for (j = 0; j < m; j++)
{
printf("a[%d][%d]= ", i, j); scanf("%f", &a[i][j]);
}
for (i = 0; i < m; i++)
{
for (j = 0; j < m; j++) printf(" %5.2f ", a[i][j]); printf("\n");
}
printf("Puterea este: "); scanf("%d", &p);
matrice_putere(a, b, m, p);
for (i = 0; i < m; i++)
{
for (j = 0; j < m; j++)
printf(" %5.2f ", b[i][j]); printf("\n");
}
}

10
13. Scrieți un subprogram recursiv care rezolvă problema turnurilor din Hanoi.

Problema turnurilor din Hanoi este următoarea: se dau trei tije verticale (fie ele 1, 2, 3), și un n
discuri de diametre diferite, cu o gaură în centru, prin care poate trece o tijă. În situația inițială
toate discurile sînt introduse pe tija 1. Regulile sînt următoarele: a) un disc mai mare nu poate fi
pus peste un disc mai mic; la o mutare se poate muta un singur disc de pe o tijă pe alta. Situația
inițială respectă regula a), discurile fiind așezate în ordine descrescătoare a diametrelor, de la
bază spre vîrf. Se cere să se găsească o serie de mutări, prin care toate discurile să fie mutate pe
tija 3.

Problema poate fi descrisă recursiv astfel:


 se mută n-1 discuri de pe tija 1 pe tija 2,
 se mută discul n de pe tija 1 pe tija 3,
 se mută n-1 discuri de pe tija 2 pe tija 3.
La fiecare mutare se folosesc următorii parametri: numărul de discuri care se mută, tija inițială
(pe care se află discurile respective), tija finală (pe care trebuie duse discurile) și tija intermediară
(cealaltă tija, care poate fi folosită pentru manevre).

Subprogramul următor memorează mutările necesare într-o matrice cu două coloane, în care
fiecare linie descrie o mutare, elementul de pe prima coloană fiind tija sursă, cel de pe a doua
coloană este tija destinație. Această matrice și numărul de mutări (numărul de linii) constituie
parametri de intrare/ieșire la fiecare apel.

#define _CRT_SECURE_NO_WARNINGS
//I: n, tija initiala, tija finala, tija interm., rezultat, nr mutari
//E: rezultat, nr mutari
#include<stdio.h>

void turnuri_hanoi(int n, int ti, int tf, int tint, int rez[][2], int* nr)
{

11
if (n == 1)
{
rez[*nr][0] = ti;
rez[*nr][1] = tf;
(*nr)++;
}
else
{
turnuri_hanoi(n - 1, ti, tint, tf, rez, nr);
rez[*nr][0] = ti;
rez[*nr][1] = tf;
(*nr)++;
turnuri_hanoi(n - 1, tint, tf, ti, rez, nr);
}
}

void main()
{
int i, n, mutari[100][2], nrm;
printf("numarul de discuri="); scanf("%d", &n);
nrm = 0;
turnuri_hanoi(n, 1, 3, 2, mutari, &nrm);
for (i = 0; i < nrm; i++)
printf("%d, %d\n", mutari[i][0], mutari[i][1]);
}

12

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