
- •Смоленский гуманитарный университет
- •Часть 1. Основы алгоритмизации
- •Тема 1 «Алгоритмы линейной структуры»
- •Ход работы
- •Тема 2 «Алгоритмы разветвляющейся структуры»
- •Ход работы
- •Тема 3 «Алгоритмы циклической структуры»
- •Ход работы
- •Тема 4 «Вложенные циклы»
- •Ход работы
- •Тема 5 «Массивы»
- •Ход работы
- •Часть 2. Программирование
- •Тема 6 «Линейная структура программы»
- •Примеры решения задач
- •Ход работы
- •Тема 7 «Разветвляющая структура программы»
- •Примеры решения задач
- •Ход работы
- •Тема 8 «Циклическая структура программы»
- •Примеры решения задач
- •1 Способ
- •2 Способ.
- •1 Способ
- •2 Способ
- •1 Способ
- •2 Способ
- •1 Способ
- •2 Способ
- •Ход работы
- •Тема 9 «Понятие подпрограммы. Организация процедур и функций»
- •Примеры решения задач
- •Ход работы
- •Тема 10 «Рекурсия»
- •Примеры решения задач
- •Ход работы
- •Тема 11 «Строковый тип данных. Методы работы со строками»
- •Ход работы
- •Тема 12 «Тип данных массив»
- •Примеры решения задач
- •1 Способ
- •2 Способ
- •1 Способ
- •2 Способ
- •1 Способ
- •2 Способ
- •Алгоритм
- •1 Способ
- •2 Способ
- •1 Способ
- •2 Способ
- •Алгоритм
- •Работа программы
- •Ход работы
- •Тема 13 «Тип данных - запись»
- •Ход работы
- •Тема 14 «Файлы. Типы файлов. Методы работы с файлами»
- •Примеры решения задач
- •1 Способ
- •2 Способ
- •Ход работы
- •Тема 15 «Множества»
- •Ход работы
- •Тема 16 «Работа с мультимедиа»
- •Ход работы
- •Максимова Наталья Адександровна Основы программирования
- •214014, Г. Смоленск, ул. Герцена, 2
Тема 10 «Рекурсия»
Цель: Познакомиться с понятием рекурсия.
Вопросы к допуску и защите:
Дать определение рекурсии.
Виды рекурсии.
Алгоритмы рекурсивных функций.
Структура рекурсивной процедуры.
Примеры решения задач
Задача 1. Вычисление факториала числа.
Решение
Program Problem1;
uses WinCrt;
var
n : integer;
f : real;
{---------------------------------------------------------------------------------------}
Procedure fac(n : integer; var f : real);
begin
if (n=0) or (n=1) then f := 1
else
begin
fac(n - 1, f);
f := f*n
end
end;
{---------------------------------------------------------------------------------------}
begin
write('Введите натуральное значение n '); readln(n);
fac(n, f);
writeln('Факториал числа ', n, ' равен ', f:12:0)
end.
Задача 2. Над цепью озер летела стая белых гусей. На каждом озере садилось половина гусей и еще полгуся, а остальные летели дальше. Все гуси сели на семи озерах. Сколько гусей было в стае?
Решение
Математически задача решается устно очень остроумным способом.
Пусть вместе со
стаей белых гусей все время летит еще
один, Серый гусь. Если к некоторому озеру
подлетит m
белых гусей и Серый, то на этом озере
садится
- ровно половина всех гусей вместе с
серым. Поэтому после каждого озера число
летящих гусей уменьшается ровно вдвое.
После семи озер оно уменьшится в 27
= 128 раз, а
остается летящим один Серый гусь. Значит,
вначале было 128 гусей, из них 127 - белых.
А теперь выполним, образно говоря, прямые рассуждения для решения задачи.
Обозначим через xk количество летящих белых гусей, когда впереди еще k озер. Тогда условие задачи записывается так:
Отсюда получаем для последовательности (xk) рекуррентное соотношение
Program Problem2;
uses WinCrt;
var
k : integer;
{----------------------------------------------------------------------------------------}
Procedure goose(x, k : integer);
begin
if k = 1 then write(x) else goose(2*x + 1, k - 1)
end;
{----------------------------------------------------------------------------------------}
begin
write('Введите число озер '); readln(k);
write('В стае было ');
goose(1, k);
writeln(' гусей')
end.
Задача 3. Мой богатый дядюшка подарил мне один доллар в мой первый день рождения. В каждый следующий день рождения он удваивал свой подарок и прибавлял к нему столько долларов, сколько лет мне исполнилось. Написать программу, подсчитывающую общую сумму денег, подаренных к N-му дню рождения и указывающую, к какому дню рождения сумма подарка превысит 100$.
Решение
Введем обозначения: k - число лет племянника, p - количество денег, которые дает дядя на каждом дне рождения, s - общая сумма денег, полученных племянником за все годы, n - счетчик числа дней рождения, который считает в обратном порядке от n (введенного пользователем) до 1.
Задаются
первоначальные значения формальным
параметрам процедуры:
n - вводится пользователем из основной
программы (вы обратили внимание, что в
этой, как и в предыдущей процедуре нет
выходных параметров и нет переменных
в самой процедуре, хотя возможны и другие
варианты).
Увеличивается число лет: k := k + 1; вычисляется подарок к k-тому дню рождения: p := 2*p + k; вызывается процедура, в которой увеличивается на p общая сумма полученных денег s и уменьшается на 1 число дней рождения:
uncle(k, p, s + p, n - 1)
Далее весь процесс повторяется, до тех пор, пока n не станет равным 1.
Program Rich_man1; { rich man - богатый }
uses WinCrt;
var
n : integer;
{---------------------------------------------------------------------------------------}
Procedure uncle(k, p, s, n : longint); {uncle - дядя}
begin
if n = 1 then write(s)
else
begin
k := k + 1;
p := 2*p + k;
uncle(k, p, s + p, n - 1)
end
end;
{---------------------------------------------------------------------------------------}
begin
write('Введите число лет племянника '); readln(n);
write('Я получу к ', n, '-ому дню рождения ');
uncle(1, 1, 1, n);
writeln(' долларов')
end.
Во второй части условия требуется определить число лет, когда сумма полученных денег будет равна или превысит 100 долларов. Для этого в процедуре меняется опорное условие: if s >= 100 then write(n), а все остальное остается без изменений.
Program Rich_man2;
uses WinCrt;
var
n : integer;
{----------------------------------------------------------------------------------------}
Procedure uncle1(k, p, s, n : longint);
begin
if s >= 100 then write(n)
else
begin
k := k + 1;
p := 2*p + k;
uncle1(k, p, s + p, n + 1)
end
end;
{--------------------------------------------------------------------------------------}
begin
write('Сумма подарка превысит 100 долларов к ');
uncle1(1, 1, 1, 1);
writeln(' -ому дню рождения')
end.
Задача 4. Перемножая большие числа, можно быстро получить переполнение. Поэтому, для того чтобы напечатать произведение, превышающее наибольшее допустимое для данного целого типа (integer или longint) числа, надо применить искусственные средства.
Составим программу для печати произведения двух чисел, которое может превы-шать максимально допустимое целое число.
Решение
Процедура multiplication умножает число a на каждую цифру числа b, начиная с цифры единиц. Последняя цифра полученного произведения, сложенная с последней цифрой имеющегося в памяти частичного произведения, печатается, а все прочие цифры запоминаются - передаются как параметры при рекурсивном обращении к процедуре multiplication. В самом конце производится умножение на первую (левую) цифру числа b. На этом умножение заканчивается. Тогда печатается начало результата - накопившееся частичное произведение без последней цифры (s div 10), а после него при возвращении из рекурсии - все остальные цифры произведения (s mod 10) в обратном порядке по сравнению с тем, как они вычислялись при входе в рекурсию.
Program Problem4; { Большое произведение }
uses WinCrt;
var
x, y : longint;
{----------------------------------------------------------------------------------------}
Procedure multiplication(a, b, s : longint);
begin
if b <> 0 then
begin
s := s+a*(b mod 10);
multiplication(a, b div 10, s div 10);
write(s mod 10:1)
end
else if s <> 0 then write(s)
end;
{----------------------------------------------------------------------------------------}
begin
write('Введите первый множитель '); readln(x);
write('Введите второй множитель '); readln(y);
write(x,'*',y:1,' = ');
if ((x < 0) and (y > 0)) or ((x > 0) and (y < 0)) then write('-');
multiplication(abs(x), abs(y), 0);
writeln
end.