Un appel de fonction récursif de queue permet au compilateur d'effectuer une optimisation spéciale qu'elle ne peut normalement pas avec une récursivité régulière. Dans une fonction récursive de queue, l'appel récursif est la toute dernière chose à exécuter. Dans ce cas, au lieu d'allouer une trame de pile pour chaque appel, le compilateur peut retravailler le code pour simplement réutiliser le cadre de pile actuel, ce qui signifie qu'une fonction réécursive de queue n'utilisera qu'un cadre de pile unique par opposition à des centaines ou même à des milliers.
Cette optimisation est possible car le compilateur sait qu'une fois l'appel récursif de queue, aucune copie précédente des variables ne sera nécessaire, car il n'y a plus de code à exécuter. Si, par exemple, une instruction d'impression suivait un appel récursif, le compilateur devrait connaître la valeur de la variable à imprimer après les retours de l'appel récursif, et donc le cadre de pile ne peut pas être réutilisé.
Voici la page Wiki si vous souhaitez plus d'informations sur la façon dont cette "enregistrement d'espace" et la réutilisation de pile fonctionne réellement, ainsi que des exemples: Appel à queue
Edit: Je n'ai pas expliqué comment cela s'applique à Quicksort, n'est-ce pas? Eh bien, certains termes sont lancés dans cet article qui rendent tout déroutant (et certains d'entre eux sont tout simplement faux). La première fonction donnée (Quicksort) fait un appel récursif à gauche, un appel récursif à droite, puis sort. Notez que l'appel récursif à droite est la toute dernière chose qui se produit dans la fonction. Si le compilateur prend en charge l'optimisation récursive de la queue (expliquée ci-dessus), seuls les appels de gauche créent de nouvelles cadres de pile; Tous les bons appels réutilisent simplement le cadre actuel. Cela peut économiser quelques Empiler les cadres, mais peut toujours souffrir du cas où la partition crée une séquence d'appels où l'optimisation de la récursivité de la queue n'a pas d'importance. De plus, même si les appels côté droit utilisent le même cadre, les appels côté gauche appelés dans Les appels à droite utilisent toujours la pile. Dans le pire des cas, la profondeur de la pile est N.
La deuxième version décrite est ne pas Une queue qui récursive Quicksort, mais plutôt un Quicksort, seul le tri de gauche se fait récursivement, et le tri droit est effectué en utilisant la boucle. En fait, ce Quicksort (comme décrit précédemment par un autre utilisateur) ne peut pas avoir l'optimisation de la récursivité de la queue qui lui est appliquée, car l'appel récursif n'est pas la dernière chose à exécuter. Comment cela marche-t-il? Lorsqu'il est implémenté correctement, le premier appel à Quicksort est le même qu'un appel côté gauche dans l'algorithme d'origine. Cependant, aucun appel récursif côté droit n'est même appelé. Comment cela marche-t-il? Eh bien, la boucle s'occupe de cela: au lieu de trier "à gauche alors à droite", il trie la gauche avec un appel, puis trie la droite en triant continuellement uniquement le les gauches de droite. C'est vraiment un son ridicule, mais il s'agit essentiellement de trier tellement de gauches que les droits deviennent des éléments uniques et n'ont pas besoin d'être triés. Cela supprime efficacement la bonne récursivité, ce qui rend la fonction moins récursive (pseudo récursif, si vous voulez). Cependant, l'implémentation réelle ne choisit pas uniquement le côté gauche à chaque fois; Il choisit le plus petit côté. L'idée est toujours la même; Il ne fait essentiellement qu'un appel récursif d'un côté au lieu des deux. La sélection du côté plus court garantira que la profondeur de la pile ne peut jamais être plus grande que Log2 (n), qui est la profondeur d'un arbre binaire approprié. En effet, le côté le plus court sera toujours au maximum de la moitié de la taille de notre section de tableau actuelle. La mise en œuvre donnée par l'article ne garantit cependant pas cela, car elle peut souffrir du même scénario du pire des cas de "gauche est l'arbre entier". Cet article donne en fait une assez bonne explication à ce sujet si vous êtes prêt à faire plus de lecture: Sélection efficace et tri partiel basé sur Quicksort