Почему доступ к элементу словаря по ключу за O(1) даже если хэш-функция не может быть O(1)?

Я вижу, как вы можете получить доступ к своей коллекции по ключу. Однако, сама хэш-функция имеет много операций за кулисами, не так ли?

Если у вас есть хорошая хэш-функция, которая является очень эффективной, она все еще может занять много операций.

Это можно объяснить?

8 ответов


на HashFunc сам имеет много операций за кулисами

Это, конечно, верно. Однако, количество этих операций зависит от размера ключ, а не по размеру хэш-таблицы в который ключ вставляется: количество операций для вычисления хэш-функции для ключа в таблице с десятью или с десятью тысячами записей.

вот почему вызов хэш-функции часто считается за O(1). Это отлично работает для ключей фиксированного размера (интегральные значения и строки фиксированной длины). Он также обеспечивает достойное приближение для ключей переменного размера с практическим верхним пределом.

как правило, время доступа к хэш-таблице равно O (k), где k - верхний предел размера хэш-ключа.


O(1) не означает мгновенный. O(1) постоянный независимо от размера данных. Хэш-функция принимает определенное количество времени, но это время не размер коллекции.


Это означает, что независимо от размера вашей коллекции, она все равно займет почти столько же времени, чтобы получить любой из ее членов.

таким образом, Другими словами, словарь с 5 членами, скажем, coud займет около 0,002 мс, чтобы получить доступ к одному из них, а также словарь из 25 членов должен взять что-то подобное. Big O означает алгоритмическую сложность по размеру коллекции вместо фактических операторов или выполняемых функций


если словарь / карта реализована как HashMap, Она имеет лучшем случае сложности of O(1), так как в лучшем случае требуется именно вычисление хэш-кода ключевого элемента для извлечения, если нет ключевых коллизий.

A хэш-карте может быть в худшем случае сложность выполнения of O(n) Если у вас много ключевых столкновений или очень плохая хэш-функция, так как в этом случае она деградирует до линейного сканирования всего массив, который содержит данные.

и O(1) не значит мгновенно, это означает, что у него есть постоянный количество. Поэтому выбор правильной реализации для словаря также может зависеть от количества элементов в коллекции, поскольку очень высокая постоянная стоимость функции будет намного хуже, если будет всего несколько записей.

вот почему dictionaryies / карты реализованы по-разному для разных сценариев. Для Java есть несколько различных реализаций, C++ использует красные / черные деревья и т. д. Вы выбрали их на основе количества данных и их лучшей/средней / худшей эффективности выполнения.


теоретически это все еще O (n), потому что в худшем случае все ваши данные могут иметь идентичный хэш и быть объединены вместе, и в этом случае вам придется линейно пройти через все это.


см. пост что означает" O (1) время доступа"?

количество операций в хэш-функции не имеет значения, пока оно занимает одинаковое (постоянное) количество времени для каждого элемента в коллекции. Например, доступ к одному элементу коллекции из 2 элементов .001 мс, а также доступ к одному элементу в коллекции 2,000,000,000 элементов .001 МС. Хотя хэш-функция может содержать сотни операторов if и несколько проведенные расчеты.


документы:

получение значения с помощью его ключа очень быстро, близко к O (1), потому что T:System.Коллекции.Родовой.Класс Dictionary ' 2 реализован в виде хэш-таблицы.

Так это может быть O(1), но может быть медленнее. Здесь вы можете найти другой поток, касающийся производительности hashtable:хэш-таблица-почему она быстрее массивов?


Как только вы учитываете тот факт, что все большие и большие словари занимают больше памяти, идя дальше вниз по иерархии кэша и в конечном итоге, чтобы замедлить пространство подкачки на диске, трудно утверждать, что это действительно O(1). Производительность словаря будет замедляться по мере его увеличения, вероятно, давая o (log N) сложность времени. Не веришь мне? Попробуйте это для себя с 1, 100, 1000, 10000 и т. д. словарные элементы, скажем, 100 миллиардов, и измерьте, сколько времени требуется на практике, чтобы найдите элемент.

однако, если вы сделаете упрощающее предположение, что вся память в вашей системе является оперативной памятью и может быть доступна в постоянное время, то вы можете утверждать, что словарь O(1). Это предположение распространено, хотя оно не совсем верно для любой машины с дисковым пространством подкачки и все еще довольно спорно в любом случае, учитывая различные уровни кэша процессора.