Коллизия возникает, когда разные ключи дают одинаковый хеш-код, претендуя на одну и ту же ячейку (бакет) в хеш-таблице.
var dict = new Dictionary<int, string>();
dict.Add(1, "Value1");
dict.Add(65537, "Value2"); // Может вызвать коллизию, если размер таблицы 65536
Ограниченный диапазон хеш-кодов:
Неидеальная хеш-функция:
Особенности данных:
Принцип: Каждый бакет содержит связанный список элементов
// Внутренняя структура Dictionary в .NET
private struct Entry
{
public int hashCode;
public int next; // Индекс следующего элемента в цепочке
public TKey key;
public TValue value;
}
Преимущества:
Недостатки:
Принцип: Поиск следующей свободной ячейки по определенному алгоритму
Варианты:
// Псевдокод линейного пробирования
index = hash(key);
while (table[index] != null)
{
index = (index + 1) % table.Size;
}
table[index] = new Entry(key, value);
Преимущества:
Недостатки:
// Пример рехеширования при добавлении
private void Resize()
{
int newSize = CalculateNewSize();
Entry[] newEntries = new Entry[newSize];
// Перераспределение всех элементов
}
// Хорошая реализация
public override int GetHashCode()
{
return HashCode.Combine(field1, field2, field3);
}
// Уменьшает необходимость рехеширования
var dict = new Dictionary<string, int>(capacity: 1000);
// Для специальных требований
var dict = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
// Анализ коллизий в существующем Dictionary
var collisionReport = dict.GroupBy(pair => pair.Key.GetHashCode() % buckets.Count)
.Where(g => g.Count() > 1)
.ToList();
Switch to SortedDictionary:
Использование Perfect Hashing:
Кастомная хеш-функция:
Коллизии — неизбежный аспект работы хеш-таблиц, но с ними можно эффективно бороться через качественные хеш-функции, правильный выбор структуры данных и параметров хеш-таблицы. .NET предоставляет эффективные встроенные механизмы обработки коллизий, но понимание их работы необходимо для создания высокопроизводительных приложений.