[Datenstruktur-Lerndatensatz 7] -Stapel und Rekursion (in der Tat mehr Analyse und Rekursion)

1. Rekursion

1. Konzept

Was Rekursion ist, haben wir in der Mathematik der High School gelernt, Rekursion. Wenn eine Wiederholungsformel als Funktion ausgedrückt wird, können wir diese Funktion natürlich aufrufen 递归函数. 递归函数Es ist eine Funktion, die sich direkt oder über eine Reihe von Anweisungen aufruft und als rekursive Funktion bezeichnet wird.

Zum Beispiel unsere Fakultätsfunktion:
F act (n) = {1, n = 0 n ⋅ F act (n - 1), n> 0 Fakt (n) = \ left \ {\ begin {align} 1, n = 0 \\ n \ cdot Fakt (n-1), n> 0 \\ \ end {align} \ right.F a c t ( n )={ 1 ,n=0nF a c t ( n- -1 ) ,n>0
Oder die bekannte Fibonacci-Sequenz:
F ib (n) = {0, n = 0 1, n = 1 F ib (n - 1) ⋅ F ib (n - 2), n> 1 Fib (n) = \ left \ {\ begin {align} 0, n = 0 \\ 1, n = 1 \\ Fib (n-1) \ cdot Fib (n-2), n> 1 \\ \ end {align} \ right.F i b ( n )=0 ,n=01 ,n=1F i b ( n- -1 )F i b ( n- -2 ) ,n>1

2. Realisieren

Wir denken , kann der konstante Term wird genannt 递归边界, wie faktorielle f(n)=1,n=0Fibonacci - Zahl oder die Fibonacci - Folge f(n)=0,n=0, f(n)=1,n=1.

Dann schreiben wir einen rekursiven Code, der die Fibonacci-Sequenz implementiert:

int Fib(int n)
{
    
    
    if (n == 0) return 0;
    else if (n == 1) return 1;
    else
    {
    
    
        return Fib(n-1) + Fib(n-2);
    }
}

int main()
{
    
    
    printf("%d", Fib(10));
    return 0;
}

Solange wir einen rekursiven Funktionsausdruck schreiben können, können wir seine rekursive Funktion schreiben. Meiner Meinung nach:Die rekursive Grenze ist die wichtigste. Wenn die Rekursionsgrenze nicht richtig gehandhabt wird, kann die Rekursion für immer fortgesetzt werden und dann in den Tod ausbrechen.

3. Härtere rekursive Analyse-Turm von Hanoi

Fügen Sie hier eine Bildbeschreibung ein

Die Spielregeln im Turm von Hanoi lauten: Bewegen Sie die Platte in A auf Platte C, und die große Platte kann nicht auf die kleine Platte gelegt werden.

Dafür versuchen wir es noch ein paar Mal:

  1. n = 1

    1. Satz 1 A ----> C.

  2. n = 2

    Der 1. Satz 1 A ----> B.

    2. Satz 2 A ----> C.

    3. Satz 1 B ----> C.

  3. n = 3

    1. Satz 1 A ----> C.

    Die zweite Runde Nr. 2 A ----> B.

    3. Satz 1 C ----> B.

    4. Satz 3 A ----> C.

    Die 5. Runde Nr. 1 B ----> A.

    6. Satz 2 B ----> C.

    7. Scheibe 1 A ----> C.

Wenn wir den ganzheitlichen Ansatz verwenden und einen Stapel von Platten von A nach C bewegen, können wir die Platten auf der A-Säule als zwei Ganzheiten betrachten, die Bodenplatte und alle Platten darauf. Dann ist unser Prozess:

  1. Alle Platten oben von A bis B.
  2. Die Bodenplatte geht von A nach C.
  3. Alle Platten oben von B bis C.

Wie bewegen wir die obere Platte nach B und C? Stellen Sie sich diesen Teil der Platte als zwei Teile vor, die untere Platte und alle Platten auf der Oberseite.

Wenn wir uns zu B bewegen, ist C unser Hilfsturm (weil sich das Spiel von A nach C bewegt, also ist B ein Hilfsturm), also werden wir im oberen Teil die Operation "Turm von Hanoi von A nach B" durchführen.

Umgekehrt, wenn Sie von B nach C wechseln, ist A der Hilfsturm. Was wir also tun, ist "Schweißkerbebetrieb von B nach C".

Starten Sie die Puppe. Bis zum Ende haben wir nur eine Platte, also führt sie offensichtlich die Operation "A bis C Turm von Hanoi" aus und hat nur eine Platte, dann verschieben Sie sie nach C.

Dann kommt unser rekursiver Ausdruck heraus:

Rekursionsgrenze: n=1时 把1号盘子 A→C

Rekursive Inhalt: ① 把n-1号盘子 A→B把n号盘子 A→C把n-1号盘子 B→C

Okay, lassen Sie uns den Code implementieren:

void hano(int n, char a, char b, char c)    // hano(n=有几个碟子,a=主塔,b=辅助塔,c=目标塔) 
{
    
    
    if (n == 1) printf("No.%d  %c -> %c\n", 1, a, c);
    else
    {
    
    
        hano(n - 1, a, c, b);   // 这里是A to B的操作,C是辅助塔
        printf("No.%d  %c -> %c\n", n, a, c);
        hano(n - 1, b, a, c); // 这里是B to C的操作,A是辅助塔
    }
    
}

int main()
{
    
    
    hano(3, 'A', 'B', 'C'); // 这里是A to C的操作
    return 0;
}

2. Die Beziehung zwischen Stapel und Rekursion

Wenn Sie in Hochsprachen die Funktion (dies ist das Verb) aufrufen müssen 调用(名词)函数, und 被调用函数Links zum Informationsaustausch zwischen den Anforderungen über den internen Stapel.

Bevor die aufgerufene Funktion ausgeführt wird, führt das System drei Dinge aus:

  1. Übergeben Sie alle aktuellen Parameter, die Rücksprungadresse und andere Informationen zum Speichern an die aufgerufene Funktion.
  2. Ordnen Sie den lokalen Variablen der aufgerufenen Funktion Speicherplatz zu
  3. Übertragen Sie die Steuerung auf den Eintrag der aufgerufenen Funktion.

Bevor die aufgerufene Funktion zur aufrufenden Funktion zurückkehrt, müssen wir drei Dinge erledigen:

  1. Speichern Sie das Berechnungsergebnis der aufgerufenen Funktion
  2. Geben Sie den Datenbereich der aufgerufenen Funktion frei
  3. Übertragen Sie die Steuerung gemäß der von der aufgerufenen Funktion gespeicherten Rücksprungadresse an die aufrufende Funktion.

Angenommen, wir führen verschachtelte Aufrufe wie rekursiv aus, dann muss die zuerst aufgerufene Funktion zuletzt zurückgegeben werden, sodass diese Beziehungen und Informationen im Compiler über den Stapel für uns gespeichert werden.

Die Informationsübertragung zwischen unserer Rekursion muss also den Stapel verwenden. Glücklicherweise wird der Compiler 递归工作栈ihn für uns verwalten, sodass wir nur die Rekursionsgrenze und den Inhalt der Rekursion berücksichtigen müssen!

Supongo que te gusta

Origin blog.csdn.net/u011017694/article/details/109428873
Recomendado
Clasificación