Кто-либо может объяснить рекурсивную функцию мне в PHP (не используя Fibonacci) на языке неспециалиста и с помощью примеров? я смотрел на пример, но Fibonacci полностью потерял меня!
Заранее спасибо ;-) Также, как часто Вы используете их в веб-разработке?
Рекурсивная функция - это функция, которая сама вызывает
Если функция продолжает вызывать саму себя, как она узнает, когда остановиться? Вы устанавливаете условие, известное как базовый вариант. Базовые случаи сообщают нашему рекурсивному вызову, когда следует остановиться, в противном случае он будет зацикливаться бесконечно.
Хорошим обучающим примером для меня, так как у меня сильная математическая подготовка, был факториал . Судя по комментариям ниже, кажется, что факториальной функции может быть слишком много, я оставлю ее здесь на всякий случай, если вы этого захотите.
function fact($n) {
if ($n === 0) { // our base case
return 1;
}
else {
return $n * fact($n-1); // <--calling itself.
}
}
Что касается использования рекурсивных функций в веб-разработке, я лично не прибегаю к использованию рекурсивных вызовов. Не то чтобы я считал плохой практикой полагаться на рекурсию, но они не должны быть вашим первым вариантом. При неправильном использовании они могут быть смертельными.
Хотя я не могу конкурировать с примером каталога, я надеюсь, что это немного поможет.
Было бы также полезно проверить этот вопрос, где принятый ответ демонстрирует в терминах непрофессионала, как работает рекурсивная функция. Несмотря на то, что вопрос OP касался Java, концепция та же,
Это функция, которая вызывает сама себя. Это полезно для прохождения определенных повторяющихся структур данных, таких как деревья. HTML DOM - классический пример.
Пример древовидной структуры в javascript и рекурсивной функции для «обхода» дерева.
1
/ \
2 3
/ \
4 5
-
var tree = {
id: 1,
left: {
id: 2,
left: null,
right: null
},
right: {
id: 3,
left: {
id: 4,
left: null,
right: null
},
right: {
id: 5,
left: null,
right: null
}
}
};
Чтобы пройтись по дереву, мы многократно вызываем одну и ту же функцию, передавая дочерние узлы текущего узла той же функции. Затем мы снова вызываем функцию, сначала в левом узле, а затем в правом.
В этом примере мы получим максимальную глубину дерева
var depth = 0;
function walkTree(node, i) {
//Increment our depth counter and check
i++;
if (i > depth) depth = i;
//call this function again for each of the branch nodes (recursion!)
if (node.left != null) walkTree(node.left, i);
if (node.right != null) walkTree(node.right, i);
//Decrement our depth counter before going back up the call stack
i--;
}
Наконец, мы вызываем функцию
alert('Tree depth:' + walkTree(tree, 0));
Отличный способ понять рекурсию - это пошаговое выполнение кода во время выполнения.
Рекурсия - это причудливый способ сказать: «Сделайте это еще раз, пока оно не будет выполнено».
Две важные вещи:
Представьте себе простую задачу: отсортировать стопку книг по алфавиту. Простой процесс - взять первые две книги и отсортировать их. А теперь переходим к рекурсивной части: есть ли еще книги? Если да, сделайте это снова. «Сделай это снова» - это рекурсия. «Есть ли еще книги?» - это проверка. И «нет, больше нет книг» - это базовый вариант.
В основном это. Он продолжает вызывать себя до тех пор, пока не будет выполнен
void print_folder(string root)
{
Console.WriteLine(root);
foreach(var folder in Directory.GetDirectories(root))
{
print_folder(folder);
}
}
Также работает с циклами!
void pretend_loop(int c)
{
if(c==0) return;
print "hi";
pretend_loop(c-);
}
Вы также можете попробовать погуглить. Обратите внимание на «Возможно, вы имели в виду» (щелкните по нему ...). http://www.google.com/search?q=recursion&spell=1
Примером может быть печать каждого файла в любых подкаталогах данного каталога (если у вас нет символических ссылок внутри этих каталогов, которые могут каким-то образом нарушить работу). Псевдокод печати всех файлов выглядит так:
function printAllFiles($dir) {
foreach (getAllDirectories($dir) as $f) {
printAllFiles($f); // here is the recursive call
}
foreach (getAllFiles($dir) as $f) {
echo $f;
}
}
Идея состоит в том, чтобы сначала распечатать все подкаталоги, а затем файлы текущего каталога. Эта идея применяется ко всем подкаталогам, и это причина для рекурсивного вызова этой функции для всех подкаталогов.
Если вы хотите попробовать этот пример, вам нужно проверить специальные каталоги .
и ..
, иначе вы застрянете в постоянном вызове printAllFiles (".")
. Кроме того, вы должны проверить, что печатать и какой у вас текущий рабочий каталог (см. opendir ()
, getcwd ()
, ...).
Рекурсия - это альтернатива циклам, они редко добавляют больше ясности или элегантности в ваш код. Хороший пример был дан в ответе Прогмана: если бы он не использовал рекурсию, он был бы вынужден отслеживать, в каком каталоге он находится в настоящее время (это называется состоянием). Рекурсии позволяют ему вести учет с использованием стека (область, в которой переменные и возвращаемый адрес метода сохраняются)
Стандартные примеры факториала и Фибоначчи бесполезны для понимания концепции, потому что их легко заменить циклом.
Проще говоря: рекурсивная функция - это функция, которая вызывает сама себя.