
- •Министерство образования и науки Российской Федерации
- •Цель лекции
- •План лекции
- •1 Происхождение вычислительных машин
- •2 Изучение алгоритмов
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Биты и их хранение
- •2 Оперативная память
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Устройства внешней памяти
- •3 Хранение и поиск файлов
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Представление числовых значений
- •2 Хранение целых чисел
- •3 Хранение дробей
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Представление текста
- •2 Представление изображений
- •Достоинства пиксельной графики
- •Недостатки пиксельной графики
- •Достоинства векторной графики
- •Недостатки векторной графики
- •3 Представление звука
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Сжатие изображений
- •2 Ошибки передачи данных
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Архитектура эвм
- •2 Связь процессора с другими устройствами
- •3 Другие архитектуры
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Машинный язык
- •2 Пример машинного языка
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Выполнение программы
- •2 Пример выполнения программы
- •3 Программы и данные
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Логические операции
- •2 Операции сдвига
- •3 Арифметические операции
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Эволюция операционных систем
- •2 Архитектура операционных систем
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Понятие процесса
- •2 Управление процессами
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Классификация сетей
- •2 Сетевые протоколы*
- •3 Безопасность сетей
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Понятие алгоритма
- •2 Представление алгоритма
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Теория решения задач
- •2 Общие методы решения задач
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Алгоритм последовательного поиска
- •2 Управление циклами
- •3 Алгоритм сортировки методом вставки
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Алгоритмы поиска и сортировки
- •2 Управление рекурсией
- •3 Разработка рекурсивных процедур
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Эффективность алгоритмов
- •2 Верификация программ
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Эволюция и классификация языков программирования
- •2 Концепции традиционного программирования
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Процедурные единицы
- •2 Реализация языка программирования
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Объектно-ориентированное программирование
- •2 Декларативное программирование
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Структуры данных
- •Integer Scores (2.9).
- •2 Статические и динамические структуры
- •3 Указатели
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Массивы
- •2 Списки
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Структура и функции стека
- •2 Реализация стека
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Очереди
- •2 Деревья
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Пользовательские типы данных
- •Int Age;
- •2 Классы
- •Int *StackEntries;
- •3 Стандартная библиотека шаблонов
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Роль операционной системы
- •2 Последовательные файлы
- •3 Вопросы программирования
- •0000000010000110
- •001100010011001100110100
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Основные положения индексации
- •2 Вопросы программирования
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Основные положения хеширования
- •2 Вопросы программирования
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Общие вопросы
- •2 Система управления базой данных
- •3 Поддержка целостности баз данных
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Модели баз данных
- •2 Реляционная модель баз данных
- •3 Объектно-ориентированные базы данных
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Интеллект и машины
- •2 Распознавание образов
- •3 Мышление
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Искусственные нейронные сети
- •2 Генетические алгоритмы
- •Контрольные вопросы
- •Невычислимые функции Цель лекции
- •План лекции
- •1 Основы машины Тьюринга
- •2 Невычислимая функция
- •3 Сложность задач
- •Листинг 1. Процедура MergeLists для объединения двух упорядоченных списков
- •Листинг 2. Алгоритм сортировки слиянием, реализованный в процедуре MergeSort
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Шифрование с открытым ключом
- •2 Модульная арифметика
- •Контрольные вопросы
- •Литература
- •Internet-ресурсы
Контрольные вопросы
1. Поясните термины: «индексация», «индекс» и «индексированный файл»?
2. Что происходит в компьютере при открытии индексированного файла?
3. Какие файлы называются инвертированными? Приведите примеры.
4. В чем заключается преимущество частичной индексации?
5. Как располагаются индексированные файлы на диске? Поясните на примере.
6. Какие функции языка С++ реализуют механизм индексации?
Лекция № 29 Хеширование данных
Цель лекции
Изучить способы хранения данных с использованием хеширования
План лекции
1. Основные положения хеширования.
2. Вопросы программирования.
1 Основные положения хеширования
Хотя индексирование обеспечивает относительно быстрый доступ к записям в структуре хранения данных, оно достигает этого за счет поддержки индекса. Хеширование (hashing) — это способ, обеспечивающий похожий доступ без излишней нагрузки. Этот способ позволяет находить запись при помощи ключевого значения, но вместо поиска ключа в индексе хеширование определяет положение записи исходя из значения ключа. Процесс можно описать так: пространство хранилища данных разделено на несколько секций, называемых сегментами (bucket). Записи распределены по блокам согласно алгоритму (называемому хеш-функцией), который преобразует ключевые значения в номера сегментов. Каждая запись хранится в сегменте, идентифицируемом при помощи этого процесса. Таким образом, чтобы найти элемент в структуре хранилища, нужно применить хеш-функцию к идентификационному ключу этого элемента и определить соответствующий сегмент; затем считать содержимое сегмента и найти в нем нужную запись. Результат применения хеширования к структуре хранения на запоминающем устройстве называется хеш-файлом (hash file). Результат применения хеш-функции к структуре хранения в оперативной памяти обычно называется хеш-таблицей (hash table).
Применим концепцию хеширования к классическому файлу сотрудников. Сначала на запоминающем устройстве выделим несколько свободных областей, которые будут играть роль сегментов. Выбор их количества и размера мы обсудим позже. Сейчас же предположим, что мы создали 40 сегментов, к которым будем обращаться как к сегменту № 0, сегменту № 1 и так далее до сегмента № 39.
Предположим, что в качестве ключа для идентификации записи сотрудника будет использоваться его идентификационный номер. Наша следующая задача — разработать хеш-функцию для преобразования этих ключей в номера сегментов. Хотя идентификаторы могут иметь форму 25X3Z или J2X35, то есть не являться числовыми значениями, они хранятся в виде комбинаций битов, и мы можем интерпретировать эти комбинации как номера. Воспользовавшись числовой интерпретацией, разделим каждый ключ на количество сегментов и запишем остаток, который в нашем случае будет целым числом от 0 до 39. Таким образом, мы можем использовать остаток от деления для идентификации одного из наших 40 сегментов (рис. 1).
Рисунок 1 – Основы системы хеширования, где в каждом сегменте хранятся записи, для которых хеш-функция дает номер этого сегмента
Многое уже было написано о хешировании. Цель лекции всех исследований — найти эффективный алгоритм хеширования, равномерно распределяющий записи по сегментам. Один из способов, называемый методом середины квадрата (midsquare method), заключается в умножении ключевого значения на само себя и выборе средних цифр из результата. Эти цифры и являются номером сегмента. Другой метод называется методом выбора (extraction method), при этом выбираются цифры, находящиеся на определенных позициях в ключе, и номер сегмента создается путем перестановки этих цифр каким-либо предопределенным методом. Сегодня достаточно популярны различные вариации процесса деления, который мы обсуждали в этом разделе. Главная задача при этом — избежать ключей, подчиненных какой-либо системе, так как система среди ключей приводит к тому, что сегменты также выбираются согласно системе. По этой причине для функции хеширования лучше использовать последние несколько цифр в телефонных номерах, так как цифры в начале номера обычно представляют географическую область, населенный пункт и т. д. Аналогично, не рекомендуется использование имен в качестве ключей, так как в зависимости от региона определенные имена встречаются чаще (сравните, например, Смит, Иван, Мухаммед и Дешпанде).
Используя эти вычисления как хеш-функцию, мы перейдем к созданию файла. Будем брать записи по одной, применять к их ключу нашу хеш-функцию деления на 40, получать номера сегмента и затем передавать записи в соответствующие сегменты (рис. 2). Позже, если нам потребуется считать определенную запись, мы применим хеш-функцию к ее ключу, найдем соответствующий сегмент и произведем поиск этой записи в сегменте.
Рисунок 2 – Хеширование значения ключевого поля 25X3Z в один из 40 сегментов
Наша система деления на 40 обладает некоторыми недостатками, основным из которых является тот факт, что, выбрав однажды хеш-функцию, мы более не можем управлять распределением записей по сегментам. Например, если при делении на 40 все ключи дали одинаковый остаток, они все будут размещены в одном сегменте. В свою очередь, получение записи потребует длительного поиска в одном сегменте, и никаких преимуществ по сравнению с последовательной структурой файла мы не получим.
Поэтому нам выгодно выбрать такую хеш-функцию, которая равномерно распределяет записи по сегментам. Можно улучшить рассмотренную систему, изменив количество сегментов. Чтобы понять почему, вспомните, что если у делимого и делителя есть общий множитель, этот множитель будет и множителем остатка. Предположим, что мы создали хеш-систему из 40 сегментов, и все ключи делятся на 5. Так как 40 также делится на 5, число 5 будет присутствовать в остатках, полученных в процессе деления, и записи распределятся по сегментам, соответствующим остаткам 0, 5, 10, 15, 20, 25, 30 и 35. Аналогично с ключами, которые делятся на 2, 4, 8, 10 и 20, так как эти числа также являются множителями 40. Такая ситуация приводит к частному решению выбрать количество сегментов, являющееся простым числом, минимизируя возможность появления общих множителей. Например, можно существенно снизить вероятность кластеризации (неравномерного распределения) в примере с записями сотрудников, используя 41 сегмент вместо 40.
Ситуация, когда два ключа при хешировании дают одинаковое значение, называется коллизией. Коллизии — это первый шаг к кластеризации, поэтому их надо избегать. К сожалению, теория вероятностей говорит, что вероятность возникновения коллизий очень высока, даже если сегментов больше, чем записей. Чтобы понять это очевидное несоответствие, представим, что происходит, когда мы помещаем записи в хеш-систему хранения с 41 пустым сегментом.
Предположим, что мы нашли хеш-функцию, произвольно распределяющую записи по сегментам, что наша система хранения пуста, и мы собираемся добавлять новые записи по одной. Первая запись будет помещена в пустой сегмент. Однако при добавлении следующей записи только 40 из 41 сегмента пусты, поэтому вероятность того, что вторая запись попадет в пустой сегмент, равна 40/41. Предполагая, что вторая запись также попала в пустой сегмент, для третьей записи останется только 39 пустых сегментов, и вероятность попадания ее в один из них равна 39/41. Продолжая этот процесс, мы обнаружим, что если первые семь записей попали в пустые сегменты, у восьмой есть вероятность, равная 34/41, что она попадет в один из оставшихся пустых сегментов.
Такой анализ позволяет нам подсчитать вероятность того, что первые восемь записей попадут в пустые сегменты — она равна произведению вероятности для каждой записи попасть в пустой сегмент, предполагая, что предыдущие записи размещены именно в пустых сегментах. Таким образом, вероятность равна (41/41)х(40/41)х(39/41)х(38/41)х ... х(34/41) = 0.482
Мы видим, что вероятность меньше половины. Таким образом, вероятность того, что по меньшей мере две из первых восьми записей попадут в один сегмент, больше, чем вероятность того, что они попадут в разные сегменты. То есть коллизия, скорее всего, произойдет даже при хранении только восьми записей в системе хеширования с 41 сегментом.
Хотя мы представили технологию хеширования в контексте создания эффективных структур хранения, хеширование не ограничивается этой областью. Например, хеширование можно использовать как средство аутентификации сообщений, передаваемых в Интернете. Идея состоит в хешировании сообщения (секретным способом) и шифровке полученного значения. Затем это значение передается вместе с сообщением. Для аутентификации сообщения получатель хеширует его (тем же секретным способом) и удостоверяется, что полученное значение равно исходному. Если же полученное при хешировании значение не равно исходному, считается, что сообщение повреждено. С этой точки зрения большинство способов выявления ошибок можно рассматривать как приложение хеширования. Например, система четности просто хеширует каждую комбинацию битов в 0 или 1 и передает результат вместе с комбинацией, чтобы он мог использоваться в процессе аутентификации.
Высокая вероятность коллизий говорит о том, что система хеширования должна быть разработана с учетом проблемы заполнения и переполнения сегментов. Один из подходов — разрешить сегментам расширяться. Например, если сегмент на запоминающем устройстве заполнен, ему выделяется дополнительная область на этом устройстве. В случае хеш-таблицы в оперативной памяти сегменты могут иметь вид связных списков, которые могут расти бесконечно.
В случаях, когда размер сегментов фиксирован, чаще всего употребляются два подхода к проблеме переполнения. Можно разрешить переполненным сегментам перемещать лишние записи в соседние сегменты. В этом случае, если новая запись должна попасть в полный сегмент, мы может поместить ее в соседний незаполненный сегмент. Конечно, это усложнит процесс поиска данных, когда мы обнаружим, что сегмент, где должна находиться искомая запись, заполнен, но этой записи там нет. Более сложная проблема возникает при удалении записей. Например, если мы удалим записи из полного сегмента, который перемещал свои записи в соседние сегменты, нужно ли искать эти перемещенные записи и записывать их обратно в предназначенный для них сегмент?
Альтернатива перемещению лишних записей из переполненного сегмента в соседние — это помещение их в область переполнения, специально зарезервированную для этой цели. Самый простой способ организации области переполнения заключается в простом сборе всех записей из всех сегментов. В этом случае поиск записи, не поместившейся в сегмент, будет выполняться во всей области переполнения. Однако традиционный подход состоит в связывании записей, не поместившихся в определенный сегмент, чтобы в области переполнения хранился набор связных списков. В этом случае файл, хранящийся в пяти сегментах, может иметь вид, показанный на рис. 3 (заполненная записями область хранения закрашена). Обратите внимание, что элементы из сегментов 1 и 4 были перемещены в область переполнения, и, если добавить еще один элемент в сегмент 2, его тоже придется переместить.
Рисунок 3 – Обработка переполнения сегментов
Относительно пустые хеш-файлы или хеш-таблицы обеспечивают эффективный доступ к данным, но если сегменты начнут переполняться, время ответа может существенно увеличиться. По этой причине со структурами хешированного хранения связана концепция фактора загрузки, то есть отношения между количеством записей, хранящихся в структуре, к общему объему сегментов. Если этот коэффициент меньше 50 %, производительность системы хеширования достаточно высока. Если коэффициент превышает 75 %, общая производительность системы падает. Однако когда фактор нагрузки достигает значения 75 %, система хранения обычно перестраивается для использования большего количества сегментов.