Рекурсия

Встречаются задачи, в которых подпрограмма вызывает саму себя. Это называется рекурсией. Таким образом можно организовать хитрые циклы, которые иным способом либо очень трудно, либо невозможно сделать. Например, процедура KRUG рисует круг, состоящий из кругов, которые в свою очередь состоят из кругов и т.д… Ёлочка – это большая ветка, состоящая из веток, которые состоят из веточек… Любые самоповторяющиеся рисунки (фракталы) создаются с помощью рекурсии. Но не только рисунки. С помощью рекурсии работает процедура закраски (в начальной позиции ставится точка, которая ставит точки вокруг себя, а те в свою очередь ставят точки вокруг них… и т.д., пока не будет достигнута граница). С помощью рекурсии можно найти кратчайший путь к выходу из лабиринта, экономно раскроить заготовку на детали и т.д. Одним словом, если встречается сложная задача, которую вроде бы решить нужно циклом, но непонятно, как его организовать – попробуйте рекурсию! Приведём пример:

Нарисовать с использованием рекурсии ёлочку.

program elka; uses graphabc; var gd,gm:integer; procedure vetka(x,y,alf,dl:real); var xk,yk,dx,dy:real; i:integer; begin xk:=x+dl*sin(alf); yk:=y-dl*cos(alf); line(round(x),round(y),round(xk),round(yk)); if dl<15 then exit; {Условие окончания рекурсии} dx:=(xk-x)/8; dy:=(yk-y)/8; for i:=1 to 8 do begin vetka(x+i*dx,y+i*dy,alf-pi*0.35,dl*(0.5-i*0.06)); vetka(x+i*dx,y+i*dy,alf+pi*0.35,dl*(0.5-i*0.06)); end; end; begin setwindowsize(700,500); vetka(320,450,0,400); end.  

 

 

 

Находим координаты (xk, yk) конца веточки и проводим отрезок из начала в конец. Затем делим ветку на 8 частей (находим шаги dx и dy) и в этих точках рекурсивно вызываем процедуру «ветка», задавая ей другие углы (влево и вправо от ветки на π*0.35) и уменьшенную длину.

Должно получиться нечто следующее:

Использование рекурсии опасно зависанием. В примере с ёлочкой каждая следующая веточка вызывается меньших размеров. Но так может продолжаться до бесконечности (а точнее, до переполнения памяти), если процесс уменьшения не остановить. В данном примере мы прекращаем рекурсивный вызов, если длина очередной веточки становится меньше 15 пикселов. (Можно сделать ограничение в 1 пиксел, но тогда иголки будут короткими). На этом примере можно сформулировать правило безопасной рекурсии: В рекурсивной процедуре проверку условия окончания рекурсии нужно выполнять ДО рекурсивного вызова.

Кроме прямой рекурсии, о которой рассказано выше, существует ещё косвенная рекурсия: подпрограмма A вызывает подпрограмму B, которая в свою очередь вызывает A … Например, круг, который состоит из квадратов, которые состоят из кругов… Здесь возникает такая проблема: одна из этих подпрограмм, например, A, описана выше и не знает о существовании подпрограммы B, которая описана ниже, следовательно, не может к ней обратиться. Для решения такой проблемы в Паскале предусмотрен механизм предварительного описания. Заголовок (только!) подпрограммы B копируют до подпрограммы A, а в конце этого заголовка после точки с запятой добавляют слово forward. Это слово показывает Паскалю, что это ещё не описание подпрограммы, а только прототип, предварительное оповещение.


 








Дата добавления: 2014-12-18; просмотров: 938;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.006 сек.