Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции по программированию..pdf
Скачиваний:
10
Добавлен:
15.11.2022
Размер:
12.2 Mб
Скачать

Далее разговор пойдет о ситуации на первый взгляд совершенно парадоксальной. Оказывается, подпрограмма в своем описании может содержать обращение к самой себе. Такая подпрограмма называется рекурсивной.

7.4.Рекурсивные подпрограммы

Вматематике рекурсивным называется определение любого поня­ тия через самого себя. Классическим примером является определение факториала целого числа, большего или равного нулю.

.

Г1,

если 7Т= О,

ть

<

если п > 0.

 

\ п (п -1 )!,

Здесь функция факториал определена через факториал. Нетрудно по­ нять справедливость такого определения. Для п > 0:

п

п—1

гг! = П i =

1 *2 х х (п - 1) •гг = п •Д г = п(п - 1)!

i=i

i=i

Вариант 0! = 1

является тривиальным. Но это ’’ опорное” значе­

ние, от которого начинается раскручивание всех последующих значе­ ний факториала:

1! = 1 *0! = 1 •1 = 1; 2! = 2-1! = 2; 3! = 3 2! = 6 и т.д.

Рассмотрим подпрограмму-функцию, использующую в своем опи­ сании приведенную выше рекурсивную формулу.

Function Factor(N Pozlnt) Pozlnt;

Begin

I f N=0

Then Factor :a 1

Else Factor := N * Factor(N - 1)

End;

Предполагается, что тип Pozlnt объявлен глобально следующим обра­ зом:

Type Pozlnt * 0..MaxInt;

Пусть в основной программе для вычисления в целой переменной л значения 3! используется оператор

При вычислении функции с аргументом 3 произойдет повторное об­ ращение к функции Factor(2). Это обращение потребует вычисления F a ctor(l). И наконец, при вычислении Fact or (0) будет получен число­ вой результат 1. Затем цепочка вычислений раскрутится в обратном порядке:

F a cto r(l)

= 1

*

Factor(O)

1

F actor(2)

2

*

F actor(l)

®

2

F actor(3)

=

3

*

Factor(2)

= 6.

Последовательность рекурсивных обращений к функции должна обя­ зательно выходить на определенное значение. А весь маршрут после­ довательных вхождений машина запоминает в специальной области памяти, называемой стеком.Таким образом, выполнение рекурсивной функции происходит в два этапа: прямой ход — заполнение стека; об­ ратный ход — цепочка вычислений по обратному маршруту, сохранен­ ному в стеке.

Использование рекурсивных функций - красивый прием с точки зрения программистской эстетики. Однако этот путь не всегда самый рациональный. Рассмотренную задачу с а! можно решить так:

F :=

1;

 

For I

:* 1

То N Do

F

F *

I;

Очевидно, что такой вариант программы будет работать быстрее, чем рекурсивный. И в том случае, когда важнейшим является сокращение времени выполнения программы, следует отдать предпочтение после­ днему варианту.

В каждой конкретной реализации Паскаля имеется ограничение на количество рекурсивных обращений к подпрограмме (глубине рекур­ сии). Это связано с ограничением на размер стека. По этой причине можно попасть в ситуацию, когда рекурсивной подпрограммой вообще не удастся воспользоваться.

Рекурсивно определена может быть не только функция, но и проце­ дура. Рассмотрим еще одну классическую задачу, известную в лите­ ратуре под названием ’’Ханойская башня” .

На площадке (назовем ее А) находится пирамида, составленная из дисков уменьшающегося размера от основания к вершине.

(x i=- 0) и целого п, которая вычисляет величину хп согласно формуле

 

1

при п = 0,

хл

1

при п < 0,

 

х хп~1

при п > 0.

6. Даны натуральные числа п и т ; найти НОД(п, т ) . Использовать программу, включающую рекурсивную процедуру вычисления НОД, основанную на соотношении НОД(п,т) = И ОД(т,г), где г — остаток от деления п на т.