- •Федеральное агенство по образованию российской федерации
- •1. Основные категории и понятия информатики
- •Предмет информатики как науки
- •1.2. Информация: структура, форма, измерение
- •2. Техническое и программное обеспечение пэвм
- •2.1. Структура аппаратных средств пэвм
- •2.2. Программное обеспечение пэвм
- •3. Основы алгоритмизации
- •Этапы разработки программ
- •3.2.Формы представления алгоритмов
- •Действие 1
- •Действие 2
- •Классификация и примеры алгоритмических структур
- •3.2.1. Алгоритм линейной структуры.
- •3.2.2. Алгоритм разветвляющейся структуры.
- •Да нет да да Рис 3.11
- •3.2.3. Алгоритмы циклической структуры.
- •4.2. Структура программы на языке Паскаль
- •4.3. Скалярные стандартные типы данных
- •4.4. Скалярные, пользовательские типы данных
- •5. Структурные типы данных
- •Массивы
- •5.3. Записи
- •5.4. Записи с вариантами
- •Множества
- •5.6.Файлы
- •6. Операции над данными скалярных типов. Выражения
- •7. Операторы языка Паскаль
- •7.1. Простые операторы
- •7.2. Структурные операторы
- •Оператор 2
- •8. Примеры программ на языке Паскаль
- •8.1. Пример 1. Арифметические выражения. Оператор присваивания
- •Пример 2. Условные операторы
- •Ввод чисел х, а
- •8.3. Пример 3. Программа обработки одномерного массива
- •8.4. Пример 4. Программа обработки двумерного массива
- •True False True False False
- •8.5. Пример 5. Программа обработки символьных строк
- •8.6. Пример 6. Программа обработки двумерного массива с вводом элементов матрицы из текстового файла
- •9.Разработка программ сложной структуры
- •9.1. Процедуры и функции
- •9.2. Область действия идентификаторов при использовании процедур и функций. Локальные и глобальные переменные
- •9.3. Передача данных в подпрограмму с помощью параметров. Формальные и фактические параметры
- •9.4. Использование процедур и функций
- •True False Рис. 9.4
- •9.5. Массивы – параметры процедур и функций
- •True False True False Рис. 9.7
- •True False True False True False Рис 9.9
- •9.6. Рекурсивные процедуры и функции
- •True False Рис. 9.10 True False
- •True False Рис. 9.12
- •9.7. Модули
- •10. Динамические структуры данных
- •Основные определения
- •10.2. Объявление и создание динамических структур данных. Указатели
- •Операции над указателями
- •Программа создания и обработки линейного списка
- •Приложение. Контрольные вопросы
- •Литература
9.6. Рекурсивные процедуры и функции
Рекурсивным называется объект, который частично определяется через самого себя. Рекурсивные определения используются во многих областях науки и, особенно, в математике.
Рассмотрим функцию определения факториала (n!); факториал – это произведение первыхnнатуральных чисел. Такое произведение можно вычислить с помощью программы, использующей оператор циклаfor. Однако, существует другое определение факториала, в котором используется рекуррентные формулы:
1!=1;
для любого n>0,n!=n*(n-1)!
Определения, использующие рекуррентные формулы, называют рекурсивными определениями. Рекурсивные определения упрощают процесс вычислений. Например, в случае определения членов ряда Фибоначчи:
Рекурсивное определение значительно проще приведенной выше формулы и имеет следующий вид:
F(1)=1;
F(2)=1;
Для любого n>2,F(n)=F(n-1)+F(n-2).
Рассмотрим рекурсивный алгоритм на примере накопления произведений. Пусть требуется написать программу, которая определяет произведение натуральных чисел от 1 до n:
P=n!=1*2*…*n.
Постановка задачи.
Входные данные:
n>0 – целое число.
Выходные данные:
P=n! – целое число.
Аномалии. n<0, в программе не рассматриваются.
Метод решения: для определения произведения использовать рекуррентные формулы:
1!=1;
для любого n>0,n!=n*(n-1)!
Блок-схема рекурсивной функции factдля определения факториала представлена на рис 9.10, а блок-схема основной программы – на рис. 9.11.
True False Рис. 9.10 True False
Текст программы на языке Паскаль.
Program Exam10;
Var
Ch, Proiz: integer;
Function Fact(n: integer): integer;
Var R: integer;
Begin
If n>0 then Fact:=n*Fact(n-1)
Else Fact:=1;
End;
Begin
Writeln('Input Ch>0 :');
Readln(Ch);
If Ch>0 then
begin
Proiz := Fact(Ch);
Writeln('Ch','!=',Proiz)
end
Else Writeln('Error! Ch<0');
Write('PRESS ANY KEY!!!');
Readln;
End.
Результаты тестирования.
1. Исходные данные:
Ch=3
Ch!=1*2*3=6
Результаты, выданные программой.
Input Ch>0 :
3
Ch!=6
PRESS ANY KEY!
2. Исходные данные:
Ch=-3
Результат- сообщение «Error!Ch<0».
Результаты, выданные программой.
Input Ch>0 :
-3
Error! Ch<0
PRESS ANY KEY!!!
Рекурсивный процесс предполагает прямой ход или рекурсивный спуск и обратный ход или рекурсивный возврат.
Прямой ход.
При каждом рекурсивном обращении к функции создается новый экземпляр памяти всех локальных переменных и параметров этой функции, который запоминается в некоторой области памяти. Глубина рекурсии определяется количеством выполненных рекурсивных вызовов. Цепочка вызовов рекурсивных подпрограмм создает в памяти связанную последовательность областей памяти, организованных по принципу стека: доступной является область, размещенная последней. Прямой ход завершается тем вызовом подпрограммы, в котором истинно условие выполнения ее нерекурсивной части.
Рекурсивный процесс выполнения функции FactдляCh=3 имеет глубину рекурсии, равную 3, как показано в таблице ниже.
Текущий уровень рекурсии |
Рекурсивный спуск (прямой ход) |
Рекурсивный возврат (обратный ход) | ||
1 |
Ch=3 Fact:=3*Fact(2-1) |
Fact:=3*2(=6) | ||
2 |
Ch=2 Fact:=2*Fact(2-1) |
Fact:=2*1(=2) | ||
3 |
Ch=1 Fact:=1 |
Ch=1Fact:=1 |
Обратный ход начинается с выполнения нерекурсивной части подпрограммы; после этого область стека, относящаяся к данному вызову удаляется и выполняется возврат к предыдущему вызову и т. д. Обратный ход завершается возвратом значения в программу, вызывавшую рекурсивную функцию.
В рекурсивной процедуре или функции должно быть условие выполнения нерекурсивных операторов для обеспечения завершения рекурсии, иначе возможны бесконечные рекурсивные вызовы и аварийное завершение программы из-за переполнения доступной памяти для стека.
В языке Паскаль допускается использование рекурсивных процедур. Рассмотрим пример рекурсивной процедуры на примере процедуры определения наибольшего общего делителя двух целых чисел.
Задание. Определить наибольший общий делитель двух целых чисел.
Постановка задачи.
Входные данные:
A,B– целые, положительные числа.
Выходные данные:
Nod– наибольший общий делительAиB.
Метод решения: рекурсивный алгоритм Евклида.
Алгоритм. Выдача наибольшего общего делителя двух целых чисел.
Входные данные.
СКАЛЯР A,B– целые, положительные числа.
Выходные данные.
СКАЛЯР Nod– целое число.
Начало
A:=0
B:=0
ЦИКЛ_ПОКА(A<=0 ИЛИB<=0)
Вывод(‘Input A,B : ’)
ввод(A,B)
КОНЕЦ_ЦИКЛА
Findnod(A,B,Nod)
Вывод(‘Nod(A,B)= ’,Nod)
Конец
Алгоритм. Процедура определения наибольшего общего делителя двух целых чисел (findnod).
Входные данные.
СКАЛЯР A,B– целые, положительные числа.
Выходные данные.
СКАЛЯР Nod– целое число.
Промежуточные данные.
СКАЛЯР R– целое число. {остаток от деления }
Начало
ЕСЛИ (A mod B <>0)
R:= A mod B
A:=B
B:= R
Findnod(A,B,Nod)
ИНАЧЕ
Nod:=B
КОНЕЦ_ЕСЛИ
Конец
Блок - схема программы