Quelle est la différence entre la récursivité normale et la récursion de queue avec des exemples?


Réponse 1:

La récursivité de queue est un sous-ensemble de récursivité où la valeur retournée est obtenue via un appel de queue, c'est-à-dire que la dernière chose qu'une fonction fait est d'appeler une autre fonction.

Comparez ces deux exemples:

public factoriel int (int n) {si (n <= 1) renvoie 1; retour n * factoriel (n - 1); }

Ce n'est pas un appel de queue, car le résultat de la factorielle est alors multiplié par quelque chose, l'appel de fonction n'est pas la dernière opération.

public int factoriel (int n) {return tailFactorial (1, n); } private int tailFactorial (int accumulator, int n) {if (n <= 1) return accumulator; return tailFactorial (accumulateur * n, n - 1); }

Il s'agit d'un appel de queue, car le résultat de la factorielle est immédiatement renvoyé.

Alors, maintenant la question est, pourquoi s'embêter? Et la réponse est l'optimisation des appels de queue - si la dernière action d'une méthode est un appel à une autre méthode, au lieu de créer un nouveau cadre de pile pour le contexte de la nouvelle méthode (arguments, variables locales, etc.), nous pouvons remplacer l'actuel. L'un des inconvénients des méthodes récursives normales est qu'elles sont vraiment abusives pour la pile d'appels. L'optimisation des appels de queue élimine ce problème et garantit que les performances d'un algorithme récursif sont exactement aussi bonnes que leur homologue itérative (mais potentiellement elles sont beaucoup plus lisibles).

Vous voudrez peut-être jeter un œil à Tail call - Wikipedia.


Réponse 2:

J'en ajoute quelques autres:

Vous ne passez pas par valeur (copie) lorsque l'appel de fin est infiniment récursif * (espace limité).

Aussi (Voir: la réponse de Hans Hyttel à Est-ce que la récursion de la queue déroulante élimine le besoin d'une pile?)

En cas de récursivité de queue, aucune liaison intermédiaire n'est nécessaire, car chaque appel récursif se produit lorsque l'appelant se termine.

Ainsi, dans un langage de programmation qui utilise uniquement la récursivité de queue, un type d'implémentation basé sur la pile n'est pas nécessaire.

Réponse de PS Rob Rix à Comment les énumérations dans Swift peuvent-elles être récursives?

* Sur une note sans rapport, peu de connaissances ou même une application imprudente des algos de base, des types, des bases du langage peuvent vous donner une illusion de récursion infinie, quand il n'y en a pas. Voir la réponse de Vladislav Zorov à En termes simples, pourquoi la récursivité utilisée dans le calcul des racines irrationnelles est-elle infiniment profonde?


Réponse 3:

J'en ajoute quelques autres:

Vous ne passez pas par valeur (copie) lorsque l'appel de fin est infiniment récursif * (espace limité).

Aussi (Voir: la réponse de Hans Hyttel à Est-ce que la récursion de la queue déroulante élimine le besoin d'une pile?)

En cas de récursivité de queue, aucune liaison intermédiaire n'est nécessaire, car chaque appel récursif se produit lorsque l'appelant se termine.

Ainsi, dans un langage de programmation qui utilise uniquement la récursivité de queue, un type d'implémentation basé sur la pile n'est pas nécessaire.

Réponse de PS Rob Rix à Comment les énumérations dans Swift peuvent-elles être récursives?

* Sur une note sans rapport, peu de connaissances ou même une application imprudente des algos de base, des types, des bases du langage peuvent vous donner une illusion de récursion infinie, quand il n'y en a pas. Voir la réponse de Vladislav Zorov à En termes simples, pourquoi la récursivité utilisée dans le calcul des racines irrationnelles est-elle infiniment profonde?


Réponse 4:

J'en ajoute quelques autres:

Vous ne passez pas par valeur (copie) lorsque l'appel de fin est infiniment récursif * (espace limité).

Aussi (Voir: la réponse de Hans Hyttel à Est-ce que la récursion de la queue déroulante élimine le besoin d'une pile?)

En cas de récursivité de queue, aucune liaison intermédiaire n'est nécessaire, car chaque appel récursif se produit lorsque l'appelant se termine.

Ainsi, dans un langage de programmation qui utilise uniquement la récursivité de queue, un type d'implémentation basé sur la pile n'est pas nécessaire.

Réponse de PS Rob Rix à Comment les énumérations dans Swift peuvent-elles être récursives?

* Sur une note sans rapport, peu de connaissances ou même une application imprudente des algos de base, des types, des bases du langage peuvent vous donner une illusion de récursion infinie, quand il n'y en a pas. Voir la réponse de Vladislav Zorov à En termes simples, pourquoi la récursivité utilisée dans le calcul des racines irrationnelles est-elle infiniment profonde?