- •Лекция 9. Рекурсия Введение
- •Рекурсивные описания алгоритмов.
- •Реализация рекурсии
- •Примеры рекурсивных и нерекурсивных описаний
- •Var I: Integer; y: Real;
- •Var X:Integer;
- •Var s: Sequence;
- •Var I: Integer;
- •Var j : integer; Buf: Char;
- •Var s : Sequence;
- •Var j : integer;
- •Техника рекурсивных описаний
- •Var I, j, y, z : Integer;
- •Var a, X : Vector; b : Integer; I : Integer;
- •Преимущества и недостатки рекурсивных алгоритмов
Реализация рекурсии
Вычисление функции F можно представить как цепочку вызовов новых копий этой функции c передачей новых значений аргумента и возвратов значений функции в предыдущую копию.
n-1
n-2 n-3
0
n!
F(n) F(n-1) F(n-2) F(1)
Цепочка вызовов обрывается при передаче нуля в новую копию функции. Движение в прямом направлении (разворачивание рекурсии) сопровождается только вычислением условия и вызовом.
Значение функции вычисляется при сворачивании цепочки вызовов.
Рекурсивное обращение к процедуре (рекурсивный вызов функции) можно представить как
Построение в памяти компьютера новой копии этой процедуры;
Передачу управления в эту новую копию (с новыми значениями параметров);
Обработку (возможно – рекурсивную) данных в этой копии;
Возврат в предыдущую копию (с прежними значениями параметров)
Примеры рекурсивных и нерекурсивных описаний
Пример 3. Функция GCD(x, y) вычисляет наибольший общий делитель (НОД) двух натуральных чисел x и y. (Алгоритм Евклида)
Алгоритм Евклида, изучаемый в школьном курсе математики в средних классах, находит НОД двух чисел, вычитая из большего числа меньшее.
{итеративное описание}
Function GCD (x, y : Integer) : Integer ;
Begin
While x <> y do
If x < y
then y := y - x
else x := x - y ;
GCD := x
End;
{рекурсивное описание}
Function GCD (x, y : Integer) : Integer ;
Begin
If x <> y
Then If x < y
then GCD:= GCD(x, y - x)
else GCD := GCD(x - y, y)
Else GCD := x
End;
Рекурсивная версия следует из свойств НОД, выраженных формулами - соотношениями:
x < y НОД(x, y) = НОД(x, y - x)
x > y НОД(x, y) = НОД(x - y, y)
НОД(x, x) = x;
Function GCD (x, y: Integer) : Integer ;
Begin
If (x <> 0)and(y <> 0)
Then GCD:= GCD(y mod x, x mod y)
else GCD := x + y
End;
Пример 4. Функция Pow(x, N) возводит положительное действительное число x в натуральную степень N. (Y = xN )
{итеративный алгоритм }
Function Pow(x: Real; N: Integer):Real;
Var I: Integer; y: Real;
Begin
y := 1;
For i:=1 to N do y := y * x;
Pow := y
End;
{рекурсивный алгоритм}
Function Pow(x: Real; N: Integer) : Real;
Begin
Case N of
0: Pow := 1;
1: Pow := x
else
Pow := Sqr(Pow(x, N div 2))*Pow(x, N mod 2)
end
End;
Итеративный алгоритм вычисления степени xN умножает y на x ровно N раз, начиная с y = 1. Для вычисления xN алгоритм выполняет N умножений.
Рекурсивный алгоритм: для вычисления xN сначала предлагается вычислить x в половинной степени, а затем результат возвести в квадрат.
x0 = 1; x1 = x;
N четно xN = (xN / 2 )2;
N нечетно xN = (x (N-1) / 2 )2 * x
В этой версии алгоритм выполнит не более log2(N) возведений в квадрат и log2(N) умножений - всего 2 log2(N) действий.
С помощью рекурсии удалось просто описать эффективный по времени (т.е. по количеству действий) алгоритм возведения в степень.
Детали рекурсивных алгоритмов
Алгоритмы, использующие рекурсию, обязаны содержать процедуру (функцию), вызываемую рекурсивно.
Всю совокупность переменных, используемых для описания рекурсивного алгоритма, можно разделить на 3 группы:
глобальные переменные алгоритма;
параметры рекурсивной процедуры (функции);
локальные переменные этой процедуры (функции).
Глобальные переменные, не являющиеся фактическими параметрами рекурсивной процедуры, сохраняют неизменными свои значения при обращениях к процедуре из основной программы или рекурсивных вызовах этой процедуры.
Локальные переменные могут изменить свои значения только в данной копии рекурсивной процедуры. Значение локальной переменной, которое она имеет в момент рекурсивного вызова, не изменится и после возврата (выхода) из рекурсии.
Procedure E(N:Integer);
