Есть несколько методов, которые гарантируют, что для поиска всегда потребуются операции O (1), даже в худшем случае.
Как я могу определить, есть ли вероятность того, что хеш-таблица будет иметь операции O (1), и, возможно, какие методы использовать в моей хеш-функции?
Наихудший случай случается, когда злоумышленник (Мэллори) сознательно предоставляет вам данные, которые Мэллори специально выбрала для замедления работы системы.
После того, как вы выбрали какую-то конкретную хеш-функцию, вероятно, чрезмерно оптимистично предположить, что Мэллори никогда не узнает, какую хеш-функцию вы выбрали. Как только Мэллори обнаружит, какую хеш-функцию вы выбрали, если вы позволите Мэллори дать вам много данных для вставки в вашу хеш-таблицу с помощью этой хеш-функции, то вы обречены: Мэллори может внутренне быстро генерировать миллиарды элементов данных, хешировать их с помощью ваших хэш-функция, позволяющая определить, какие элементы данных могут столкнуться, а затем предоставить вам миллионы элементов данных «один на тысячу», которые могут столкнуться, что приводит к поискам, которые работают намного медленнее, чем O (1).
Все методы, которые гарантируют «O (1) поиск даже в худшем случае», позволяют избежать этой проблемы, выполняя небольшую дополнительную работу над каждой вставкой, чтобы гарантировать, что в будущем каждый возможный поиск может быть успешным за O (1) время. , В частности, мы предполагаем (в худшем случае), что Мэллори рано или поздно обнаружит, какую хеш-функцию мы используем; но он получает возможность вставить только несколько элементов данных, прежде чем мы выберем другую хеш-функцию - хеширование таблиц или какое-либо другое универсальное хеширование - которое мы специально выбираем таким образом, чтобы все данные, которые у нас есть, можно было найти в 2 или 3 зонда - т. е. O (1). Поскольку мы выбираем эту функцию случайным образом, мы можем быть уверены, что Мэллори не будет знать, какую функцию мы выбрали какое-то время. Даже если Мэллоринемедленно дает нам данные, которые, даже если эта новая хеш-функция сталкивается с предыдущими данными, затем мы можем выбрать еще одну свежую новую хеш-функцию, так что после перепрошивки все предыдущие данные, которые он и все остальные передали нам, теперь можно просматривать в 2 или 3 пробах в наихудшем случае - т.е. O (1) поисков в наихудшем случае.
Довольно просто случайным образом выбрать новую хеш-функцию и перефразировать всю таблицу достаточно часто, чтобы гарантировать, что каждый поиск всегда равен O (1). Хотя это гарантирует, что каждый поиск всегда равен O (1), эти методы при вставке N-го элемента в хеш-таблицу, которая уже содержит N-1 элементов, могут иногда требовать O (N) времени для этой вставки. Тем не менее, можно спроектировать систему так, чтобы, даже когда Мэллори преднамеренно предоставлял вам новые данные, которые с помощью новой хеш-функции сталкивались с предыдущими данными, система может принимать множество элементов от Мэллори и других, прежде чем ей потребуется выполнить полная O (N) перестройка. Методы хэширования, которые выбирают новую функцию и перефразируют, чтобы гарантировать O (1) поиск, даже в худшем случае, включают:
- Хеширование кукушки гарантирует, что каждый поиск ключа завершится максимум с двумя вычислениями хеш-функции и двумя поисками таблиц.
- Хеширование в классиках гарантирует, что каждый поиск ключа будет успешным после проверки небольшого числа последовательных записей в таблице (возможно, H = 32).
- динамическое идеальное хеширование - статья Дитцфельбингера 1994 года - первая, которую я прочитал, в которой указывалось, что, хотя она и перефразирует «часто», чтобы гарантировать, что каждый поиск ключа всегда завершается успешно с 2 вычислениями хешей и 2 поисками, это возможно чтобы выполнить полную перефразировку настолько редко, что, хотя каждая полная перефразировка использует время O (n), ожидаемая средняя стоимость вставок и удалений амортизируется за O (1).
Структуры данных / Хеш-таблицы