- •Программирование и алгоритмические языки. Курс за второй семестр. Абстрактные типы данных.
- •Задача о раскраске.
- •Перечисление последовательностей фиксированной длины.
- •Var I:tСтраны; c:tЦвет;
- •Два взгляда на диаграммы – графы и автоматы.
- •Деревья
- •Как сократить перебор с возвратом. Перечисление последовательностей переменной длины
- •Словарный порядок на последовательностях произвольной длины
- •Статическая реализация стеков.
- •Очереди. Статическая реализация.
- •Статическая реализация деревьев.
- •Автоматы как структуры данных
- •Статическая реализация графов. Проблема фрагментации памяти. Списочные структуры.
- •Общая схема реализации автомата как списка.
- •Обработка кучи.
- •Динамическая реализация абстрактных типов ссылками. Ссылочные типы Паскаля.
- •Ссылочные типы Паскаля. Синтаксис типов.
- •Объявление списочной структуры в Паскале.
- •Реализация стеков.
- •Реализация очередей.
- •Основные операции над списками.
- •Обработка деревьев. Деревья выражений.
- •Поиск атома.
- •Различные объединения типов. Записи типов с вариантами.
- •Создание дерева. Перевод из префиксной записи. Представление записи.
- •Анализ алгоритма вычисления. Дерево как последовательность ветвей.
- •Задача синтаксического анализа.
- •Графы-выражения.
- •Раздельное описание абстрактных типов. Модульное программирование.
- •Проблема с кратным использованием модулей.
- •Деревья как структуры данных.
- •Деревья поиска.
- •Поиск в дереве поиска.
- •Включение в дерево поиска.
- •Другие обходы дерева. Обход в ширину.
- •Рекурсивные процедуры и функции. Примеры применения.
- •Поиск в дереве.
- •Проблемы с семантикой рекурсии.
- •Введение в машинно-ориентированное (ссылочное) программирование. Оператор Goto.
- •Создание новых структурных операторов.
- •Формальная семантика goto и неструктурных программ.
- •Мини-Паскаль.
- •Представление сложных типов. Адресная арифметика.
- •Проблемы реализации ввода-вывода. Идея буферизации.
- •Реализация процедур read и write.
- •Реализация структур управления.
- •Путь наверх. Реализация процедур-подпрограмм.
- •Передача параметров.
- •Сохранение и восстановление значений. Соглашение о связях.
- •Введение в теоретическое программирование. Границы программирования. Принципиальная и практическая неразрешимость.
- •О формальной спецификации. Мир задачи как автомат.
- •Процедуры как функции на множестве состояний. Процедуры как преобразователи предикатов.
- •Универсальные методы решения задач.
Деревья как структуры данных.
Как обычно, структуры данных мы ассоциируем с некоторым семейством функций: fIT, где I – некоторое множество “индексов” (указателей или ключей) со следующими основными операциями: выборка, поиск, вычисление значения по ключу, поиск ключа по значению (вычисление обратной функции), сохранение значения по ключу (переопределение функции в заданной точке), создание нового ключа (расширение области определения), удаление ключа (сужение области определения). Реализация всех этих операций связана с некоторым порядком перечисления ключей.
Дерево как структуру данных естественно рассматривать как функцию на путях, «словах».
Пример. Декодирование текста, записанного азбукой Морзе.
Центральная проблема: найти по коду Морзе его значение (букву в латинском алфавите).
Как хранить таблицу соответствий кодов и букв?
F={0,1}*Last[‘a’..’z’]
…………….
1 1 1 ‘s’
0 0 0 ‘o’
…………….
-
1
0 1 1
-
1
Упражнение. 1) Завершить задачу декодирования.
2) Выяснить, сколько раз встречается каждое слово в тексте. Результатом должно быть [‘a’..’z’]*Cardinal
3) Что за функция «дерево выражений»?
В применении к деревьям эта задача формулируется как задача обхода дерева в некотором или заданном порядке. Рассмотрим задачу на примере задачи поиска.
procedure Poisk(root:pNode;x:tInfo;var key:pNode;var found:boolean);
begin
found:=false;
pt:=root;
push(stack,root);
while not found and {не кончились вершины} do
begin
pop(stack,pt);
if pt^.info=x then
begin
found:=true;
key:=pt;
end
else {перейти к следующему}
end;
if pt^.left<>nil then
begin
if pt^.right<>nil then push(stack,pt^.right);
pt:=pt^.left;
end
else if pt^.right<>nil then pt:=pt^.right;
end;
end; {Завести стек и хранить в нём ссылки на ещё не пройденные вершины дерева, то есть правые ссылки пройденных на данном пути вершин}
Очевидно, порядок обхода – знакомый лексикографический порядок.
Деревья поиска.
Задача поиска значения по ключу существенно более простая: в бинарном дереве – это идея дихотомического поиска. Продолжим эту идею на обратную задачу.
Бинарное дерево называется деревом поиска, если для каждой вершины дерева слева от него хранятся меньшие, а справа – большие значения в некотором порядке на типе хранимых значений.
Поиск в дереве поиска.
Procedure Dpoisk (root:pNode;x:tInfo;var pt:pNode;var found:boolean);
Begin
found:=false;
pt:=root;
while not found and (pt<>nil) do
begin
if pt^.info=x then found:=true
else
if pt^.info>x then pt:=pt^.left
else pt:=pt^.right;
end;
end;
Замечание. Данный поиск будет действительно дихотомическим, если исходное дерево полное (идеально сбалансированное).