Цепные хеш-таблицы и хеш-таблицы с открытым адресом - PullRequest
44 голосов
/ 01 апреля 2010

Может ли кто-нибудь объяснить основные различия между (преимуществами / недостатками) двух реализаций?

Какая реализация рекомендуется для библиотеки?

Ответы [ 5 ]

56 голосов
/ 01 апреля 2010

Статья Википедии о хеш-таблицах дает отчетливо лучшее объяснение и обзор различных схем хеш-таблиц, которые использовали люди, чем я могу выразить все мои мысли. На самом деле, вам, вероятно, лучше прочитать эту статью, чем задавать вопрос здесь. :)

Тем не менее ...

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

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

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

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

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

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

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

Если вы работаете, например, с GTK, то обнаружите, что в GLib .

есть хорошая хеш-таблица.
2 голосов
/ 15 марта 2017

Поскольку дано превосходное объяснение, я бы просто добавил визуализации, взятые из CLRS для дальнейшей иллюстрации:

Открытая адресация: Open Addressing:

Сцепление: Chaining:

1 голос
/ 06 июня 2017

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

Метод цепочки:

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

Открытая адресация с линейным зондом:

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

Существует еще один подход: Цепочка с бинарными деревьями поиска . При таком подходе при столкновении они сохраняются в двоичном дереве поиска, а не в связанном списке. Следовательно, наихудший сценарий здесь будет O(log n). На практике этот подход лучше всего подходит при крайне неоднородном распределении.

0 голосов
/ 26 апреля 2019

Открытая адресация против отдельной цепочки

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

Другая идея: записи в хеш-таблице - это просто указатели на начало связанного списка («цепочки»); элементы связанного списка содержат ключи ... это называется "отдельная цепочка" это также называется "открытое хеширование"

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

Источник: http://cseweb.ucsd.edu/~kube/cls/100/Lectures/lec16/lec16-25.html

0 голосов
/ 12 апреля 2016

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

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

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

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

...