АПЕЛЬСИНЫ
4Добавим молоко. Передадим хеш-функции строку «молоко».
МОЛОКО АПЕЛЬСИНЫ
Продолжайте действовать так, и со временем весь массив будет заполнен ценами на товары.
А теперь вы спрашиваете: сколько стоит авокадо? Искать в массиве ничего не нужно, просто передайте строку «авокадо» хеш-функции.
«авокадо» -> (XI* 4
Результат показывает, что значение хранится в элементе с индексом 4. И оно, конечно, там и находится!
АВОКАДО = 1.V1
' / /
Хеш-функция сообщает, где хранится цена, и вам вообще не нужно ничего искать! Такое решение работает, потому что:
Хеш-функция неизменно связывает название с одним индексом. Каждый раз, когда она вызывается для строки «авокадо», вы получаете обратно одно и то же число. При первом вызове этой функции вы узнаете, где следует сохранить цену авокадо, а при последующих вызовах она сообщает, где взять эту цену.
Хеш-функция связывает разные строки с разными индексами. «Авокадо» связывается с индексом 4, а «молоко» — с индексом 0. Для каждой строки находится отдельная позиция массива, в которой сохраняется цена этого товара.
□ Хеш-функция знает размер массива и возвращает только действительные индексы. Таким образом, если длина массива равна 5 элементам, хеш-функция не вернет 100, потому что это значение не является действительным индексом в массиве.
Поздравляю: вы создали «Мэгги»! Свяжите воедино хеш-функцию и массив, и вы получите структуру данных, которая называется хеш-таблицей. Хеш-таблица станет первой изученной вами структурой данных, с которой связана дополнительная логика. Массивы и списки напрямую отображаются на адреса памяти, но хеш-таблицы устроены более умно. Они определяют место хранения элементов при помощи хеш-функций.
Вероятно, хеш-таблицы станут самой полезной из сложных структур данных, с которыми вы познакомитесь. Они также известны под другими названиями: «ассоциативные массивы», «словари», «отображения», «хеш- карты» или просто «хеши». Хеш-таблицы исключительно быстро работают! Помните описание массивов и связанных списков из главы 2? Обращение к элементу массива происходит мгновенно. А хеш-таблицы используют массивы для хранения данных, поэтому при обращении к элементам они не уступают массивам.
С
>>> book = dictQ
ПУСТАЯ
ХЕШ-ТАБЛИЦА
корее всего, вам никогда не придется заниматься реализацией хеш-таблиц самостоятельно. В любом приличном языке существует реализация хеш- таблиц. В Python тоже есть хеш-таблицы; они называются словарями. Новая хеш-таблица создается функцией diet:
book — новая хеш-таблица. Добавим в book несколько цен:
>>> book["apple"] = 0.67 < Апельсины стоят 67 центов
>>> book["milk"] = 1.49 -« Молоко стоит 1 доллар 49 центов
>>> book["avocado"] = 1.49 >>> print book
{'avocado': 1.49, 'apple': 0.67, 'milk': 1.49}
Пока все просто! А теперь запросим цену авокадо:
>
с цт-
>> print book["avocado"]
1.49 ч Цена авокадо
Хеш-таблица состоит из ключей и значений. В хеше book имена продуктов являются ключами, а цены — значениями. Хеш-таблица связывает ключи со значениями.
В следующем разделе приведены примеры, в которых хеш-таблицы приносят большую пользу.
Упражнения
О чень важно, чтобы хеш-функции были последовательными, то есть неизменно возвращали один и тот же результат для одинаковых входных данных. Если это условие будет нарушено, вы не сможете найти свой элемент после того, как он будет помещен в хеш-таблицу!
Какие из следующих функций являются последовательными?
f(x) = 1 ч Возвращает "1" для любых входных значений
f(x) = rand() ч Возвращает случайное число
f(x) = next_empty_slot() ч Возвращает индекс следующего
f(x) = len(x) ч Возвращает длину пустого элемента в хеш-таблице
полученной строки
Примеры использования
Хеш-таблицы повсеместно применяются на практике. В этом разделе представлены некоторые примеры.
Использование хеш-таблиц для поиска
В вашем телефоне есть удобная встроенная телефонная книга. С каждым именем связывается номер телефона.
М АМА 52Л
AL6X N\AMN\MCr -> 2 3* 4-6S0
-jANfc MAR'N 4-lS 5^7 ЗйТ'Л
Предположим, вы хотите построить такую телефонную книгу. Имена людей в этой книге связываются с номерами. Телефонная книга должна поддерживать следующие функции:
добавление имени человека и номера телефона, связанного с этим именем;
получение номера телефона, связанного с введенным именем.
Такая задача идеально подходит для хеш-таблиц! Хеш-таблицы отлично работают, когда вы хотите:
создать связь, отображающую один объект на другой;
найти значение в списке.
Построить телефонную книгу, в общем-то, несложно. Начните с создания новой хеш-таблицы: >>> phone_book = dict()
Кстати, в Python предусмотрена сокращенная запись для создания хеш- таблиц: она состоит из двух фигурных скобок:
>>> phone_book = {} < То же, что phoneJ>ook = dict()
Добавим в телефонную книгу несколько номеров:
>>> phone_book["jenny"] = 8675309 >>> phone_book["emergency"] = 911
Вот и все! Теперь предположим, что вы хотите найти номер телефона Дженни (Jenny). Просто передайте ключ хешу:
>
■ХЕШ-ТАБЛИЦА КАК ТЕЛЕФОННАЯ КНИГА
>> print phone_book["jenny"]
8675309 ч Номер Дженни
А теперь представьте, что то же самое вам пришлось бы делать с массивом.
Как бы вы это сделали? Хеш-таблицы упрощают моделирование отношений между объектами.
Хеш-таблицы используются для поиска соответствий в гораздо большем масштабе. Например, представьте, что вы хотите перейти на веб-сайт — допустим, http://adit.io. Ваш компьютер должен преобразовать символическое имя adit.io в 1Р-адрес.
АЫТ.\0 -Ь \13.2SS.2AZ.SS
Для любого посещаемого веб-сайта его имя преобразуется в 1Р-адрес:
(xOOGLG. с.о*а74.12S. 2.ЭЛ.133 FAceeoevt.coM-* |73. 252. ScfuBD.CotA 23.235. А-Ч".
Связать символическое имя с IP-адресом? Идеальная задача для хеш- таблиц! Этот процесс называется преобразованием DNS. Хеш-таблицы — всего лишь один из способов реализации этой функциональности.
И сключение дубликатов
П редположим, вы руководите избирательным участком. Естественно, каждый избиратель может проголосовать всего один раз. Как проверить, что он не голосовал ранее? Когда человек приходит голосовать, вы узнаете его полное имя, а затем проверяете по списку уже проголосовавших избирателей.
Е сли имя входит в список, значит, этот человек уже проголосовал — гоните наглеца! В противном случае вы добавляете имя в список и разрешаете ему проголосовать. Теперь предположим, что желающих проголосовать много и список уже проголосовавших достаточно велик.
Каждый раз, когда кто-то приходит голосовать, вы вынуждены просматривать этот гигантский список и проверять, голосовал он или нет. Однако существует более эффективное решение: воспользоваться хешем!
Сначала создадим хеш для хранения информации об уже проголосовавших
людях:
>>> voted = {}
Когда кто-то приходит голосовать, проверьте, присутствует ли его имя в хеше:
>>> value = voted.get("tom")
Функция get возвращает значение, если ключ "tom" присутствует в хеш- таблице. В противном случае возвращается None. С помощью этой функции можно проверить, голосовал избиратель ранее или нет!
Код выглядит так: voted = {}
Do'stlaringiz bilan baham: |