Ожидаемая производительность попыток по сравнению с массивами сегментов с постоянным коэффициентом загрузки

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

Изменить: я рассматриваю строки как эквивалентные позиционным дробям в диапазоне [0..1]. Таким образом, они могут быть отображены в любой целочисленный диапазон путем умножения и получения результата.

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

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

Каковы преимущества попытки тогда?

Если распределение равномерное, я не вижу ничего, что могло бы улучшить ситуацию. Но я могу ошибаться.

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

Итак, мой вопрос: каковы преимущества производительности попыток над массивами сегментов, которые можно формально продемонстрировать? Какие дистрибутивы обеспечивают эти преимущества?

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

Спасибо


person simeonz    schedule 01.01.2013    source источник


Ответы (2)


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

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

person Thomas    schedule 01.01.2013
comment
Под общими префиксами подразумевается плотная кластеризация ключей в нескольких подинтервалах. И, вероятно, рекурсивно проявляющийся. Существует ли формальная модель - распределение или что-то еще, что характеризует такого рода явления. Я имею в виду, что мы говорим о каком-то случайном входе, верно. Или это что-то совершенно искусственное по своей природе, например. относится к человеческому языку? Можно ли использовать try для ключей, которые не являются текстом как таковым, а строками вещей в более абстрактном смысле? - person simeonz; 02.01.2013
comment
Конечно, попытки могут использоваться для последовательностей вещей, но они работают лучше, если алфавит небольшой. Работают только единицы и нули, работает 26 букв, 256 разных октетов в IP-адресе по-прежнему работает, но чем больше алфавит, тем более расточительным становится тройка. - person Thomas; 02.01.2013
comment
Хорошо, если я могу обобщить то, что вы подразумевали в своем ответе. Для однородного распределения, для врезных запросов, попытки работают не хуже, чем сбалансированные деревья поиска, но для сильно перекошенных распределений они работают лучше, чем массивы сегментов. Какой-то компромисс. Кроме того, для префиксных запросов и т. д. они работают лучше, чем сбалансированные деревья поиска, когда распределение неравномерно. Я хотел, чтобы некоторые указатели выявили общий феномен префикса, наблюдаемый со строками. То есть как можно формально количественно оценить его влияние на работоспособность таких структур, но достаточно вашего ответа. - person simeonz; 03.01.2013
comment
Просто что-то забыл. Спасибо за ответ. - person simeonz; 03.01.2013

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

Другое дело, что вам нужно сопоставить строку с дробью для использования с массивами сегментов. Поэтому, если у вас есть короткие ключи, теоретически попытка может быть более эффективной, потому что вам не нужно выполнять сопоставление.

person Sergey Zyuzin    schedule 01.01.2013
comment
Вы правы насчет вставки, но я хотел оставить это за рамками обсуждения. Предположим, как я уже сказал, что данные имеют некоторый известный средний размер, не слишком динамичный. То есть количество биллинговых записей, сделанных в телефонной компании за день. Я также думаю, что вставку можно деамортизировать, за счет сохранения старого массива на некоторое время после выделения нового и перемещения нескольких записей из него после каждой вставки. - person simeonz; 02.01.2013
comment
Что касается сопоставления ключей, сама строка представляет собой битовый шаблон, выровненный по левому краю, точно так же, как двоичная позиционная дробь в интервале [0..1]. На самом деле, в каком-то смысле это дробь. Все, что вам нужно сделать, это взять начальные биты (от первых символов в строке) и дополнить их 0 справа, если строка слишком короткая. Этого достаточно, чтобы отобразить целочисленный битовый шаблон фиксированного размера в некотором интервале. Это будет интервал степени двойки, но это выбор, который нам разрешено делать. - person simeonz; 02.01.2013