Vous êtes sur la page 1sur 3

CHAPITRE 2 – RÉCURSIVITÉ

I – Fonction récursive

Une fonction est dite récursive si elle s’appelle elle-même.


Une fonction récursive est toujours constitué d’un (ou plusieurs) cas de base et d’un appel récursif
(simple ou multiple).

Exemple : On rappelle la définition de la factorielle de n, notée n!


n !=n×(n−1)×(n−2)×...×3×2×1
On peut définir par récurrence n! pour n ≥ 1 :

{
n !=n×(n−1) ! si n>1
1 !=1 si n=1
Ce qui donne une fonction récursive fact(n) (codé ici en Python) :
fact(n) :
if n == 1 : cas de base
return 1
else :
return n*fact(n-1) appel récursif

L’appel de fact(4) donne :

fact(4) = 4 * fact(3)

3 * fact(2)

2 * fact(1)

D’où, en remontant : fact(4) = 4 * 3 * 2 * 1


= 4 * 3 * 2
= 4 * 6
= 24

On peut également avoir des fonctions avec plusieurs appels récursifs, comme la suite de Fibonacci
(double récursivité), avec n ≥ 0 :

{
fibo(n)=fibo(n−1)+ fibo(n−2) si n>1
fibo(1)=1 si n=1
fibo(0)=0 si n=0

1
II – Diviser pour régner

Diviser pour régner (Divide and Conquer) est une technique algorithmique consistant à :

Diviser : découper un problème initial en sous-problèmes ;


Régner : résoudre les sous-problèmes (récursivement ou directement s'ils sont assez petits) ;
Combiner : calculer une solution au problème initial à partir des solutions des sous-problèmes.

Cette technique fournit des algorithmes efficaces pour de nombreux problèmes, comme la recherche
d'un élément dans un tableau trié (recherche dichotomique), le tri (tri fusion, tri rapide), la
multiplication de grands nombres (algorithme de Karatsuba) ou l’exponentiation rapide.

Exemples : i) Recherche dichotomique (du grec dikhotomia : « division en deux parties »)

L est une liste de nombres triée (en ordre croissant) ;


elem un élément qui appartient à cette liste.

def dicho(elem, L):


"""
On recherche l’élément elem dans la liste L
et on renvoie son indice.
"""
if len(L)==1:
return 0
else:
m = len(L)//2
# si la valeur est égale à l’élément, on retourne
# sa position
if L[m] == elem:
return m
# si la valeur est plus grande que l’élément, on
# cherche dans la partie de gauche de la liste
elif L[m] > elem:
return dicho(elem,L[:m])
# sinon dans la partie de droite de la liste
else:
return m + dicho(elem,L[m:])

ii) Exponentiation rapide


Si n est pair alors x n=(x 2 )n/ 2 et si n est impair, alors x n=x⋅(x 2)(n−1)/ 2 .
def exp_rapide(x,n):
if n == 0:
return 1
else:
if n%2 == 0:
return exp_rapide(x*x,n//2)
else:
return x*exp_rapide(x*x,(n-1)//2)

2
III – Exemples de récursivité

A] Maximum d’un tableau de nombres


Pour parcourir le tableau, à l’instar d’un algorithme itératif, et garder en mémoire le maximum
temporaire, on est obligé de rajouter un argument (ici m).

def maximum(L,m):
if L == []:
return m
else
if L[0] > m:
return maximum(L[1:],L[0])
else:
return maximum(L[1:],m)

Exemple : >>> L = [4,2,5,3]


>>> maximum(L,L[0]) # on initialise avec m = L[0]
5

B] Tri fusion
Le tri fusion est un algorithme de type Diviser pour Régner :
1 – Diviser : on divise notre tableau en tableaux 2 fois plus petits ;
2 – Régner : on trie chacun des tableaux récursivement ;
3 – Fusion : on fusionne les tableaux triés obtenus par récursivité.

def tri_fusion(L):
if len(L) == 1:
return L
else:
m = len(L)//2
Lg = tri_fusion(L[:m])
Ld = tri_fusion(L[m:])
return fusion(Lg,Ld)

def fusion(L1,L2):
R = []
while L1 != [] and L2 != [] :
if L1[0] < L2[0]: # L.pop(0) renvoie le
R.append(L1.pop(0)) # premier élément de L
else: # et le supprime
R.append(L2.pop(0))
R += L1 + L2 # on concatène à R
return R # L1 et L2 (l’une des
# deux étant vide)

Exemple : >>> L = [4,2,5,3]


>>> tri_fusion(L)
[2,3,4,5]

Vous aimerez peut-être aussi