Cтраница 3
К счастью, существует простой способ избежать возникновения проблемы кластеризации - двойное хеширование. Основная стратегия остается той же, что и при выполнении линейного зондирования. Единственное различие состоит в том, что вместо исследования каждой позиции таблицы, следующей за конфликтной, мы используем вторую хеш-функцию для получения постоянного шага, который будет использоваться для последовательности зондирования. [31]
Мри ниюипьшвзннн раздельного связывания время поиска уяйличнян-етсн постепенно - когда количество ключей р таблиц улваивж: теяр ьрсмй поиска уд-ншпзастся. Это же справедливо л о отношению такиы методам с открытой адреса-пи как линейное зондирование и льойнос хеширование для разреженных тайдиин но по мере залолntнич та & иицы шраты возрастают коренным образом и, что гораздо хуже, наступает момент, когда никакие дополнительные ключи вообшс не могут быть вставлены. [32]
Давайте рассмотрим следующие два крайних случая заполненной наполовину ( М - 2N) таблицы линейного зондирования: в лучшем случае позиции таблицы с четными индексами могли бы быть пустыми, а с нечетными - занятыми. В худшем случае первая половина позиций таблицы могла бы быть пустой, а вторая - заполненной. [33]
Эти относительные значения ВРЕМЕНИ построения и поиска в таблицах состоящих из случайных последовательностей 32-разрядных ц & лых ч нее л h ПОДТВЕРЖДАЕТ, что для ключей, которые легко поддастся хешированию, кэширование работает значительно быстрее, ЧЕМ поиск с использованием дерева. Двоимое леширо-яэние работает медлвннвд, чем раздельное связывание и линейное зондирование для разреженных таблиц ( нэ-эа необходимости вычисления второй кеш-функции), но значительна быстрее линейного зондирования, ядгдн таблица заполняется; кроме того, этот метод - ЕДИНСТВЕННЫЙ, который МОЖЕТ обеспечить быстрый поиск с использованием лишь небольшого дополнительного объема памяти, Динамические хеш-таблицы, построенный с использованием линейного аондироаания и расширения путем удвоения, требуют больших затрат времени при конструировании, чем другие лзш-гзблнцы, из за необходимости распределений памяти н повторного хеширования, но несомненно обеспечивают наиболее быстрый поиск. [34]
![]() |
Данные экспериментального исследования реализаций хеш-таблиц. [35] |
Эти относительные значения времени построения и поиска в таблицах символов, состоящих из случайных последовательностей 32-разрядных целых чисел, подтверждают, что для ключей, которые легко поддаются хешированию, хеширование работает значительно быстрее, чем поиск с использованием дерева. Двойное хеширование работает медленнее, чем раздельное связывание и линейное зондирование для разреженных таблиц ( из-за необходимости вычисления второй хеш-функции), но значительно быстрее линейного зондирования, когда таблица заполняется; кроме того, этот метод - единственный, который может обеспечить быстрый поиск с использованием лишь небольшого дополнительного объема памяти. Динамические хеш-таблицы, построенные с использованием линейного зондирования и расширения путем удвоения, требуют больших затрат времени при конструировании, чем другие хеш-таблицы, из-за необходимости распределения памяти и повторного хеширования, но несомненно обеспечивают наиболее быстрый поиск. Этот метод является предпочтительным, когда чаще всего выполняется поиск, и когда заранее нельзя точно предвидеть количество ключей. [36]
На этой диаграмме демонстрируется процесс удаления Хиз таблицы, показанной на рис. 14.7. Во второй строке показан результат простого удаления Хиз таблицы, что неприемлемо, поскольку М и Р отрезаются от своих хеш-позиций пустой позицией, оставленной ключом X. Поэтому ключи М, S, Ни Р ( расположенные справа от Хв этом же кластере) повторно вставляются в указанном порядке с использованием хеш-значений, указанных вверху, и с разрешением конфликтов с помощью линейного зондирования. [37]
Двойное хеширование аналогично линейному зондированию, за исключением того, что вторая хеш-функция используется для определения шага поиска, который будет использоваться после обнаружения каждого конфликта. Шаг поиска должен быть ненулевым, а размер таблицы и шаг поиска должны быть взаимно простыми числами. Функция remove для линейного зондирования ( см. программу 14.5) не работает с двойным хешированием, поскольку любой ключ может присутствовать во множестве различных последовательностей зондирования. [38]
В случае разреженной ( слабо заполненной) таблицы ( значение а мало) можно рассчитывать, что в большинстве случаев поиска пустая позиция будет найдена в результате всего нескольких зондирований. В случае почти полной таблицы ( значение а близко к 1) для выполнения поиска могло бы потребоваться очень большое количество зондирований, а когда таблица полностью заполнена, поиск может даже привести к бесконечному циклу. Как правило, при использовании линейного зондирования во избежание больших затрат времени при поиске стремятся к тому, чтобы не допустить заполнения таблицы. [39]
![]() |
Данные экспериментального исследования реализаций хеш-таблиц. [40] |
Эти относительные значения времени построения и поиска в таблицах символов, состоящих из случайных последовательностей 32-разрядных целых чисел, подтверждают, что для ключей, которые легко поддаются хешированию, хеширование работает значительно быстрее, чем поиск с использованием дерева. Двойное хеширование работает медленнее, чем раздельное связывание и линейное зондирование для разреженных таблиц ( из-за необходимости вычисления второй хеш-функции), но значительно быстрее линейного зондирования, когда таблица заполняется; кроме того, этот метод - единственный, который может обеспечить быстрый поиск с использованием лишь небольшого дополнительного объема памяти. Динамические хеш-таблицы, построенные с использованием линейного зондирования и расширения путем удвоения, требуют больших затрат времени при конструировании, чем другие хеш-таблицы, из-за необходимости распределения памяти и повторного хеширования, но несомненно обеспечивают наиболее быстрый поиск. Этот метод является предпочтительным, когда чаще всего выполняется поиск, и когда заранее нельзя точно предвидеть количество ключей. [41]
С увеличением количества ключей в хеш-таблице производительность поиска уменьшается. При использовании раздельного связывания время поиска увеличивается постепенно - когда количество ключей в таблице удваивается, время поиска удваивается. Это же справедливо по отношению к таким методам с открытой адресацией, как линейное зондирование и двойное хеширование для разреженных таблиц, но по мере заполнения таблицы затраты возрастают коренным образом и, что гораздо хуже, наступает момент, когда никакие дополнительные ключи вообще не могут быть вставлены. Эта ситуация отличается от деревьев поиска, в которых рост происходит естественным образом. Например, в RB-дереве затраты на поиск возрастают лишь несущественно ( на одно сравнение) при каждом удвоении количества узлов в дереве. [42]
Многие из них представляют интерес и находят важные применения. Однако, как обычно, следует избегать опрометчивого применения усложненных методов, если только это не обусловлено серьезными причинами, а компромисс между производительностью и сложностью не проанализирован самым тщательным образом, поскольку раздельное связывание, линейное зондирование и двойное хеширование просты, эффективны и приемлемы для большинства приложений. [43]
Однако, как правило, при использовании схемы с открытой адресацией другие ключи также исследуются, особенно, когда таблица начинает приближаться к заполненному состоянию. В примере, приведенном на рис. 14.7, поиск ключа N сопряжен с просмотром ключей С, Е, R и I, ни один из которых не имеет такого же хеш-значения. Это явление называется кластеризацией, поскольку оно связано с процессом образования кластеров. Оно может значительно замедлять линейное зондирование для почти заполненных таблиц. [44]
Раздельное сшсш ванне использует дополнительный объем памяти для: метолы с открытой адресацией используют дополнительную память НЕЯВНО внутри таблицы для свершения последовательностей мндирювднин. Следующий конкретный пример шшю трнрует ситуацию. Предначожнм что имеется та & лнца Af списков, построенная при полоти раздельного связывания, что средняя длина списков равна 4, а каадый элемент и каждая связь занимают по одному машинному слову. В атом случае таблица занимает 9Л / слов в памяти НА / для то ft и 5 Л / для связей К и д гя выполнения пояска в среднем требуется 2 зондирования, Но при лжгсйном зондировании для 4М элементов ь таблице размером 9А / требуется всею ( ] ] / ( - 4 / 9)) / 2 - 14 зондирований для обнаружения попвдання мри поиске - что яа 30 процентов меньше, чем требуется для рамс ль кого связывания при том же объеме используемой ггамятн; а при линейном зондировании лшв 4Л / элементов ь таблице размером 6Af требуется 2 зондирований АЛ ч обнаружения лонада-ння при поиске ( п среднем) Hh следовательно, используется памяти на 33 процента MC ] ibEi ] eh чем при раздельном связывании при том же времени выполнения. [45]