Академический Документы
Профессиональный Документы
Культура Документы
Курсовая
Курсовая
ВВЕДЕНИЕ..............................................................................................................3
1 Рекурсия................................................................................................................4
1.1 Понятие рекурсии....................................................................................4
1.2 Применение рекурсивных алгоритмов.................................................8
2 Итерации.............................................................................................................13
2.1 Понятие итерационных алгоритмов..........................................13
2.1.1 Цикл с известным числом повторений (for)..........................13
2.1.2 Цикл с предусловием. Оператор while...................................15
2.1.3 Цикл с постусловием. Оператор repeat..................................16
2.1.4 Вложенные циклы....................................................................18
2.2 Применение итерационных алгоритмов.............................................19
3 Сравнение рекурсивных и итерационных алгоритмов...................................22
3.1 Вычисление N-го числа Фибоначчи....................................................22
3.2 Вычисление факториала.......................................................................23
ЗАКЛЮЧЕНИЕ.....................................................................................................26
Список литературы...............................................................................................27
2
ВВЕДЕНИЕ
3
1 Рекурсия
4
Безусловные рекурсивные процедуры приводят к бесконечным
процессам, и на эту проблему нужно обратить особое внимание, так как
практическое использование процедур с бесконечным самовызовом
невозможно.
Следовательно, главное требование к рекурсивным процедурам
заключается в том, что вызов рекурсивной процедуры должен выполняться
по условию, которое на каком-то уровне рекурсии станет ложным.
Если условие истинно, то рекурсивный спуск продолжается. Когда оно
становится ложным, то спуск заканчивается и начинается поочередный
рекурсивный возврат из всех вызванных на данный момент копий
рекурсивной процедуры. Структура рекурсивной процедуры может
принимать три разных формы:
1) форма с выполнением действий до рекурсивного вызова (на
рекурсивном спуске);
procedure Rec;
begin
S;
if условие then
Rec;
end;
2) форма с выполнением действий после рекурсивного вызова (на
рекурсивном возврате);
procedure Rec;
begin
if условие then
Rec;
S;
end;
5
3) форма с выполнением действий как до, так и после рекурсивного
вызова (с выполнением действий как на рекурсивном спуске, так и на
рекурсивном возврате).
procedure Rec;
begin
S1;
if условие then
Rec;
S2 ;
end;
Все формы рекурсивных процедур находят применение на практике.
Многие задачи, в том числе вычисление факториала, безразличны к тому,
какая используется форма рекурсивной процедуры. Однако есть классы
задач, при решении которых программисту требуется сознательно управлять
ходом работы рекурсивных процедур и функций. Такими, в частности,
являются задачи, использующие списковые и древовидные структуры
данных.
Рассмотрим пример рекурсивной функции rever выводящею цифры
переданного ей числа n в обратном порядке.
procedure rever (n: integer);
begin
write (n mod 10);
if (n div 10) <> 0 then
rever (n div 10)
end;
begin
rever (3096);
end.
Алгоритм работы функции:
6
1. На вход функции rever в качестве параметра n поступает число
3096.
2. Процедура rever выводит на экран остаток от деления на 10. Это
число 6.
3. Переход на новую строку не происходит, т.к. используется write.
4. Проверяется условие того, что 3096 при деление нацело на 10
больше нуля.
5. Вызывается rever с фактическим параметром, равным 309.
6. Вторая запущенная процедура выводит на экран цифру 9 и
запускает третью процедуру с параметром 30.
7. Третья процедура выводит 0 и вызывает четвертый rever с 3 в
качестве параметра.
8. Четвертая процедура выводит 3 на экран и ничего больше не
вызывает, т.к. условие (3 div 10) <> 0 ложно.
9. Четвертая процедура завершается и передает управление третьей.
10. Третья процедура завершается и передает управление второй.
11. Вторая процедура завершается и передает управление первой.
12. Первая процедура завершается и передает управление в
основную ветку программы.
В итоге, процедура rever была вызвана четыре раза (глубина рекурсии
равна 4), хотя из основной программы к ней было единственное обращение.
Наличие условия в теле рекурсивной функции (или процедуры), при
котором она больше себя не будет вызывать, очень важно. В противном
случае, как и в ситуации с циклами, может произойти так называемое
зацикливание.
Возможна чуть более сложная схема: функция A вызывает функцию B,
а та в свою очередь вызывает A. Это называется сложной рекурсией. Ниже
представлен пример сложной рекурсии.
procedure A(n: integer); {Полное описание процедуры A}
begin
7
writeln(n);
B(n-1);
end;
procedure B(n: integer); {Полное описание процедуры B}
begin
writeln(n);
if n<10 then
A(n+2);
end;
8
Рисунок 1.1 - Бинарное дерево
9
Рисунок 1.2 - Результат обхода дерева тремя различными структурами
рекурсивной процедуры
Еще один пример рекурсии - это фракталы. Фракталами называют
геометрические объекты, линии, поверхности, пространственные тела,
имеющие сильно изрезанную форму и обладающие свойством самоподобия
(«fractus» - делить, ломать).
Ниже приведены примеры фракталов.
10
Рисунок 1.3 - Кривая коха
12
2 Итерации
13
оператор;
или
for параметр := нач_знач downto кон_знач do
оператор;
14
2.1.2 Цикл с предусловием. Оператор while
16
Рисунок 2.3 - Блок-схема цикла repeat
17
2.1.4 Вложенные циклы
20
Рисунок 2.5 - Блок-схема алгоритма метода трапеций
22
for k := 2 to n do
begin
t := y;
y := x + y;
x := t;
end;
Iteration := y; {итерация}
end;
Var
n:integer = 20;
begin
writeln('Рекурсивный алгоритм : F(', n, ')= ', Recursion(n));
writeln('Итерационный алгоритм : F(', n, ')= ', Iteration(n));
end.
23
Ниже приставлен код вычисления факториала на языке
программирования Pascal.
function FacRecursive(n: Integer): Real;
begin
if n = 0 then
FacRecursive := 1
else FacRecursive := n * FacRecursive(n - 1)
end;
function FacIteration(n: Integer): Real;
var
s, i: integer;
begin
s := 1;
for i := 1 to n do
S := S * i;
FacIteration:=s;
end;
var
n: integer;
begin
write('n: ');
readln(n);
writeln('Итерация: ',FacIteration(n));
writeln('Рекурсия: ',FacRecursive(n));
end.
Как и при вычислении числа Фибоначчи, рекурсивный код алгоритма
более компактный, но на него затрачивается большее количество памяти.
Важнейшим достоинством рекурсивного подхода к программированию
является краткость записи и прозрачность рекурсивных алгоритмов. Не
следует также забывать об ориентации рекурсивного программирования на
24
математическую форму записи, а следовательно, о возможности
доказательства правильности построенных алгоритмов.
Однако, если существует очевидное итеративное решение, не следует
заменять его на рекурсию, поскольку активация рекурсивной процедуры
потребует дополнительных затрат времени и памяти множество объектов,
т.е. множество переменных, констант, типов и процедур, которые
определены в ней. При каждом рекурсивном вызове процедуры порождается
новое множество локальных переменных. Хотя они имеют те же самые
имена, что и локальные переменные предыдущего поколения, их значения
могут быть различными, а конфликты по именам разрешаются с помощью
правил, определяющих область действия идентификаторов. Аналогичные
утверждения справедливы и для параметров рекурсивных процедур
(функций). При этом все предыдущие поколения локальных переменных
сохраняются в области памяти, называемой стеком вызова подпрограмм. В
данном случае его можно называть стеком рекурсивных вызовов. Кроме
локальных переменных, в стеке сохраняется текущее состояние вычислений,
т.е. адрес той команды, на которую нужно вернуться, чтобы закончить
вычисления, прерванные вызовом подпрограммы. Очевидно, что при
большой глубине рекурсии может возникнуть проблема нехватки памяти
(переполнение стека рекурсивных вызовов). В итеративных алгоритмах такие
проблемы, как правило, не возникают.
25
ЗАКЛЮЧЕНИЕ
26
Список литературы
27