Ответ
В Python для разрешения коллизий в словарях (dict
) используется метод открытой адресации (open addressing).
Этот подход, в отличие от метода цепочек (chaining), не требует создания связанных списков для элементов с одинаковым хешем, что экономит память.
Ключевые аспекты реализации:
-
Псевдослучайное зондирование (Probing): При возникновении коллизии (когда хеш указывает на уже занятую ячейку) Python вычисляет новый индекс для вставки по специальной формуле. Этот процесс повторяется до тех пор, пока не будет найдена свободная ячейка. Это обеспечивает эффективное распределение элементов по таблице.
-
Сохранение порядка вставки (с Python 3.7+): Современные словари сохраняют порядок добавления элементов. Это достигается за счет разделения хеш-таблицы на две структуры: разреженный массив индексов и плотный массив, хранящий пары ключ-значение в порядке их вставки.
-
Изменение размера (Resizing): Когда таблица заполняется примерно на 2/3, ее размер увеличивается, а все элементы перехешируются в новую, более просторную таблицу. Это необходимо для сохранения амортизированной сложности операций
O(1)
и уменьшения вероятности коллизий.
# Концептуальный пример
# 1. Создается словарь
my_dict = {}
# 2. Добавляется первый элемент
# hash('a') % table_size -> index 3
my_dict['a'] = 1
# 3. Добавляется второй элемент с тем же хешем (коллизия)
# hash('b') % table_size -> index 3 (занято!)
# Python вычисляет новый индекс (например, 5) и размещает элемент там
my_dict['b'] = 2