Форум программистов, компьютерный форум, киберфорум
PHP для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/58: Рейтинг темы: голосов - 58, средняя оценка - 4.67
3 / 3 / 0
Регистрация: 18.09.2011
Сообщений: 61

Как работает рекурсивная функция?

28.12.2013, 19:58. Показов 11759. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Готовлюсь к собеседованию и прохожу всякие вопросы которые там будут, наткнулся с "рекурсивная функция" и не могу понять как она работает, кто знает обьясните на примере...
Вот такой пример факториала:
PHP
1
2
3
4
5
6
function fac($x) {
if ($x === 0) return 1;
else
return $x*fac($x-1);
}
echo fac(5);
если х ровно 0 выводит 1
если не ноль то число х множим на свою же функцию и -1 --- это обьясните, не догоняю как оно работает, зачем -1? можно же циклом сделать но так же лучше
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
28.12.2013, 19:58
Ответы с готовыми решениями:

Неправильно работает рекурсивная функция
Всем привет. Ребят, есть вот такая задача: Есть организация. У неё есть всякие подразделения (ID). У каждого подразделения есть баллы,...

Рекурсивная функция
Помогите исправить мою ошибку в функции. Код: <?php function open_read($open){ $dir = $open; $files = scandir($dir); ...

Рекурсивная функция для произведения чисел
Добрый вечер. Пытаюсь решить задачу: нужно создать рекурсивную функцию, которая должна выводить произведение чисел от 5 до 15. На...

14
Почетный модератор
Эксперт HTML/CSSЭксперт PHP
 Аватар для KOPOJI
16844 / 6724 / 880
Регистрация: 12.06.2012
Сообщений: 19,967
28.12.2013, 20:11
Цитата Сообщение от женя610 Посмотреть сообщение
Вот такой пример факториала:
Лучше уж такой, немного грамотнее будет..
PHP
1
2
3
4
5
6
function fac($x) {
    if ($x === 0)
        return 1;
    return $x*fac($x-1);
}
echo fac(5);
Цитата Сообщение от женя610 Посмотреть сообщение
обьясните
Все очень просто.
В начале стоит проверка: является ли число Х нулем. Факториал от нуля - единица (по определению), поэтому можно сразу вернуть ответ.
Далее завершается выполнение этой функции совместно с вызовом этой же функции еще раз.
И так по кругу, т.е., рекурсивно.
Факториал - это произведение всех чисел до заданного.
В данном случае производится произведение "в обратную" сторону, т.е., не от 1 до X, а от X до 1. Именно поэтому и написано X - 1 - это уменьшение числа (ведь на X мы уже умножили результат).
Можно сказать, что это и есть некоего рода "цикл" - функция "зацикливается", при каждом новом вызове уменьшая значение аргумента до тех пор, пока X не станет равным нулю и не выполнится первое условие (x === 0) - тогда функция вернет 1 в последний раз и на этом этот "цикл" закончится.
З.Ы. просто, по сути, это другой подход, функциональный..
2
3 / 3 / 0
Регистрация: 18.09.2011
Сообщений: 61
28.12.2013, 20:22  [ТС]
спасибо, это понял
Теперь скажите зачем вообще нужна это рекурсивная функция? Приведите еще пример, что бы я понял как и когда ее нужно применять кроме этого примера
ее используют вместо цикла или что?
0
Почетный модератор
Эксперт HTML/CSSЭксперт PHP
 Аватар для KOPOJI
16844 / 6724 / 880
Регистрация: 12.06.2012
Сообщений: 19,967
28.12.2013, 20:45
вариантов масса. Например, поиск файлов в директории можно реализовать с помощью рекурсии. Особенно удобно это делать, если необходимо реализовать поиск с "заходом" в поддиректории и поиска файлов внутри, навскидку, как-то так
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function searchFiles($dir)
{
    if(!is_dir($dir))
        return false;
 
    static $files = array();
 
    $dir .= substr($dir, -1) == '/' ? '' : '/';
 
    foreach(scandir($dir) as $file)
    {
        if($file == '.' || $file == '..')
            continue;
        if(is_dir($dir . $file))
            searchFiles($file);
        else
            $files[] = $file;
    }
 
    return $files;
}
0
3 / 3 / 0
Регистрация: 18.09.2011
Сообщений: 61
28.12.2013, 20:52  [ТС]
KOPOJI, Вот вопрос еще
PHP
1
    return 2*fac($x-1);
fac(3);
выполняется так:
2*3-1 = 5
2*2-1 = 3
2*1-1 = 0
и выводит 8
А если факториал
PHP
1
    return $x*fac($x-1);
то как оно считает? например число 5 в факториале ровно 120, по выше приведенному примеру как то так должно
5*5-1 =24
5*4-1 =19
5*3-1 =14
5*2-1 =9
5*1-1 =4
ровно 70, а должно быть 120 значит не верно, как считает напишите
0
Почетный модератор
Эксперт HTML/CSSЭксперт PHP
 Аватар для KOPOJI
16844 / 6724 / 880
Регистрация: 12.06.2012
Сообщений: 19,967
28.12.2013, 21:01
Вы совсем неверно считаете. Почему у вас всегда x == 5 ? Ведь я говорил, что return завершает текущий вызов функции и вызывает следующую. К тому же, скобки надо расставлять верно.
5 * (5-1)! = 5 * 4 = 20
20 * (4-1)! = 20 * 3 = 60
60 * (3-1)! = 60 * 2 = 120
120 * (1-1)! = 120 * 1 = 120
1
3 / 3 / 0
Регистрация: 18.09.2011
Сообщений: 61
28.12.2013, 21:10  [ТС]
спасибо Вам большое с этого примера я и понял как работает и зачем надо рекурсивная ф-ция
0
1 / 1 / 0
Регистрация: 24.02.2019
Сообщений: 101
14.04.2019, 09:54
Всем привет.
Изучаю рекурсивную функцию. Пример выше мне понятен да еще и с пошаговым разбором ))
Не могу понять как работает код:
PHP
1
2
3
4
5
6
7
8
9
10
11
function echoRec($n)
{
    if ($n == 1) {
        echo $n . " "; // просто выводим
    } else {
        //echo $n . " "; // выводим переданное
    echoRec($n - 1); // выводим предыдущее
        echo $n . " "; // выводим переданное
    }
}
echoRec(4); // выведем все до n-ти
Пошагово в коде что происходит?
n = 4, далее заходим в теле else. Снова вызывается функция, но уже со знач n = 3. Происходит вывод на экран "3". Далее, уже
n = 3, далее заходим в теле else. Снова вызывается функция, но уже со знач n = 2. Происходит вывод на экран "2". Далее, уже
n = 2, далее заходим в теле else. Снова вызывается функция, но уже со знач n = 1. Аргумент равен "0". Функция заканчивает работу {строка echoRec($n - 1)}.
Но n = 1, поэтому выполняется тело опер if и выводится "1".
Вопросы:
1. А когда тогда выводится "4"?
2. И почему вывод происходит 1 2 3 4, а не 4 3 2 1 ?
0
Эксперт PHP
4925 / 3920 / 1620
Регистрация: 24.04.2014
Сообщений: 11,441
14.04.2019, 10:19
Цитата Сообщение от xat55 Посмотреть сообщение
Пошагово в коде что происходит?
n = 4, далее заходим в теле else. Снова вызывается функция, но уже со знач n = 3. Происходит вывод на экран "3". Далее, уже
n = 3, далее заходим в теле else. Снова вызывается функция, но уже со знач n = 2. Происходит вывод на экран "2". Далее, уже
n = 2, далее заходим в теле else. Снова вызывается функция, но уже со знач n = 1. Аргумент равен "0". Функция заканчивает работу {строка echoRec($n - 1)}.
Не так
n = 4, заходим в тело else. Вызывается функция, со знач n = 3.
n = 3, заходим в тело else. Вызывается функция, со знач n = 2.
n = 2, заходим в тело else. Вызывается функция, со знач n = 1.
n = 1, заходим в тело if. Происходит вывод на экран "1".
Происходит вывод на экран "2".
Происходит вывод на экран "3".
Происходит вывод на экран "4".
1
1 / 1 / 0
Регистрация: 24.02.2019
Сообщений: 101
14.04.2019, 10:32
А если в коде строчки поменять местами:
PHP
1
2
echo $n . " "; // выводим переданное
echoRec($n - 1); // выводим предыдущее
То, тогда, действительно, будет вывод таким:
4 3 2 1

