
- •1.1. Основные этапы создания программы
- •1.2. Алгоритмы
- •2.1. Структура типов в Turbo Pascal
- •Стандартные скалярные типы. Типы целых чисел
- •2.3. Операции побитовой обработки
- •2.4. Представление вещественных чисел в эвм
- •2.5. Символьный тип
- •2.6. Булевский тип
- •2.7. Перечисленный тип
- •2.8. Интервальный тип (диапазон)
- •3.1. Структура программы на turbo pascal
- •3.2. Основные операторы языка
- •3.2.1. Простые операторы
- •3.2.2. Операторы ввода-вывода
- •3.2.3. Структурные операторы
- •3.2.4. Условные операторы
- •3.2.5. Операторы повтора (цикла)
- •4.1. Массивы
- •4.2. Строковый тип
- •4.3. Множества
- •5.1. Процедуры и функции
- •5.2. Процедуры и функции пользователя
- •5.3. Передача параметров по значению и по ссылке
- •5.4. Рекурсивные процедуры и функции
- •6.1. Структура модулей
- •6.2. Компиляция и использование модулей
- •7.1. Записи
- •7.2. Вложенные записи
- •7.3. Записи с вариантами (вариантные записи)
- •7.4. Файлы
- •7.5. Подпрограммы для работы с файлами
- •7.5.1. Процедуры
- •7.5.2. Функции
- •7.6. Примеры программ для обработки файлов
- •7.7. Текстовые файлы
- •8.1. Структура оперативной памяти для программ на Turbo Pascal
- •8.2. Динамические структуры данных
- •8.3. Основные процедуры и функции для работы с динамическими переменными
- •8.4. Динамика выделения памяти в куче
- •8.5. Линейные списки. Способы создания и обработки
- •8.6. Нелинейные списки. Способы создания и обработки
- •Библиографический список
- •Оглавление
- •394026 Воронеж, Московский просп., 14
5.4. Рекурсивные процедуры и функции
Рекурсивным называется объект, частично определяемый через самого себя, например:
Рекурсия
в программировании
– это способ организации программ, при
котором подпрограмма прямо или косвенно
вызывает саму себя. Если подпрограмма
вызывает себя в своем теле, то такая
рекурсия называется прямой.
Если же подпрограмма
вызывает подпрограмму
,
которая прямо или косвенно вызывает
,
то такая рекурсия называется косвенной.
Любая рекурсивная подпрограмма должна содержать два обязательных элемента:
- условие завершения, в противном случае процесс рекурсивного обращения будет бесконечным;
87
- способ выражения одного шага решения посредством другого, более простого шага.
Проиллюстрируем механизм рекурсии на примере вычисления факториала числа.
Function fact(n: integer): real;
begin
if n = 1 then fact: = 1 {Условие завершения рекурсии}
else
fact:
= n
* fact(n-1)
{Происходит рекурсивное} {обращение к
функции , но уже с меньшим значением
}
end;
Рассмотрим более подробно вычисление fact(5).
На
первом шаге
,
поэтому происходит повторное обращение
к функции уже со значением
,
затем со значением
и так далее, пока
не станет равным 1, то есть, не будет
достигнуто условие, позволяющее
организовать своевременную остановку
процесса. Процесс рекурсивных вызовов
называется рекурсивным
спуском.
Процесс
возврата из рекурсивных вызовов,
наступающий после получения
называется рекурсивным
возвратом.
;
Но
для выполнения рекурсивного возврата
необходимо одновременно хранить в стеке
в течение всего времени работы функции
коэффициенты:
.
Если
значение
достаточно велико, то возможно переполнение
стека и аварийное завершение программы.
Рассмотрим
функцию, реализующую возведение целого
числа
в целую неотрицательную степень
:
88
Function Power (a, n : integer): real;
begin
if n = 0 then power: =1
else
begin
if odd(n) then power: = a*power(a, n-1)
{Если
показатель степени будет четным, то
можно сократить} {число обращений,
использовав зависимость
}
else power: = power(a*a, n div 2);
end;
end;
Используем рекурсию для нахождения минимального элемента в одномерном массиве:
type mas=array[1..10] of real;
var n: integer;
a: mas;
function minX(const x: mas; n: integer): real;
var result: real; i: integer;
begin
write(n,' - ');
for i:=1 to n do
write(x[i]:3:0, ' ');
writeln;
if n = 1 then result: = x[n]
else
begin
result: =minX(x,n-1);
writeln('x[n] result');
writeln(x[n]:3:0, ' ',result:3:0);
if x[n] < result then result: = x[n];
89
end;
minX: = result;
end;
begin
n: = 5;
a[1]: = 23; a[2]: = 10; a[3]: = 85;
a[4]: = 3; a[5]: = 16;
writeln(minX(a,n));
end.
Механизм работы программы иллюстрируется следующим протоколом:
5 - 23 10 85 3 16
4 - 23 10 85 3
3 - 23 10 85
2 - 23 10
1 - 23
x[n] result
10 23
85 10
3 10
16 3
3
Рекурсивные подпрограммы чаще всего применяют для компактной записи рекурсивных по своей природе алгоритмов, а также для работы со структурами данных, которые определяются в терминах рекурсии. Любую рекурсивную подпрограмму можно реализовать без применения рекурсии.
Достоинством рекурсии является компактная запись. К недостаткам относятся: расход времени и памяти на повторные вызовы функции и передачу ей параметров, а также возможность переполнения стека.
90
Контрольные вопросы и упражнения
1. Чем отличаются процедуры от функций?
2. Чем отличаются формальные параметры от фактических?
3. В чем различие между параметрами-значениями и параметрами переменными?
4. Какие обязательные элементы должны содержать рекурсивные процедуры и функции?
5. Что такое рекурсивный спуск и рекурсивный возврат?
Разработать программы для решения следующих задач:
6.
Построить матрицу
,
где
- квадратные матрицы,
-
единичная матрица.
Ввод
матриц, вывод матриц на экран и
формирование матрицы
оформить в виде подпрограмм.
7.
Получить
,
где
- квадратные матрицы,
-
натуральное число.
Ввод
матриц, вывод матриц на экран и
формирование матрицы
оформить в виде подпрограмм.
8. Даны три целочисленные квадратные матрицы. Найти ту из них, где больше нулевых строк.
Ввод матриц, вывод матриц на экран, поиск нулевых строк оформить в виде подпрограмм.
9.
По вещественным числам
и
вычислить с точностью
величину:
.
Для вычисления корней использовать следующий ряд Тейлора:
91
,
где
,
.
Вычисление корней оформить в виде процедуры или функции.
10. Разработать
программу для умножения симметричных
матриц на n-мерный вектор. Матрица
-
го порядка задана:
а) верхним треугольником;
б) одномерным вектором, полученным из представления симметричной матрицы в виде верхнего треугольника, путем построчной записи.
Ввод матриц, вывод матриц на экран, нахождение произведения оформить в виде подпрограмм.
11. Составить программу, подсчитывающую число сочетаний с повторениями, применив формулу
.
Проверить
работоспособность программы при
возрастающих значениях
и
.
Использовать подпрограммы.
-
По вещественному числу
вычислить величину
;
Корни
вычислить с точностью
по итерационной формуле:
Вычисления
производить до тех пор, пока
.
92
13.
По заданным вещественным векторам
размерности
вычислить:
Использовать подпрограммы.
14.
Среди простых чисел, не превышающих
,
найти такие, в двоичной записи которых
максимальное число единиц. Оформить в
виде отдельных подпрограмм процесс
представления числа в двоичной системе
счисления и подсчета количества единиц
в двоичном представлении.
15. Разработать программу для перевода целых чисел из десятичной системы счисления в троичную и пятеричную. Перевод оформить в виде подпрограмм.
16.
Напечатать все цифры десятичной записи
числа
,
представив ”длинные” натуральные
числа в виде массивов из цифр и реализовав
нужные операции над ними. Использовать
подпрограммы.
17.
Напечатать все цифры десятичной записи
числа
,
представив ”длинные” натуральные
числа в виде массивов из цифр и реализовав
нужные операции над ними. Использовать
подпрограммы.
18. Решить задачу 17, разбивая длинные числа не на отдельные цифры, а на группы цифр по 5 цифр.
19. Решить задачу 17, разбивая длинные числа не на отдельные цифры, а на группы цифр по 10 цифр.
93
20.
Разработать программу, которая по
заданным
элементным
массивам
и
вычисляет:
21.
Разработать программу, которая по
заданным
элементным
массивам
,
,
вычисляет:
22.
Разработать рекурсивную и нерекурсивную
процедуру или функцию для нахождения
-
го числа Фибоначчи. Числа Фибоначчи
определяются рекуррентными соотношениями:
.
Установите, сколько вызовов функции
понадобится при
.
Сколько будет вызовов, дублирующих
раннее осуществленные.
23.
Разработать рекурсивную и нерекурсивную
подпрограммы от вещественного
и целого
,
которые вычисляют величину
24.
Разработать рекурсивную и нерекурсивную
подпрограммы для вычисления биномиального
коэффициента
по следующей формуле:
94
.
25.
Разработать рекурсивную логическую
функцию, проверяющую, является ли
симметричной часть строки
,
начинающаяся
- м и кончающаяся
-
м ее элементами.
26. Разработайте рекурсивный и нерекурсивный варианты процедуры обращения строки.
27.
Разработайте рекурсивную процедуру
или функцию, которая находит наибольший
общий делитель (НОД) двух натуральных
чисел
и
.
Для решения задачи воспользоваться
свойствами НОД:
ЗАНЯТИЕ 6. МОДУЛИ