45 комментариев
|
Илья
|
29.09.2011 в 15:40
|
Прочитал, что на некоторых функциональных языках задача разложения рекурсии в цикл решается на уровне компилятора. Говорят, что так сделано в Erlang.
|
|
Злата
|
06.12.2011 в 15:33
|
Очень интересно представлн материал: образно и понятно. Спасибо!
|
|
Николай
|
09.04.2012 в 15:00
|
Очень понятное изложение материала. Огромное спасибо!
|
|
Александр
|
25.10.2012 в 17:10
|
Класс! Очень толково.
|
|
Дмитрий
|
03.12.2012 в 22:07
|
Интересное представление материала. Очень полезно и занимательно. СПАСИБО
|
|
Аноним
|
13.12.2012 в 20:24
|
Здраствуте я поддерживаю выше сказаное, можно у вас попросить о помощи?, мне нужен код программы или исходник, на курсовую работу, времени мало на подготовку и я просто не смогу усвоить весь материал за короткое время, программа на тему «рекурсивный алгоритм поиска в массивах данных» Пожалуйста
|
|
юрий
|
10.05.2013 в 22:52
|
не понятен образ рекурсии «змей пожирающий свой хвост» и про двух волков…немного ясно становится первое объяснение с rec(a),далее если оператор writeln(a)ставим перед if (rec2(a))ничего не меняется ,идет вывод цифр в том же порядке-в чем фишка? не написано для чего нужна рекурсия,то же самое можно делать с иттерацией не переполняя память или как?
|
|
Акгуль
|
23.11.2013 в 13:09
|
Очень интересный и точный материал! Спасибо!
|
|
Олег
|
29.01.2014 в 01:59
|
Материал супер. Узнал кое-что новое, хоть и с рекурсией дружу уже 2 года.
|
|
Александр
|
06.05.2014 в 01:55
|
2 дня не мог написать функцию, а просто нужно было ещё раз почитать про суть подхода. Спасибо за доступное и полезное изложение материала.
|
|
Alexandr
|
10.08.2014 в 15:14
|
Огромное спасибо! Все разжевано и понятно. Идеальный материал для студентов.
|
|
NK
|
30.10.2014 в 08:24
|
Юрию «не понятен образ рекурсии «змей пожирающий свой хвост» и про двух волков…»
С образами рекурсии сложно, да. Они не объяснять должны, а давать образную картинку. Про двух волков… Может, будет интереснее так:«За что же, не боясь греха, кукушка хвалит петуха? За то, что хвалит он кукушку»
|
|
Галина
|
23.11.2014 в 18:25
|
Тарас Викторович, большое спасибо.Тема рекурсии включена в демоверсии ЕГЭ по информатике и очень актуальна. А вот изложения материала в доступной и понятной форме мало.
|
|
Юрий
|
27.03.2015 в 16:55
|
В примере с функциями loop_imitation(i, n) выводиться будут значения до 11 включительно.
|
|
Taras
|
27.03.2015 в 18:06
|
Спасибо, исправил.
|
|
mikserok
|
11.05.2015 в 11:58
|
Это оптимизация называется хвостовая рекурсия. Она встроена во все современые компиляторы. Так что если у вас процедура или функция вызывает сама себя всего 1 раз скорей всего она будет превращена в цикл на уровне машинных команд (асм) или уровне байткода. Точнее даже раньше на уровне внутренеего представления вашей проги — объектных команд компирятора.
|
|
roamer
|
24.10.2015 в 23:23
|
Цикл на erlang (как вариант):
%% =================================
cycle_1_cycle(F,I, N2, Step) ->
case (I = ok;
true ->
F(I),
cycle_1_cycle(F,I+Step, N2, Step)
end.
%% Цикл по одной переменной
cycle_1(F, N1, N2, Step) ->
cycle_1_cycle(F, N1, N2, Step).
%% =================================
Пример вызова:
cycle_1(fun(X)-> io:format(«~p~n»,[X]) end, 3,10,1).
|
|
roamer
|
24.10.2015 в 23:31
|
Sorry. Как-то странно и непонятно опубликовался текст (выше).
4-я строка сверху должна быть:
case (I _знак_меньше_или_равно_ N2) of
Следующая за ней (почему-то пропущена) должна быть:
false -> ok;
Последняя строка: должны быть двойные кавычки (а не те, что там «нарисовались»)…
|
|
Аноним
|
22.11.2015 в 21:36
|
Все хорошо. Но как сделать большой файловый стек?
|
|
Аноним
|
18.03.2016 в 01:36
|
Спасибо вам большое за разжевывание !
|
|
Perman
|
16.07.2016 в 22:53
|
Очень внятно изложил всю суть, класс
|
|
Галина
|
10.08.2016 в 09:53
|
Лучшего изложения материала по рекурсиям я не встречала. Спасибо!
|
|
Виталий
|
17.08.2016 в 17:59
|
В частности для дерева на рис. 3 и 4 прямой обход дает последовательность узлов: A, B, C, D, E, G, H.
Отлично изложен материал. У вас похоже здесь ошибка в составе дерева на рис. 3.
|
|
Taras
|
17.08.2016 в 19:19
|
Спасибо, Виталий. Исправил.
|
|
Николай
|
20.09.2016 в 20:30
|
Очень понятное объяснение! Побольше бы таких материалов!!! Класс!!!
|
|
Макс
|
19.10.2016 в 21:25
|
поясните, пожалуйста, новичку такой момент.
Общее правило, что команды выполняются последовательно, сначала первая, затем вторая и т.д. В самом первом примере здесь вначале идет проверка условия if, затем рекурсионный вызов Rec(a-1), а за ним вывод на печать
if a>0 then
Rec(a-1);
writeln(a);
Но если команды выполняются последовательно, то до печати ведь дело не должно дойти, поскольку рекурсионный вызов завернул процесс и снова вызвал функцию, где опять первым пунктом идет проверка условия и за ним снова рекурсионный вызов!?
Почему же тогда команда вывода на печать накапливается в стеке? Ведь по идее она не должна запускаться и поэтому она не может быть незаконченной?
|
|
Taras
|
19.10.2016 в 21:42
|
Каждый новый вызов Rec происходит с на единицу меньшим значением параметра. В конце концов параметр окажется равен нулю и тогда новый вызов не произойдет. Дальше последняя вызванная Rec напечатает свой параметр и завершит работу. После этого предпоследняя Rec напечатает параметр и т.д.
|
|
Макс
|
20.10.2016 в 00:28
|
и все равно не въезжаю, почему после того, как последняя Rec напечатает свой параметр и завершит работу, почему после этого выполняется предпоследняя команда на печать? Она ведь на запускалась и поэтому не может находиться в стеке, поскольку там хранятся только незавершенные команды, т.е. те которые начаты, но не закончены. А эта предпоследняя команда на печать, как и предыдущие, они не ведь не начинались?
|
|
Taras
|
20.10.2016 в 00:38
|
Предпоследняя Rec начала выполнятся. Когда она встретила последний вызов Rec, то оставшаяся невыполненной часть (печать параметра) отправилась в стек. Когда последний вызов Rec завершился, из стека достается эта невыполненная часть и выполняется.
|
|
Макс
|
20.10.2016 в 01:20
|
ок, поясните плз в коде, когда именно начинает выполняться предпоследняя и предыдущие перед ней?
if a>0 then
Rec(a-1);
writeln(a);
Ведь здесь четко видно, что вызов Rec выполняется раньше writeln? И что до writeln дело не доходит
|
|
Taras
|
20.10.2016 в 18:37
|
В предпоследней Rec будет вызов Rec(0). Он завершится, после этого выполниться writeln.
|
|
Макс
|
20.10.2016 в 19:50
|
да, согласен, вызов с Rec(0) завершится и после него выполнится команда writenln. Здесь как раз-таки все понятно.
Но почему после этого начнут выполняться предыдущие whriteln? Ведь по идее их не должно быть в стеке?
Как я пытался показать в предыдущем комментарии, Rec(a-1) расположен в коде раньше, чем whriteln. Поэтому вначале выполняется Rec(a-1) и он заворачивает процесс к началу функции. И в этом случае по идее до команды whrieln дело не доходит, т.е. она не выполняется. А если она не выполняется, то она и не останавливается, не прерывается. Следовательно она и не должна попадать в стек!
Т.е. whriteln может выполниться только один раз, когда происходит вызов Rec(0) и после этого всё!
Сорри, что может быть напрягаю, но уже зациклился on this point и не могу понять, где ошибка в этих рассуждениях?
|
|
Taras
|
20.10.2016 в 20:02
|
Каждый раз, когда одна функция вызывает другую, ее состояние (локальные переменные, значения параметров) и точка, где такой вызов произошел, отправляются в стек.
Вызываем Rec(1). Он доходит до вызова Rec(0), отправляет в стек значение параметра (a = 1), и место с которого надо продолжить выполнение (сразу после вызова Rec(0)). Только после этого начинается выполнение Rec(0). Когда Rec(0) закончилась, из стека достается инфа, что a = 1 и надо выполнять код Rec(1) после вызова Rec(0).
|
Do'stlaringiz bilan baham: |