2016-07-09 7 views
2

Ich versuche zu verstehen, was genau Rekursion ist und konnte keine Antwort auf das Folgende finden.Was ist und ist keine Rekursion?

Mein aktuelles Verständnis von Rekursion ist, dass es sich jederzeit eine Methode nennt.

I.E

Menu() 
{ 
if(i<2) 
{Console.WriteLine();} 
else 
{Menu();}  
} 

Das Vorstehende ist ein Beispiel für die Rekursion Aufruf einer Methode selbst.

Was ich bin mir nicht sicher über ein Szenario wie ist:

Menu() 
{ 
if(i<2) 
{Console.WriteLine();} 
else 
{Console.WriteLine("Something Went Wrong!"); MenuError();}  
} 

MenuError() 
{ 
Console.WriteLine("Something went wrong!"); 
Menu(); 
} 

Wenn die Methode eine Methode aufruft, die dann ruft es diese noch Rekursion?

+1

Ich weiß nicht, ob es als rekursiv oder nicht betrachtet wird. Aber ich weiß eine Sache, die definitiv in Betracht gezogen wird: [Reentrant] (https://en.wikipedia.org/wiki/Reentrancy_ (Computing)) (Eine Reentrant-Funktion ist eine Funktion, die ein zweites Mal vom selben Call-Stack aufgerufen wird bevor der erste Anruf abgeschlossen ist) –

+2

Angenommen, ich habe eine Reihe von Methoden. Angenommen, ich zeichne eine gerichtete Kante von einer Methode zu einer anderen (möglicherweise selbst), wenn sie Code hat, um sie "aufzurufen" (angenommen, dass der gesamte Code erreichbar ist). Rekursion, in Bezug auf die Graphentheorie, ist immer dann, wenn es einen Zyklus gibt, selbst oder nicht. –

+0

http://www.etymonline.com/index.php?term=recursion Wenn der gleiche Thread früher oder später "zurückfährt", um die von ihm ausgeführte Funktion aufzurufen, handelt es sich um eine Rekursion. Es gibt keinen konzeptionellen Unterschied zwischen Ihren Beispielen, der Punkt ist, dass sie die Funktion erneut aufruft, bevor sie von dem früheren Aufruf zurückkommt. –

Antwort

5

Mein aktuelles Verständnis von Rekursion ist, dass es sich jederzeit eine Methode nennt.

Das ist richtig. Rekursive Definitionen sind selbstverweisende Definitionen.

Zwei interessante Eigenschaften rekursiver Definitionen sind Produktivität und Terminierung. Ein Programm ist produktiv, wenn es weiterhin Ausgaben liefert, obwohl die volle Ausgabe niemals kommen kann (daher kann es nicht enden). Ein Programm wird beendet, wenn es seine volle Ausgabe in endlicher Zeit liefert.

Zum Beispiel ist dies ein produktives, nicht-Abschlussprogramm:

Naturals(int i) { 
    Console.WriteLine(i); 
    Naturals(i + 1); 
} 

Dies ist ein Abschlussprogramm:

UpToTen(int i) { 
    Console.WriteLine(i); 
    if (i < 10) UpToTen(i + 1); 
} 

Dies ist ein nicht-produktives Programm:

DoNothing() { 
    DoNothing(); 
} 

Wenn Menu Anrufe MenuError und MenuError Anrufe Menu, wird dies manchmal gegenseitige Rekursion genannt. Der einzige Unterschied ist unsere Organisation; wir können den Code umschreiben, um nur eine Methode zu haben, indem wir MenuError einreihen.

Menu() { 
    if (i < 2) { 
    Console.WriteLine(); 
    } 
    else { 
    Console.WriteLine("Something Went Wrong!"); 
    Console.WriteLine("Something went wrong!"); 
    Menu(); 
    } 
} 

Sie können in der Tat abstrakt Rekursion selbst:

// General definition 
A Fix<A>(Func<Func<A>,A> f) { 
    return f(() => Fix(f)); 
} 

// Special definition for void functions 
void Fix(Action<Action> f) { 
    f(() => Fix(f)); 
} 

void Menu(Action menu) { 
    if (i < 2) { 
    Console.WriteLine(); 
    } 
    else { 
    Console.WriteLine("Something Went Wrong!"); 
    Console.WriteLine("Something went wrong!"); 
    menu(); 
    } 
} 

Fix(Menu); 

Hier ist ein weiteres Beispiel Fix mit der Fakultäts-Funktion zu definieren.

Func<int, int> Fac(Func<Func<int, int>> fac) { 
    return i => i == 0 ? 1 : i * fac()(i - 1); 
} 

// Fix<Func<int, int>>(Fac) is the factorial function 

Sie fragen sich vielleicht, warum Fix die Signatur nicht A Fix<A>(Func<A,A> f) stattdessen haben. Dies liegt daran, dass C# eine strikte Sprache ist, dh Argumente werden ausgewertet, bevor die Funktionsanwendung ausgewertet wird. Mit der einfacheren Signatur würde das C# -Programm in unendlicher Rekursion enden.

+0

Vielen Dank das ist eine wirklich großartige Erklärung! – Spooler

0

Ja, es ist immer noch Rekursion. Es gibt verschiedene Arten der Rekursion wie Tail-Rekursion, Baumrekursion usw. Sie können google für Ruhe auschecken.

Übrigens, wenn der Wert von i größer als oder gleich 2 ist, erhalten Sie Stapelüberlauffehler, da jeder einen anderen aufrufen wird.

+1

Es war wirklich nur zum Beispiel Zwecke. Eingriff ist also immer etwas, das eine Methode Aufrufe nennt diese Methode? – Spooler

+1

@Spooler: Ich würde sagen, das ist wahr. –

Verwandte Themen