Добавлено через 8 минут
Я правильно понял, что идет своего рода накопление данных, как в массиве, и только потом вывод на экран?

Все равно, непонятно, идет накопление данных в обратном порядке (4 3 2 1), а вывод в прямом (1 2 3 4).

Можете разъяснить поподробнее?

Добавлено через 3 минуты
Цитата Сообщение от Jewbacabra Посмотреть сообщение
Происходит вывод на экран "2".
Происходит вывод на экран "3".
Происходит вывод на экран "4".
После вывода на экран "1" непонятно почему в такой последовательности? Что побудило выходить данные в таком порядке?
0
Эксперт PHP
4925 / 3920 / 1620
Регистрация: 24.04.2014
Сообщений: 11,441
14.04.2019, 10:41
Цитата Сообщение от xat55 Посмотреть сообщение
Можете разъяснить поподробнее?
Почитай про стек вызовов.

Если бы в данной функции заменить рекурсивный вызов на функцию заглушку
PHP
1
2
3
4
5
6
7
8
9
10
11
12
function foo($n) {
    echo "In foo function: $n ";
}
function echoRec($n) {
    if ($n == 1) {
        echo $n . " ";
    } else {
        foo($n - 1);
        echo $n . " ";
    }
}
echoRec(4);
Тогда пошаговое описание работы функции было бы таким (каждай вложенный вызов функции на отступе, выполнение кода идет сверху вниз, отступы значения не имеют, нужны только для визуального выделения)
n = 4, заходим в тело else. Вызывается функция foo, со знач n = 3.
n = 3. Происходит вывод на экран "In foo function: $n ".
Происходит вывод на экран "4".

