Je connais le concept général de récursivité. Je suis tombé sur le concept de récursion de queue tout en étudiant l'algorithme Quicksort. Dans cette vidéo de l'algorithme de tri rapide du MIT à 18h30, le professeur dit qu'il s'agit d'un algorithme récursif de queue. La récursion de la queue n’est pas claire pour moi.
Quelqu'un peut-il expliquer le concept avec un exemple approprié?
Quelques réponses fournies par la communauté SO ici .
Réponses:
La récursion de la queue est un cas particulier de récursivité dans lequel la fonction appelante ne calcule plus après un appel récursif. Par exemple, la fonction
est queue récursive (puisque l'instruction finale est un appel récursif) alors que cette fonction n'est pas récursive:
puisqu'il effectue des calculs après le retour de l'appel récursif.
La récursion de la queue est importante car elle peut être mise en œuvre plus efficacement que la récursion générale. Lorsque nous effectuons un appel récursif normal, nous devons insérer l'adresse de retour dans la pile d'appels, puis passer à la fonction appelée. Cela signifie que nous avons besoin d'une pile d'appels de taille linéaire dans la profondeur des appels récursifs. Lorsque nous avons la récursion de la queue, nous savons que dès que nous revenons de l'appel récursif, nous allons revenir immédiatement, afin que nous puissions ignorer toute la chaîne de fonctions récursives et revenir directement à l'appelant initial. Cela signifie que nous n'avons pas du tout besoin d'une pile d'appels pour tous les appels récursifs et que nous pouvons implémenter l'appel final comme un simple saut, ce qui nous permet de gagner de la place.
la source
def recurse(x): if x < 0 return 1; for i in range 100{ (do calculations) recurse(x)}
Simplement dit, la récurrence finale est une récurrence dans laquelle le compilateur pourrait remplacer l'appel récursif par une commande "goto", de sorte que la version compilée n'aura pas à augmenter la profondeur de la pile.
Parfois, la conception d’une fonction queue récursive nécessite la création d’une fonction d’aide avec des paramètres supplémentaires.
Par exemple, ce n'est pas une fonction queue-récursive:
Mais ceci est une fonction queue-récursive:
parce que le compilateur pourrait réécrire la fonction récursive en une fonction non récursive, en utilisant quelque chose comme ceci (un pseudocode):
La règle pour le compilateur est très simple: lorsque vous trouvez "
return thisfunction(newparameters);
", remplacez-le par "parameters = newparameters; goto start;
". Mais cela ne peut être fait que si la valeur renvoyée par l'appel récursif est renvoyée directement.Si tous les appels récursifs dans une fonction peuvent être remplacés de la sorte, il s’agit d’une fonction récursive.
la source
Ma réponse est basée sur l'explication donnée dans l'ouvrage Structure et interprétation des programmes informatiques . Je recommande fortement ce livre aux informaticiens.
Approche A: Processus récursif linéaire
La forme du processus pour l' approche A ressemble à ceci:
Approche B: Processus Itératif Linéaire
La forme du processus pour l' approche B ressemble à ceci:
Le processus itératif linéaire (approche B) s'exécute dans un espace constant, même s'il s'agit d'une procédure récursive. Il convient également de noter que, dans cette approche, un ensemble de variables définit l’état du processus à tout moment, à savoir.
{product, counter, max-count}
. C'est également une technique par laquelle la récursion en queue permet l'optimisation du compilateur.Dans l'approche A, l'interprète conserve davantage d'informations cachées, qui constituent essentiellement la chaîne des opérations différées.
la source
Tail-récursion est une forme de récursion dans laquelle les appels récursifs sont les dernières instructions de la fonction (d'où provient la partie tail). De plus, l'appel récursif ne doit pas être composé avec des références à des cellules de mémoire stockant des valeurs précédentes (références autres que les paramètres de la fonction). De cette façon, nous ne nous soucions pas des valeurs précédentes et un cadre de pile suffit pour tous les appels récursifs; tail-récursion est un moyen d'optimiser les algorithmes récursifs. L'autre avantage / optimisation réside dans le fait qu'il existe un moyen simple de transformer un algorithme récursif en un algorithme équivalent utilisant l'itération au lieu de la récursion. Alors oui, l'algorithme pour le tri rapide est bien récursif.
Voici la version itérative:
la source