Treap - Treap
Treap | |||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Тип | Рандомизированный двоичное дерево поиска | ||||||||||||||||||||
Сложность времени в нотация большой O | |||||||||||||||||||||
|
Часть серия на |
Вероятностный структуры данных |
---|
Случайные деревья |
Связанный |
В Информатика, то трогать и рандомизированное двоичное дерево поиска две тесно связанные формы двоичное дерево поиска структуры данных которые поддерживают динамический набор упорядоченных ключей и позволяют бинарный поиск среди ключей. После любой последовательности вставок и удалений ключей форма дерева будет случайная переменная с тем же распределением вероятностей, что и случайное двоичное дерево; особенно, с большой вероятностью его высота пропорциональна логарифм количества ключей, так что каждая операция поиска, вставки или удаления занимает логарифмическое время.
Описание
Treap был впервые описан Раймунд Зайдель и Сесилия Р. Арагон в 1989 г .;[1][2] его имя чемодан из дерево и куча.Это Декартово дерево в котором каждому ключу дается (случайно выбранный) числовой приоритет. Как и в случае любого двоичного дерева поиска, обход по порядку порядок узлов такой же, как отсортированный порядок ключей. Структура дерева определяется требованием, чтобы оно было упорядочено в куче: то есть номер приоритета для любого нелистового узла должен быть больше или равен приоритету его дочерних узлов. Таким образом, как и в случае с декартовыми деревьями в более общем смысле, корневой узел является узлом с максимальным приоритетом, и его левое и правое поддеревья формируются таким же образом из подпоследовательностей отсортированного порядка слева и справа от этого узла.
Эквивалентный способ описания treap состоит в том, что он может быть сформирован путем вставки узлов с наивысшим приоритетом в двоичное дерево поиска без какой-либо перебалансировки. Следовательно, если приоритеты являются независимыми случайными числами (из распределения по достаточно большому пространству возможных приоритетов, чтобы гарантировать, что два узла вряд ли будут иметь одинаковый приоритет), то форма треугольника имеет то же распределение вероятностей, что и форма а случайное двоичное дерево поиска, дерево поиска, сформированное путем вставки узлов без перебалансировки в случайно выбранном порядке вставки. Поскольку известно, что деревья случайного двоичного поиска имеют логарифмическую высоту с высокой вероятностью, то же самое верно и для treap.
Арагон и Зайдель также предлагают назначать более высокие приоритеты часто используемым узлам, например, с помощью процесса, который при каждом доступе выбирает случайное число и заменяет приоритет узла этим числом, если он выше, чем предыдущий приоритет. Эта модификация может привести к потере случайной формы дерева; вместо этого часто используемые узлы с большей вероятностью будут находиться рядом с корнем дерева, что приведет к ускорению их поиска.
Наор и Ниссим[3] описать приложение в обслуживании сертификаты авторизации в криптосистемы с открытым ключом.
Операции
Treaps поддерживают следующие основные операции:
- Чтобы найти заданное значение ключа, примените стандартный алгоритм двоичного поиска в двоичном дереве поиска, игнорируя приоритеты.
- Чтобы вставить новый ключ Икс в treap, сгенерируйте случайный приоритет у за Икс. Бинарный поиск для Икс в дереве и создайте новый узел в позиции листа, где двоичный поиск определяет узел для Икс должен существовать. Тогда, пока Икс не является корнем дерева и имеет больший приоритет, чем его родитель z, выполнить вращение деревьев который меняет отношения родитель-потомок между Икс и z.
- Чтобы удалить узел Икс из трепа, если Икс это лист дерева, просто удалите его. Если Икс имеет одного ребенка z, удалять Икс из дерева и сделать z быть потомком родителя Икс (или сделать z корень дерева, если Икс не имел родителя). Наконец, если Икс имеет двух дочерних элементов, поменяйте местами его положение в дереве с положением его непосредственного преемника z в отсортированном порядке, что привело к одному из предыдущих случаев. В этом последнем случае своп может нарушить свойство упорядочивания кучи для z, поэтому для восстановления этого свойства может потребоваться дополнительное вращение.
Массовые операции
В дополнение к одноэлементным операциям вставки, удаления и поиска, для treaps было определено несколько быстрых "массовых" операций: союз, пересечение и установить разницу. Они полагаются на две вспомогательные операции, расколоть и присоединиться.
- Чтобы разделить треп на два трепа меньшего размера, меньшие, чем ключ Икс, и те, которые больше ключа Икс, вставлять Икс в treap с максимальным приоритетом - большим, чем приоритет любого узла в treap. После этой вставки Икс будет корневым узлом treap, все значения меньше чем Икс будут найдены в левом подзаголовке, и все значения больше, чем Икс будут найдены в правом подзаголовке. Это стоит столько же, сколько и одно введение в треп.
- Соединяя два трепа, которые являются продуктом предыдущего разделения, можно с уверенностью предположить, что наибольшее значение в первом трепе меньше наименьшего значения во втором трепе. Создать новый узел со значением Икс, так что Икс больше, чем это max-value в первом treap, и меньше, чем min-value во втором treap, назначьте ему минимальный приоритет, затем установите его левый дочерний элемент в первую кучу, а его правый дочерний элемент - во вторую кучу. При необходимости поверните, чтобы исправить порядок кучи. После этого это будет листовой узел, и его можно будет легко удалить. В результате получается один треп, объединенный из двух исходных трепов. Это фактически «отменяет» раскол и стоит столько же. В более общем смысле, операция соединения может работать с двумя переходами и ключом с произвольным приоритетом (то есть необязательно, чтобы он был наивысшим).
Алгоритм соединения следующий:
функция присоединиться (L, k, R) если Prior (k, k (L)) и Prior (k, k (R)) возвращаться Узел (L, k, R) если Prior (k (L), k (R)) возвращаться Узел (слева (L), k (L), соединить (справа (L), k, R)) возвращаться Узел (соединение (L, k, слева (R), k (R), справа (R))
Алгоритм разделения следующий:
функция разделить (T, k) если (T = ноль) возвращаться (ноль, ложь, ноль) (L, (m, c), R) = выставить (T) если (к = м) возвращаться (L, правда, R) если (kвозвращаться (L ', b, присоединиться (R', m, R)) если (k> m) (L ', b, R') = разделить (R, k) возвращаться (присоединиться (L, m, L '), b, R))
Союз двух треапов т1 и т2, представляющие множества А и B это треп т что представляет А ∪ B. Следующий рекурсивный алгоритм вычисляет объединение:
функция союз (т1, т2): если т1 = ноль: возвращаться т2 если т2 = ноль: возвращаться т1 если приоритет (т1) <приоритет (t2): замена т1 и т2 т<, т> ← разделить т2 на ключе (т1) возвращаться join (union (left (t1), т<), ключ (t1), union (right (t1), т>))
Здесь, расколоть предполагается, что он возвращает два дерева: одно содержит ключи меньше, чем его ключ ввода, а другое - большие. (Алгоритм неразрушающий, но существует и деструктивная версия на месте.)
Алгоритм пересечения аналогичен, но требует присоединиться вспомогательная рутина. Сложность каждого из объединения, пересечения и различия равна О(м бревно п/м) для трипов размеров м и п, с м ≤ п. Более того, поскольку рекурсивные вызовы union независимы друг от друга, они могут выполняться в параллели.[4]
Split и Union вызывают Join, но не имеют прямого отношения к критериям балансировки treaps, такая реализация обычно называется реализация на основе соединения.
Обратите внимание, что если хеш-значения ключей используются в качестве приоритетов и структурно равные узлы объединены уже при построении, то каждый объединенный узел будет уникальным представлением набора ключей. При условии, что может существовать только один одновременный корневой узел, представляющий данный набор ключей, два набора могут быть проверены на равенство путем сравнения указателей, которое является постоянным во времени.
Этот метод можно использовать для улучшения алгоритмов слияния, чтобы они работали быстро, даже когда разница между двумя наборами небольшая. Если входные наборы равны, функции объединения и пересечения могут немедленно выйти из строя, возвращая один из входных наборов в качестве результата, тогда как функция разности должна возвращать пустой набор.
Позволять d быть размером симметричной разности. Модифицированные алгоритмы слияния также будут ограничены О(d бревно п/d).[5][6]
Рандомизированное двоичное дерево поиска
Рандомизированное бинарное дерево поиска, введенное Мартинесом и Рурой впоследствии в работу Арагона и Зейделя по treaps,[7] хранит одни и те же узлы с одинаковым случайным распределением формы дерева, но поддерживает различную информацию в узлах дерева, чтобы поддерживать его рандомизированную структуру.
Вместо того, чтобы хранить случайные приоритеты на каждом узле, рандомизированное двоичное дерево поиска хранит небольшое целое число на каждом узле, количество его потомков (считая себя за единицу); эти числа могут поддерживаться во время операций вращения дерева только при постоянном дополнительном времени на поворот. Когда ключ Икс должен быть вставлен в дерево, в котором уже есть п узлов алгоритм вставки выбирает с вероятностью 1 / (п + 1) разместить Икс в качестве нового корня дерева, а в противном случае он рекурсивно вызывает процедуру вставки, чтобы вставить Икс внутри левого или правого поддерева (в зависимости от того, больше или меньше его ключ корня). Число потомков используется алгоритмом для вычисления необходимых вероятностей для случайных выборов на каждом шаге. Размещение Икс в корне поддерева может быть выполнено либо как в treap, вставив его в лист и затем повернув вверх, либо с помощью альтернативного алгоритма, описанного Мартинесом и Рурой, который разбивает поддерево на две части, которые будут использоваться как левая и правые потомки нового узла.
Процедура удаления для рандомизированного двоичного дерева поиска использует ту же информацию для каждого узла, что и процедура вставки, но, в отличие от процедуры вставки, ей требуется в среднем только O (1) случайных решений для объединения двух поддеревьев, спускающихся от левого и правого дочерних элементов удалил узел в единое дерево. Это потому, что присоединяемые поддеревья в среднем находятся на глубине (log n); для соединения двух деревьев размера n и m в среднем требуется Θ (log (n + m)) случайных выборов. Если левое или правое поддерево удаляемого узла пусто, операция соединения тривиальна; в противном случае левый или правый дочерний элемент удаленного узла выбирается в качестве корня нового поддерева с вероятностью, пропорциональной количеству его потомков, и соединение выполняется рекурсивно.
Сравнение
Информация, хранящаяся на каждом узле в рандомизированном двоичном дереве, проще, чем в treap (маленькое целое число, а не случайное число высокой точности), но она делает большее количество обращений к генератору случайных чисел (O (logп) вызовов на вставку или удаление, а не один вызов на вставку), а процедура вставки немного сложнее из-за необходимости обновлять количество потомков на узел. Небольшое техническое отличие состоит в том, что в treap существует небольшая вероятность столкновения (два ключа имеют одинаковый приоритет), и в обоих случаях будут статистические различия между генератором истинных случайных чисел и генератором случайных чисел. генератор псевдослучайных чисел обычно используется на цифровых компьютерах. Однако в любом случае различия между теоретической моделью идеального случайного выбора, использованной для разработки алгоритма, и возможностями реальных генераторов случайных чисел исчезающе малы.
Хотя treap и рандомизированное двоичное дерево поиска имеют одинаковое случайное распределение форм дерева после каждого обновления, история модификаций деревьев, выполняемых этими двумя структурами данных в последовательности операций вставки и удаления, может быть различной. Например, в treap, если три числа 1, 2 и 3 вставлены в порядке 1, 3, 2, а затем номер 2 удален, оставшиеся два узла будут иметь такие же родительско-дочерние отношения, что и они. делал до вставки среднего числа. В рандомизированном двоичном дереве поиска дерево после удаления с равной вероятностью будет любым из двух возможных деревьев на его двух узлах, независимо от того, как дерево выглядело до вставки среднего числа.
Смотрите также
Рекомендации
- ^ Арагон, Сесилия Р .; Зайдель, Раймунд (1989), «Рандомизированные деревья поиска» (PDF), Proc. 30-й симпозиум Основы компьютерных наук (FOCS 1989), Вашингтон, округ Колумбия: IEEE Computer Society Press, стр. 540–545, Дои:10.1109 / SFCS.1989.63531, ISBN 0-8186-1982-1
- ^ Зайдель, Раймунд; Арагон, Сесилия Р. (1996), «Рандомизированные деревья поиска», Алгоритмика, 16 (4/5): 464–497, Дои:10.1007 / s004539900061
- ^ Наор, М.; Ниссим, К. (апрель 2000 г.), «Отзыв сертификата и обновление сертификата» (PDF), Журнал IEEE по избранным областям коммуникаций, 18 (4): 561–570, Дои:10.1109/49.839932[постоянная мертвая ссылка ].
- ^ Blelloch, Guy E .; Рейд-Миллер, Маргарет (1998), «Операции быстрого набора с использованием treaps», Proc. 10-й симпозиум ACM. Параллельные алгоритмы и архитектуры (SPAA 1998), Нью-Йорк, Нью-Йорк, США: ACM, стр. 16–26, Дои:10.1145/277651.277660, ISBN 0-89791-989-0.
- ^ Лильензин, Олле (2013). «Конфлуентно постоянные множества и карты». arXiv:1301.3388. Bibcode:2013arXiv1301.3388L. Цитировать журнал требует
| журнал =
(помощь) - ^ Конфлюентные наборы и карты на GitHub
- ^ Мартинес, Конрадо; Роура, Сальвадор (1997), «Рандомизированные бинарные деревья поиска», Журнал ACM, 45 (2): 288–323, Дои:10.1145/274787.274812
внешняя ссылка
- Сборник ссылок и информации о treap Сесилия Арагон
- Структуры открытых данных - раздел 7.2 - Treap: рандомизированное двоичное дерево поиска, Пэт Морин
- Анимированный треап
- Рандомизированные бинарные деревья поиска. Конспекты лекций из курса Джеффа Эриксона в UIUC. Несмотря на название, в первую очередь речь идет о трепах и пропустить списки; Деревья рандомизированного двоичного поиска упоминаются лишь кратко.
- Высокопроизводительное хранилище ключей и значений на основе treap автор: Junyi Sun
- Реализация treaps в VB6. Реализация treaps в Visual Basic 6 как COM-объекта.
- Реализация Treap в ActionScript3
- Чистый Python и Cython treap и duptreap в памяти
- Treaps в C #. Рой Клеммонс
- Pure Go в памяти, неизменные треки
- Постоянная библиотека хранения ключей и значений Pure Go