Vous êtes sur la page 1sur 4

ALGORITHMIQUE ET LANGAGE C – L1S2–MPI TD 8 – GROUPE D1

ROSELINE DESCOUT-RENIER JEUDI 27 MARS 2014

Objectifs de la séance : Algorithmes récursifs et arbres d’exécution récursive ;


Maîtrise des conditions d’arrêt des fonctions récursives.

Exercices étudiés pendant la séance : 1 – 2 – 3 TD6.

Exercice 1 : Recherche à la main des premières valeurs :


Fib(0) = 0 Fib(1) = 1 valeurs données dans l’énoncé
Fib(2) = 0 + 1 = 1 Fib(3) = 1 + 1 = 2 Fib(4) = 2 + 1 = 3 Fib(5) = 3 + 2 = 5
Fib(6) = 5 + 3 = 8 Fib(7) = 8 + 5 = 13 Fib(8) = 13 + 8 = 21

1. Arbre d’exécution récursive pour Fib(6) :


Fib(6)

Fib(5) Fib(4)

Fib(4) Fib(3) Fib(3) Fib(2)

Fib(3) Fib(2) Fib(2) Fib(1) Fib(2) Fib(1) Fib(1) Fib(0)

Fib(2) Fib(1) Fib(1) Fib(0) Fib(1) Fib(0) 1 Fib(1) Fib(0) 1 1 0

Fib(1) Fib(0) 1 1 0 1 0 1 0

1 0

2. Programme :
Pseudo-code : Code en C :
#include <stdio.h>

/* Prototype de la fonction récursive */


