Что такое хэш-коллизия
Хэш-коллизия — это ситуация, при которой две разные входные данные (ключи) имеют одинаковое значение. Они могут возникать, потому что хэш-функции, используемые для преобразования ключей в индексы, не являются идеальными и имеют ограниченное количество возможных значений.
Как возникают коллизии?
Принимает входные данные (например, строку или целое число) и возвращает фиксированное значение, которое обычно используется для индексирования массива или другого контейнера данных. Однако, поскольку количество возможных входных данных потенциально бесконечно, а количество возможных выходных значений хэш-функции ограничено, неизбежно возникают ситуации, когда разные входные данные производят одинаковое хэш-значение. Это и называется хэш-коллизией.
Представим, что у нас есть простая хэш-функция для строк, которая возвращает длину строки в качестве хэш-значения. Для строк "cat" и "dog" хэш-значение будет одинаковым (3), что приводит к коллизии.
Управление коллизиями
Существует несколько методов для управления хэш-коллизиями. Два наиболее распространенных метода — это цепочки (chaining) и открытая адресация (open addressing).
1. Цепочки (Chaining):
- В этом методе каждая ячейка хэш-таблицы содержит указатель на список (например, связанный список) всех элементов, которые имеют одно и то же хэш-значение.
- Когда происходит коллизия, новый элемент просто добавляется в этот список.
```go
type Entry struct {
key string
value int
next *Entry
}
type HashMap struct {
buckets []*Entry
}
func (m *HashMap) Put(key string, value int) {
index := hash(key) % len(m.buckets)
entry := m.buckets[index]
for entry != nil {
if entry.key == key {
entry.value = value
return
}
entry = entry.next
}
m.buckets[index] = &Entry{key: key, value: value, next: m.buckets[index]}
}
func hash(key string) int {
hash := 0
for _, char := range key {
hash += int(char)
}
return hash
}
```
2. Открытая адресация (Open Addressing):
- В этом методе все элементы хранятся непосредственно в хэш-таблице. Если ячейка, определенная хэш-функцией, уже занята, используется альтернативная стратегия для нахождения следующей доступной ячейки.
- Наиболее распространенные стратегии включают линейное пробирование (linear probing), квадратичное пробирование (quadratic probing) и двойное хеширование (double hashing).
```go
type HashMap struct {
keys []string
values []int
size int
}
func (m *HashMap) Put(key string, value int) {
index := hash(key) % len(m.keys)
for m.keys[index] != "" {
if m.keys[index] == key {
m.values[index] = value
return
}
index = (index + 1) % len(m.keys)
}
m.keys[index] = key
m.values[index] = value
m.size++
}
func hash(key string) int {
hash := 0
for _, char := range key {
hash += int(char)
}
return hash
}
```
Хэш-коллизия происходит, когда две разные входные данные имеют одинаковое хэш-значение. Это может вызвать проблемы. Для управления коллизиями используются методы, такие как цепочки и открытая адресация.
June 2, 2024, easyoffer