C: Хранение до миллиона записей в хеш-таблице - PullRequest
4 голосов
/ 25 июля 2011

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

Ответы [ 6 ]

3 голосов
/ 25 июля 2011

Если вам нужна хеш-таблица с миллионом записей, обычно у вас будет как минимум 2 миллиона блоков. Я не помню всю статистику (ключевой термин «парадокс дня рождения»), но подавляющее большинство ведер будет иметь ноль или один предмет. В принципе, вы можете быть очень невезучим и получить все предметы в одном ведре, но вам, возможно, придется повезти еще больше, чем тем людям, которые, похоже, поражаются молнией через день.

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

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

Связанные списки - не единственный способ справиться с коллизиями - в этой теме есть огромное количество знаний. Уолтер Брайт (разработчик языка программирования D) выступает за использование двоичных деревьев, а не связанных списков, утверждая, что его Dscript значительно улучшил производительность по сравнению с Javascript благодаря этому выбору дизайна.

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

В принципе, вы можете так же легко использовать трепы, красно-черные деревья или деревья AVL. Интересным вариантом может быть использование Splay-деревьев для обработки столкновений. Но в целом, это небольшая проблема для некоторых проектировщиков библиотек и несколько настоящих навязчивых идей, о которых нужно беспокоиться.

3 голосов
/ 25 июля 2011

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

1 голос
/ 25 июля 2011

Общее количество записей не имеет значения, только среднее количество записей на сегмент (N / размер хэша). Используйте хеш-функцию с большим доменом (например, 20 бит или даже больше), чтобы обеспечить это.

Конечно, это займет больше памяти, но это все, это общий обмен памяти с быстродействием.

1 голос
/ 25 июля 2011

Вы можете использовать Дерево вместо Списка в отдельных «корзинах». (AVL или аналогичный)

РЕДАКТИРОВАТЬ: ну, Skip List будет делать то же самое. (и, кажется, быстрее) - O (log n) - это то, к чему вы стремитесь.

0 голосов
/ 02 августа 2012

Если ваши ключи имеют нормальное распределение (это очень большой IF), то ожидаемое количество вставок в хеш-таблицу для исчерпания всех корзин в хеш-таблице составляет M * logM (натуральный логарифм, в базу e), где Mэто количество ведер.

Был удивлен, не мог найти это легко онлайн!

Я разместил его в в моем блоге и проверил его с помощью Code, используя rand (). Это довольно хорошая оценка.

0 голосов
/ 25 июля 2011

Не уверен, поможет ли это вам или нет, но возможно: http://memcached.org/

...