- •2008 № I информатика
- •2008 № 4 Информатика
- •2. Статья "Частотный анализ"
- •1. Общие вопросы
- •2. Особенности выполнения рекурсивных алгоритмов
- •3. Рекурсивные функции и процедуры для обсуждения
- •2008 Nt 5 информатика
- •4. Задания на использование рекурсии
- •2008 № 5 Информатика
- •2008 N» 5 информатика
- •2008 N» 5 информатика
- •2008 № 5 Информатика
- •5. Прямая и косвенная рекурсия
- •5. Формы рекурсивных процедур6
- •2008 № 5 Информатика
2008 № 5 Информатика
Begin
write ('Введите очередное число
последовательности') ; readln{n); If n <> 0 Then Begin
{Рекурсивно вызываем процедуру Output для ввода очередного числа} Output;
(После 'возвращения' из нее выводим введенное число} write(n, ' '} End Else
write ('Числа последовательности
в обратном порядке: ') End;
20. Задача "Ханойские башни".
Имеется три стержня А, В, С. На стержень А нанизаны п дисков таким образом, что диаметр дисков увеличивается при их просмотре сверху вниз. Требуется переместить все диски на стержень В, используя диск С как вспомогательный и соблюдая следующие правила:
1) перекладывать диски можно по одному;
2) снятый диск нельзя отложить — он должен быть надет на один из стержней;
3) диски нельзя размещать на дисках меньшего размера.
Решение
Если диск один — задача решается одним перемещением. Сложнее, если дисков больше. Предположим, что мы умеем перекладывать пирамиду из (п — 1) диска. Тогда для перемещения п дисков необходимо:
1) переместить верхние (п — 1) дисков на стержень С;
2) перенести последний, самый большой, диск со стержня А на стержень В;
3) переместить пирамиду из (п — 1) дисков со стержня С на стержень В.
Решение задачи для (п — 1) дисков аналогично. В результате таких рекурсивных действий можно прийти к ситуации, когда количество перемещаемых дисков равно 1, а такую задачу мы решать умеем.
В программе следует использовать две процедуры, одна из которых — рекурсивная:
1) процедуру перемещения одного диска:
Procedure MoveOneDisk(a, b: char); Begin
Write{a, '->', b, ' ') End;
2) процедуру перемещения п дисков:
Procedure MoveDisks(n: byte; a, b, c: char); Begin
If n = l Then
{Используем процедуру MoveOneDisk} MoveOneDisk(a, b)
Else
Begin
MoveDiskstn - 1, a, c, b); write(a,'->', b, ' '); MoveDisks(n — 1, c, b, a) End End;
Можно также задачу при п = 1 отдельно не рассматривать:
Procedure MoveDiskstn: byte; a, b, с: char); Begin
If n > 0 Then Begin
MoveDisks(n - 1, a, c, b); writeta,'->', b, ' '); MoveDiskstn - 1, c, b, a) End End;
5. Прямая и косвенная рекурсия
Обычная" рекурсия, при которой процедура илр функция обращается к самой себе, называется "прямой рекурсией". Существует также разновидность рекурсии которую называют косвенной, или непрямой. Такой ре-курсией является ситуация, когда процедура А вызыва ет себя в качестве вспомогательной не непосредственно а через другую вспомогательную процедуру Б, которая в свою очередь, обращается к процедуре А.
Косвенную рекурсию демонстрирует следующа* программа, в которой находятся и выводятся вс( простые числа, не превышающие некоторого зна чения п.
Создадим функцию логического типа с именем Prim проверяющую, является ли число i — ее параметр, прос там. Чтобы ответить на этот вопрос, достаточно прове рить делимость г на все простые числа, не превышающе квадратный корень из г. Перебор таких простых чисе можно организовать так: рассмотреть первое просто число — 2, а затем использовать функцию NextPrin, возвращающую следующее за значением ее параметр; простое число:
Function Prim(j: word): boolean;
Var k: word;
Begin
k := 2; (первое простое число} While (k * k <= j) And (j mod k <> 0) Do k := NextPrim(k);
(Значение к 'пробегает' последовательность простых чисел, начиная с 2 и до корня из j, при этом проверяется, делится ли j на одно из таких простых чисел} If j mod k = 0
(Если встретилось составное число} Then Prim : = false Else Prim := true End;
Функцию же NextPrim можно оформить так: Function NextPrim(i: word): word; Var p: word; Begin
p := i + 1;
2008 N. 5 ИНФОРМАТИКА
While notd'iimfp)) Do N"Xt.Pr i m ; - jj
End
И пси потеряются на "простоту" числа/), начиная со шачепии, на I большего шачепин параметра /, и делается .m> с homoiijiiIo функции Prim (т.е. функция Prim нмзмнает функпик> N<:*xr.Pr im, а последняя обращается к I'rim, т.е. имеет место к(Ч*венная рекурсия).
При косвенной рекурсии возникает проблема —■ если нерпой ошютгь функцию Pi im/гоона будет иснольижать еще не описанную функцию N<xt pr im, ччч1 и языке программирования I Ьскаль недопустимо(аналогичнои если, naiWxijxrr, первой описать функцию N>-xt Pr im). Выходом янляето! так na.tbiiviCMiK' "опережаюп^х* описание" функции. Оно лчкакусктся (мим, тл> :к1пхинкж НАШ41 и.ч функций ука «лки-тся пер1*ым со слуиаЧжымслопом For w.i i d:
Function N<'Xt.Prim(i: ward): word; Forward; — после чего полностью описывается сгорая функция:
Function Pr im(j : word): boolean;
Var k: word;
Begin
:i taivM — нерпам функция; Function NextPrim; Var ;: word; Begin
OGpiuijaeM Ш1ил\;и(ие mi ti>, что в полном описи 1ии функ-цииЫехг.Ргхт в лн^ичжесписок 1\юрмяльш>\хпярлмитроа и тип ремулкпгт не ук;иыв:шл\:л (они уже объявлены piuteti).
Замечим также, что число 2 — простое, а число 1 простым не считается. Это означает, что значение 2 в основной программе должно быть вынелено без проверки, которая ндхшодится с иомопи»к) функции Prim для всех нечетных чисел, не превышающих п.