Aller au contenu

Récursivité

Vous ne pouvez pas comprendre la récursivité sans avoir d’abord compris la récursivité.

Récursivité : notion et exemples.

Quelques exemples

img img img

Toutes ces images ont un point commun : on dit qu'elles sont autoréférentes : on trouve dans l'image une référence à l'image elle-même.

Un procédé (au sens large) est dit récursif lorsqu'il possède la propriété de faire référence à lui-même à un moment donné lors de la description de ce procédé.

Certains objets de la vie courante peuvent être définis de manière récursive :

  • lors d'une mise en abîme
  • dans un arbre généalogique

Application aux algorithmes

Toute fonction calculable (au sens intuitif) est récursive (au sens large).

Énoncé du problème. Pour tout entier nNn\in \mathbb{N}^{*}, on définit le problème P(n)\mathcal{P}(n) suivant :

« Calculer la somme des nn premiers entiers : S=1+2+3++nS = 1 + 2 + 3 + \ldots + n »

  • Méthode 1. Il est possible d'écrire une fonction python itérative (avec une boucle), qui prenne en entrée un entier n et qui renvoie l'entier S associé :

    1
    2
    3
    4
    5
    6
    def somme(n):
        """ int -> int"""
        S = 0
        for i in range(1, n + 1):
            S = S + i
        return S
    
  • Méthode 2. Il est possible d'écrire une fonction python récursive (faisant référence à elle-même), qui prenne en entrée un entier n et qui renvoie l'entier S associé :

    1. On sait résoudre le problème dans le cas où n=1n = 1. Dans ce cas la solution est S=1S = 1.

    2. Dans le cas général, on veut résoudre le problème de difficulté nn, c'est à dire P(n):\mathcal{P}(n) : « Calculer la somme des nn premiers entiers : S=1+2+3++nS = 1 + 2 + 3 + \ldots + n ».

      1. On suppose que l'on connait la réponse SS' au problème de difficulté n1n - 1. On connait donc S=1+2+3++n1S' = 1 + 2 + 3 + \ldots + n - 1.

      2. À l'aide de SS', on construit SS la solution au problème P(n)\mathcal{P}(n). Il suffit de remarquer que : S=1+2+3++(n1)+n=S+nS = 1 + 2 + 3 + \ldots + (n - 1) + n = S' + n

    3. On aboutit donc au code python ci-dessous :

      1
      2
      3
      4
      5
      6
      7
      8
      def somme(n):
          # Cas de base:
          if n == 1:
              return 1
          # Cas général
          else:
              Sp = somme(n - 1) # appel dit récursif
              return Sp + n
      

Remarque. On peut faire le lien avec la définition par récurrence de la suite un=somme(n)u_n = \text{somme}(n), définie pour tout n1n \geq 1 par :

un={1si n=1un1+nsinon. u_{n} = \begin{cases} 1&\text{si } n = 1\\ u_{n - 1} + n &\text{sinon.} \end{cases}

On considère un problème à résoudre, qui dépend d'un certain paramètre nNn \in \mathbb{N}, que l'on appelle le rang (la "difficulté") du problème.

Pour écrire un algorithme de manière récursive, la méthode générale est la suivante :

  • Identifier le cas de base. Il s'agit de trouver dans quel cas la résolution du problème est "simple" (souvent n=0n = 0 ou 11)
  • Résoudre le problème de manière récursive.
    • On suppose connue la solution des problèmes de rang strictement inférieur à nn.
    • On construit la solution du problème de rang nn à l'aide de la solution d'un problème de rang inférieur.

Récursivité : première application

  1. (un)(u_n) est une suite arithmétique de raison 55 et de premier terme u0=2u_0 = 2. Écrire une fonction python récursive u qui étant donné un entier nn calcule unu_n.

    1
    2
    3
    4
    5
    6
    7
    8
    def u_n(n):
        """ int -> int """
        # Cas de base
        if n <= 0:
            return 2
        else:
            avant = u(n - 1) # appel récursif
            return 5 + avant
    
  2. (vn)(v_n) est une suite géométrique de raison 2-2 et de premier terme v0=8v_0 = 8. Écrire une fonction python récursive v qui étant donné un entier nn calcule vnv_n.

    1
    2
    3
    4
    5
    6
    7
    8
    def v(n):
        """ int -> int """
        # Cas de base
        if n <= 0:
            return 8
        else:
            avant = v(n - 1) # appel récursif
            return -2*avant