Я хочу реализовать хеш-таблицу с использованием деревьев двоичного поиска, чтобы уменьшить сложность поиска в процессе раздельного связывания с O (n) (используя связанный список) до O (log n) (используя BST). Можно ли это сделать, и если да, то как? Было бы легче понять, если решение шаг за шагом, реализация логики.
Я хочу сократить время поиска в хеш-таблице (сборка с использованием отдельной цепочки), но в то же время я не хочу увеличивать время вставки. Для моего проекта я не могу изменить хэш-функцию, чтобы уменьшить коллизии. Но из-за масштабируемости происходят столкновения. Я пытаюсь найти обходной путь, чтобы я мог как-то работать с лучшим доступом и вставить время в случае коллизии ... то есть управлять текущим состоянием, а не реструктурировать весь алгоритм. Если не получится, придется реструктурировать. Так есть идеи?
Ответы:
То, что вы просите, возможно, учитывая ваши ограничения.
Анализ
Сильной стороной хеш-таблицы является ее быстрый поиск и скорость вставки. Чтобы получить эту скорость, нужно оставить любое подобие порядка в таблице: то есть все записи перемешаны. Список приемлем для использования в качестве записи таблицы, потому что, хотя обход равен O (n), списки имеют тенденцию быть короткими, если хеш-таблица достаточно велика, а объекты, хранящиеся в таблице, хешируются с использованием алгоритма хеширования хорошего качества.
Бинарное дерево поиска (BST) имеет быструю вставку и поиск в O (log 2 n). Это также накладывает ограничение на элементы, которые он хранит: должен быть какой-то способ упорядочить элементы. Учитывая два элемента A и B, хранящихся в дереве, должна быть возможность определить, предшествует ли A B или имеют ли они эквивалентный порядок.
Хеш-таблица не накладывает такого ограничения: элементы в хеш-таблице должны иметь два свойства. Во-первых, должен быть способ определить, эквивалентны ли они; во-вторых, должен быть способ вычисления детерминированного хеш-кода. Заказ не является обязательным.
Если у ваших элементов хеш-таблицы есть порядок, то вы можете использовать BST в качестве записи хеш-таблицы для хранения объектов с одинаковым хеш-кодом (коллизиями). Однако из-за того, что BST имеет O (log 2 n) поиск и вставку, это означает, что наихудший случай для всей структуры (хеш-таблица плюс BST) технически лучше, чем использование списка в качестве записи таблицы. В зависимости от реализации BST потребуется больше памяти, чем список, но, вероятно, не намного больше.
Обратите внимание, что обычно издержки и поведение BST ничего не приводят к таблице в реальных ситуациях в виде блоков хеш-таблиц, поэтому теоретически низкая производительность списка является приемлемой. Другими словами, хеш-таблица компенсирует слабость списка, размещая меньше элементов в каждом списке (сегменте). Тем не менее : проблема конкретно гласила, что хеш-таблица не может увеличиваться в размере, и коллизии происходят чаще, чем обычно в хеш-таблице.
Реализация
Я не собираюсь помещать код здесь, потому что, честно говоря, он не является действительно необходимым, и вы все равно не дали язык.
Я бы просто скопировал любую стандартную хеш-таблицу, содержащую стандартную библиотеку вашего языка, в новый класс, а затем изменил тип сегмента таблицы со списка на дерево. В зависимости от языка и его стандартной библиотеки это может быть очень простым делом.
Обычно я бы не рекомендовал копировать и вставлять кодирование, подобное этому. Тем не менее, это простой способ очень быстро получить проверенную в бою структуру данных .
источник
Использование бинарного дерева для обработки коллизий в хеш-таблице не просто возможно - это было сделано.
Уолтер Брайт наиболее известен как изобретатель языка программирования D , но также написал вариант ECMAScript под названием DMDScript . В прошлом заголовок DMDScript (или, возможно, предка - кажется, я помню имя DScript) гласил, что его хеш-таблицы имеют тенденцию превосходить таковые во многих похожих языках. Причина - обработка столкновений с использованием бинарных деревьев.
Я не помню точно, откуда это, но используемые деревья были наивными двоичными деревьями, без схемы частичного баланса (не AVL, красно-черный или что-то еще), что имеет смысл, поскольку предполагается, что размер самой хеш-таблицы изменяется, когда она переполняется и вы не получите абсурдно невероятную частоту столкновений хешей, двоичные деревья всегда должны быть маленькими. По сути, наихудший случай по-прежнему такой же, как использование связанного списка для обработки коллизий (за исключением того, что вы платите цену двух указателей за узел вместо одного), но в среднем случае уменьшается объем поиска в каждом хэш-сегменте.
источник