- •Структуры и алгоритмы обработки данных
- •Логическая и физическая структуры данных
- •Классификация структур данных
- •Основные операции над структурами данных
- •Алгоритм и примеры задач, решаемых с помощью алгоритмов
- •Адресация и распределение памяти
- •Адресные пространства и модели оперативной памяти
- •Формирование физического адреса в реальном режиме
- •Особенности адресации в защищенном режиме
- •Кэширование
- •Анализ алгоритмов
- •Быстродействие – основной показатель эффективности алгоритма
- •Подсчет числа простейших операций
- •Лучший, средний и худший случаи
- •Алгоритмы и платформы
- •Виртуализация памяти
- •Использование кэша
- •Выравнивание данных
- •Рандомизированные алгоритмы
- •Общая характеристика записей и способы описания в Delphi
- •Многоуровневые записи
- •Выравнивание и упакованные записи
- •Записи с вариантной частью
- •Массивы
- •Общая характеристика массивов
- •Статические (стандартные) массивы
- •Многомерные статические массивы
- •Свойства статических массивов
- •Открытые массивы
- •Динамические массивы
- •Динамические векторы
- •Многомерные динамические массивы
- •Массивы типа Variant
- •Вставка и удаление в массиве
- •Связные списки и алгоритмы их обработки
- •Списки и их разновидности
- •Односвязный список
- •Общая характеристика односвязного списка
- •Структура элемента односвязного списка
- •Формирование односвязного списка
- •Просмотр односвязного списка
- •Вставка элемента в односвязный список
- •Удаление элемента из односвязного списка
- •Линейный двухсвязный список
- •Структура элемента двухсвязного списка
- •Реализация операций в линейном двухсвязном списке
- •Нелинейный двухсвязный список
- •Нелинейный трехсвязный список
- •Определение плекса и его общие признаки
- •Иерархическая списковая структура. Сетевая структура
- •Достоинства и недостатки связных списков
- •Функциональные и свободные списки
- •Общая характеристика функционального и свободного списка
- •Методы формирования свободного списка
- •Стеки, очереди, деки и операции в них
- •Общая характеристика
- •Очередь
- •Динамические множества и словари
- •Общая характеристика
- •Операции в динамических множествах
- •Деревья
- •Общая характеристика и некоторые определения
- •Представление дерева в памяти
- •Естественное представление дерева
- •Представление дерева с помощью вектора
- •Представление дерева с использованием списков сыновей
- •Методы обхода деревьев
- •Бинарное дерево
- •Структура бинарного дерева
- •Формирование бинарного дерева
- •Обход бинарного дерева
- •Преобразование любого дерева к бинарному дереву
- •Включение и исключение в дереве
- •Включение в дереве
- •Исключение в дереве
- •Поиск: определение и общая терминология
- •Линейный (последовательный) поиск
- •Последовательный поиск в упорядоченной таблице
- •Последовательный поиск при накоплении запросов
- •Индексно-последовательный поиск
- •Бинарный поиск
- •Поиск, использующий бинарное дерево
- •Сортировка
- •Общие сведения и некоторые определения
- •Внутренняя сортировка
- •Сортировка прямыми включениями
- •Сортировка бинарными включениями
- •Сортировка прямым выбором
- •Сортировка прямым обменом
- •Сортировка методом Шелла
- •Сортировка с помощью бинарного дерева
- •Пирамидальная сортировка
- •Быстрая сортировка разделением
- •Внешняя сортировка
- •Сортировка прямым слиянием
- •Сортировка естественным слиянием
- •Сортировка многопутевым слиянием
- •Многофазная сортировка
- •Хеширование и хеш-таблицы
- •Общие сведения и определения
- •Коллизии при хешировании
- •Разрешение коллизий при хешировании
- •Разрешение коллизий методом открытой адресации
- •Разрешение коллизий методом цепочек
- •Функции хеширования
- •Поисковые деревья
- •Бинарное дерево поиска
- •Структура бинарного дерева поиска и алгоритм поиска
- •Вставка элемента в бинарное дерево поиска
- •Удаление из бинарного дерева поиска
- •Красно-черные деревья
- •Определение красно-черного дерева, структура его элементов
- •Повороты
Разрешение коллизий методом цепочек
Имеется несколько причин, почему повторное хеширование может быть неадекватным методом для обработки коллизий при хешировании. Во-первых, оно предполагает фиксированный размер таблицы. Если число записей превысит этот размер, то невозможно выполнять вставки без выделения таблицы большего размера и повторного вычисления значений хеширования для ключей всех записей, находящихся уже в таблице, используя новую хеш-функцию. Более того, из такой таблицы трудно удалить запись. Например, предположим, что в позиции рosInd находится запись Rec1. При добавлении некоторой записи Rec2, чей ключ k2 хешируется в рosInd, эта запись должна быть вставлена в первую свободную позицию rh(рosInd), rh(rh(рosInd)), .... Предположим, что Rec1 затем удаляется, так что ячейка с индексом рosInd становится свободной. Поиск записи Rec2 начинается с позиции h(k2), что равно рosInd. Но поскольку эта позиция уже свободна, процесс поиска может ошибочно сделать вывод, что записи Rec2 нет в таблице.
Одно возможное решение этой проблемы состоит в маркировании удаленной записи как «удаленная» (логическое удаление), а не «свободная», и продолжении поиска, когда встречается такая «удаленная» позиция. Но это реально, если только выполняется небольшое число удалений. В противном случае при неудачном поиске придется организовать поиск по всей таблице, потому что большинство позиций будет отмечено как «удаленные», а не «свободные».
Другой метод разрешения коллизий при хешировании называется методом цепочек или методом, использующим связывание (chaining). Он представляет собой организацию связанного списка (цепочки) из всех записей, чьи ключи хешируются в одно и то же значение. Предположим, что хеш-функция выдает значения в диапазоне от 0 до N-1. Тогда описывается некоторый массив arrHeader, имеющий размер N и состоящий из узлов заголовков. Элемент arrHeader[i] указывает на список всех записей, чьи ключи хешируются в i.
Вставка c помощью хеширования осуществляет доступ к заголовку списка arrHeader[k], где k = h(Key). Затем производится вставка элемента с ключом Key в k-ый список. На рисунке 12.2 показан метод цепочек. Предполагается, что имеется массив заголовков из 10 элементов и что хеш-функция равна Key Mod 10. Предполагается также, что включение очередного элемента производится в конец списка. На рисунке представлен пример поступления ключей в таком порядке:
75, 66, 42, 192, 91, 40, 49, 87, 67, 16, 417, 130, 372, 227
Рисунок 12.2 Разрешение коллизий методом цепочек
Удаление узла из таблицы, которая построена по методу цепочек, заключается просто в исключении узла из связанного списка. Удаленный узел никак не влияет на эффективность алгоритма поиска. Алгоритм будет работать так, как если бы этот узел никогда не вставлялся в таблицу. Отметим, что эти списки могут быть динамически переупорядочены для получения большей эффективности поиска.
Поиск выполняется очень просто: сначала аргумент поиска ArgSearch хешируется в некоторый индекс, допустим в индекс k, а затем в k-ом списке осуществляется поиск ключа, равного значению ArgSearch.
Основным недостатком метода цепочек является то, что для узлов указателей требуется дополнительное пространство памяти. Однако в алгоритмах, которые используют метод цепочек, первоначальный массив меньше, чем в алгоритмах, которые используют повторное хеширование. Это происходит из-за того, что при методе цепочек ситуация не становится критичной, если весь массив становится заполненным. Всегда имеется возможность выделить дополнительные узлы и добавить их к различным спискам. Конечно, если эти списки станут очень длинными, то теряет смысл вся идея хеширования.