
- •Занятие № 1. Алгоритм. Язык и среда программирования.
- •Занятие № 2. Язык программирования Pascal.
- •Занятие № 3. Переменные. Простейшие линейные алгоритмы.
- •Занятие № 4. Стандартные операции ввода/вывода.
- •Занятие № 5. Ветвление с простым условием.
- •Занятие № 6. Составные условия.
- •Занятие № 7. Множественное ветвление. Безусловный переход.
- •Занятие № 8. Самостоятельная работа. Занятие № 9. Цикл со встроенным счётчиком (с параметром).
- •Занятие № 10. Стандартные функции. Преобразование типов. Операции над строковым типом данных.
- •Занятие № 11. Циклы с условием
- •Занятие № 12. Самостоятельная работа. Занятие № 13. Введение в машинную графику в Pascal.
- •Занятие № 14. Вывод текста в графическом режиме.
- •Занятие № 15. Простейшая анимация.
- •Занятие № 16. Построение графиков функций.
- •Занятие № 17. Самостоятельная работа. Занятие № 18. Вспомогательный алгоритм. Процедуры и функции пользователя.
- •Занятие № 19. Структурные типы данных. Понятие линейного массива.
- •1. Заполнение вводом с клавиатуры:
- •4. Описание предустановленных массивов.
- •5. Заполнение данными из внешнего файла.
- •Занятие № 20. Простейшие задачи на операции с линейным массивом.
- •1. Подсчёт количества элементов удовлетворяющих некоторому условию.
- •3. Раскрашивание массива.
- •4. Поиск минимального и максимального элементов.
- •5. Копирование и перестановка элементов. Занятие № 21. Сортировка линейного массива.
- •1. Сортировка прямого обмена.
- •2. Обменная сортировка (метод «Пузырька»).
- •Занятие № 22. Понятие двумерного массива.
- •Занятие № 23. Решение задач на тему «Двумерные массивы».
- •Занятие № 24. Самостоятельная работа. Занятие № 25. Множества.
- •В этом случае описано множество a, которое может включать в себя элементы – целые числа в интервале от 1 до 12. Существует возможность описания константных множеств:
- •Задача: составить программу, определяющую количество дней в указанном месяце, указанного года.
- •Занятие № 26. Записи.
- •Занятие № 27. Файлы данных. Текстовые файлы.
- •Занятие № 28. Решение задач (текстовый файл). Занятие № 29. Файлы данных. Типизированные файлы.
- •Занятие № 30. Самостоятельная работа.
- •Занятие № 31. Библиотеки пользователя.
- •Занятие № 32. Некоторые процедуры и функции модуля dos.
- •Занятие № 33. Рекуррентные последовательности и формулы. Рекурсивные алгоритмы.
- •Занятие № 35. Элементы объектно-ориентированного программирования.
Занятие № 33. Рекуррентные последовательности и формулы. Рекурсивные алгоритмы.
В программировании существует один очень мощный метод с которым мы познакомимся на этом занятии. Он называется рекурсией. Начинающему программисту он может показаться довольно сложным именно поэтому начнём наше рассмотрение этого метода издалека. В математике достаточно часто встречаются последовательности чисел, в которых существует закономерности между каждым последующим числом в зависимости от предыдущего, либо предыдущих. Например:
1, 2, 3, 4, …
2, 4, 6, 8, … (1)
2, 4, 8, 16, 32, …
Приведённые последовательности в математики называются прогрессиями (две первые арифметическими, последняя – геометрической) и выражаются специальными формулами, которые показывают как выражается некоторый произвольный член в зависимости от предыдущего. Например для арифметической прогресси можно записать следующую формулу:
ai=ai-1+d
Формулы, выражающие очередной член последовательности через один или несколько предыдущих членов, называются рекуррентными соотношениями.
Приведем иную последовательность: 1, 1, 2, 3, 5, 8, 13, …
В этой последовательности каждый следующий член равен сумме двух предыдущих членов. Такая последовательность получила название чисел Фибоначчи (под Фибоначчи - Леонардо Пизанский, итальянский математик, живший на рубеже ХП-ХШ в.в., известен "Книгой абака" в которой систематично изложил достижения арабских математиков для Западной Европы). Для такой последовательности можно записать следующую рекуррентную формулу:
аi=аi-1+аi-2 a1=a2=l
Счетчик (типа а=а+1) является также примером рекуррентного вычисления величины.
Теперь попытаемся написать программу, которая будет вычислять n-ый член такой последовательности. Понятно, что в этом случае очень удобно воспользоваться циклом (например с параметром) и написание такой программы предоставим читателю на самостоятельную работу.
Программы производящие те же действия (расчёт n-го члена) можно написать и с помощью метода информатики – рекурсии.
Можно рассмотреть еще один пример такой последовательности:
последовательность 2, 3, 5, 9, 17, ..., задаваемую рекуррентным соотношением ai=2*ai-1-1, ai=2. В этом случае можно легко написать алгоритм рекуррентного вычисления членов последовательности. Под рекурсией понимают ситуацию, когда вспомогательный алгоритм вызывает сам себя непосредственно, либо посредством дополнительных вспомогательных алгоритмов.
Этот процесс не может продолжаться бесконечно, поэтому требуется также предусмотреть условие, при котором подобные вызовы прекратятся – условие выхода из рекурсии.
Например, для вычисления n-го члена последовательности (1) можно написать следующую функцию:
function row(n: integer): integer;
begin
if n=1 then row:=2 else row:=2+row(n-1);
end;
Прокомментируем работу данной функции. Предположим, что нужно вычислить 3-й член для этого требуется узнать второй, а, в свою очередь, для этого требуется узнать первый, который известен – это 2. Т.о., знание первого члена числового ряда и есть условие выхода из рекурсии. Для того, чтобы узнать третий член потребуется вызов функции с параметром 3:
WriteLn(row(3));
При это функция вызывает себя с параметром 2, затем снова с параметром 1, однако, у нас стоит условие, где указывается, что в случае значения параметра n=1 требуется возвратить результат 2. Попытаемся пояснить также эту ситуацию на равенстве:
row(3)=2+row(2)=2+2+row(1)=2+2+2=6
Приведём ещё один пример. Составим рекурсивную функция для расчета n-го члена ряда Фибоначчи. Воспользуемся тем, что нам известны два первых члена ряда (условие выхода из рекурсии):
function fib(n: integer):integer;
begin
case n of
1,2: fib:=1;
else fib:=fib(n-1)+fib(n-2);
end;
end;
Теперь следует понять одну очень важную речь, что рекурсии можно распространить не только на числовые ряды, но и на ситуации. Например, для того, чтобы перевести целое положительное число из десятичной системы счисления в любую другую позиционную систему счисления по основанию P требуется производить поэтапное целочисленное деление на основание системы счисления в которую осуществляется перевод (P) и собирать целочисленные остатки в обратном порядке (см. школьный курс информатики). Эта ситуация рекурсивна, поэтому её можно запрограммировать с помощью нашего метода. Для простоты решения задачи создадим дополнительную функцию, позволяющую осуществлять преобразования числового типа данных в строковый, т.к. результат работы нашей основной функции будет строка, являющаяся числом в системе счисления по основанию P. Приведём функцию, позволяющую осуществлять преобразование десятичных чисел в двоичную систему счисления (P=2).
function IntToStr(n: integer): string;
var t: string;
begin str(n,t); IntToStr:=t; end;
function DecToBin(a: word): string;
begin
if a>0 then
DecToBin:=DecToBin(a div 2)+IntToStr(a mod 2)
else DecToBin:='';
end;
Рекурсивные алгоритмы, могут быть нескольких видов.
Рекурсия бывает:
1. Конечной и бесконечной. Бесконечный рекурсивный вызов вспомогательного алгоритма приводит к ошибке переполнения стека, т.к. при каждом вызове происходит запоминание очередного адреса перехода к рекурсивному вспомогательному алгоритму, что требует выделения памяти стека.
2. Прямой и косвенной. Прямой рекурсия считается в том случае, если вызов вспомогательного алгоритма осуществляется непосредственно самим вспомогательным алгоритмом. При вызове вспомогательного алгоритма посредством других вспомогательных алгоритмов будем иметь дело с косвенной рекурсией.
3. Терминальной и нетерминальной. Терминальной рекурсия считается, если рекурсивный вызов осуществляется последней командой вспомогательного алгоритма. В противном случае рекурсия нетерминальная.
Например, рекурсия, использованная в первом алгоритме по расчёту чисел Фибоначчи является конечной, прямой, терминальной.
Контрольные вопросы:
1. Определите вид рекурсии в примере № 2 приведённом на занятии.
Задание:
1. Последовательность чисел 2, 3, 5, 9, 17, … задается следующим рекуррентным соотношением: ai=2*ai-1-1, ai=2
Вычислить значение n-го члена последовательности использовав рекуррентное соотношение:
а) с помощью цикла;
б) используя рекурсию.
2. Напишите функцию, осуществляющую рекурсивный поиск числа.
3. Найти рекуррентное соотношение и составить программу для расчета n-го члена следующей последовательности:
1, 2, 6, 24, 120, 720,…
4. Найти рекуррентное соотношение и составить программу для расчета n-го члена следующей последовательности:
1, 2, 11, 26, 57, 120,…