2016-07-09 3 views
2

Я пытаюсь понять, что именно является рекурсией и не удалось найти ответ на следующее.Что такое и не рекурсия?

Мое настоящее понимание рекурсии заключается в том, что это когда-либо метод вызывает себя.

т.е.

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

Выше приведен пример рекурсии метод вызова себя.

То, что я не уверен, что это сценарий, как:

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

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

Если метод вызывает метод, который затем вызывает его это еще рекурсии?

+1

Я не знаю, считается ли это рекурсивным или нет. Но я знаю одну вещь, которая определенно считается: [Reentrant] (https://en.wikipedia.org/wiki/Reentrancy_ (вычисления)) (Функция повторного входа - это функция, которая получает второй вызов по тому же стеку вызовов до завершения первого вызова) –

+2

Предположим, у меня есть набор методов. Предположим, что я рисую направленное ребро от одного метода к другому (возможно, самому себе), если у него есть код, чтобы «вызвать» его (предположим, что весь код доступен). Рекурсия, в терминах теории графов, - это когда-либо есть цикл, я или иначе. –

+0

http://www.etymonline.com/index.php?term=recursion Если тот же самый поток «убежит» рано или поздно, чтобы вызвать выполняемую им функцию, это рекурсия. Между вашими примерами нет принципиальной разницы, дело в том, что он снова вызывает функцию, прежде чем она вернется с предыдущего вызова. –

ответ

5

Мое нынешнее понимание рекурсии заключается в том, что это когда-либо вызов метода .

Это правильно. Рекурсивные определения являются определениями самореференции.

Два интересных свойства рекурсивных определений: Производительность и Прекращение. Программа продуктивна, если она по-прежнему дает выход, хотя полная выходная мощность может никогда не появиться (следовательно, она не может завершиться). Программа завершается, если она дает полный выход за конечное время.

Например, это продуктивно, не-терминатор программа:

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

Это программа терминатор:

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

Это непродуктивный программа:

DoNothing() { 
    DoNothing(); 
} 

Если Menu звонки MenuError и MenuError звонки Menu, это иногда называют взаимной рекурсии. Единственная разница - наша организация; мы можем переписать код, чтобы иметь только один метод, введя в таблицу MenuError.

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

Вы можете на самом деле абстрактная рекурсия сами:

// 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); 

Вот другой пример использования Fix определить функцию факториала.

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 

Вы можете задаться вопросом, почему Fix не имеет подписи A Fix<A>(Func<A,A> f) вместо этого. Это связано с тем, что C# является строгим языком, что означает, что он оценивает аргументы, прежде чем оценивать приложение функции. С более простой сигнатурой программа C# закончится бесконечной рекурсией.

+0

Спасибо, что это действительно отличное объяснение! – Spooler

0

Да, это еще рекурсия. Существуют различные типы рекурсии, такие как рекурсия хвоста, рекурсия деревьев и т. Д. Вы можете проверить google для отдыха.

Кстати, во втором случае, если значение i больше или равно 2, вы получите ошибку переполнения стека, так как каждый вызовет другую.

+1

Это было действительно только для примера. Таким образом, вторжение - это когда-нибудь, что метод вызывает вызовы этим методом? – Spooler

+1

@Spooler: Я бы сказал, что это правда. –