Декартово дерево — различия между версиями
(+ split) |
|||
Строка 8: | Строка 8: | ||
== Операция split == | == Операция split == | ||
− | + | == Операция split == | |
+ | |||
+ | Операция <tex>\mathrm{split}</tex>(''распилить'') позволяет сделать следующее: разрезать декартово дерево <tex>T</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>\mathrm{split}(T, x) \to \{T_1, T_2\}</tex>. | ||
+ | |||
+ | Как же устроена сея замечательная операция? | ||
+ | |||
+ | Рассмотрим случай, в котором требуется распилить дерево по ключу, большему ключа корня. | ||
+ | Посмотрим, как будут устроены результирующие деревья <tex>T_1</tex> и <tex>T_2</tex>: | ||
+ | * <tex>T_1</tex>: левое поддерево <tex>T_1</tex> совпадёт с левым поддеревом <tex>T</tex>. Для нахождения правого поддерева <tex>T_1</tex>, нужно распилить правое поддерево <tex>T</tex> на <tex>T^R_1</tex> и <tex>T^R_2</tex> по ключу <tex>x</tex> и взять <tex>T^R_1</tex>. | ||
+ | * <tex>T_2</tex> совпадёт с <tex>T^R_2</tex>. | ||
+ | |||
+ | Случай, в котором требуется распилить дерево по ключу, меньше либо равному ключа в корне, рассматривается симметрично. | ||
+ | |||
+ | Оценим время работы операции <tex>\mathrm{split}</tex>. Во время выполнения вызывается одна операция <tex>\mathrm{split}</tex> для | ||
+ | дерева хотя бы на один меньшей высоты и делается ещё <tex>\mathcal{O}(1)</tex> операция. Тогда итоговая трудоёмкость этой операции | ||
+ | равна <tex>\mathcal{O}(h)</tex>, где <tex>h</tex> {{---}} высота дерева. Так как высота декартова дерева {{---}} | ||
+ | <tex>\mathcal{O}(\log n)</tex>, то и операция <tex>\mathrm{split}</tex> работает за <tex>\mathcal{O}(\log n)</tex>. | ||
+ | |||
+ | {{TODO|t=Запилить рисунок}} | ||
== Операция merge == | == Операция merge == |
Версия 05:42, 8 апреля 2011
Эта статья про Курево
Декартово дерево — это структура данных, объединяющая в себе бинарное дерево поиска и бинарную кучу (отсюда и второе её название:
и дерамида (дерево+пирамида).Более строго, это структура данных, которая хранит пары
в виде бинарного дерева таким образом, что она является бинарным деревом поиска по и бинарной пирамидой по . Предполагая, что все и все являются различными, получаем, что если некоторый элемент дерева содержит , то всех элементов в левом поддереве , у всех элементов в правом поддереве , а также и в левом, и в правом поддереве имеем: .Дерамиды были предложены Сиделем (Siedel) и Арагоном (Aragon) в 1996 г.
Содержание
Операция split
Операция split
Операция
(распилить) позволяет сделать следующее: разрезать декартово дерево по ключу и получить два других декартовых дерева: и , причем в находятся все ключи дерева , не большие , а в — большие ..
Как же устроена сея замечательная операция?
Рассмотрим случай, в котором требуется распилить дерево по ключу, большему ключа корня. Посмотрим, как будут устроены результирующие деревья
и :- : левое поддерево совпадёт с левым поддеревом . Для нахождения правого поддерева , нужно распилить правое поддерево на и по ключу и взять .
- совпадёт с .
Случай, в котором требуется распилить дерево по ключу, меньше либо равному ключа в корне, рассматривается симметрично.
Оценим время работы операции
. Во время выполнения вызывается одна операция для дерева хотя бы на один меньшей высоты и делается ещё операция. Тогда итоговая трудоёмкость этой операции равна , где — высота дерева. Так как высота декартова дерева — , то и операция работает за .
TODO: Запилить рисунок
Операция merge
А тут будет merge
Операция add
Операция
добавляет в дерево элемент , где — ключ, а — приоритет.Реализация №1:
- Разбиваем наше дерево по ключу, который мы хотим добавить, то есть .
- Сливаем первое дерево с новым элементом, то есть .
- Сливаем получившиеся дерево со вторым, то есть .
Реализация №2:
Сначала спускаемся по дереву (как в обычном бинарном дереве поиска по
), но останавливаемся на первом элементе, в котором значение приоритета оказалось меньше . Мы нашли позицию, куда будем вставлять наш элемент. Теперь вызываем от найденного элемента (от элемента вместе со всем его поддеревом), и возвращаемые ею и записываем в качестве левого и правого сына добавляемого элемента.
Операция remove
Операция
удаляет из дерева элемент с ключом .Реализация №1:
- Разбиваем наше дерево по ключу, который мы хотим удалить, то есть .
- Теперь отделяем от второго дерева элемент , опять таки разбивая по ключу , то есть .
- Сливаем первое дерево со третьим, то есть .
Реализация №2:
Спускаемся по дереву (как в обычном бинарном дереве поиска по
), ища удаляемый элемент. Найдя элемент, мы просто вызываем его левого и правого сыновей, и возвращаемое ею значение ставим на место удаляемого элемента, то есть .