- •Программирование и алгоритмические языки. Курс за второй семестр. Абстрактные типы данных.
- •Задача о раскраске.
- •Перечисление последовательностей фиксированной длины.
- •Var I:tСтраны; c:tЦвет;
- •Два взгляда на диаграммы – графы и автоматы.
- •Деревья
- •Как сократить перебор с возвратом. Перечисление последовательностей переменной длины
- •Словарный порядок на последовательностях произвольной длины
- •Статическая реализация стеков.
- •Очереди. Статическая реализация.
- •Статическая реализация деревьев.
- •Автоматы как структуры данных
- •Статическая реализация графов. Проблема фрагментации памяти. Списочные структуры.
- •Общая схема реализации автомата как списка.
- •Обработка кучи.
- •Динамическая реализация абстрактных типов ссылками. Ссылочные типы Паскаля.
- •Ссылочные типы Паскаля. Синтаксис типов.
- •Объявление списочной структуры в Паскале.
- •Реализация стеков.
- •Реализация очередей.
- •Основные операции над списками.
- •Обработка деревьев. Деревья выражений.
- •Поиск атома.
- •Различные объединения типов. Записи типов с вариантами.
- •Создание дерева. Перевод из префиксной записи. Представление записи.
- •Анализ алгоритма вычисления. Дерево как последовательность ветвей.
- •Задача синтаксического анализа.
- •Графы-выражения.
- •Раздельное описание абстрактных типов. Модульное программирование.
- •Проблема с кратным использованием модулей.
- •Деревья как структуры данных.
- •Деревья поиска.
- •Поиск в дереве поиска.
- •Включение в дерево поиска.
- •Другие обходы дерева. Обход в ширину.
- •Рекурсивные процедуры и функции. Примеры применения.
- •Поиск в дереве.
- •Проблемы с семантикой рекурсии.
- •Введение в машинно-ориентированное (ссылочное) программирование. Оператор Goto.
- •Создание новых структурных операторов.
- •Формальная семантика goto и неструктурных программ.
- •Мини-Паскаль.
- •Представление сложных типов. Адресная арифметика.
- •Проблемы реализации ввода-вывода. Идея буферизации.
- •Реализация процедур read и write.
- •Реализация структур управления.
- •Путь наверх. Реализация процедур-подпрограмм.
- •Передача параметров.
- •Сохранение и восстановление значений. Соглашение о связях.
- •Введение в теоретическое программирование. Границы программирования. Принципиальная и практическая неразрешимость.
- •О формальной спецификации. Мир задачи как автомат.
- •Процедуры как функции на множестве состояний. Процедуры как преобразователи предикатов.
- •Универсальные методы решения задач.
Реализация процедур read и write.
read(f,x) ~ x:=f^; get(f);
write(f,e) ~ f^:=e; put(f);
Кроме того, с обработкой буфера связаны операторы: reset(f), который считывает первую компоненту файла (если есть), close(f) – выводит содержимое буфера в файл.
Суть идеи буферизации – распараллелить обмен со внешними носителями на два независимо выполняемые отдельные исполнителя:
1) Быстрый обмен в оперативной памяти;
2) Обмен между буфером и физическим файлом. То есть параллельно с основной программой работает копирование из файла в буфер. Так работают ввод и вывод.
Реализация структур управления.
Оставим в нашем мини-Паскале два оператора: оператор присваивания и бинарное присваивание вида y:=[y]x, где - одна из базовых операций, к которым мы отнесём арифметические операции: +, *, -, div.
В реальности на ещё более низком уровне реализации (микропрограммирование) эти операции не базовые, но реализуются с помощью операций над битами (логические операции, операции сдвига и т.д.).
Принцип сведения содержательных операций для нас не нов (пример – сложение столбиком). Очевидно, такого присваивания достаточно для пошагового вычисления любых арифметических выражений.
Все структуры управления реализуются с помощью оператора условного перехода:
if B then goto M, где М – метка (адрес команды), а В – базовый предикат (= или ).
Упражнение. Выяснить, являются ли необходимыми операции сравнения. (нет).
if B then S1 else S2
if B then goto M;
S2; goto M2
M: S1
M2:
S1 S2
while B do S
S
M:
M N:
+
Все остальные циклы и структуры выражаются через while.
Очевидно, существует алгоритм (транслятор), осуществляющий автоматический перевод с языка более высокого уровня на язык низкого уровня.
Упражнение*. Запрограммировать на мини-Паскале программу вычисления суммы 10 чисел.
Упражнение*. Написать алгоритм построения по любой блок-схеме последовательности операторов в мини-Паскале.
Задача сложения 10-ти чисел:
var a:array[1..10] of integer;
begin
s:=0; i:=1;
while i<=10 do
begin
s:=s+a[i];
i:=succ(i);
end;
write(s);
end.
goto prog;
prog:
s:=0;
i:= 0;
p:=addr(A);
i:=1;
N: if i>10 then goto M;
s:=s+p^;
p:=p+cSizeOfInteger;
goto N;
M:
write(s);
Замечание: Потеря эффективности. В случае непроцедурного программирования на мини-Паскале мы могли бы сэкономить память (переменная i) и время выполнения за счёт трактовки p как счётчика цикла: if p<10*cSizeOfInteger.
Путь наверх. Реализация процедур-подпрограмм.
Понятие подпрограммы как выделенного фрагмента программы, реализующего некую операцию – первый в программировании пример структуризации, разделения логики и реализации. Первые языки высокого уровня – Fortran и Basic – базировались именно на идее языка программирования как набора стандартных подпрограмм.
Пример: вызов и возврат.
Рассмотрим частный случай процедуры без параметров.
Procedure Proc;
begin
z:=x+y; proc
end;
B
goto
……. Vozvrat^
End.
Vozvrat Goto
proc
{подготовка возврата}
вызов
возврат
Положить в vozvrat адрес следующей после goto команды:
Vozvrat:=ThisAddr+cLenGoto, где cLenGoto – длина команды goto.
{Выразить через бинарное присваивание}
vozvrat:=ThisAddr;
vozvrat:=vozvrat+cLenGoto
goto prog; {подпрограмма вызывается только явным образом – первой выполняется первая команда основной программы}
proc: {z:=x+y}
z:=x;
z:=z+y;
goto vozvrat^;
prog: … goto proc … vozvrat:=ThisAddr;
vozvrat:=vozvrat+cLenGoto; goto proc; {главная программа}