Лекция 6: Словари. Хеш-таблицы
TRANSCRIPT
![Page 1: Лекция 6: Словари. Хеш-таблицы](https://reader034.vdocuments.mx/reader034/viewer/2022042516/557ed9e7d8b42a815a8b4c9d/html5/thumbnails/1.jpg)
Лекция 6: Словари.
Хеш-таблицы.
Курносов Михаил Георгиевич
к.т.н. доцент Кафедры вычислительных систем
Сибирский государственный университет
телекоммуникаций и информатики
http://www.mkurnosov.net
![Page 2: Лекция 6: Словари. Хеш-таблицы](https://reader034.vdocuments.mx/reader034/viewer/2022042516/557ed9e7d8b42a815a8b4c9d/html5/thumbnails/2.jpg)
Контроль
2
1. Что такое AVL-дерево?
2. Вычислительная сложность в худшем случае
операции добавления элемента в AVL-дерево.
3. Вычислительная сложность в худшем случае
операции поиска элемента в AVL-дереве.
4. Вычислительная сложность в худшем случае
операции удаления элемента из AVL-дерева.
![Page 3: Лекция 6: Словари. Хеш-таблицы](https://reader034.vdocuments.mx/reader034/viewer/2022042516/557ed9e7d8b42a815a8b4c9d/html5/thumbnails/3.jpg)
Словарь (Map)
3
� Словарь (ассоциативный массив, associative array,
map, dictionary) – структура данных для хранения
пар вида “ключ (key) – значение (value)”
� В словаре не могут присутствовать пары
с одинаковыми ключами
Ключ (Key) Значение (Value)
Слон 890
Кит 1200
Лев 260
Жираф 530
![Page 4: Лекция 6: Словари. Хеш-таблицы](https://reader034.vdocuments.mx/reader034/viewer/2022042516/557ed9e7d8b42a815a8b4c9d/html5/thumbnails/4.jpg)
Хеш-таблицы (Hash Table)
4
� Хеш-таблица (Hash table) – это структура данных
для хранения пар (ключ, значение). Доступ к элементам
осуществляется по ключу
� Ключи могут быть строками, числами, указателями
� Хеш-таблицы позволяют в среднем за
время О(1) выполнять добавление, поиски и удаление
элементов
![Page 5: Лекция 6: Словари. Хеш-таблицы](https://reader034.vdocuments.mx/reader034/viewer/2022042516/557ed9e7d8b42a815a8b4c9d/html5/thumbnails/5.jpg)
Хеш-таблицы (Hash Table)
5
Ключ
(Key)
Value:
160
“Антилопа Гну”
Хеш-таблица
(Hash table)
Хеш-функция
(Hash function)
hash(key)
0
1
2
…
h – 1
Хеш-функция – отображает (преобразует)
ключ (key) в номер элемента (index) массива
(в целое число от 0 до h – 1).
Ячейки массива называются buckets, slots.
index
![Page 6: Лекция 6: Словари. Хеш-таблицы](https://reader034.vdocuments.mx/reader034/viewer/2022042516/557ed9e7d8b42a815a8b4c9d/html5/thumbnails/6.jpg)
Хеш-таблицы (Hash Table)
6
Хеш-таблица
(Hash table)
0
1
2
…
h – 1
� На практике, обычно известна информация о
диапазоне значений ключей
� На основе этого выбирается размер h хеш-таблицы
и выбирается хеш-функция
� Коэффициент αααα заполнения хеш-таблицы
(load factor, fill factor) – отношение числа n
хранимых элементовв хеш-таблицы к размеру h
массива (среднее число элементов на одну ячейку)
� = �ℎ
� Пример: h = 128, в хеш-таблицу добавили 50
элементов,тогда α = 50 / 128 ≈ 0.39
� От этого коэффициента зависит среднее время
выполнения операций добавления, поиска и
удаления элементов
![Page 7: Лекция 6: Словари. Хеш-таблицы](https://reader034.vdocuments.mx/reader034/viewer/2022042516/557ed9e7d8b42a815a8b4c9d/html5/thumbnails/7.jpg)
Хеш-функции (Hash function)
� Хеш-функция (Hash function) – это функция преобразующая
значения ключа (например: строки, числа, файла) в целое число
� Значение возвращаемое хеш-функцией называется хеш-кодом
(hash code), контрольной суммой (hash sum) или хешем (hash)
#define HASH_MUL 31
#define HASH_SIZE 128
unsigned int hash(char *s)
{
unsigned int h = 0;
char *p;
for (p = s; *p != '\0'; p++) {
h = h * HASH_MUL + (unsigned int)*p;
}
return h % HASH_SIZE;
} 7
![Page 8: Лекция 6: Словари. Хеш-таблицы](https://reader034.vdocuments.mx/reader034/viewer/2022042516/557ed9e7d8b42a815a8b4c9d/html5/thumbnails/8.jpg)
Хеш-функции (Hash function)
8
Требования к хэш-функциям:
� Быстрое вычисление хэш-кода по значению ключа. Сложность
вычисления хэш-кода не должна зависеть от n – количества
элементов в хеш-таблице.
� Детерминированность. Для заданного значения ключа хэш-
функция всегда должна возвращать одно и то же значение.
� Равномерность. Хеш-функция должна равномерно заполнять
массив. Желательно, чтобы все хэш-коды формировались с
одинаковой вероятностью.
![Page 9: Лекция 6: Словари. Хеш-таблицы](https://reader034.vdocuments.mx/reader034/viewer/2022042516/557ed9e7d8b42a815a8b4c9d/html5/thumbnails/9.jpg)
Понятие коллизии (Collision)
9
� Коллизия (Collision) – это совпадение значений хеш-функции
для двух разных ключей
Keys HashesHash function
Жираф
Слон
Муха Цеце
Волк
127
...
05
04
03
02
01
00
Collision!
hash(“Волк”) = 2 hash(“Жираф”) = 2
Существуют хеш-функции без коллизий – идеальные хеш-функции (perfect hash function)
![Page 10: Лекция 6: Словари. Хеш-таблицы](https://reader034.vdocuments.mx/reader034/viewer/2022042516/557ed9e7d8b42a815a8b4c9d/html5/thumbnails/10.jpg)
Разрешение коллизий (Collision Resolution)
10
Метод цепочек (Chaining) – закрытая адресация.
Элементы с одинаковым значением хеш-функции объединяются в
связный список. Указатель на список хранится в советующей ячейке
хеш-таблицы.
� При коллизии элемент добавляется в начало списка.
� Поиск и удаление элемента требуют просмотра всего списка.
Keys HashesHash function
Жираф
Слон
Муха Цеце
Волк
127
...
05
04
03
02
01
00
Муха Цеце NULL
Слон NULL
Жираф Волк
NULL
![Page 11: Лекция 6: Словари. Хеш-таблицы](https://reader034.vdocuments.mx/reader034/viewer/2022042516/557ed9e7d8b42a815a8b4c9d/html5/thumbnails/11.jpg)
Разрешение коллизий (Collision Resolution)
11
Открытая адресация (Open addressing)
В каждой ячейке хеш-таблицы хранится не указатель на связный
список, а один элемент (ключ, значение).
Если ячейка с индексом hash(key) занята, то осуществляется поиск
свободной ячейки в следующих позициях таблицы.Hash Элемент
0 B
1
2
3 A
4 C
5 D
6
7
Линейное хеширование (linear probing) – проверяются
позиции:
hash(key) + 1, hash(key) + 2, …, (hash(key) + i) mod h, …
Если свободных ячеек нет, то таблица заполнена.
Пример:
� hash(D) = 3, но ячейка с иднексом 3 занята.
� Присматриваем ячейки: 4 – занята, 5 – свободна.
![Page 12: Лекция 6: Словари. Хеш-таблицы](https://reader034.vdocuments.mx/reader034/viewer/2022042516/557ed9e7d8b42a815a8b4c9d/html5/thumbnails/12.jpg)
Эффективность хеш-таблиц
12
Хеш-таблица требует предварительной инициализации ячеек
значениями NULL – трудоемкость O(h)
Операция Вычислительная
сложность
в среднем случае
Вычислительная
сложность
в худшем случае
Add(key, value) O(1) O(1)
Lookup(key) O(1 + n/h) O(n)
Delete(key) O(1 + n/h) O(n)
Min() O(n + h) O(n + h)
Max() O(n + h) O(n + h)
![Page 13: Лекция 6: Словари. Хеш-таблицы](https://reader034.vdocuments.mx/reader034/viewer/2022042516/557ed9e7d8b42a815a8b4c9d/html5/thumbnails/13.jpg)
Пример хэш-функции для чисел
13
� Ключи: размер файла – число.
� Значение, хранимое в словаре: название файла.
� Требуется разработать хеш-функцию
hash(filesize) → [0..1023]
function hash(filesize)
return filesize mod 1024
end function
![Page 14: Лекция 6: Словари. Хеш-таблицы](https://reader034.vdocuments.mx/reader034/viewer/2022042516/557ed9e7d8b42a815a8b4c9d/html5/thumbnails/14.jpg)
Пример хэш-функции для строк
14
hash � = ℎ�( ��) ∙ � ���
��=
= �[0]ℎ�� + �[1]ℎ�� +⋯+ � � − 2 ℎ + � � − 1 ,
где s – ключ (строка), L – длина строки, s[i] – код символа i.
![Page 15: Лекция 6: Словари. Хеш-таблицы](https://reader034.vdocuments.mx/reader034/viewer/2022042516/557ed9e7d8b42a815a8b4c9d/html5/thumbnails/15.jpg)
Хеш-таблицы (Hash Table)
15
Длину h хеш-таблицы выбирают как простое число.
Для такой таблицы модульная хеш-функция дает
равномерное распределение значений ключей
hash(key) = key mod h
![Page 16: Лекция 6: Словари. Хеш-таблицы](https://reader034.vdocuments.mx/reader034/viewer/2022042516/557ed9e7d8b42a815a8b4c9d/html5/thumbnails/16.jpg)
Реализация хеш-таблицы
16
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HASHTAB_SIZE 71
#define HASHTAB_MUL 31
struct listnode {
char *key;
int value;
struct listnode *next;
};
struct listnode *hashtab[HASHTAB_SIZE];
![Page 17: Лекция 6: Словари. Хеш-таблицы](https://reader034.vdocuments.mx/reader034/viewer/2022042516/557ed9e7d8b42a815a8b4c9d/html5/thumbnails/17.jpg)
Реализация хеш-таблицы
17
int hashtab_hash(char *key)
{
int h = 0;
char *p;
for (p = key; *p != '\0'; p++) {
h = h * HASHTAB_MUL + (int)*p;
}
return h % HASHTAB_SIZE;
}
![Page 18: Лекция 6: Словари. Хеш-таблицы](https://reader034.vdocuments.mx/reader034/viewer/2022042516/557ed9e7d8b42a815a8b4c9d/html5/thumbnails/18.jpg)
Реализация хеш-таблицы
18
void hashtab_init(struct listnode **hashtab)
{
int i;
for (i = 0; i < HASHTAB_SIZE; i++) {
hashtab[i] = NULL;
}
}
![Page 19: Лекция 6: Словари. Хеш-таблицы](https://reader034.vdocuments.mx/reader034/viewer/2022042516/557ed9e7d8b42a815a8b4c9d/html5/thumbnails/19.jpg)
Реализация хеш-таблицы
19
void hashtab_add(struct listnode **hashtab,
char *key, int value)
{
struct listnode *node;
int index = hashtab_hash(key);
node = malloc(sizeof(*node));
if (node != NULL) {
node->key = key;
node->value = value;
node->next = hashtab[index];
hashtab[index] = node;
}
}
![Page 20: Лекция 6: Словари. Хеш-таблицы](https://reader034.vdocuments.mx/reader034/viewer/2022042516/557ed9e7d8b42a815a8b4c9d/html5/thumbnails/20.jpg)
Реализация хеш-таблицы
struct listnode *hashtab_lookup(
struct listnode **hashtab,
char *key)
{
int index;
struct listnode *node;
index = hashtab_hash(key);
for (node = hashtab[index];
node != NULL; node = node->next)
{
if (strcmp(node->key, key) == 0) {
return node;
}
}
return NULL;
} 20
![Page 21: Лекция 6: Словари. Хеш-таблицы](https://reader034.vdocuments.mx/reader034/viewer/2022042516/557ed9e7d8b42a815a8b4c9d/html5/thumbnails/21.jpg)
Реализация хеш-таблицы
21
int main()
{
struct listnode *node;
hashtab_init(hashtab);
hashtab_add(hashtab, "Tigr", 190);
hashtab_add(hashtab, "Slon", 2300);
hashtab_add(hashtab, "Volk", 60);
node = hashtab_lookup(hashtab, "Slon");
printf("Node: %s, %d\n",
node->key, node->value);
return 0;
}
![Page 22: Лекция 6: Словари. Хеш-таблицы](https://reader034.vdocuments.mx/reader034/viewer/2022042516/557ed9e7d8b42a815a8b4c9d/html5/thumbnails/22.jpg)
Реализация хеш-таблицы
void hashtab_delete(struct listnode **hashtab,
char *key)
{
int index;
struct listnode *p, *prev = NULL;
index = hashtab_hash(key);
for (p = hashtab[index]; p != NULL; p = p->next) {
if (strcmp(p->key, key) == 0) {
if (prev == NULL
hashtab[index] = p->next;
else
prev->next = p->next;
free(p);
return;
}
prev = p;
}
} 22
![Page 23: Лекция 6: Словари. Хеш-таблицы](https://reader034.vdocuments.mx/reader034/viewer/2022042516/557ed9e7d8b42a815a8b4c9d/html5/thumbnails/23.jpg)
Реализация хеш-таблицы
23
int main()
{
struct listnode *node;
/* ... */
hashtab_delete(hashtab, "Slon");
node = hashtab_lookup(hashtab, "Slon");
if (node != NULL) {
printf("Node: %s, %d\n",
node->key, node->value);
} else {
printf("Key 'Slon' not found\n");
}
return 0;
}
![Page 24: Лекция 6: Словари. Хеш-таблицы](https://reader034.vdocuments.mx/reader034/viewer/2022042516/557ed9e7d8b42a815a8b4c9d/html5/thumbnails/24.jpg)
Задание
24
� Прочитать в Sedgewick2001 про хеш-функции для
вещественных чисел (с. 575).