Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
2011_12 Комп.Науки_2сем.doc
Скачиваний:
4
Добавлен:
13.09.2019
Размер:
476.67 Кб
Скачать

19.5.2.Глубокая рекурсия

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

Если стек все равно переполняется, перепишите алгоритм в не рекурсивном виде.

19.5.3.Итерация и рекурсия, необоснованное применение рекурсии

Итерация – это организация обработки данных с помощью циклов.

Пример: Вычислим число Фибоначчи с заданным номером с помощью цикла и рекурсивно.

f0=f1=1; fn=fn-1+fn-2 при n>1

Итерационный вариант

Рекурсивный вариант

function Fib(n:integer): integer;

var i,f1,f2,f3: integer;

begin

if (n=1) or (n=2) then Fib:=1

else begin

f1:=1; f2:=1;

for i:=3 to n do

begin f3:=f1+f2;

f1:=f2; f2:=f3

end

Fib:=f3

end;

end;

function RF(n:integer):integer;

begin

if (n=1) or (n=2) then RF:=1

else RF:=RF(n-1)+RF(n-2)

end;

Вычислим рекурсивно 5-ое число Фибоначчи.

Сколько рекурсивных вызовов произойдет?

Для вычисления 4-го числа надо вычислить 3-ое и 2-е, для вычисления 3-го – 2-ое и 1-ое, затем повторно вычислить 2-ое; наконец, повторно вычислить 3-е, 2-ое и 1-ое.

Каждый вызов при n>1 приводит к двум дальнейшим вызовам, т.е. число вызовов растет экспоненциально.

Всего будет 8 рекурсивных вызовов. Кроме того, заново вычисляются числа Фибоначчи, которые уже были вычислены.

Вывод: рекурсивная программа вычисления чисел Фибоначчи непригодна для практического использования.

19.6.Когда использовать рекурсию

Рекурсия полезна при решении задач, которые естественным образом разбиваются на несколько подзадач, каждая из которых является более простым случаем исходной задачи. Но даже если задача определена рекурсивно, не всегда лучшим способом решения задачи является рекурсивный алгоритм. Во многих случаях вместо краткого рекурсивного алгоритма лучше воспользоваться циклом. Хотя программа станет длиннее, работать она будет быстрее.

19.7.Формы рекурсивных подпрограмм

В общем случае любая рекурсивная подпрограмма P включает в себя некоторое множество операторов S и один или несколько условных операторов рекурсивного вызова P. Пока условие истинно, рекурсивный спуск продолжается. Когда условие становится ложным, спуск заканчивается и начинается рекурсивный возврат из всех вызванных на данный момент копий рекурсивной подпрограммы.

Рассмотрим четыре разные формы рекурсивных подпрограмм на примере процедур (для функций аналогично):

  1. Действия выполняются до рекурсивного вызова (на рекурсивном спуске).

procedure P(n); begin S; //выполняется на рекурсивном спуске if условие then Р(n-1) end;

  1. Действия выполняются после рекурсивного вызова (на рекурсивном возврате).

procedure P(n); begin if условие then P(n-1); S; //выполняется на рекурсивном возврате end;

  1. Действия выполняются до и после рекурсивного вызова (на рекурсивном спуске и на рекурсивном возврате).

    procedure P(n);

    begin

    S1; //выполняется на рекурсивном спуске;

    if условие then P(n-1);

    S2; //выполняется на рекурсивном возврате

    end;

    procedure P(n);

    begin

    if условие then

    begin

    S1; //выполняется на рекурсивном спуске

    P(n-1);

    S2 //выполняется на рекурсивном возврате

    end

    end.

  2. Каскадная рекурсия – рекурсивные вызовы образуют дерево, например, при рекурсивном вычислении чисел Фибоначчи, при обходе деревьев.

procedure P(n); begin S; //может отсутствовать if условие1 then P(n-1); S1; //может отсутствовать if условие2 then P(n-1); S2 //может отсутствовать

end;

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]