int fib(int n);
Programme principal :
Début int main(void) {
entier n, fibo ; int n, fibo;
écrire “ Entrer un nombre entier positif ou nul ” ; printf("\nEntrer un nombre entier positif ou nul :");
lire n ; scanf("%d", &n);

fibo ← fib(n) ; fibo = fib(n);

écrire “ Le résultat de la suite de Fibonacci pour ” n printf("\nLe résultat de la suite de Fibonacci pour %d
“ est ” fibo. est %d.\n", n, fibo);
return 0;
Fin }

Fonction Fibo (entier n) /* Déclaration de la fonction récursive */


Début int fib(int n) {
si n = 0 faire if (n == 0) {
retourner 0 ; return 0;
}
sinon si n = 1 faire else if (n == 1) {
retourner 1 ; return 1;
}
sinon faire else {
retourner Fibo(n-1) + Fibo(n-2) ; return fib(n-1) + fib(n-2);
finsi }
Fin }
Remarques :
• Une fonction récursive est avant tout une fonction : le prototype, la déclaration et l’appel de la fonction se
font de la même manière que pour une fonction “ simple ”.
• Éviter les déclarations de variable locale dans la fonction récursive (celle que la fonction retournerait, par
exemple). À chaque appel de la fonction, une nouvelle variable locale serait déclarée, et un nouvel espace
mémoire serait alloué. Comme on ne maîtrise pas le nombre d’appels de la fonction, la quantité d’espace
mémoire utilisé par une fonction récursive peut rapidement devenir ingérable.

Exercice 2 :
Recherche à la main des premières valeurs :
somme(0) = 02 = 0 somme(1) = 02 + 12 = 1
somme(2) = 02 + 12 + 22 = 5
= somme(1) + 22
somme(3) = 02 + 12 + 22 + 32 = 14
= somme(2) + 32
somme(4) = 02 + 12 + 22 + 32 + 42 = 30
= somme(3) + 42
somme(n) = somme(n-1) + n2

Pseudo-code : Code en C :
#include <stdio.h>

int sommeCarres(int n);


Programme principal :
Début int main(void) {
entier n, somme ; int n, somme;
écrire “ Entrer un nombre entier positif ou nul ” ; printf("\nEntrer un nombre entier positif ou nul :");
lire n ; scanf("%d", &n);

somme ← sommeCarres(n) ; somme = sommeCarres(n);

écrire “ Le résultat de la somme des carrés de 0 à ” n printf("\nLe résultat de la somme des carrés pour %d
“ est ” somme. est %d.\n", n, somme);

Fin return 0;
}
Fonction sommeCarres (entier n)
Début int sommeCarres(int n) {
si n = 0 faire if (n == 0) {
retourner 0 ; return 0;
}
sinon faire else {
retourner sommeCarres(n-1) + n*n ; return sommeCarres(n-1) + n*n;
finsi }
Fin }
Exercice 3 – division :
Recherche de l’algorithme :
On veut diviser a = 43 par b = 10 : le quotient doit valoir 4 et le reste 3.
43 – 10 = 33 compteur = 0
→ 33 – 10 = 23 compteur = 1
→ 23 – 10 = 13 compteur = 2
→ 13 – 10 = 3 compteur = 3
Le reste est le résultat d’un certain nombre de soustraction de b à a.
Le quotient est le nombre de soustractions nécessaires pour obtenir le reste (compteur à incrémenter à chaque appel
de la fonction).

Ce raisonnement fonction si a est supérieur à b. Si on veut diviser a = 10 par b = 43, le quotient vaut 0 et le reste
vaut 10 (soit la valeur de a).

Pseudo-code : Code en C :
#include <stdio.h>

int resteDivisionEntiereRecursive(int a, int b);


int quotientDivisionEntiereRecursive(int a, int b);
Programme principal :
Début int main(void) {
entier a, b ; int a, b;
écrire “ Entrer un nombre entier >= 0 ” ; printf("\nEntrer un nombre entier positif ou nul :");
lire a ; scanf("%d", &a);
écrire “ Entrer un autre entier >=0 ” ; printf("\nEntrer un autre nombre entier positif ou nul :");
lire b ; scanf("%d", &b);

entier reste = fonctionReste(a, b) ; int reste = resteDivisionEntiereRecursive(a, b);


écrire “ Le reste vaut ” reste ; printf("\nLe reste de %d par %d est %d.\n", a, b, reste);

entier quotient = fonctionQuotient(a, b) ; int quotient = quotientDivisionEntiereRecursive(a, b);


écrire “ Le quotient vaut ” quotient ; printf("\nLe quotient de %d par %d est %d.\n", a, b, quotient);

Fin return 0;
}
Fonction fonctionReste(entier a, entier b)
Début int resteDivisionEntiereRecursive(int a, int b) {
si a < b faire if (a < b) {
retourner a ; return a;
}
sinon faire else {
retourner fonctionReste(a-b, b) ; return resteDivisionEntiereRecursive(a - b, b);
finsi }
Fin }
Fonction fonctionQuotient(entier a, entier b)
Début int quotientDivisionEntiereRecursive(int a, int b) {
si a < b faire if (a < b) {
retourner 0 ; return 0;
}
sinon faire else {
retourner fonctionQuotient(a-b, b) + 1 ; return quotientDivisionEntiereRecursive(a - b, b) + 1;
finsi }
Fin }

Remarques :
• La fonction calculant le reste de la division entière est une récursivité terminale, puisque la dernière
opération de la fonction récursive est l’appel de cette même fonction.
• La fonction calculant le quotient de la division entière est une récursivité non terminale, puisqu’il y a
d’autres opérations après l’appel de la fonction récursive.
Exercice 3 – multiplication :
Recherche de l’algorithme :
On veut multiplier a = 3 par b = 4 :
somme = 0 compteur = 0
somme = somme + 3 compteur = 1
somme = somme + 3 compteur = 2
somme = somme + 3 compteur = 3
somme = somme + 3 compteur = 4

Il faut donc additionner b fois le nombre a.


Autrement dit, la fonction somme s’obtient en ajoutant a à la fonction somme obtenue précédemment, pour laquelle
les paramètres valaient a et b – 1, et ce jusqu’à ce que le deuxième paramètre soit nul.
La condition d’arrêt de la fonction récursive est la nullité du deuxième terme.
Remarque : si a = 0, le résultat vaut 0. On peut donc économiser les b appels de la fonction (qui vont tous calculer
0 + 0) en ajoutant immédiatement cette condition d’arrêt.

Pseudo-code : Code en C :
#include <stdio.h>

int multiplication(int a, int b);


Programme principal :
Début int main(void) {
entier a, b ; int a, b;
écrire “ Entrer un nombre entier >= 0 ” : printf("\nEntrer un nombre entier positif ou nul :");
lire a ; scanf("%d", &a);
écrire “ Entrer un autre nombre entier >= 0 ” ; printf("\nEntrer un autre nombre entier positif ou nul :");
lire b ; scanf("%d", &b);

entier multiple = multiplication(a, b) ; int multiple = multiplication(a, b);

écrire “ Le résultat vaut ” multiple ; printf("\nLe résultat de la multiplication de %d par %d est


%d.\n", a, b, multiple);

Fin return 0;
}
Fonction multiplication(entier a, entier b)
Début int multiplication(int a, int b) {
si a = 0 ou b = 0 faire if (a == 0 || b == 0) {
retourner 0 ; return 0;
}
sinon faire else {
retourner multiplication(a, b-1) + a ; return multiplication(a, b - 1) + a;
finsi }
Fin }

Vous aimerez peut-être aussi