- •Программирование и алгоритмические языки. Курс за второй семестр. Абстрактные типы данных.
- •Задача о раскраске.
- •Перечисление последовательностей фиксированной длины.
- •Var I:tСтраны; c:tЦвет;
- •Два взгляда на диаграммы – графы и автоматы.
- •Деревья
- •Как сократить перебор с возвратом. Перечисление последовательностей переменной длины
- •Словарный порядок на последовательностях произвольной длины
- •Статическая реализация стеков.
- •Очереди. Статическая реализация.
- •Статическая реализация деревьев.
- •Автоматы как структуры данных
- •Статическая реализация графов. Проблема фрагментации памяти. Списочные структуры.
- •Общая схема реализации автомата как списка.
- •Обработка кучи.
- •Динамическая реализация абстрактных типов ссылками. Ссылочные типы Паскаля.
- •Ссылочные типы Паскаля. Синтаксис типов.
- •Объявление списочной структуры в Паскале.
- •Реализация стеков.
- •Реализация очередей.
- •Основные операции над списками.
- •Обработка деревьев. Деревья выражений.
- •Поиск атома.
- •Различные объединения типов. Записи типов с вариантами.
- •Создание дерева. Перевод из префиксной записи. Представление записи.
- •Анализ алгоритма вычисления. Дерево как последовательность ветвей.
- •Задача синтаксического анализа.
- •Графы-выражения.
- •Раздельное описание абстрактных типов. Модульное программирование.
- •Проблема с кратным использованием модулей.
- •Деревья как структуры данных.
- •Деревья поиска.
- •Поиск в дереве поиска.
- •Включение в дерево поиска.
- •Другие обходы дерева. Обход в ширину.
- •Рекурсивные процедуры и функции. Примеры применения.
- •Поиск в дереве.
- •Проблемы с семантикой рекурсии.
- •Введение в машинно-ориентированное (ссылочное) программирование. Оператор Goto.
- •Создание новых структурных операторов.
- •Формальная семантика goto и неструктурных программ.
- •Мини-Паскаль.
- •Представление сложных типов. Адресная арифметика.
- •Проблемы реализации ввода-вывода. Идея буферизации.
- •Реализация процедур read и write.
- •Реализация структур управления.
- •Путь наверх. Реализация процедур-подпрограмм.
- •Передача параметров.
- •Сохранение и восстановление значений. Соглашение о связях.
- •Введение в теоретическое программирование. Границы программирования. Принципиальная и практическая неразрешимость.
- •О формальной спецификации. Мир задачи как автомат.
- •Процедуры как функции на множестве состояний. Процедуры как преобразователи предикатов.
- •Универсальные методы решения задач.
Обработка деревьев. Деревья выражений.
Несмотря на очень сложный вид (синтаксис), выражения обозначают функции и можно считать (если нужно привести – преобразовать), что выражения заданы в стандартном синтаксисе, в функциональной или префиксной нотации. Таким выражением будет элементарное выражение (терм) (обычно константа или переменная). Если e1,…en – выражение, а f – знак операции, то строка вида f(e1,…,en) – также выражение.
Деревом называется граф, состоящий либо из одной вершины, либо имеющий вид:
где e1,…,en – деревья
Примеры:
ax2+bx+c
p:=1; for i:=1 to n do p:=p*a;
С обработкой выражений связаны три классические задачи программирования:
-
Синтаксический анализ: выяснить, является ли произвольный текст правильно построенным выражением.
-
Трансляция: по заданному выражению построить семантически эквивалентные выражения в другом синтаксисе (как правило более низкого уровня).
-
Выполнение: вычислить значение данного выражения.
Для точной постановки задачи надо строго определить синтаксис и семантику конкретного языка. Для наших целей выберем язык с минимальным по возможностям синтаксисом и очевидной семантикой.
Константы: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.
Переменные: a, b, c, d, …, z
Знаки операций: + , - , * , /.
Выражение рассматривается в стандартной функциональной нотации.
ax2+bx+c – уже недопустимо
+*a*xx+*bxc
Семантика: арифметика целых чисел.
Задача по вычислению. Даны правильно построенное выражение и значения входящих в него переменных. Вычислить значение выражения.
ax+2b +*ax*2b
a1
x2
b3
АТОМ
Идея: свести вычисление выражения к последовательному вычислению атомов, то есть выражений с одним знаком операции.
left right
АТОМ
left<right
type tVariable=array[‘a’..’z’] of integer;
pComponent=^tComponent;
tComponent=record
info:char; {?}
left, right:pComponent; {Ссылки на левый и правый аргументы
(потомков)}
end;
function ExpVal(root:pComponent;variable:tVariable);
var pt:pComponent; {ссылка на следующий (next) вычисляемый атом}
begin
while {пока есть атомы} do
begin
{pt:= }
{Найти ссылку на первый атом, положить его в pt}
Вычисление атомов в лексикографическом порядке. (left<right)
{Сократить дерево, заменить атом на его значение}
pt^.info:=AtomVal(pt);
dispose(pt^.left);
dispose(pt^.right);
pt^.left:=nil;
pt^.right:=nil;
end;
end;
Конечно, можно не удалять вершины физически, а лишь помечать как удалённые.