166 lines
12 KiB
Markdown
166 lines
12 KiB
Markdown
---
|
||
title: Hash Tables and Hashing Functions
|
||
localeTitle: Хэш-таблицы и функции хеширования
|
||
---
|
||
### Введение в хеширование
|
||
|
||
Хеширование предназначено для решения проблемы необходимости эффективного поиска или хранения элемента в коллекции.
|
||
Например, если у нас есть список из 10 000 слов английского языка, и мы хотим проверить, указано ли данное слово в списке, было бы неэффективно последовательно сравнивать слово со всеми 10 000 элементами, пока мы не найдем совпадение. Даже если список слов лексикографически отсортирован, как в словаре, вам все равно потребуется некоторое время, чтобы найти искомое слово.
|
||
Хеширование - это метод, позволяющий сделать вещи более эффективными, эффективно сужая поиск с самого начала.
|
||
|
||
## Что такое хеширование?
|
||
|
||
Хеширование означает использование некоторой функции или алгоритма для сопоставления данных объекта с некоторым репрезентативным целым значением.
|
||
Этот так называемый хеш-код (или просто хеш) можно затем использовать как способ сузить наш поиск при поиске элемента на карте.
|
||
Как правило, эти хеш-коды используются для создания индекса, в котором значение сохраняется.
|
||
|
||
## Как работает хэш
|
||
|
||
В хэш-таблицах вы храните данные в виде пар ключей и значений. Ключ, который используется для идентификации данных, задается как вход для функции хэширования. Хэш-код, который является целым числом, затем отображается на фиксированный размер, который у нас есть.
|
||
|
||
Хэш-таблицы должны поддерживать 3 функции.
|
||
|
||
* insert (ключ, значение)
|
||
* get (ключ)
|
||
* удалить (ключ)
|
||
|
||
В качестве примера, чтобы помочь нам понять концепцию, предположим, что мы хотим сопоставить список строковых ключей со строковыми значениями (например, сопоставить список стран со своими столичными городами).
|
||
Итак, скажем, мы хотим сохранить данные в таблице на карте.
|
||
|
||
Ключ | Стоимость
|
||
\---------------- | -------------
|
||
Куба | Гавана
|
||
Англия | Лондон
|
||
Франция | Париж
|
||
Испания | Мадрид
|
||
Швейцария | Берн
|
||
|
||
Предположим, что наша хеш-функция состоит в том, чтобы просто взять длину строки.
|
||
|
||
Для простоты мы будем иметь два массива: один для наших ключей и один для значений.
|
||
Поэтому, чтобы поместить элемент в хэш-таблицу, мы вычисляем его хеш-код (в этом случае просто подсчитываем количество символов), затем кладем ключ и значение в массивы по соответствующему индексу.
|
||
Например, у Кубы есть хеш-код (длина) 4.
|
||
Таким образом, мы сохраняем Кубу в 4-й позиции в массиве ключей, а Гавана - в 4-м индексе массива значений и т. Д. И мы получаем следующее:
|
||
|
||
Должность | Ключ-массив | Массив значений
|
||
\--------------------- | ------------------ | --------- ------
|
||
1 | |
|
||
2 | |
|
||
3 | |
|
||
4 | Куба | Гавана
|
||
5 | Испания | Мадрид
|
||
6 | Франция | Париж
|
||
7 | Англия | Лондон
|
||
8 | |
|
||
9 | |
|
||
10 | |
|
||
11 | Швейцария | Берн
|
||
|
||
Теперь в этом конкретном примере все работает очень хорошо.
|
||
Наш массив должен быть достаточно большим для размещения самой длинной строки, но в этом случае это всего лишь 11 слотов.
|
||
Мы немного теряем пространство, потому что, например, в наших данных нет 1-буквенных ключей, а также ключей от 8 до 10 букв. Но в этом случае потерянное пространство тоже не так плохо. Взятие длины строки является приятным и быстрым, а также процесс нахождения значения, связанного с заданным ключом (конечно, быстрее, чем до пяти сопоставлений строк).
|
||
|
||
Но что нам делать, если наш набор данных имеет строку, которая имеет более 11 символов?
|
||
Что, если у нас есть еще одно слово с 5 символами «Индия» и попробуйте присвоить его индексу, используя нашу хэш-функцию. Поскольку индекс 5 уже занят, нам нужно сделать вызов, что с ним делать. Это называется столкновением.
|
||
|
||
Если в нашем наборе данных была строка с тысячами символов, и вы создадите массив тысяч индексов для хранения данных, это приведет к потерям пространства. Если бы наши ключи были случайными словами с английского языка, где столько слов с одинаковой длиной, использование длины как функции хэширования было бы бесполезным.
|
||
|
||
## Обработка столкновений
|
||
|
||
Для обработки столкновений используются два основных метода.
|
||
|
||
1. Раздельная цепочка
|
||
2. Открытая адресация
|
||
|
||
#### Раздельная цепочка
|
||
|
||
Обработка столкновений хэшей путем отдельной цепочки использует дополнительную структуру данных, предпочтительно связанный список для динамического распределения, в ведра. В нашем примере, когда мы добавляем Индию в набор данных, она добавляется к связанному списку, хранящемуся в индексе 5, тогда наша таблица будет выглядеть так.
|
||
|
||
Должность | Связанные списки глав |
|
||
\--------------------- | ---------------------------- -------- |
|
||
1 | |
|
||
2 | |
|
||
3 | |
|
||
4 | [Куба-Гавана\] |
|
||
5 | \[Испания-Мадрид\] -> \[Индия-Дели\] |
|
||
6 | \[Франция-Париж\] |
|
||
7 | \[Англия-Лондон\] |
|
||
8 | |
|
||
9 | |
|
||
10 | |
|
||
11 | \[Швейцария-Берн\] |](https://en.wikipedia.org/wiki/Linear_probing)
|
||
|
||
Чтобы найти предмет, сначала переходим к ведру, а затем сравниваем ключи. Это популярный метод, и если используется список ссылок, хэш никогда не заполняется. Стоимость `get(k)` в среднем равна `O(n)` где n - количество ключей в ковше, общее количество ключей - N.
|
||
Проблема с отдельной цепочкой заключается в том, что структура данных может расти без ограничений.
|
||
|
||
#### Открытая адресация
|
||
|
||
Открытая адресация не вводит никакой новой структуры данных. Если происходит столкновение, мы ищем доступность в следующем месте, генерируемом алгоритмом. Open Addressing обычно используется, когда пространство для хранения является ограниченным, то есть встроенным процессором. Открытая адресация не обязательно быстрее, чем отдельная цепочка.
|
||
|
||
Методы открытой адресации
|
||
|
||
* \[Линейное зондирование
|
||
* [Квадратичное зондирование](https://en.wikipedia.org/wiki/Quadratic_probing)
|
||
* [Двойной хеши](https://en.wikipedia.org/wiki/Double_hashing)
|
||
|
||
## Как использовать хэширование в вашем коде.
|
||
|
||
#### питон
|
||
```
|
||
# Few languages like Python, Ruby come with an in-built hashing support.
|
||
# Declaration
|
||
my_hash_table = {}
|
||
my_hash_table = dict()
|
||
|
||
# Insertion
|
||
my_hash_table[key] = value
|
||
|
||
# Look up
|
||
value = my_hash_table.get(key) # returns None if the key is not present || Deferred in python 3, available in python 2
|
||
value = my_hash_table[key] # throws a ValueError exception if the key is not present
|
||
|
||
# Deletion
|
||
del my_hash_table[key] # throws a ValueError exception if the key is not present
|
||
|
||
# Getting all keys and values stored in the dictionary
|
||
keys = my_hash_table.keys()
|
||
values = my_hash_table.values()
|
||
```
|
||
|
||
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [Код запуска](https://repl.it/CVtK)
|
||
|
||
#### Джава
|
||
```
|
||
// Java doesn't include hashing by default, you have to import it from java.util library
|
||
// Importing hashmaps
|
||
import java.util.HashMap;
|
||
|
||
// Declaration
|
||
HashMap<Integer, Integer> myHashTable = new HashMap<Integer, Integer>(); // declares an empty map.
|
||
|
||
// Insertion
|
||
myHashTable.put(key, value);
|
||
|
||
// Deletion
|
||
myHashtable.remove(key);
|
||
|
||
// Look up
|
||
myHashTable.get(key); // returns null if the key K is not present
|
||
myHashTable.containsKey(key); // returns a boolean value, indicating the presence of a key
|
||
|
||
// Number of key, value pairs in the hash table
|
||
myHashTable.size();
|
||
```
|
||
|
||
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [Код запуска](https://repl.it/CVt1)
|
||
|
||
## Ресурсы
|
||
|
||
* Для дальнейшего чтения вы хотите попробовать эту [ссылку](http://geeksquiz.com/hashing-set-1-introduction/) , которая объясняет хеширование с использованием другого примера.
|
||
* [Хеширование через 60 секунд](https://www.youtube.com/watch?v=x05KubVlh_M) .
|
||
* [Хвост кукушки](https://www.youtube.com/watch?v=HRzg0SzFLQQ)
|
||
* [Consisten Hashing](https://www.youtube.com/watch?v=jznJKL0CrxM)
|
||
* [Цветные фильтры](https://www.youtube.com/watch?v=-SuTGoFYjZs)
|
||
* [Стратегии хеширования](https://www.youtube.com/watch?v=D65JQ0qQwZk)
|
||
* [Хеширование паролей](https://crackstation.net/hashing-security.htm)
|
||
* [Разница между Хешированием и шифрованием](http://stackoverflow.com/questions/326699/difference-between-hashing-a-password-and-encrypting-it) |