3. Dr Mariem Abdouli
Algorithme récursif :
C’est un algorithme qui s’appelle lui-même
Tout algorithme récursif doit :
– avoir au moins un cas qui ne comporte pas d’appel récursif :
cas de base (ou condition d’arrêt) (par exemple lorsque le
tableau possède 0 éléments)
– définir les bons cas de base :
• ils doivent être atteignables quelque soit l’exemple en entrée
• (par exemple en s’assurant que le tableau dans l’appel récursif est plus
petit que celui en entrée)
Exemple : Le calcul de la factorielle de N.
N!= N*(N-1)*(N-2)*…*2*1 , on peut écrire ainsi N!=
N*(N-1)!
3
Complexité des algorithmes récursifs
4. Dr Mariem Abdouli 4
Complexité des algorithmes récursifs
1 Solution itérative
fonction fact(n : entier) :
entier
i, f : entier
f 1
pour i de 2 à n faire
f f *i
finpour
return f
fin
2 Solution récursive
fonction fact(n : entier) : entier
si (n=1) ou (n=0) alors
return 1
sinon
return n * fact(n-1)
finsi
fin
Cas de base
Appel récursif
Itératif vs récursif
5. Dr Mariem Abdouli 5
Complexité des algorithmes récursifs
Itératif vs récursif Fact(5) =5*fact(4)
=5*4*fact(3)
=5*4*3*fact(2)
=5*4*3*2*fact(1)
=5*4*3*2*1*fact(0)
Fact(5) =5*fact(4) 1
=5*4*fact(3) 2
=5*4*3*fact(2) 6
=5*4*3*2*fact(1) 24
=5*4*3*2*1*fact(0) 120
6. Dr Mariem Abdouli 6
Complexité des algorithmes récursifs
• L’exécution d’un appel récursif passe par deux phases :
– la phase de descente
– la phase de remontée
• Lors de la phase de descente, chaque appel récursif fait à son
tour un appel récursif
• En arrivant à la condition d’arrêt, on commence la phase de
remontée qui se poursuit jusqu’à ce que l’appel initial soit
terminé, ce qui termine le processus récursif
7. Dr Mariem Abdouli 7
Récursivité simple:
Prenons l’exemple de la fonction puissance: x n
L’algorithme correspondant est:
Fonction puissance (x,n)
debut
si (n=0) alors renvoyer 1
sinon renvoyer x*puissance (x, n-1)
fin
Cas de base
= condition d’arrêt
Appel récursif
Complexité des algorithmes récursifs
On distingue plusieurs types de récursivité
8. Dr Mariem Abdouli 8
Récursivité multiple:
Une fonction récursive peut contenir plus d’un appel récursif
Prenons l’exemple de calcul des combinaisons Cp
n en utilisant la relation de
Pascal
L’algorithme correspondant est:
Fonction combinaison (n,p)
Debut
si (p=0 ou p=n) alors renvoyer 1
sinon renvoyer combinaison (n-1, p) + combinaison (n-1,p-1)
fin
Complexité des algorithmes récursifs
Fonction combinaison(n : entier, p : entier) : entier
si (p=1) ou (p=n) alors return 1
sinon
return combinaison (n-1, p) +
combinaison(n-1, p-1)
finsi
fin
9. Dr Mariem Abdouli 9
Récursivité mutuelle:
Deux fonctions sont dites mutuellement récursives si elles dépends les unes des
autres
Prenons l’exemple de la définition de la parité:
Les algorithmes correspondants sont:
Fonction pair (n)
Debut
si (n=0) alors renvoyer vrai
sinon renvoyer impaire (n-1)
Fin
Fonction impair (n)
Debut
si (n=0) alors renvoyer faux
sinon renvoyer paire (n-1)
fin
Complexité des algorithmes récursifs
10. Dr Mariem Abdouli 10
Récursivité imbriquée:
Prenons l’exemple de la fonction d’Ackermann:
L’algorithme correspondant est:
Fonction Ackermann (m,n)
Debut
si (m=0) alors n+1
sinon si n=0 alors Ackermann (m-1,1)
sinon Ackermann(m-1, Ackermann (m, n-1))
Fin
Complexité des algorithmes récursifs
11. Dr Mariem Abdouli 11
Récursivité terminale - non terminale:
Principe de transformation d’un algorithme récursif non terminal à un algorithme
récursif terminal:
•Ajouter un paramètre qui stocke le résultat intermédiaire.
•Ce paramètre est appelé paramètre d’accumulation.
Complexité des algorithmes récursifs
Fonction somme-entier (n)
debut
Si n=0 Alors Retourner 0
Si non Retourner n +somme-entier(n-1)
Fin Si
fin
Fonction somme-entier (n, val)
debut
Si n=0 Alors Retourner val
Si non Retourner somme-entier(n-1, n+val)
Fin Si
fin
Algorithme récursif
non terminal
Algorithme récursif
terminal
12. Dr Mariem Abdouli 12
Complexité des algorithmes récursifs
• Avantages :
– théoriquement plus de nécessité de garder en mémoire la pile
d’appels récursifs
– ces programmes peuvent être écrits facilement de manière itérative
Comment transformer une récursivité non terminale ?
fonction fact(n : entier) : entier
si (n=1) ou (n=0) alors
return 1
sinon
return n * fact(n-1)
finsi
fin
fonction factoriel(n : entier, resultat : entier) : entier
si (n=1) alors
return resultat
sinon
return factoriel(n-1, resultat *n)
finsi
fin
13. Dr Mariem Abdouli 13
Calcule de la complexité : Les équations de récurrences
Le calcul de la complexité algorithmique d’un algorithme récursif se calcule par
l’utilisation de l’équation de récurrence:
Equation1: C(n) = a*C(n-b) + f(n)
Equation2: C(n) = a*C(n/b) + f(n)
•Avec pour chaque type un cas de base mentionné.
•L’équation 2 est utilisé dans les algorithmes utilisant le paradigme
« diviser pour régner ».
Complexité des algorithmes récursifs
14. Dr Mariem Abdouli 14
Exemple: La fonction factorielle
Fonction factorielle (n)
Debut
si (n=1) alors renvoyer 1 (o.l (test) : 1)
sinon renvoyer n*factorielle (n-1) (o.a (- et *) : 2)
fin si
Fin
Equation1 : Récursivité
C(n) = 1 ;n=1
C(n-1) + 3
Pour calculer la complexité C(n), il existe deux méthodes qui sont le calcul par
substitution et la calcul par somme d’équations.
Complexité des algorithmes récursifs
15. Dr Mariem Abdouli 15
On peut calculer la solution par substitution:
C(n) = 3 + C (n-1)
= 3 + [3 + C (n-2)]
= 3 + [3 + [3 + C (n-3)]]
…
= 3*(n-1) + C (n-(n-1)) pour i= n-1
= 3*(n-1) + C(1)
= 3* (n-1) +1
= 3*n-2
→ C(n) = 3n-2
→ C(n) = O(n)
Complexité des algorithmes récursifs
16. Dr Mariem Abdouli 16
On peut calculer la solution par somme d’équations:
C(n) = C (n-1) + 3
C (n-1)= C (n-2) + 3
C (n-2)= C (n-3) + 3
…..
C(2) = C(1) + 3
C(1) = 1
→ C(n) = 1 + 3 (n-1)
→ C(n) = 3n-2
→ C(n) = O(n)
Complexité des algorithmes récursifs
17. Dr Mariem Abdouli 17
Complexité des algorithmes récursifs
Déplacer n rondelles d’un piquet à
un autre avec la condition :
Tout au long des déplacements, on
ne met jamais une rondelle plus
grande sur une rondelle plus petite
Exemple 2 : Tour de Hanoï
Solution : fonction récursive
Déplacer n (>0) rondelles du piquet 1 au piquet 3 revient à :
• Déplacer n-1 rondelles (les plus petites) du piquet 1 au piquet 2
• Déplacer la rondelle la plus grande du piquet 2 au piquet 3
• Déplacer n-1 rondelles (les plus petites) du piquet 2 au piquet 3
C(n)= 2*C(n-1) +1 si n>0
0 si n=0
18. Dr Mariem Abdouli 18
Complexité des algorithmes récursifs
Exemple 2 : C(n)= 2*C(n-1) +1 si n>0
0 si n=0
• Pour calculer la solution générale de cette équation, on peut
procéder par substitution :
• 20* C(n) = 20* 2* C(n-1)+ 20* 1
21 * C(n-1) =2* 2* C(n-2)+ 21*1
22* C(n-2)= 22* 2* C(n-3)+ 22* 1
23* C(n-3) = 23* 2* C(n-4)+ 23* 1
…
2n-1* C(1)= 2n-2* 2* C(2)+ 2n-2* 1
2n- * C(0)= 2n-2 * 0
------------------------------------------
• C(n) = 2n-2 *0 +1* 𝑖
• 1
• n
19. Dr Mariem Abdouli 19
Exercice:
La suite FIBONACCI est la suivante:
Fib (1) = 1
Fib (2) = 1
Fib (n) = Fib (n-1) + Fib (n-2)
Proposer un algorithme itératif et un algorithme récursif qui permettent de
calculer Fib (n). Calculer leurs complexités.
Comparer les deux complexités, et comment expliquer vous cette différence
entre les deux complexités.
Solution :
Fonction fib-itératif(n)
entier fib1 = 1 , fib2 = 1 , S
Debut
si (n≤2) alors retourner 1
fin si
pour i de 3 à n faire
S = fib1 + fib2
fib1 = fib2
fib2= S
fin pour
retourner S
fin
C(n) = 2 + ∑i=3 (3) → Citératif(n) = O(n)
Complexité des algorithmes récursifs
20. Dr Mariem Abdouli 20
Fonction fib-récursif(n)
Debut
si (n≤2) alors retourner 1
si non retourner fib-récursif(n-1) + fib-récursif(n-2)
fin si
fin
C(n) = 1 pour n≤2
C(n-1) + C(n-2) + 3
Le nombre d'itérations pour un algorithme de taille (n-1) est supérieur au nombre
d'itérations pour un algorithme de taille (n-2)
C'est à dire : C(n-2) ≤ C(n-1)
Et puisque: C(n) = C(n-1) + C(n-2) + 3
Alors:
C (n) ≤ C(n-1) + C(n-1) + 3 → C(n) ≤ 2C(n-1) +3
Commençons le calcule de C(n) :
C(n) ≤ 2C(n-1) +3
C(n-1) ≤ 2C(n-2) +3
C(n-2) ≤ 2C(n-3) +3
...
C(2) ≤ 2C(1) +3
C(n) ≤ 2n-1 +3n → Crécursif(n) = O(2n)
Complexité des algorithmes récursifs
21. Dr Mariem Abdouli 21
Complexité des algorithmes récursifs
Fib (5) Fib (4)
Fib (6)
Fib (3) Fib (2)
Fib (3)
Fib (4) Fib (2)
Fib (1)
Fib (3)
Fib (1)
Fib (2)
Fib (1)
Fib (2)
Fib (2)
Nous remarquons que pour n = 6, le calcul de Fib(3) est réalisé 3 fois.
Ce ci explique la complexité très grande de l’algorithme récursif (O(2n)) par
rapport à l’algorithme itératif (O(n)), puisque plusieurs calculs se répètent.
Ce problème de calcul redondant sera résolu par l’utilisation de la
programmation dynamique, que nous allons la voir dans le chapitre suivant.
23. Dr Mariem Abdouli 23
Le principe du paradigme « diviser pour régner » :
Equation2 : Récursivité + Paradigme « Diviser pour régner »
Complexité des algorithmes récursifs
• Spécifier la solution du problème en fonction de la (ou des) solution(s) d’un (ou
de plusieurs) sous-problème(s) plus simple(s) à traiter de façon récursive
• Le paradigme "diviser pour régner " parcourt trois étapes à chaque appel
récursif à savoir :
– Diviser : le problème en un certain nombre de sous-problèmes de taille
moindre
– Régner : sur les sous-problèmes en les résolvant d’une façon récursive ou
directement si la taille d’un sous-problème est assez réduite
– Combiner : les solutions des sous-problèmes en une solution globale pour le
problème initial
24. Dr Mariem Abdouli 24
Equation2 : Récursivité + Paradigme « Diviser pour régner »
Complexité des algorithmes récursifs
25. Dr Mariem Abdouli 25
Equation2 : Récursivité + Paradigme « Diviser pour régner »
Complexité des algorithmes récursifs
26. Dr Mariem Abdouli 26
Equation2 : Récursivité + Paradigme « Diviser pour régner »
Complexité des algorithmes récursifs
• Le temps d’exécution d’un algorithme "diviser pour régner" se
décompose suivant les trois étapes du paradigme de base
– Diviser : le problème en a sous-problèmes chacun de taille 1/b de la
taille du problème initial. Soit D(n) le temps nécessaire à la division du
problèmes en sous-problèmes
– Régner : soit a*C(n/b) le temps de résolution des a sous-problèmes
– Combiner : soit Comb(n) le temps nécessaire pour construire la
solution finale à partir des solutions aux sous-problèmes
• Finalement le temps d’exécution global de l’algorithme est :
C(n) = a*C(n/b) +D(n) + Comb(n)
• Soit la fonction f(n) qui regroupe D(n) et Comb(n).
• C(n) est alors définie :
C(n) = a*C(n/b) + f(n)
27. Dr Mariem Abdouli 27
Equation2 : Récursivité + Paradigme « Diviser pour régner »
Complexité des algorithmes récursifs
• Le "théorème général" permet de connaître le
comportement asymptotique des équations
de récurrence qui s’écrivent sous la forme
suivante :
C(n) = a*C(n/b) + f(n)
• Pour l’utiliser il faut définir le comportement
asymptotique de la fonction f(n) par rapport à
a
28. Dr Mariem Abdouli 28
Equation2 : Récursivité + Paradigme « Diviser pour régner »
Complexité des algorithmes récursifs
29. Dr Mariem Abdouli 29
Complexité des algorithmes récursifs
Fonction recherche_binaire(L : entier, inf : entier, sup : entier, x : entier) : booléen
si (inf <= sup) alors
mil (inf + sup)div 2
si (x = L[mil]) alors return vrai
sinon
si (L[mil] > x) alors
return recherche_binaire(L, inf, mil, x)
sinon
return recherche_binaire(L, mil+1, sup, x)
finsi
finsi
sinon return faux
fin
C(n)
C(n/2)
C(n) = C(n/2) + c
Equation2 : Récursivité + Paradigme « Diviser pour régner »
Recherche dichotomique (Binaire)
30. Dr Mariem Abdouli 30
Complexité des algorithmes récursifs
Fonction Tri_fusion (T, debut, fin) : tableau entier
milieu : entier
si (debut ≥ fin) alors
retourner T[max(debut, fin)]
sinon
milieu (debut + fin) div 2
Tri_fusion(T, debut, milieu)
Tri_fusion(T, milieu+1, fin)
Retourner Fusionner(T, debut, milieu, fin)
finsi
fin
Equation2 : Récursivité + Paradigme « Diviser pour régner »
Tri fusion
C(n)
C(n/2)
C(n/2)
O(n) = c*n
C(n) = 2C(n/2) + C*n
31. Dr Mariem Abdouli 31
Complexité des algorithmes récursifs
Equation2 : Récursivité + Paradigme « Diviser pour régner »
Tri fusion
C(n) = 2C(n/2) + C*n
Selon l’équation 2 de récurrence :
C(n) = aC(n/b) + O(nk)
Nous avons:
a = 2
b = 2
K = 1
→ a = bk
→ C(n) = O(n*log2(n))