web-dev-qa-db-fra.com

Tous les algorithmes itératifs peuvent-ils être exprimés de manière récursive?

Sinon, existe-t-il un bon exemple d'exemple qui montre un algorithme itératif pour lequel il n'existe pas de contrepartie récursive?

S'il est vrai que tous les algorithmes itératifs peuvent être exprimés de manière récursive, y a-t-il des cas dans lesquels cela est plus difficile à faire?

De plus, quel rôle le langage de programmation joue-t-il dans tout cela? Je peux imaginer que les programmeurs de régime ont une prise différente sur l'itération (= récursion de la queue) et une utilisation de la pile que des programmeurs Java uniquement.

45
eljenso

Tous les algorithmes itératifs peuvent-ils être exprimés de manière récursive?

Oui, mais la preuve n'est pas intéressante:

  1. Transformez le programme avec tout son flux de contrôle en une seule boucle contenant une seule instruction de cas dans laquelle chaque branche est éventuellement un flux de contrôle de ligne droite, dont break, return, exit, raise, et ainsi de suite. Introduisez une nouvelle variable (appelez-le le "Compteur de programme") que l'instruction de cas utilise pour décider du bloc d'exécution suivant.

    Cette construction a été découverte lors des grandes "guerres de programmation structurées" des années 1960 lorsque des personnes affirment la puissance expressive relative de diverses constructions de flux de contrôle.

  2. Remplacez la boucle avec une fonction récursive et remplacez chaque variable locale mutable avec un paramètre à cette fonction. VOILÀ! Itération remplacée par récursivité.

Cette procédure équivaut à écrire un interprète pour la fonction d'origine. Comme vous pouvez l'imaginer, il se traduit par un code illisible et ce n'est pas une chose intéressante à faire. Toutefois, certaines des techniques peuvent être utiles pour une personne ayant des antécédents dans une programmation impérative qui apprend à programmer dans une langue fonctionnelle pour la première fois.

18
Norman Ramsey

Comme vous le dites, chaque approche itérative peut être transformée en une "récursive" et avec des appels de queue, la pile n'explosera pas non plus. :-) En fait, c'est en fait à quel point le système met en œuvre toutes les formes courantes de boucle. Exemple dans le schéma:

(define (fib n)
  (do ((x 0 y)
       (y 1 (+ x y))
       (i 1 (+ i 1)))
      ((> i n) x)))

Ici, bien que la fonction ait l'air itérative, elle recute en réalité sur une lambda interne qui prend trois paramètres, x, y et i et vous appelant de nouvelles valeurs à chaque itération.

Voici une manière dont la fonction pourrait être développée macro:

(define (fib n)
  (letrec ((inner (lambda (x y i)
                    (if (> i n) x
                        (inner y (+ x y) (+ i 1))))))
    (inner 0 1 1)))

De cette façon, la nature récursive devient plus apparente visuellement.

8
Chris Jester-Young

Définir itératif comme:

function q(vars):
  while X:
    do Y

Peut être traduit comme:

 function q(vars):
    if X:
      do Y
      call q(vars)

Y dans la plupart des cas inclurait l'incrémentation d'un compteur testé par X. Cette variable devra être transmise en "Vars" d'une certaine manière lorsque vous allez à la route récursive.

6
Johan

Comme indiqué par le socle dans le leur réponse , nous pouvons construire des preuves montrant comment récursion et les itérations sont équivalentes et peuvent être utilisées pour résoudre le même problème; Cependant, même si nous savons que les deux sont équivalents, il y a des inconvénients pour utiliser un sur l'autre.

Dans les langues qui ne sont pas optimisées pour la récursivité, vous pouvez constater qu'un algorithme utilisant l'itération préformes plus rapidement que la récursive et également, même dans des langages optimisées, vous pouvez constater qu'un algorithme utilisant l'itération écrite dans une langue différente est plus rapide que la récursive. En outre, il peut ne pas y avoir de manière évidente d'un algorithme donné à l'aide de la récursion par rapport à l'itération et inversement. Cela peut conduire à un code difficile à lire qui conduit à des problèmes de maintenabilité.

1
rjzii