2. Хеш-таблицы. Общие понятия.
В случае, если требуется динамическая
структура данных, поддерживающая лишь
словарные операции, часто пользуются методом
хеширования.
Хеш-таблица – это обобщение обычного
массива с расширенной адресацией,
использующее понятие хеш-функции.
3. Хеш-таблицы. Прямая адресация.
Пусть возможными ключами являются числа
0, 1, … m-1 (число m не велико). Пусть ключи
каждого элемента динамического множества
различны.
Для хранения динамического множества
можно использовать массив T[0..m-1],
называемый таблицей с прямой адресацией,
каждая позиция (ячейка) которого
соответствует определенному ключу.
5. Хеш-таблицы. Прямая адресация.
Прямая адресация не применима:
если число возможных ключей большое
если ключи не являются ограниченными
упорядоченными целыми числами.
Кроме того, если число реально присутствующих
ключей k мало по сравнению с общим
количеством возможных ключей много памяти
тратится зря.
6. Хеш-таблицы. Коллизии.
Для того чтобы решить возникшие проблемы,
можно выделить массив относительно
небольшого размера, и сопоставить каждому
значению ключа ячейку с номером h(k), где
k – значение ключа, h – некоторая функция,
называемая хеш-функцией.
Проблема в этом случае состоит в том, что для
двух разных ключей значения хеш-функции
могут совпасть. В таком случае говорят, что
случилась коллизия.
7. Хеш-таблицы. Коллизии.
Одним из способов решения проблемы коллизий в
хеш-таблицах является технология сцепления
элементов. Идея состоит в том, чтобы элементы,
имеющие одно и то же хеш-значение, связывать в
список.
При равномерном хешировании (вероятность
попадания элемента в ячейку с некоторым номером
не зависит от того, куда попали другие элементы),
время поиска элемента в хеш-таблице составляет
где n – кол-во внесенных элементов,
m – размер хеш-таблицы.
m
n=+Θ αα ),1(
10. Хеш-таблицы. Выбор хеш-функции.
Идеальной хеш-функцией, является такая
функция, при использовании которой коллизии
не случаются, если размер хеш-таблицы больше
количества внесенных элементов.
При отсутствии информации о характере
вносимых элементов выбор идеальной функции
невозможен.
Хорошая хеш-функция должна хорошо «переме-
шивать» ключи по ячейкам.
Хеш-функция должна оставаться детермини-
рованной.
11. Хеш-таблицы. Выбор хеш-функции.
При построении хеш-функции предполагают,
что ее область определения – целые
неотрицательные числа.
Если ключи не являются целыми неотрица-
тельными числами, их к ним приводят.
Например, строку можно привести к числу с
помощью ASCII кода:
“ppt” = 255*255*112+255*112+116 = 7311476
12. Хеш-таблицы. Выбор хеш-функции.
Наиболее распространенные методы построения
хеш-функции:
Деление с остатком: h(k) = k mod m, где m –
размер хеш-таблицы.
Умножение: , A-некоторая
константа в интервале (0..1), kA mod 1 –
дробная часть произведения kA, m – размер
хеш-таблицы. Пример удачного значения
константы A=0.6180339887…
)1mod()( kAmkh =
13. Хеш-таблицы. Выбор хеш-функции.
Если знать заранее хеш-функцию h, то можно
специально подобрать данные так, что все n
ключей попадут в одну ячейку.
Единственный выход из такого положения –
случайно выбирать хеш-функцию из
некоторого множества во время исполнения
программы. Такой подход называется
универсальным хешированием, множество
хеш-функций – универсальным семейством.
14. Хеш-таблицы. Выбор хеш-функции.
Семейство H является универсальным, если для
любых двух ключей x,y число функций
для которых h(x)=h(y) равно |H|/m.
Построить универсальное семейство можно так:
при условии что m – простое число > max(«байт»)
x= <x0,x1,…xr>, где xi – «байт» числа x
a= <a0,a1,…ar>, где a – последовательность, с
элементами, принадлежащими множеству [0..m-1].
Hh∈
1,}{,mod)(
0
+=== ∑=
rHhHmxaxh
r
i a
aiia
15. Хеш-таблицы. Открытая адресация.
Открытая адресация – еще один способ
решения проблемы коллизий в хеш-таблице.
При открытой адресации списков нет, все
элементы хранятся в ячейках хеш-таблицы.
Таким образом количество внесенных
элементов не может быть больше размера
таблицы, т.е. коэффициент заполнения всегда
меньше 1.
16. Хеш-таблицы. Открытая адресация.
При открытой адресации, добавляя новый
элемент, мы просматриваем таблицу пока не
встретим свободное место.
Если просматривать таблицу последовательно,
скорость работы алгоритма составит O(n).
Идея состоит в том, что порядок просмотра
таблицы должен зависеть от ключа.
Хеш-функция при открытой адресации
получает второй параметр – номер попытки.
17. Хеш-таблицы. Открытая адресация.
nil 0
nil 1
2
3
4
5
nil 6
nil 7
8
9
k1
k2
k3
k5
k8
k4
k7
k6
U
K
Последовательность
испробованных мест
<h(k,0),h(k,1),..h(k,m-1)>
называется последова-
тельностью проб для
заданного ключа k.
Хеш-функция h(k,i)
должна быть такой, что
каждое из чисел 0..m-1
должно появиться в
последовательности
проб ровно 1 раз.
19. Хеш-таблицы. Открытая адресация.
Наиболее распространенные методы построения
хеш-функции при открытой адресации:
Линейная последовательность проб:
h(k,i) = (h`(k)+i) mod m, т.е. для ключа k начинают с ячейки
номер h`(k), а затем перебирают ячейки подряд.
Квадратичная последовательность проб:
h(k,i) = (h`(k)+с1*i+ с2*i2
) mod m, здесь h`(k) обычная хеш-
функция, c1 и c2-константы.
Двойное хеширование:
h(k,i) = (h1`(k)+i*h2`(k)) mod m, здесь h1`(k) и h2`(k) обычные
хеш-функции, т.е. просматриваются ячейки начиная с h1`(k) c
шагом h2`(k)
20. Хеш-таблицы. Открытая адресация.
При равномерном хешировании в случае с открытой
адресацией все перестановки множества {0..m-1}
равновероятны. Скорость поиска при равномерном
хешировании составляет
Хуже всего работает линейная последовательность
проб – она может привести к образованию кластеров
Двойное хеширование - один из лучших методов
открытой адресации.
заполненияткоэффициен
m
nгде),
1
1
ln
1
( −=
−
Θ α
αα
21. Применимость хеш-таблиц.
Главное достоинство хеш-таблиц – высокая
скорость поиска информации. Главный
недостаток – большой расход памяти.
Хеш-таблицы следует применять только при
условии что количество сохраняемых
элементов сравнимо с ее размером.
Если количество сохраняемых элементов
меньше размера таблицы лучше применять
хеширование с открытой адресацией.
22. Древовидные структуры данных
Корневое дерево – ациклический неориентированный граф, в
котором одна из вершин выделена и называется корнем.
Пусть x-произвольная вершина дерева с корнем r. Существует
единственный путь из r в x, причем все вершины на этом пути
называются предками x. Если y предок x, то x потомок y.
Для каждой вершины x в дереве можно рассмотреть поддерево с
корнем x.
Если <x,y> - последнее ребро на пути из корня в x, то y –
родитель x, x – ребенок y.
Вершины имеющие общего родителя - братья.
Вершина не имеющая детей – лист, все остальные – внутренние.
Число детей у вершины – ее степень.
Длина пути от корня до вершины – глубина вершины.
Максимальная глубина – высота дерева.
24. Древовидные структуры данных.
Способ «Родитель-дети».
Если заранее известно, что степень вершины
корневого дерева ограничена константой k, то
часто применяют способ реализации
древовидной динамической структуры
«родитель-дети».
Идея состоит в том, что каждую вершину
можно представить как структуру, помимо
ключа и дополнительной информации
хранящую ссылку на вершину-родитель и k
ссылок на вершины-дети.
26. Древовидные структуры данных.
Способ «Левый ребенок – правый брат».
Если изначально k не известно, а также в
целях экономии памяти, можно использовать
способ «левый ребенок – правый брат».
В этом случае вершина дополнительно хранит
три ссылки: на своего родителя, на самого
левого своего ребенка, на своего правого
брата.