Ich kenne das allgemeine Konzept der Rekursion. Beim Studium des Quicksort-Algorithmus bin ich auf das Konzept der Schwanzrekursion gestoßen. In diesem Video von Quick Sort Algorithmus vom MIT um 18:30 Sekunden sagt der Professor, dass dies ein rekursiver Schwanzalgorithmus ist. Mir ist nicht klar, was Schwanzrekursion wirklich bedeutet.
Kann jemand das Konzept mit einem richtigen Beispiel erklären?
Einige Antworten der SO-Community hier .
algorithms
reference-request
recursion
Aussenseiter
quelle
quelle
Antworten:
Die Schwanzrekursion ist ein Sonderfall der Rekursion, bei dem die aufrufende Funktion nach einem rekursiven Aufruf keine Berechnung mehr vornimmt. Zum Beispiel die Funktion
ist rekursiv (da der letzte Befehl ein rekursiver Aufruf ist), während diese Funktion nicht rekursiv ist:
da es einige Berechnungen durchführt, nachdem der rekursive Aufruf zurückgekehrt ist.
Die Schwanzrekursion ist wichtig, da sie effizienter implementiert werden kann als die allgemeine Rekursion. Wenn wir einen normalen rekursiven Aufruf machen, müssen wir die Rücksprungadresse auf den Aufrufstapel legen und dann zur aufgerufenen Funktion springen. Dies bedeutet, dass wir einen Aufrufstapel benötigen, dessen Größe in der Tiefe der rekursiven Aufrufe linear ist. Wenn wir eine Schwanzrekursion haben, wissen wir, dass wir, sobald wir von dem rekursiven Aufruf zurückkehren, auch sofort zurückkehren, sodass wir die gesamte Kette rekursiver Funktionen, die zurückkehren, überspringen und direkt zum ursprünglichen Aufrufer zurückkehren können. Das bedeutet, dass wir für alle rekursiven Aufrufe überhaupt keinen Aufrufstapel benötigen und den endgültigen Aufruf als einfachen Sprung implementieren können, wodurch Platz gespart wird.
quelle
def recurse(x): if x < 0 return 1; for i in range 100{ (do calculations) recurse(x)}
Einfach gesagt, ist die Schwanzrekursion eine Rekursion, bei der der Compiler den rekursiven Aufruf durch einen "goto" -Befehl ersetzen könnte, sodass die kompilierte Version die Stapeltiefe nicht erhöhen muss.
Manchmal müssen Sie zum Entwerfen einer rekursiven Endfunktion eine Hilfsfunktion mit zusätzlichen Parametern erstellen.
Dies ist beispielsweise keine Schwanzrekursivfunktion:
Dies ist jedoch eine schwanzrekursive Funktion:
weil der Compiler die rekursive Funktion in eine nicht rekursive Funktion umschreiben könnte, indem er so etwas wie diesen (einen Pseudocode) verwendet:
Die Regel für den Compiler ist sehr einfach: Wenn Sie "
return thisfunction(newparameters);
" finden, ersetzen Sie sie durch "parameters = newparameters; goto start;
". Dies ist jedoch nur möglich, wenn der vom rekursiven Aufruf zurückgegebene Wert direkt zurückgegeben wird.Wenn alle rekursiven Aufrufe in einer Funktion auf diese Weise ersetzt werden können, handelt es sich um eine rekursive Endfunktion.
quelle
Meine Antwort basiert auf der Erklärung im Buch Struktur und Interpretation von Computerprogrammen . Ich kann dieses Buch Informatikern nur empfehlen.
Ansatz A: Linearer rekursiver Prozess
Die Form des Prozesses für Ansatz A sieht folgendermaßen aus:
Ansatz B: Linearer iterativer Prozess
Die Form des Prozesses für Ansatz B sieht folgendermaßen aus:
Der lineare iterative Prozess (Ansatz B) wird im konstanten Raum ausgeführt, obwohl der Prozess ein rekursiver Prozess ist. Es sollte auch beachtet werden, dass bei diesem Ansatz eine festgelegte Variable den Zustand des Prozesses an jedem Punkt definiert, nämlich.
{product, counter, max-count}
. Dies ist auch eine Technik, mit der die Schwanzrekursion die Compileroptimierung ermöglicht.In Ansatz A gibt es mehr verborgene Informationen, die der Interpreter verwaltet. Dies ist im Grunde die Kette der zurückgestellten Operationen.
quelle
Die Schwanzrekursion ist eine Form der Rekursion, bei der die rekursiven Aufrufe die letzten Anweisungen in der Funktion sind (daher kommt der Schwanzteil). Darüber hinaus darf der rekursive Aufruf nicht aus Referenzen auf Speicherzellen bestehen, in denen vorherige Werte gespeichert sind (Referenzen, die keine Parameter der Funktion sind). Auf diese Weise kümmern wir uns nicht um vorherige Werte, und ein Stapelrahmen reicht für alle rekursiven Aufrufe aus. Die Schwanzrekursion ist eine Möglichkeit, rekursive Algorithmen zu optimieren. Der andere Vorteil / die Optimierung besteht darin, dass es eine einfache Möglichkeit gibt, einen rekursiven Algorithmus für den Schwanz in einen äquivalenten Algorithmus umzuwandeln, der Iteration anstelle von Rekursion verwendet. Also ja, der Algorithmus für Quicksort ist in der Tat rekursiv.
Hier ist die iterative Version:
quelle