Vous êtes sur la page 1sur 6

Chapitre 7 : Récursivité

Objectif général
Résoudre des problèmes définis récursivement.

I. Notion de récursivité
I.1 Définition
La récursivité est un concept très puissant si on arrive à décomposer un problème en un ou plusieurs
sous-problèmes qui sont de même nature. Il est de même quand on décompose un objet en groupes
de composants qui présentent les mêmes propriétés et qui ne contiennent qu'un sous-ensemble de
l'objet. Une notion est dite récursive si elle, entre, elle même dans sa composition ou dans sa
définition.
Exemples
 « Mon ascendant est mon père, ma mère ou un de leurs ascendants »
 De même, un algorithme est dit récursif s’il fait appel à lui-même. Ainsi, la fonction factorielle :
n! = (n-1)! * n
Cette expression ne fait que déplacer le problème de l’ordre n à l’ordre n-1, sans le résoudre. Par
bonheur, en faisant ainsi décroître l’ordre, on parvient à une relation sans indétermination : 1! = 1
(ou éventuellement (0 ! = 1). Grâce à cette propriété, le traitement récursif de la factorielle n’est pas
un cercle vicieux. Son algorithme s’écrit :

« Algorithme Récursif » « Algorithme Itératif »


Factorielle (Don n : Entier) : Entier Fonction Factorielle (Don n : Entier) : Entier
--Précond : n 0 --Précond : n 0
Début Variable
Si (n  1) Resultat : Entier
Alors Début
Factorielle  1 Resultat  1
Fonction Sinon Pour i de 1 à n Faire
Factorielle  n * Factorielle (n-1) Resultat  Resultat * i
FinSi FinPour
Fin Factorielle  Résultat
Fin

 Les entiers naturels sont définis d’une manière récursive par deux règles :
 0 est un entier naturel.
 Le successeur d'un entier naturel est un entier naturel.
 La définition récurrente des suites mathématiques :
 U0 = 1
 Un = aUn-1 + b
 Les chaînes de caractères sont définies récursivement -Une chaîne de caractères est soit :
 Une chaîne vide, soit,
 Un caractère suivi d'une chaîne.

Hind Elouedi Page 1


Chapitre 7 : Récursivité

I.2. types de récursivité


Il existe deux types de récursivité :
 La récursivité des objets : Entiers naturels, chaînes de caractères,...
 La récursivité des traitements ou des actions : Factorielle, suites,...
Au niveau de ce chapitre, on s’intéressera à la récursivité des actions, elle se base sur l'utilisation de
la notion de module (procédures et fonctions). Il existe deux types de récursivité des actions :
 Récursivité directe : Une action est directement récursive si son corps présente un ou plusieurs
appels à l'action elle-même.
 Récursivité indirecte : Une action est indirectement récursive si son exécution peut entraîner
indirectement un ou plusieurs appels à l'action elle-même.
I.3. notions de base
Exemple
Reprenons l’exemple de la fonction Factorielle, on a : n ! = n * (n-1) !.
On peut remarquer que, dans le cas de la récursivité, il est nécessaire de conserver en mémoire les
expressions intermédiaires non résolues dans ce qu’on appelle une pile. Une fois parvenue à la
propriété 1! = 1, ces expressions seront dépilées et résolues.

Analysons la pile en appelant Factorielle (3) :

n=1
n=2 n=2 n=2
n=3 n=3 n=3 n=3 n=3
Etat initial (a) (b) (c) (d) (e) Etat final

(a) Premier appel de Factorielle (3), on affecte au paramètre n la valeur 3. Comme (n > 1) on calcule
n * Factorielle (n-1) : n = 3, n-1 = 2 on appelle alors Factorielle (2)
(b) Deuxième appel, n prend la valeur 2, n >1, on appelle Factorielle (1)
(c) Troisième appel, on affecte à n la valeur 1, la condition (n>1) n’est plus vérifiée, donc on quitte
la fonction, on libère la pile de son sommet, on retourne où la fonction Factorielle (1) a été
appelée en retournant la valeur 1.
(d) on peut maintenant calculer n * Factorielle (1), n (sommet de la pile) vaut 2, Factorielle (1) vaut
1, on peut retourner 2, puis on dépile n.
(e) on peut calculer n * Factorielle (2), n vaut 3 (sommet de la pile), Factorielle (2) vaut 2, 3 * 2 = 6,
on retourne 6, la pile est vidée et retrouve son état initial.
 Notion d'environnement : Il est formé par l'ensemble de données (variables et paramètres)
utilisées par un module lors d'une exécution. Chaque fois que le module est appelé
récursivement, un nouvel environnement est généré, un nouvel ensemble de variables locales et
de paramètres est créé. Bien qu'elles portent le même nom que celles créées à l'appel précédent,
leurs valeurs sont différentes et on utilise toujours le dernier jeu de variables créé. Cet
environnement est détruit lorsque l'exécution prend fin.
Si un module appelle un autre module sans que son exécution ne soit terminée, l'environnement
du premier est suspendu et il sera réactivé lorsque l'exécution du second sera terminée.
L’ensemble des environnements existant pour une exécution (suspendus ou actif) forme ce qu’on
appelle une pile d’environnement.

Hind Elouedi Page 2


Chapitre 7 : Récursivité

 Terminaison : Les traitements engendrés par une définition récursive doivent être finis pour que
le calcul puisse se terminer. Tout appel récursif doit donc contenir une clause conditionnelle telle
que l'évaluation puisse dans certains cas se faire sans récursivité. Dans le cas de la fonction
Factorielle(n), la condition d’arrêt est : n ≤ 1.

 Valeur d'arrêt : C'est la valeur pour laquelle les appels récursifs s'arrêtent. Pour le cas de
Factorielle (n), la valeur d'arrêt est n = 1.

 Profondeur : Dans la plupart des cas, la récursivité est appliquée à une valeur entière qui diminue
d'une unité à chaque exécution. Dans ce cas, si on considère fi cette valeur lors du premier appel
et ft cette même valeur à la terminaison, on dit que la récursivité est de profondeur (fi – ft).
La profondeur indique le nombre de niveaux de récursivité, c’est à dire le nombre
d’environnements qui peuvent être suspendus en même temps. Par exemple, pour la fonction
Factorielle (3), la profondeur est égale à 2.

II. Itération ou récursivité ?


Une solution récursive est généralement plus lente en exécution et plus coûteuse en mémoire qu’une
solution itérative. Cependant, elle est souvent plus facile à concevoir, et plus élégante d’un point de
vue logique et formel, comme par exemple pour le calcul d'une factorielle.
Si le temps de calcul ou la mémoire utilisée sont prohibitifs pour de grands nombres de données, il
est toujours possible de traduire un algorithme récursif en itératif.
Généralement, la solution récursive doit être écartée au profit d’une solution itérative dans les cas
suivants :
 Si la solution itérative est évidente.
 Si la profondeur de la récursivité ne peut pas être limitée.
 Si l’exécution récursive entraîne des répétitions de traitement qu’une exécution itérative permet
d’éviter.
La solution récursive est retenue dans les cas suivants :
 Quand l'énoncé du problème ou la structure de données utilisée est récursif.
 Quand il n'y a pas de solution itérative évidente ou meilleure.

II.1. Redondance des traitements


Dans ce cas, la solution itérative sera retenue bien que la solution récursive soit évidente. Voici dans
ce qui suit un exemple.

Exemple :
La suite de Fibbonacci est définie comme suit pour tout n  0 :
F(0) = 0, F(1) = 1
F(n) = F(n-2) + F(n-1) pour n >1

Son algorithme s’écrit :


Fonction Fibo (Don n : Entier) : Entier
Début
Si (n = 0 Ou n =1)
Alors Fibo  n
Sinon Fibo  Fibo (n-2) + Fibo(n-1)
FinSi
Fin

Hind Elouedi Page 3


Chapitre 7 : Récursivité

Figure 7.1 : Arbre d’exécution (Trace) de la fonction Fibo (4)

Pour éviter la redondance de traitements, on peut envisager l’écriture de la version itérative de la


fonction Fibo :

Fonction Fibo (Don n : Entier) : Entier


Variable
i, x, y, z : Entier
Début
Si (n = 0 Ou n =1)
Alors Fibo  n
Sinon
x0 y1 i2
TantQue (i  n) Faire
zx+y
xy
yz
ii+1
FinTantQue
Fibo  z
FinSi
Fin

II.2. Solution itérative non évidente


Dans ce cas, la solution itérative n’est pas évidente, alors que l’action est définie récursivement.

Exemple
Soit la fonction d'Ackermann définie pour tous les entiers positifs m et n de la manière suivante :
 Acker (0,n) = n + 1
 Acker (m,0) = Acker (m-1,1) pour m  1
 Acker (m,n) = Acker(m-1, Acker (m,n-1)) pour m  1 et n  1

Hind Elouedi Page 4


Chapitre 7 : Récursivité

Fonction Acker (Don m : Entier, Don n : Entier) : Entier


Début
Si (m = 0)
Alors Acker  n + 1
Sinon Si (n = 0)
Alors Acker  Acker (m-1,1)
Sinon Acker  Acker (m-1, Acker (m, n-1))
FinSi
FinSi
Fin

II.3. Définition d’algorithmes récursifs


La définition des algorithmes récursifs comporte trois étapes :
 Etape 1 : Paramétrage du problème :
 On doit faire apparaître tous les paramètres dont la solution dépend.
 On doit définir la taille du problème à résoudre qui doit décroître à chaque appel récursif.
 Etape 2 : Recherche d'un cas trivial ainsi que sa solution : C'est l'étape clé de l'algorithme.
 Etape 3 : Décomposition du cas général : Le but est de ramener le problème à un ou plusieurs
problèmes de taille inférieure.
III. Jeu des tours de Hanoï
III.1. Définition du problème
L’exemple le plus classique pour illustrer la méthode récursive est celui des Tours de Hanoï :
N disques sont empilés par ordre de diamètre décroissant (tous les disques sont de diamètres
différents) sur un piquet A. Deux autres piquets B et C peuvent recevoir des disques, à condition que
ceux-ci soient toujours empilés selon la même règle du diamètre décroissant. Le but du jeu est de
transporter les N disques du piquet A au piquet C, en utilisant éventuellement le piquet B, tout en
respectant les deux règles suivantes :
 Ne déplacer qu’un seul disque à la fois.
 Ne placer un disque que sur un disque de diamètre supérieur, ou un piquet libre.
III.2. Démarche récursive
 Paramétrage du problème
 N : nombre de disques
 A, B, C : les piquets (départ, intermédiaire et arrivée).
 Recherche de la valeur d’arrêt
Si (N = 1) Alors « Déplacer un disque de A vers C » : Déplacer (A, C)
 Décomposition du cas général
Résoudre le problème pour N disques ne présente pas de difficulté si on sait le résoudre pour (N-1)
disques ; en effet, transporter les N disques du piquet A au piquet C, c’est :
 Transporter les (N-1) premiers disques de A vers B (C piquet intermédiaire), puis
 Déplacer le disque restant de A vers C, et enfin,
 Transporter les (N-1) disques de B vers C (A piquet intermédiaire).

Hind Elouedi Page 5


Chapitre 7 : Récursivité

III.3. Algorithme
La solution algorithmique est sous forme d’une procédure qui se présente comme suit :
Procédure Hanoi (Don n : Entier ; Don A : Chaîne, Don B : Chaîne, Don C : Chaîne)
--Précond : n  1
Début
Si (n = 1) Alors
Ecrire ("Déplacer un disque de ", A, " vers ", C)
Sinon
Hanoi (n-1, A, C, B)
Ecrire ("Déplacer un disque de ", A, " vers ", C)
Hanoi (n-1, B, A, C)
FinSi
Fin
Dans ce qui suit, voici un exemple d’exécution de cette procédure pour :
Hanoi (3, "Piquet A", "Piquet B", "Piquet C")

Figure 7.2 : Tours de Hanoi : Hanoi (3, A, B ,C)

Le nombre de déplacements est une fonction du nombre de disques, en effet :


 Si n = 0  nombre de déplacements = 0
 Si n = 1  nombre de déplacements = 1
 Si n = 2  nombre de déplacements = 3
 Si n = 3  nombre de déplacements = 7
 Si n = 5  nombre de déplacements = 31
 Si n = 8  nombre de déplacements = 255
 ...
  n  1  nombre de déplacements = 2n - 1

Hind Elouedi Page 6

Vous aimerez peut-être aussi