Вывод будет именно в таком порядке, потому что инструкция echo в функции выполнится раньше. Если строки поменять местами
PHP
1
2
echo $n . " ";
foo($n - 1);
То будет наоборот.

В случае рекурсивного вызова все остается точно также.
1
1 / 1 / 0
Регистрация: 24.02.2019
Сообщений: 101
14.04.2019, 11:32
Цитата Сообщение от Jewbacabra Посмотреть сообщение
Почитай про стек вызовов.
Если не сложно, то киньте ссылку, где можно почитать без "воды". Пока то, что я нашел, понял, стек - это не резиновое хранилище (память) для данных.
Пока не смог найти ответ на вопрос, ведь"обход" функции был в обратном порядке, а почему вывод на экран в прямом.
0
Эксперт PHP
4925 / 3920 / 1620
Регистрация: 24.04.2014
Сообщений: 11,441
14.04.2019, 11:41
Цитата Сообщение от xat55 Посмотреть сообщение
Пока не смог найти ответ на вопрос, ведь"обход" функции был в обратном порядке, а почему вывод на экран в прямом.
Я же ответил на этот вопрос. Попробуй сам вместо интерпретатора построчно выполнять данную функцию, или в phpstorm с помощью xdebug построчно выполнять, там как раз и стек вызовов будет виден.
1
1 / 1 / 0
Регистрация: 24.02.2019
Сообщений: 101
14.04.2019, 14:35
Цитата Сообщение от xat55 Посмотреть сообщение
Пока не смог найти ответ на вопрос, ведь"обход" функции был в обратном порядке, а почему вывод на экран в прямом.
Почитал про стек. Вроде, стало понятно.
Цитата Сообщение от Jewbacabra Посмотреть сообщение
Попробуй сам вместо интерпретатора построчно выполнять данную функцию, или в phpstorm с помощью xdebug построчно выполнять, там как раз и стек вызовов будет виден.
Поставил эту прогу, пока не знаю как ею пользоваться )) Жаль... Хотел стек вызовов увидеть.

Еще вопрос (я новичок в программировании).
Подскажите, почему, если я поставлю в код вместо строки
PHP
1
echo " ". $n;
эту строку:
PHP
1
return $n;
то результат будет только: "1" ?
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
function echoRec($n)
{
    if ($n == 1) {
        echo $n . " "; // просто выводим
    } else {
        //echo $n . " "; // выводим переданное
    echoRec($n - 1); // выводим предыдущее
    return $n;   
    }
    
}
echoRec(4); // выведем все до 15-ти
?>
В чем, в данном случае, принципиальная разница между этими операторами?
PHP
1
echo
- выводит на экран
PHP
1
return
- возвращает значение
0
Эксперт PHP
4925 / 3920 / 1620
Регистрация: 24.04.2014
Сообщений: 11,441
14.04.2019, 14:58
Цитата Сообщение от xat55 Посмотреть сообщение
В чем, в данном случае, принципиальная разница между этими операторами?
Собственно в этом и разница
Цитата Сообщение от xat55 Посмотреть сообщение
echo выводит на экран
Цитата Сообщение от xat55 Посмотреть сообщение
return возвращает значение
return ничего не выводит, вывод в коде функции может быть только при $n = 1, что и наблюдается
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
14.04.2019, 14:58
Помогаю со студенческими работами здесь

Рекурсивная функция вывода данных из БД
Доброго времени суток!Столкнулся с проблемой поиска и дальнейшего вывода данных из базы данных. Вдоваться в подробности не буду, объясню...

Как работает рекурсивная функция
Есть функция вывода бинарного дерева struct Node { int x; Node *l,*r; }; void show(Node *Tree) { if (Tree!=NULL)

Объяснить как работает рекурсивная функция и стек вызовов на моем примере
Объясните пожалуйста как работает рекурсивная функция и стек вызовов на моем примере. Здесь известный алгоритм &quot;Разделяй и...

В VS 2015 не работает рекурсивная функция, которая работает в C++Builder
Добрый день! Перенес блок кода из старого учебного проекта под C++Builder, который там всегда стабильно работал, на VS 2015. Одна из...

Не работает рекурсивная функция
Файл &quot;Tree.js&quot; function changeDisplay(id){ //Функция открытия закрытия дерева var ul = document.getElementById('ul' +...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
Влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
Установка Android SDK, NDK, JDK, CMake и т.д.
8Observer8 25.01.2026
Содержание блога Перейдите по ссылке: https:/ / developer. android. com/ studio и в самом низу страницы кликните по архиву "commandlinetools-win-xxxxxx_latest. zip" Извлеките архив и вы увидите. . .
Вывод текста со шрифтом TTF на Android с помощью библиотеки SDL3_ttf
8Observer8 25.01.2026
Содержание блога Если у вас не установлены Android SDK, NDK, JDK, и т. д. то сделайте это по следующей инструкции: Установка Android SDK, NDK, JDK, CMake и т. д. Сборка примера Скачайте. . .
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru