
- •Утверждаю Зам.Директора по учебной работе
- •Основы Алгоритмизации и программирования учебно-методическое пособие
- •220301 Автоматизированные системы обработки информации и правления
- •Введение
- •Основные этапы решения задач на эвм
- •Глава 1 способы записи алгоритма
- •1.1 Алгоритм и его свойства
- •Схемы алгоритма
- •1.2 Структуры алгоритмов
- •1.2.1 Алгоритм линейной структуры
- •1.2.2 Алгоритм разветвляющейся структуры
- •1.2.3 Алгоритм циклической структуры
- •1.2.4 Алгоритм со структурой итерационных циклов
- •1.2.5 Алгоритм со структурой вложенных циклов
- •Глава 2 программа на языке высокого уровня
- •2.1 Системы программирования
- •2.2 Характеристика языка программирования Паскаль
- •2.3 Алфавит и структура программы на Паскале Алфавит программы
- •Структура программы
- •Глава 3 Стандартные типы данных
- •3.1 Данные. Типы
- •3.2 Вещественные типы
- •3.3 Целочисленные типы
- •3.4 Символьный тип
- •3.5 Логический тип
- •4 Представление основных структур программирования: итерация, ветвление, повторение
- •4.1 Линейная структура (следование)
- •Var X,y,f: real;
- •4.2 Разветвляющая структура (ветвление)
- •4.3 Циклическая структура (повторение)
- •4.3.1 Оператор цикла с параметром
- •I : Integrer; {номер числа }
- •4.3.2 Оператор цикла с постусловием
- •I,n: integer;
- •4.3.3 Оператор цикла с предусловием
- •4.3.4 Итерационные циклы
- •Var r,a:real;
- •Приближенное вычисление функций
- •Решение уравнений приближенными методами
- •Метод деления отрезка пополам
- •Xsl, Xpr, a, b, e, y1, y2, Lev, Prav, y: Real;
- •Метод Ньютона
- •Метод прохождения отрезка с переменным шагом
- •Вычисление определенных интегралов
- •1. Метод прямоугольников
- •X: Real;
- •2. Метод трапеций
- •X: Real;
- •Глава 5 Типы данных, определяемые пользователем
- •5.1 Пользовательский тип данных
- •5.1.1 Типизированные константы
- •5.1.2 Перечисляемый тип
- •I:1..6; loto: num;
- •5.2 Массивы
- •I : integer;
- •5.2.1. Работа с одномерными массивами
- •I,sum : integer;
- •Var a: array [1..N] of real;
- •Var I,s,r: integer;
- •I : list;
- •I : integer;
- •X : mass;
- •I, j, p, n, m, k:integer;
- •I, j, k, nd : integer;
- •Xmin : real;
- •X : mass;
- •Var I, j, nd : integer;
- •X : mass;
- •5.2.2 Работа с двумерными массивами( матицы)
- •Var I,j,n : integer;
- •I,j,n,m : integer;
- •5.2.3 Сортировка массивов
- •Сортировка методом "пузырька"
- •X : Array [1..Nmax] Of Real;
- •X : Array [1..Nmax] Of Real;
- •Сортировка выбором
- •Обменная сортировка
- •Var m:array[1..1000] of integer;
- •I,z,n:integer; Key:byte;
- •Сортировка слиянием
- •Var { Описание массивов и переменных}
- •X, y: array[1..1000] of integer;
- •5.3 Строковые типы
- •Var s: string[10];
- •5.3.1 Операции над строками
- •5.3.2 Стандартные процедуры и функции для строк
- •Функция Length
- •Функция Upcase
- •Функция Copy
- •Функция Роs
- •I, n, p: integer;
- •I: integer;
- •I: integer;
- •Insert (word2, text, I);
- •Insert (chr (k-32), t, I);
- •Insert (chr (k-80), t, I);
- •Insert (‘е’, t, I);
- •Глава 6 Процедуры и функции
- •6.1 Процедуры
- •I : Integer;
- •I, n: integer;
- •Input _ mas (k, n);
- •I,n : Integer;
- •I,k : Integer;
- •6.2 Функции
- •I:Integer;
- •2) Массивы;
- •I,n : Integer;
- •I : Integer;
- •I,tn,tk:Real;
- •Глава 7 Программирование рекурсивных алгоритмов
- •7.1 Понятие рекурсии
- •7.2 Техника построения рекурсивных алгоритмов
- •7.3 Формы рекурсий
- •If Prim(I) then
- •7.4 Рекурсия и итерация
- •7.5 Программирование с использованием рекурсии
- •Var p: Integer;
- •Var X, y: Integer; begin
- •Var z: Real; begin
- •Var I:integer; j:real;
- •Глава 8 Файлы
- •8.1 Текстовые файлы
- •I,n : Integer; {Вспомогательные переменные}
- •8.2 Типизированные файлы
- •X,m,s : Real;
- •8.3 Нетипизированные файлы
- •Глава 9 Записи
- •9.1 Описание записи
- •I: integer;
- •9.2 Оператор присоединения
- •I, j, k, m : integer;
- •X: real;
- •9.3 Вложенные записи
- •9.4 Записи с вариантами
- •Information: record
- •I, k, n : integer;
- •Vedom : Array [1..Nmax] Of Stud;
- •I,j : Integer;
- •Vedom : File Of Stud;
- •Vedom : File Of Stud;
- •I,j,kdv,k2 : Integer;
- •If Not Eof (Ftel) Then
- •If Not Eof(Ftel) then
- •If Not Eof(FilComp) then
- •Глава 10 Динамические структуры данных
- •10.1 Распределение памяти при выполнении программ
- •Верхняя граница памяти ms-dos
- •10.2 Ссылочные переменные
- •10.3 Процедуры управления кучей
- •10.4 Использование переменных ссылочного типа
- •I: Integer;
- •I, k : Integer;
- •Val(b, k, code);{Превратили второй символ в ч исло}
- •10.5 Списки
- •Var Ch : Char;
- •Var Ch : Char;
- •10.6 Деревья
- •10.7 Константы ссылочного типа
- •Глава 11. Язык Паскаль. Графический модуль Graph Список используемой литературы Основная
- •Дополнительная
If Prim(I) then
Write(i:6)
End. {Primzahlen}
Функция Prim определяет, является ли j простым числом, для этого просматриваются все простые числа начиная с двух, вплоть до корня изу, и проверяется, делится ли у на одно из таких простых чисел. Для поиска следующего простого числа используется функция Next, которая, в свою очередь, для идентификации простых чисел использует функцию Prim. Однако в Паскале любой идентификатор перед употреблением должен быть описан и при использовании подобных функций возникает проблема ссылок вперед. Для того чтобы такого рода вызовы стали возможны, вводится опережающее описание функции Next, которое предшествует обращению к ней и состоит из ее заголовка с указанием директивы forward, заменяющей тело функции. Теперь в функции Prim можно ис: пользовать обращение к Next - ее формальные параметры уже известны и компилятор может правильно организовать ее вызов. Полное описание функции Next помещается в программе после описания Prim, и в этом описании уже можно не указывать объявленные ранее формальные параметры.
Рекурсия более высокого порядка
Используя более мощные виды рекурсии, можно записывать относительно лаконичными средствами и более сложные вычисления. Одновременно с этим, поскольку определения довольно абстрактны, растет сложность отладки и понимания программ.
Если в определении функции рекурсивный вызов является аргументом вызова этой же самой функции, то в такой рекурсии можно выделить различные порядки (order) в соответствии с тем, на каком уровне рекурсии находится вызов. Такую форму рекурсии называют рекурсией более высокого порядка. Функции, которые мы до сих пор определяли, были функциями с рекурсией нулевого порядка. В качестве классического примера рекурсии первого порядка часто приводится функция Аккермана:
А(m, n) = n+1 при m = 0;
А(m, n) = А(m-1,1) при n = 0;
А(m, n) = А(m-1, А(m, n-1)) в остальных случаях.
Кажущаяся простота этой функции обманчива. Вызов функции завершается всегда, однако ее вычисление довольно сложно, число рекурсивных вызовов растет лавинообразно уже при малых значениях аргумента.
В практике программирования рекурсий высокого порядка стараются избегать, разбивая определение на несколько частей и используя подходящие параметры для сохранения и передачи промежуточных результатов.
7.4 Рекурсия и итерация
Многие рекурсивные определения можно заменить нерекурсивными и организовать вычисления без использования рекурсии.
В программировании есть два средства реализации повторяющихся вычислений/процессов:
• с помощью итерации в форме цикла - последовательного повторения некоторого процесса до тех пор, пока не удовлетворится некоторое условие;
• с помощью рекурсии - вложения одной операции в другую, когда при отрицательном результате проверки условия выполнение процесса «приостанавливается» и происходит самовключение выполняемого процесса сначала уже в качестве подпрограммы для еще не выполненной до конца первоначальной подпрограммы.
Программы, использующие рекурсивные процедуры и функции, отличаются простотой, наглядностью и компактностью текста. Такие качества рекурсивных алгоритмов вытекают из того, что рекурсивная процедура/функция описывает, что нужно делать, а нерекурсивная акцентирует внимание на том, как нужно делать. Итерация требует меньше места в памяти и машинного времени, чем рекурсия, которой необходимы затраты на управление стеком. Однако существуют некоторые функции, которые легко можно определить рекурсивно, но которые нельзя определить в терминах обычных алгебраических выражений, например функция Аккермана. Для многих задач рекурсивная формулировка совершенно прозрачна, в то время как построение итерации оказывается весьма сложным делом.
Пример 7.8 Задача о ханойских башнях. Даны 3 столбика - А, В, С. На столбике А один на другом находятся 4 диска разного диаметра, и каждый меньший диск находится на большем. Требуется переместить эти 4 диска на столбик С, сохранив их взаиморасположение. Столбик В разрешается использовать как вспомогательный. За один шаг допускается перемещать только один из верхних дисков какого-либо столбика, и больший диск не разрешается класть на диск меньшего диаметра.
Для определения подхода к решению поставленной задачи рассмотрим более общий случай с и дисками. Если мы сформулируем решение для и дисков в терминах решения для n-1 дисков, то поставленная проблема будет решена, поскольку задачу для n-1 дисков можно будет, в свою очередь, решить в терминах n-2 дисков и т. д. до тривиального случая одного диска. А для случая одного диска решение элементарно: нужно переместить единственный диск со столбика А на столбик С. Таким образом мы получим рекурсивное решение задачи. Рассмотрим словесное описание алгоритма.
Если n = 1, переместить единственный диск со столбика А на столбик С и остановиться.
Переместить верхние n-1 дисков со столбика А на столбик В, используя столбик С как вспомогательный.
Переместить оставшийся диск со столбика А на столбик С.
Переместить n-1 дисков со столбика В на столбик С, используя столбик А как вспомогательный.
Приведем программу Hanoi_Towers, которая решает поставленную задачу с помощью рекурсивной процедуры Move Disks. n - число дисков на столбике Source, Source - исходный столбик, Dest - столбик, на который нужно переставить диски, Тmр - вспомогательный столбик.
{Ханойские башни}
Program Hanoi_Towers;
Var
n: integer;
Procedure Move_Disks (n : byte; Source, Dest, Tmp : char); Begin {Move_Disks} if n = 1 then
Writeln('Переставить диск1 со столбика', Source,
'на столбик', Dest)
else
begin
{Переставляем n-1 верхних дисков с исходного столбика на вспомогательный, используя целевой диск как промежуточный }
Move_Disks(n-1, Source, Tmp, Dest);
WriteLn('Переставить диск', п, 'со столбика', Source, 'на столбик', Dest);
{Переставляем n-1 дисков, расположенные на вспомогательном столбике, на целевой, используя исходный диск как промежуточный}
Move_Disks(n-1, Tmp, Dest, Source);
End
End; {Move_Disks}
{Основная программа}
Begin {Hanoi_Towers}
Writeln('Введите число дисков:');
ReadLn(n);
Move_Disks(n, 'А', 'С, 'В');
End. {Hanoi_Towers}
Нельзя, однако, рекомендовать применять рекурсию повсеместно, и прежде всего это касается традиционных вычислительных процессов, не являющихся существенно рекурсивными. И не столько из-за времени выполнения рекурсивных программ, сколько из-за сложности их отладки. Поэтому программист должен оценить, насколько целесообразно облегчать работу по написанию программы, подвергая себя при этом опасности усложнить отладку и резко увеличить время счета.