Рандомизированное бинарное дерево поиска
Рандомизированное бинарное дерево поиска (англ. Randomized binary search tree, RBST) — структура данных, представляющая собой бинарное дерево поиска.
Содержание
Основная идея и связанные определения
Как известно, можно подобрать такую последовательность операций с бинарным деревом поиска в наивной реализации, что его глубина будет пропорциональна количеству ключей, что отрицательно скажется на быстродействии. Поэтому, если поддерживать инвариант "случайности" в дереве, то можно добиться того, что математическое ожидание глубины дерева будет небольшим. Дадим рекурсивное определение случайного бинарного дерева поиска.
| Определение: |
| Пусть — бинарное дерево поиска. Тогда
1) Если пусто, то оно является случайным бинарным деревом поиска. 2) Если непусто (содержит вершин, ), то — случайное бинарное дерево поиска тогда и только тогда, когда его левое и правое поддеревья ( и ) оба являются RBST, а также выполняется соотношение . |
Из определения следует, что каждый ключ в случайном размера n может оказаться корнем с вероятностью 1/n.
Идея RBST состоит в том, что хранимое дерево постоянно является случайным бинарным деревом поиска. Далее подробно будет описана реализация операций над RBST, которая позволит добиться этой цели. Заметим лишь, что хранение RBST в памяти ничем не отличается от хранения обычного дерева поиска: хранится указатель на корень; в каждой вершине хранятся указатели на её сыновей.
(Похожие идеи используются в декартовом дереве, поэтому во многих русскоязычных ресурсах термин рандомизированное бинарное дерево поиска используется как синонимическое название декартового дерева и декартового дерева по неявному ключу)
Операции
Операции, не связанные с изменением структуры дерева, выполняются как в обычном дереве поиска.
Вставка
Рассмотрим рекурсивный алгоритм вставки ключа в RBST состоящее из вершин. С вероятностью вставим ключ в корень дерева, использую процедуру insert_at_root. С вероятностью вставим его в правое поддереао, если он больше корня, или в левое поддерево, если меньше. Ниже приведён псевдокод процедуры вставки insert, процедуры insert_at_root, а также процедуры split(k), разбивающей дерево на два поддерева, в одном из которых все ключи строго меньше , а в другом больше, либо равны; приведена достаточно очевидная рекурсивная реализация. (через Node обозначен тип вершины дерева, дерево представляется как указатель на корень)
Node insert (x, T)
int r = random(0..size(t))
if (r = n)
T = insert_at_root(x, T)
if (x < root key)
T = insert(x, T left)
else
T = insert(x, T right)
return T
Заметим, что если дерево пусто, то insert с вероятностью 1 делает корнем.
// вставляет ключ x в дерево T Node insert_at_root (x, T) ...создать вершины L и R split(x, T, L, R) ...создать новую вершину T T T key = x T left = L T left = R return T
// разделяет дерево T по x
// результат: деревья L и R
split (x, T, L, R)
if (T пусто)
...создать пустые L И R
else if (x < T T key)
R = T
split (x, T left, L, R left)
else
L = T
split (x, T right, L right, R)
Далее рассмотрим как меняется свойство дерева быть случайным при вставке в него ключей.
| Лемма: |
Пусть после операции split от дерева по ключу были получены деревья и . Тогда если было случайным бинарным деревом поиска, содержащим множество ключей , то деревья и — независимые случайные бинарные деревья поиска, содержащие соответственно множества ключей и . |
| Теорема: |
Если — случайное бинарное дерево поиска, содержащее множество ключей , , тогда процедура insert(x, T) вернёт случайное бинарное дерево поиска , содержащее множество ключей . |
Пусть — множество ключей, — какая-то фиксированная перестановка элементов . Из приведённой выше теоремы следует, что если в изначально пустое дерево добавлять ключи P по порядку, то получим дерево , являющееся RBST.
Удаление
Алгоритм удаления использует операцию merge — слияние двух деревьев, удовлетворяющих условию: все ключи в одном из деревьев меньше ключей во втором. Для того, чтобы удалить некоторый ключ из RBST сначала найдём вершину с этим ключом в дереве, используя стандартный алгоритм поиска. Если вершина не найдена, то выходим из алгоритма; в противном случае сливаем правое и левое поддеревья (заметим, что ключи в левом поддереве меньше ключей в правом), удаляем , а корень образовавшегося дерева делаем новым сыном родителя . Псевдокод процедур удаления и слияния приведён ниже.
// удаляет ключ x из дерева T
Node remove(x, T)
if (T пусто)
...выйти, вернув пустое дерево
if (x < T T key)
T left = delete(x, T left)
else if (x > T T key)
T right = delete(x, T right)
else
...создать пустое дерево Q
Q = merge(T left, T right)
T = Q
return T
// сливает деревья L и R // результат: дерево T Node merge(L, R) int m = L size int n = R size int total = m + n if (total = 0) ...вернуть пустое T int r = random(1..total) if (r < m) // с вероятностью m / (m + n) L right = merge(L right, R) return L if (r < m) // с вероятностью m / (m + n) R left = merge(L, R left) return R
Докажем, что данный алгоритм не оставляет случайное дерево случайным.
| Лемма: |
Пусть и — независимые случайные бинарные деревья поиска, содержащие соответственно множества ключей и , причём (то есть каждый элемент меньше каждого элемента ). Тогда — случайное бинарное дерево поиска, содержащее множество ключей = . |
| Теорема: |
Если — случайное бинарное дерево поиска, содержащее множество ключей , тогда процедура delete(x, T) вернёт случайное бинарное дерево поиска , содержащее множество ключей |
Анализ времени работы
Достаточно очевидно, что время работы приведённых алгоритмов пропорционально глубине дерева. Но т.к. математическое ожидание глубины случайного бинарного дерева поиска есть , где — число вершин в дереве, то математическое ожидание времени работы поиска, вставки и удаления — также .
Смотри также
Ссылки
Литература
- Martínez, Conrado; Roura, Salvador (1997), "Randomized binary search trees", Journal of the ACM 45 (2): 288–323
- Seidel, Raimund; Aragon, Cecilia R. «Randomized Search Trees», 1996 г.
- Randomized binary search trees. Lecture notes from a course by Jeff Erickson at UIUC. Despite the title, this is primarily about treaps and skip lists; randomized binary search trees are mentioned only briefly.