- •Иркутский государственный технический университет
- •1. Определения графов
- •7.4.5. Массив дуг
- •8.4.2. Трансверсаль
- •8.5.4. Алгоритм нахождения максимального потока
- •8.6.3. Выделение компонент сильной связности
- •8.7.1. Длина дуг
- •8.7.2. Алгоритм Флойда
- •8.7.3. Алгоритм Дейкстры
- •Глава 9 Деревья
- •9.1. Свободные деревья
- •9.1.1. Определения
- •9.1 .2. Основные свойства деревьев
- •9.2. Ориентированные, упорядоченные и бинарные деревья
- •9.2.1. Ориентированные деревья
- •9.2.2. Эквивалентное определение ордерева
- •9.2.3. Упорядоченные деревья
- •9.2.4. Бинарные деревья
- •9.3. Представление деревьев в эвм
- •9.3.1. Представление свободных, ориентированных и упорядоченных деревьев
- •9.3.2. Представление бинарных деревьев
- •9.3.3. Обходы бинарных деревьев
- •9.3.4. Алгоритм симметричного обхода бинарного дерева
- •9.4. Деревья сортировки
- •9.4.1. Ассоциативная память
- •9.4.2. Способы реализации ассоциативной памяти
- •9.4.3. Алгоритм бинарного (двоичного) поиска
- •9.4.4. Алгоритм поиска в дереве сортировки
- •9.4.5. Алгоритм вставки в дерево сортировки
- •9.4.6. Алгоритм удаления из дерева сортировки
- •9.4.7. Вспомогательные алгоритмы для дерева сортировки
- •9.4.8. Сравнение представлений ассоциативной памяти
- •9.4.9. Выровненные деревья
- •9.4.10. Сбалансированные деревья
- •9.5. Кратчайший остов
- •9.5.1. Определения
- •9.5.2. Схема алгоритма построения кратчайшего остова
- •9.5.3. Алгоритм Краскала
- •Глава 10 Циклы
- •10.1. Фундаментальные циклы и разрезы
- •10.1.1. Циклы и коциклы
- •10.1.2. Независимые множества циклов и коциклов
- •10.1.3. Циклический и коциклический ранг
- •10.2. Эйлеровы циклы
- •10.2.1. Эйлеровы графы
- •10.2.2. Алгоритм построения эйлерова цикла в эйлеровом графе
- •10.2.3. Оценка числа эйлеровых графов
- •10.3. Гамильтоновы циклы
- •10.3.1. Гамильтоновы графы
- •10.3.2. Задача коммивояжера
- •Глава 11 Независимость и покрытия
- •11.1. Независимые и покрывающие множества
- •11.1.1. Покрывающие множества вершин и ребер
- •11.1.2. Независимые множества вершин и ребер
- •11.1.3. Связь чисел независимости и покрытий
- •11.2. Построение независимых множеств вершин
- •11.2.1. Постановка задачи отыскания наибольшего независимого множества вершин
- •11.2.2. Поиск с возвратами
- •11.2.3. Улучшенный перебор
- •11.2.4. Алгоритм построения максимальных независимых множеств вершин
- •11.3. Доминирующие множества
- •11.3.1. Определения
- •11.3.2. Доминирование и независимость
- •11.3.3. Задача о наименьшем покрытии
- •11.3.4. Эквивалентные формулировки знп
- •11.3.5. Связь знп с другими задачами
- •Глава 12 Раскраска графов
- •12.1. Хроматическое число
- •Ух, . . . ,Vn одноцветные классы,доказательство
- •12.2. Планарность
- •12.2.2. Эйлерова характеристика
- •12.2.3. Теорема о пяти красках
- •12.3. Алгоритмы раскрашивания
- •12.3.1. Точный алгоритм раскрашивания
- •12.3.2. Приближенный алгоритм последовательного раскрашивания
- •12.3.3. Улучшенный алгоритм последовательного раскрашивания
9.3.4. Алгоритм симметричного обхода бинарного дерева
Реализация обходов бинарного дерева с помощью рекурсивной процедуры не вызывает затруднений. В некоторых случаях из соображений эффективности применение явной рекурсии оказывается нежелательным. Следующий очевидный алгоритм реализует наиболее популярный симметричный обход без рекурсии, но с использованием стека.
Алгоритм 9.1. Алгоритм симметричного обхода бинарного дерева
Вход: бинарное дерево, представленное списочной структурой, r — указатель на корень. Выход: последовательность узлов бинарного дерева в порядке симметричного обхода.
Т: = ; р: = r { вначале стек пуст и р указывает на корень дерева }
М : { анализирует узел, на который указывает р }
if р = nil then
if T = 0 then
stop { обход акончен }
end if
р Т { левое поддерево обойдено }
yield р { очередной узел при симметричном обходе }
р:=р.r { начинаем обход правого поддерева
else
р Т { запоминаем текущий узел ... }
р:=р.l { ... и начинаем обход левого поддерева }
end if
goto M
9.4. Деревья сортировки
В этом разделе обсуждается одно конкретное применение деревьев в программировании, а именно деревья сортировки. При этом рассматриваются как теоретические вопросы, связанные, например, с оценкой высоты деревьев, так и практическая реализация алгоритмов, а также целый ряд прагматических аспектов применения деревьев сортировки и некоторые смежные вопросы.
9.4.1. Ассоциативная память
В практическом программировании для организации хранения данных и доступа к ним часто используется механизм, который обычно называют ассоциативной памятью. При использовании ассоциативной памяти данные делятся на порции (называемые записями), и с каждой записью ассоциируется ключ. Ключ — это значение из некоторого вполне упорядоченного множества, а записи могут иметь произвольную природу и различные размеры. Доступ к данным осуществляется по значению ключа, которое обычно выбирается простым, компактным и удобным для работы.
Пример
Ассоциативная память используется во многих областях жизни.
1. Толковый словарь или энциклопедия: записью является словарная статья, а ключом — заголовок словарной статьи (обычно его выделяют жирным шрифтом).
2. Адресная книга: ключом является имя абонента, а записью — адресная информация (телефон(ы), почтовый адрес и т. д.).
3. Банковские счета: ключом является номер счета, а записью — финансовая информация (которая может быть очень сложной).
Таким образом, ассоциативная память должна поддерживать по меньшей мере три основные операции:
- добавить (ключ, запись);
- найти (ключ): запись;
- удалить (ключ).
Эффективность каждой операции зависит от структуры данных, используемой для представления ассоциативной памяти. Эффективность ассоциативной памяти в целом зависит от соотношения частоты выполнения различных операций в данной конкретной программе.
ЗАМЕЧАНИЕ
Таким образом, невозможно указать способ организации ассоциативной памяти, который оказался бы наилучшим во всех возможных случаях.
9.4.2. Способы реализации ассоциативной памяти
Для представления ассоциативной памяти используются следующие основные структуры данных:
неупорядоченный массив;
упорядоченный массив;
дерево сортировки — бинарное дерево, каждый узел которого содержит ключ и обладает следующим свойством: значения ключа во всех узлах левого поддерева меньше, а во всех узлах правого поддерева больше, чем значение ключа в узле;
таблица расстановки (или хэш-таблица).
При использовании неупорядоченного массива алгоритмы реализации операций ассоциативной памяти очевидны:
операция «добавить (ключ, запись)» реализуется добавлением записи в конец массива;
операция «найти (ключ): запись» реализуется проверкой в цикле всех записей в массиве;
операция «удалить (ключ)» реализуется поиском удаляемой записи, а затем перемещением всех последующих записей на одну позицию вперед.
Для упорядоченного массива имеется эффективный алгоритм поиска, описанный в следующем подразделе. Реализация остальных операций очевидна.
Основное внимание в этом разделе уделено алгоритмам выполнения операций с деревом сортировки.
ОТСТУПЛЕНИЕ
Таблицы расстановки являются чрезвычайно важным практическим приемом программирования, подробное описание которого выходит за рамки этого учебника. Вкратце основная идея заключается в следующем. Подбирается специальная функция, которая называется хэш-функцией, переводящая значение ключа в адрес хранения записи (адресом может быть индекс в массиве, номер кластера на диске и т. д.). Таким образом, имея ключ, с помощью хэш-функции сразу определяется место хранения записи и открывается доступ к ней. Хэш-функция подбирается таким образом, чтобы разным ключам соответствовали, по возможности, разные адреса из диапазона возможных адресов записей. Как правило, мощность множества ключей существенно больше размера пространства адресов, которое, в свою очередь, больше количества одновременно хранимых записей. Поэтому при использовании хэширования возможны коллизии — ситуации, когда хэш-функция сопоставляет один и тот же адрес двум актуальным записям с различными ключами. Различные методы хэширования отличаются друг от друга способами разрешения коллизий и приемами вычисления хэш-функций.