Hashtables - это структура данных, которая поддерживает O (1) поиск и вставку.
Хеш-таблица обычно имеет пару ключ и значение, где ключ используется в качестве параметра функции ( хеш-функция ), которая будет определять расположение значения во внутренней структура данных , обычно массив.
Поскольку вставка и поиск зависят только от результата хеш-функции, а не от размера хеш-таблицы или количества хранимых элементов, хеш-таблица имеет O (1) вставку и поиск.
Однако есть одно предостережение . То есть, когда хеш-таблица становится все более и более полной, будут хеш-коллизии , где хеш-функция вернет элемент массива, который уже занят. Для этого потребуется разрешение коллизий , чтобы найти другой пустой элемент.
При возникновении коллизии хеша поиск или вставка не могут быть выполнены за O (1) раз. Однако хорошие алгоритмы разрешения коллизий могут уменьшить количество попыток найти другое подходящее пустое место или увеличение размера хеш-таблицы может уменьшить количество коллизий в первую очередь.
Таким образом, теоретически, только хеш-таблица, поддерживаемая массивом с бесконечным числом элементов и совершенной хэш-функцией, сможет достичь производительности O (1) , поскольку это единственный способ избегать коллизий хешей, которые увеличивают количество необходимых операций. Поэтому для любого массива конечного размера в тот или иной момент будет меньше, чем O (1) из-за коллизий хешей.
Давайте посмотрим на пример. Давайте используем хеш-таблицу для хранения следующих (key, value)
пар:
(Name, Bob)
(Occupation, Student)
(Location, Earth)
Мы реализуем хеш-таблицу с массивом из 100 элементов.
key
будет использоваться для определения элемента массива для хранения пары (key
, value
). Для определения элемента будет использоваться hash_function
:
hash_function("Name")
возврат 18
hash_function("Occupation")
возвращает 32
hash_function("Location")
возвращает 74 .
Из приведенного выше результата мы назначим пары (key, value)
в элементы массива.
array[18] = ("Name", "Bob")
array[32] = ("Occupation", "Student")
array[74] = ("Location", "Earth")
Вставка требует только использования хэш-функции и не зависит от размера хеш-таблицы или ее элементов, поэтому ее можно выполнить за O (1) раз.
Аналогично, при поиске элемента используется хеш-функция.
Если мы хотим найти ключ "Name"
, мы выполним hash_function("Name")
, чтобы определить, в каком элементе массива находится нужное значение.
Кроме того, поиск не зависит ни от размера хеш-таблицы, ни от количества хранимых элементов, поэтому операция O (1).
Все хорошо. Попробуем добавить дополнительную запись ("Pet", "Dog")
. Однако есть проблема, поскольку hash_function("Pet")
возвращает 18 , что является тем же хешем для клавиши "Name"
.
Поэтому нам нужно разрешить это столкновение хэшей. Давайте предположим, что использованная нами функция разрешения коллизий хэшей нашла, что новый пустой элемент равен 29 :
array[29] = ("Pet", "Dog")
Поскольку в этой вставке произошло столкновение хэшей, наша производительность была не совсем O (1).
Эта проблема также возникает, когда мы пытаемся найти ключ "Pet"
, так как попытка найти элемент, содержащий ключ "Pet"
, выполнив hash_function("Pet")
, всегда будет возвращать 18 изначально.
Как только мы посмотрим на элемент 18, мы найдем ключ "Name"
вместо "Pet"
. Когда мы обнаружим это несоответствие, нам нужно разрешить коллизию, чтобы получить правильный элемент, который содержит действительный ключ "Pet"
. Повторное сопоставление коллизии хеша - это дополнительная операция, которая делает хеш-таблицу неработающей во время O (1).