Декартово дерево — различия между версиями
VVolochay (обсуждение | вклад) (→Реализация №2:) |
|||
Строка 1: | Строка 1: | ||
''Эта статья про Курево'' | ''Эта статья про Курево'' | ||
− | '''Декартово дерево''' {{---}} это структура данных, объединяющая в себе бинарное дерево поиска и бинарную кучу (отсюда и второе её название: | + | == Описание == |
+ | '''Декартово дерево''' {{---}} это структура данных, объединяющая в себе бинарное дерево поиска и бинарную кучу (отсюда и второе её название: treap (tree + heap) и дерамида (дерево + пирамида), так же существует название курево (куча + дерево). | ||
Более строго, это структура данных, которая хранит пары <tex> (X,Y) </tex> в виде бинарного дерева таким образом, что она является бинарным деревом поиска по <tex>x</tex> и бинарной пирамидой по <tex>y</tex>. Предполагая, что все <tex>X</tex> и все <tex>Y</tex> являются различными, получаем, что если некоторый элемент дерева содержит <tex>(X_0,Y_0)</tex>, то у всех элементов в левом поддереве <tex>X < X_0</tex>, у всех элементов в правом поддереве <tex> X > X_0</tex>, а также и в левом, и в правом поддереве имеем: <tex> Y < Y_0</tex>. | Более строго, это структура данных, которая хранит пары <tex> (X,Y) </tex> в виде бинарного дерева таким образом, что она является бинарным деревом поиска по <tex>x</tex> и бинарной пирамидой по <tex>y</tex>. Предполагая, что все <tex>X</tex> и все <tex>Y</tex> являются различными, получаем, что если некоторый элемент дерева содержит <tex>(X_0,Y_0)</tex>, то у всех элементов в левом поддереве <tex>X < X_0</tex>, у всех элементов в правом поддереве <tex> X > X_0</tex>, а также и в левом, и в правом поддереве имеем: <tex> Y < Y_0</tex>. | ||
Строка 7: | Строка 8: | ||
Дерамиды были предложены Сиделем (Siedel) и Арагоном (Aragon) в 1996 г. | Дерамиды были предложены Сиделем (Siedel) и Арагоном (Aragon) в 1996 г. | ||
− | == | + | == Операции в декартовом дереве == |
+ | === Split === | ||
[[file:split.png|thumb|400px|Операция split]] | [[file:split.png|thumb|400px|Операция split]] | ||
− | Операция <tex>\mathrm{ | + | Операция <tex>\mathrm{Split}</tex> (''разрезать'') позволяет сделать следующее: разрезать декартово дерево <tex>T</tex> по ключу |
<tex>x</tex> и получить два других декартовых дерева: <tex>T_1</tex> и <tex>T_2</tex>, причем в <tex>T_1</tex> | <tex>x</tex> и получить два других декартовых дерева: <tex>T_1</tex> и <tex>T_2</tex>, причем в <tex>T_1</tex> | ||
находятся все ключи дерева <tex>T</tex>, не большие <tex>x</tex>, а в <tex>T_2</tex> {{---}} большие <tex>x</tex>. | находятся все ключи дерева <tex>T</tex>, не большие <tex>x</tex>, а в <tex>T_2</tex> {{---}} большие <tex>x</tex>. | ||
− | <tex>\mathrm{ | + | <tex>\mathrm{Split}(T, x) \to \{T_1, T_2\}</tex>. |
Эта операция устроена следующим образом. | Эта операция устроена следующим образом. | ||
Строка 25: | Строка 27: | ||
Случай, в котором требуется разрезать дерево по ключу, меньше либо равному ключа в корне, рассматривается симметрично. | Случай, в котором требуется разрезать дерево по ключу, меньше либо равному ключа в корне, рассматривается симметрично. | ||
− | Оценим время работы операции <tex>\mathrm{ | + | Оценим время работы операции <tex>\mathrm{Split}</tex>. Во время выполнения вызывается одна операция <tex>\mathrm{Split}</tex> для |
дерева хотя бы на один меньшей высоты и делается ещё <tex>\mathcal{O}(1)</tex> операция. Тогда итоговая трудоёмкость этой операции | дерева хотя бы на один меньшей высоты и делается ещё <tex>\mathcal{O}(1)</tex> операция. Тогда итоговая трудоёмкость этой операции | ||
− | равна <tex>\mathcal{O}(h)</tex>, где <tex>h</tex> {{---}} высота дерева | + | равна <tex>\mathcal{O}(h)</tex>, где <tex>h</tex> {{---}} высота дерева. |
− | |||
− | == | + | === Merge === |
[[file:merge.png|thumb|400px|Операция merge]] | [[file:merge.png|thumb|400px|Операция merge]] | ||
− | Рассмотрим вторую операцию с декартовыми деревьями {{---}} <tex>\mathrm{ | + | Рассмотрим вторую операцию с декартовыми деревьями {{---}} <tex>\mathrm{Merge}</tex>(''слить''). |
С помощью этой операции можно слить два декартовых дерева в одно. | С помощью этой операции можно слить два декартовых дерева в одно. | ||
Строка 39: | Строка 40: | ||
ключи во втором(''правом''). В результате получается дерево, в котором есть все ключи из первого и второго деревьев. | ключи во втором(''правом''). В результате получается дерево, в котором есть все ключи из первого и второго деревьев. | ||
− | <tex>\mathrm{ | + | <tex>\mathrm{Merge}(T_1, T_2) \to T</tex> |
Рассмотрим принцип работы этой операции. Пусть нужно слить деревья <tex>T_1</tex> и <tex>T_2</tex>. | Рассмотрим принцип работы этой операции. Пусть нужно слить деревья <tex>T_1</tex> и <tex>T_2</tex>. | ||
Строка 52: | Строка 53: | ||
<tex>T_1</tex> и дерева <tex>T_2</tex>. | <tex>T_1</tex> и дерева <tex>T_2</tex>. | ||
− | Рассуждая аналогично операции <tex>\mathrm{ | + | Рассуждая аналогично операции <tex>\mathrm{Split}</tex> приходим к выводу, что трудоёмкость операции <tex>\mathrm{Merge}</tex> |
− | равна <tex>\mathcal{O}( | + | равна <tex>\mathcal{O}(h)</tex>, где <tex>h</tex> {{---}} высота дерева. |
− | == | + | === Insert === |
− | Операция <tex>\mathrm{ | + | Операция <tex>\mathrm{Insert}(T, k)</tex> добавляет в дерево <tex>T</tex> элемент <tex>k</tex>, где <tex>k.x</tex> {{---}} ключ, а <tex>k.y</tex>{{---}} приоритет. |
− | ===Реализация №1 | + | ==== Реализация №1 ==== |
− | # Разобьём наше дерево по ключу, который мы хотим добавить, то есть <tex>\mathrm{ | + | # Разобьём наше дерево по ключу, который мы хотим добавить, то есть <tex>\mathrm{Split}(T, k.x) \to \{T_1, T_2\}</tex>. |
− | # Сливаем первое дерево с новым элементом, то есть <tex>\mathrm{ | + | # Сливаем первое дерево с новым элементом, то есть <tex>\mathrm{Merge}(T_1, k) \to T_1</tex>. |
− | # Сливаем получившиеся дерево со вторым, то есть <tex>\mathrm{ | + | # Сливаем получившиеся дерево со вторым, то есть <tex>\mathrm{Merge}(T_1, T_2) \to T</tex>. |
+ | ==== Реализация №2 ==== | ||
+ | # Сначала спускаемся по дереву (как в обычном бинарном дереве поиска по <tex>k.x</tex>), но останавливаемся на первом элементе, в котором значение приоритета оказалось меньше <tex>k.y</tex>. | ||
+ | # Теперь вызываем <tex>\mathrm{Split }(T, k.x) \to \{T_1, T_2\}</tex> от найденного элемента (от элемента вместе со всем его поддеревом) | ||
+ | # Полученные <tex>T_1</tex> и <tex>T_2</tex> записываем в качестве левого и правого сына добавляемого элемента. | ||
+ | # Полученное дерево подвешиваем на место элемента, найденного в первом пункте. | ||
− | === | + | === Remove === |
− | + | Операция <tex>\mathrm{Remove}(T, x)</tex> удаляет из дерева <tex>T</tex> элемент с ключом <tex>x</tex>. | |
+ | ==== Реализация №1 ==== | ||
− | + | # Разобьём наше дерево по ключу, который мы хотим удалить, то есть <tex>\mathrm{Split }(T, k.x) \to \{T_1, T_2\}</tex>. | |
− | + | # Теперь отделяем от первого дерева элемент <tex>x</tex>, опять таки разбивая по ключу <tex>x</tex>, то есть <tex>\mathrm{Split }(T_1, k.x - \varepsilon) \to \{T_1, T_3\}</tex>. | |
+ | # Сливаем первое дерево со вторым, то есть <tex>\mathrm{Merge }(T_1, T_2) \to T</tex>. | ||
− | ===Реализация | + | ====Реализация №2==== |
+ | # Спускаемся по дереву (как в обычном бинарном дереве поиска по <tex>x</tex>), ища удаляемый элемент. | ||
+ | # Найдя элемент, вызываем <tex>Merge</tex> его левого и правого сыновей, и возвращаемое ею значение ставим на место удаляемого элемента, то есть <tex>\mathrm{Merge }(T.l, T.t) \to T</tex>. | ||
− | + | == Высота декартового дерева == | |
− | + | Мы уже выяснили, что сложность операций с декартовым деревом линейно зависит от его высоты. В действительности высота декартова дерева может быть линейной относительно его размеров. Например, высота декартова дерева, построенного по набору ключей <tex>(1, 1), \ldots, (n, n)</tex>, будет равна <tex>n</tex>. Во избежание таких случаев, полезным оказывается выбирать приоритеты в ключах случайно. | |
− | |||
− | == | + | == Ссылки == |
− | |||
− | |||
− | |||
Todo | Todo | ||
[[Категория:Дискретная математика и алгоритмы]] | [[Категория:Дискретная математика и алгоритмы]] | ||
[[Категория:Деревья поиска]] | [[Категория:Деревья поиска]] |
Версия 18:39, 11 апреля 2012
Эта статья про Курево
Содержание
Описание
Декартово дерево — это структура данных, объединяющая в себе бинарное дерево поиска и бинарную кучу (отсюда и второе её название: treap (tree + heap) и дерамида (дерево + пирамида), так же существует название курево (куча + дерево).
Более строго, это структура данных, которая хранит пары
в виде бинарного дерева таким образом, что она является бинарным деревом поиска по и бинарной пирамидой по . Предполагая, что все и все являются различными, получаем, что если некоторый элемент дерева содержит , то у всех элементов в левом поддереве , у всех элементов в правом поддереве , а также и в левом, и в правом поддереве имеем: .Дерамиды были предложены Сиделем (Siedel) и Арагоном (Aragon) в 1996 г.
Операции в декартовом дереве
Split
Операция
(разрезать) позволяет сделать следующее: разрезать декартово дерево по ключу и получить два других декартовых дерева: и , причем в находятся все ключи дерева , не большие , а в — большие ..
Эта операция устроена следующим образом.
Рассмотрим случай, в котором требуется разрезать дерево по ключу, большему ключа корня. Посмотрим, как будут устроены результирующие деревья
и :- : левое поддерево совпадёт с левым поддеревом . Для нахождения правого поддерева , нужно разрезать правое поддерево на и по ключу и взять .
- совпадёт с .
Случай, в котором требуется разрезать дерево по ключу, меньше либо равному ключа в корне, рассматривается симметрично.
Оценим время работы операции
. Во время выполнения вызывается одна операция для дерева хотя бы на один меньшей высоты и делается ещё операция. Тогда итоговая трудоёмкость этой операции равна , где — высота дерева.Merge
Рассмотрим вторую операцию с декартовыми деревьями —
(слить).С помощью этой операции можно слить два декартовых дерева в одно. Причем, все ключи в первом(левом) дереве должны быть меньше, чем ключи во втором(правом). В результате получается дерево, в котором есть все ключи из первого и второго деревьев.
Рассмотрим принцип работы этой операции. Пусть нужно слить деревья
и . Тогда, очевидно, у результирующего дерева есть корень. Корнем станет вершина из или с наибольшим ключом . Но вершина с самым большим из всех вершин деревьев и может быть только либо корнем , либо корнем . Рассмотрим случай, в котором корень имеет больший , чем корень . Случай, в котором корень имеет больший , чем корень , симметричен этому.Если
корня больше корня , то он и будет являться корнем. Тогда левое поддерево совпадёт с левым поддеревом . Справа же нужно подвесить объединение правого поддерева и дерева .Рассуждая аналогично операции
приходим к выводу, что трудоёмкость операции равна , где — высота дерева.Insert
Операция
добавляет в дерево элемент , где — ключ, а — приоритет.Реализация №1
- Разобьём наше дерево по ключу, который мы хотим добавить, то есть .
- Сливаем первое дерево с новым элементом, то есть .
- Сливаем получившиеся дерево со вторым, то есть .
Реализация №2
- Сначала спускаемся по дереву (как в обычном бинарном дереве поиска по ), но останавливаемся на первом элементе, в котором значение приоритета оказалось меньше .
- Теперь вызываем от найденного элемента (от элемента вместе со всем его поддеревом)
- Полученные и записываем в качестве левого и правого сына добавляемого элемента.
- Полученное дерево подвешиваем на место элемента, найденного в первом пункте.
Remove
Операция
удаляет из дерева элемент с ключом .Реализация №1
- Разобьём наше дерево по ключу, который мы хотим удалить, то есть .
- Теперь отделяем от первого дерева элемент , опять таки разбивая по ключу , то есть .
- Сливаем первое дерево со вторым, то есть .
Реализация №2
- Спускаемся по дереву (как в обычном бинарном дереве поиска по ), ища удаляемый элемент.
- Найдя элемент, вызываем его левого и правого сыновей, и возвращаемое ею значение ставим на место удаляемого элемента, то есть .
Высота декартового дерева
Мы уже выяснили, что сложность операций с декартовым деревом линейно зависит от его высоты. В действительности высота декартова дерева может быть линейной относительно его размеров. Например, высота декартова дерева, построенного по набору ключей
, будет равна . Во избежание таких случаев, полезным оказывается выбирать приоритеты в ключах случайно.Ссылки
Todo