6

Ich weiß, was ein Tail rekursive Algorithmus ist wie written out in this SO answer. Allerdings gehe ich durch diese video of quick sort algorithm from MIT und um 18:30 Sekunden sagt der Professor, dass dies Tail rekursive Algorithmus ist. Ich verbinde nicht, wie das tail rekursiv ist. Wir machen keine Berechnung bei irgendeinem Schritt der Rekursion oder sind wir? Können Sie erklären, warum dies als Beispiel für einen tail rekursiven Algorithmus angeführt wird? Bitte stützen Sie Ihre Antwort auf die Prämisse, dass ich weiß, was ein rekursiver Algorithmus ist. Der Teil, der mir nicht klar ist, warum heißt es Schwanz rekursiv?Warum wird eine schnelle Sortierung als tailrekursiver Algorithmus bezeichnet?

+2

Haben Sie gelesen, dass Wikipedia-Artikel aus der vorherigen Frage? – Andrey

+2

@Andrey Ja, habe ich getan, aber ich habe die Antwort in SO gefunden, mit der ich verlinkt habe, um einfacher und klarer zu verstehen. – Geek

+0

mögliches Duplikat von [Was ist Tail-Rekursion?] (Http://stackoverflow.com/questions/33923/what-istail-recursion). Sobald Sie die Definition von tail recursive, einer Definition des Algorithmus bei 17:28, sehen, ist es klar, dass es tail rekursiv ist, da der Rückgabewert des rekursiven Schritts der Rückgabewert eines Aufrufs an sich selbst ist. –

Antwort

1

Der erste Schritt der rekursiven Funktion ist die Partitionierung. Und dann, als letzten Schritt, rufen Sie die rekursive Funktion auf den beiden Partitionen auf.

Aus Wikipedia:

In der Informatik ein Endrekursion ist ein Unterprogramm-Aufruf, die in einem anderen Verfahren als seine letzte Aktion geschieht; es kann einen Rückgabewert Wert erzeugen, der dann sofort von der aufrufenden Prozedur zurückgegeben wird.

7

Bei der Tail-Rekursion geht es nicht um die Berechnung in Schritten. Es geht darum, "die Rekursion könnte ausgewertet werden, ohne Call-Stack aufzubauen." Das Beispiel von What is tail recursion? ist ein besonderer Fall. Wenn Sie das Beispiel tiefer aussehen kann, was Sie finden ist, dass

def recsum(x): 
if x==1: 
    return x 
else: 
    return x+recsum(x-1) 

1) den obigen Code erfolgreich auszuführen, müssen Sie den Call-Stack aufzubauen. Aber

def tailrecsum(x,running_total=0): 
    if x==0: 
    return running_total 
    else: 
    return tailrecsum(x-1,running_total+x) 

2) den obigen Code ausführen können, Sie brauchen nicht wegen running_total den Call-Stack aufzubauen. Erstellen Sie einfach den Aufruf-Stack für den "Original-Aufruf" und für die Rekursion müssen Sie keinen Aufruf-Stack erstellen, da der Status, der zur Auswertung dieser Funktion benötigt wird, in running_total gespeichert wird.

Und, über die Schnellsortierung, ich denke der Professor wahrscheinlich meinte, dass Quick-Sortierung könnte optimiert werden, indem "Tail-Recusion" verwendet wird. Für die zwei Verzweigungsteile von qsort() können wir eine Tail-Rekursion auf einer Seite verwenden, die höhere Elemente (basierend auf der Pivot-Position) aufweist.

enter image description here

+2

können Sie die Anruflisten in Ihre Antwort einfügen, um sie weiter zu erklären. Für mich sieht es so aus, als müssten Sie den Call-Stack in beiden Prozeduren erstellen. tailrecsum ruft tail rekursive Summe Aufrufe tailrecsum .... Also der Call-Stack baut sich auf ... Ist das nicht ? – Geek

+1

Dies ist die Fortsetzung meines vorherigen Kommentars ... Wie kann der Compiler einen rekursiven Aufruf berechnen, ohne den Stack zu erstellen? Wie gut haben Sie mit "Call-Stack aufbauen" gemeint? – Geek

+2

@Geek: Ich bin nur ein Anfänger in diesem Thema, und ich bin gerade dabei, "Struktur und Interpretation von Computerprogrammen" (SICP) zu lesen, die kostenlos online verfügbar ist; Das Konzept der Tail-Rekursion ist eng mit dem Thema "Lineare Rekursion versus Iteration" verknüpft. SICP hat hier sehr viel zu sagen: http://mitpress.mit.edu/sicp/full-text/book/B-Z-H-11.html#%_sec_1.2.1. Dieser Link von SICP erklärt es sehr deutlich. – favq

4

Haben Sie einen Blick auf die Wiki-Seite von Quicksort. Es gibt eine Version von Schwanz rekursive

function quicksort(array, 'left', 'right') 

    // If the list has 2 or more items 
    if 'left' < 'right' 

     // See "Choice of pivot" section below for possible choices 
     choose any 'pivotIndex' such that 'left' ≤ 'pivotIndex' ≤ 'right' 

     // Get lists of bigger and smaller items and final position of pivot 
     'pivotNewIndex' := partition(array, 'left', 'right', 'pivotIndex') 

     // Recursively sort elements smaller than the pivot 
     quicksort(array, 'left', 'pivotNewIndex' - 1) 

     // Recursively sort elements at least as big as the pivot 
     quicksort(array, 'pivotNewIndex' + 1, 'right') 

Nach der Definition von Tail recursion, der letzten Methodenaufruf von quicksort selbst, das ist Endrekursion. Aber einige andere Implementierungen sind nicht tail rekursiv.

quicksort(left) + pivot + quicksort(right) 

Da die letzte Aktion in quicksort ist sorted_left + pivot + sorted_right

+2

Können andere die Richtigkeit bestätigen? –