Fonctionnement d’un programme récursif

icône de pdf
Signaler

Les fonctions récursives permettent de simplifier l’écriture de nombreux problèmes. Nous présentons ici leur fonctionnement et une méthodologie d’écriture et d’analyse de ces fonctions.

I. Introduction à la récursivité

Une fonction récursive est une fonction qui s’appelle elle-même. Voici un premier exemple classique.

f3bb1972-28b1-48a3-ad4b-eb04aeeb8da7

Cette fonction implémente simplement une façon (récursive) de définir la puissance d’un nombre a≠0 : a0=1 et an=a×an−1.

On remarque que la fonction commence par une condition d’arrêt qui traite le cas de base. Pour étudier le fonctionnement interne de cette fonction, on peut réécrire la fonction précédente :

Mot-clé

Un cas de base est une valeur de l’argument pour laquelle le problème se résout immédiatement.

e47d7081-1d5b-412f-b624-471b2024281f

II. Pile d’exécution

Lors de l’appel d’une fonction récursive, une structure de pile est utilisée en interne ( pour une présentation plus détaillée des piles en informatique).

Une pile fonctionne comme un empilement d’objets (l’image d’une pile d’assiettes est adaptée) : on peut empiler un objet en haut de la pile et enlever le sommet de la pile (on dit dépiler), mais on ne peut pas accéder à un objet qui n’est pas en haut de la pile.

La pile utilisée, appelée pile d’exécution, est de taille limitée. Au-delà d’un certain nombre d’appels récursifs, 1 000 par défaut en Python, il y a une erreur de dépassement de la taille de la pile (stack overflow). Cette pile contient une trace de tous les appels de fonction qui ne se sont pas encore terminés.

Concrètement, un appel récursif à expo(2, 3) donne, de manière très simplifiée :

783932e9-7cd4-444b-ad08-f5c63fa29b92

Évolution de la pile d’exécution, puis dépilement pour évaluer :

8af6b5f3-fb3c-4443-b284-e96b6a50825c

III. Écriture d’une fonction récursive

Une fonction récursive simple s’écrit sous la forme :

f6eccaba-53e2-4e4e-85a2-1bb96ab2f002

Pour écrire une fonction récursive on :

− détermine le type de données à renvoyer ;

− détermine pour quelle(s) valeur(s) de l’argument le problème est résolu et on écrit la condition d’arrêt ;

− détermine de quelle manière la taille du problème est réduite (argument entier qui décroît strictement, liste dont la taille diminue, etc.) ;

− écrit l’appel récursif en prenant garde à ce que le type de données qu’il renvoie soit cohérent avec celui renvoyé par la condition d’arrêt.

IV. Étude de la complexité d’une fonction récursive

On note Tn le nombre d’opérations nécessaires pour évaluer une fonction récursive sur un problème de taille n. Pour évaluer Tn on cherche une relation de récurrence impliquant Tn, puis on résout la relation de récurrence.

Exemple : nombre d’opérations pour le calcul de la puissance d’un nombre. On a T0=1 et Tn+1=Tn+1. On reconnaît une suite arithmétique, d’où Tn=n+1.

Voici quelques complexités classiques :

adf60f98-3b52-41b9-b1d3-d670980928d6