- •Программирование и алгоритмические языки. Курс за второй семестр. Абстрактные типы данных.
- •Задача о раскраске.
- •Перечисление последовательностей фиксированной длины.
- •Var I:tСтраны; c:tЦвет;
- •Два взгляда на диаграммы – графы и автоматы.
- •Деревья
- •Как сократить перебор с возвратом. Перечисление последовательностей переменной длины
- •Словарный порядок на последовательностях произвольной длины
- •Статическая реализация стеков.
- •Очереди. Статическая реализация.
- •Статическая реализация деревьев.
- •Автоматы как структуры данных
- •Статическая реализация графов. Проблема фрагментации памяти. Списочные структуры.
- •Общая схема реализации автомата как списка.
- •Обработка кучи.
- •Динамическая реализация абстрактных типов ссылками. Ссылочные типы Паскаля.
- •Ссылочные типы Паскаля. Синтаксис типов.
- •Объявление списочной структуры в Паскале.
- •Реализация стеков.
- •Реализация очередей.
- •Основные операции над списками.
- •Обработка деревьев. Деревья выражений.
- •Поиск атома.
- •Различные объединения типов. Записи типов с вариантами.
- •Создание дерева. Перевод из префиксной записи. Представление записи.
- •Анализ алгоритма вычисления. Дерево как последовательность ветвей.
- •Задача синтаксического анализа.
- •Графы-выражения.
- •Раздельное описание абстрактных типов. Модульное программирование.
- •Проблема с кратным использованием модулей.
- •Деревья как структуры данных.
- •Деревья поиска.
- •Поиск в дереве поиска.
- •Включение в дерево поиска.
- •Другие обходы дерева. Обход в ширину.
- •Рекурсивные процедуры и функции. Примеры применения.
- •Поиск в дереве.
- •Проблемы с семантикой рекурсии.
- •Введение в машинно-ориентированное (ссылочное) программирование. Оператор Goto.
- •Создание новых структурных операторов.
- •Формальная семантика goto и неструктурных программ.
- •Мини-Паскаль.
- •Представление сложных типов. Адресная арифметика.
- •Проблемы реализации ввода-вывода. Идея буферизации.
- •Реализация процедур read и write.
- •Реализация структур управления.
- •Путь наверх. Реализация процедур-подпрограмм.
- •Передача параметров.
- •Сохранение и восстановление значений. Соглашение о связях.
- •Введение в теоретическое программирование. Границы программирования. Принципиальная и практическая неразрешимость.
- •О формальной спецификации. Мир задачи как автомат.
- •Процедуры как функции на множестве состояний. Процедуры как преобразователи предикатов.
- •Универсальные методы решения задач.
Деревья
Назовём автомат инициальным, если выделено некоторое начальное состояние 0 такое, что любое другое состояние достижимо из него: xX sF* : (Automaton(0,s)=x).
Деревом называется инициальный автомат T, в котором разные пути приводят в разные состояния: s,s| F* (T(0,s)T(0,s|)).
Обычно деревья связывают не только собственно с деревьями, но с генеалогическим древом, что подсказывает терминологию. Начальное состояние – корень, конечное – листья.
корень
t1 t1,t2,t3,…
0 1 Пример бинарного дерева F={0,1}
родители(предки)дети(потомки)
Упражнение. 1) Дать определение дерева на языке теории графов (т.е. в терминах соединения вершин). 2) Дать формальное определение родственной терминологии (родители, дети, дядья, кузены, деды, внуки).
Фундаментальный пример дерева даёт класс всех последовательностей некоторого базового типа T, или класс всех функций NT.
Дерево позиционное, если на входном алфавите, т.е. на множестве F, зафиксирован некоторый линейный порядок (сравнение). Например, F={0<1} или F={1<0}. Это позволяет нам говорить о старшинстве в одном поколении. Если же это сравнение определяет порядковый тип, то таким же (порядковым) будет и произвольный класс путей в лексикографическом (словарном) порядке.
Упражнение. Определить во введённых нами терминах какой-либо однозначный порядок наследования имущества.
Как сократить перебор с возвратом. Перечисление последовательностей переменной длины
Вернёмся к задаче о раскраске. Идея её проста – перебирать и проверять неполные, незаконченные раскраски, т.е. все последовательности c1…ck, kn, n – число стран. Если неполная раскраска неправильна, то нет смысла перебирать раскраски большей длины, надо искать новый вариант – возврат.
Словарный порядок на последовательностях произвольной длины
c1…ck c1|…c|L, т.е. i0 (ci0ci0| and ii0 (ci=c|I) or (i (ci=ci|) and k<L)
Технический приём: дополнить меньшее слово фиктивным элементом, например пробелом, наименьшим по определению.
можно:=false;
pаскраска:=Первая раскраска; {<первый цвет>}
while (не кончилась раскраска) do
begin
{Пустая раскраска – последовательность длины 0}
if правильная (раскраска) then if полная (раскраска) then
begin
можно:=true {печать (раскраска)}
else {раскраска правильная, но не полная}
{дополнить} раскраска:=раскраска + первый цвет
else {возврат} раскраска:=succ(раскраска);
end;
end;
Переход к следующей раскраске при новом определении словарного порядка:
-
Выбрасывать все последние значения с конца последовательности до тех пор, пока не выкинем первый элемент, у которого есть следующий. Если такого нет, то раскраска кончилась.
-
Если раскраски не кончились, возвратить следующий за последним, выкинутым в раскраску.
Последовательность, из конца которой можно выкидывать и в конец которой можно добавлять элементы, называется стеком (stack).
Стеком называется абстрактный тип данных, множеством значений которого является множество всех последовательностей произвольной длины (динамический тип) элементов некоторого базового типа Т со следующими операциями:
-
Push ([x:tStack], y:T), х – имя стека, затолкнуть y в стек.
Семантика: x:=x+y (добавление элементов в конец последовательности)
-
Pop ([x:tStack],y:T), x – имя стека, извлечь y из стека.
if x=c1…cn then pop=cn. Длина стека уменьшается на 1: x=c1…cn-1.
Попытка взять элемент из пустого стека считается ошибкой.
-
Empty ([x:tStack]):boolean; – стек пуст.
if Empty([x:tStack]){=true} then {длина стека равна нулю}.
-
Характерные для динамических типов операции Create([x:tStack]) и Destroy([x:tStack]) рассмотрим позднее.
Стеки также называют «магазинной» памятью.
Переход к следующей раскраске, если такой нет, то к пустой.
procedure Новая (var раскраска:tStack);
var x:tЦвет;
Begin
pop(stack,x);
while not empty(stack) and (x=последний цвет) do pop(stack,x);
if not empty(stack) then push(succ(x));
End;
Дополнить раскраску=push(stack,первый цвет)
Кончились раскраски – empty(stack)
Упражнение. Завершить реализацию перебора с возвратом, написав процедуру «Правильная».
c1…ck+1 – правильная, то c1…сk – правильная.
i[1,k] (соседи(ck,ck+1))
раскраска(1)раскраска(k+1)
(Выходим за пределы стековых операций).