Декартово дерево — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(Ссылки)
(Высота декартового дерева)
Строка 86: Строка 86:
 
== Высота декартового дерева ==
 
== Высота декартового дерева ==
 
Мы уже выяснили, что сложность операций с декартовым деревом линейно зависит от его высоты. В действительности высота декартова дерева может быть линейной относительно его размеров. Например, высота декартова дерева, построенного по набору ключей <tex>(1, 1), \ldots, (n, n)</tex>, будет равна <tex>n</tex>. Во избежание таких случаев, полезным оказывается выбирать приоритеты в ключах случайно.
 
Мы уже выяснили, что сложность операций с декартовым деревом линейно зависит от его высоты. В действительности высота декартова дерева может быть линейной относительно его размеров. Например, высота декартова дерева, построенного по набору ключей <tex>(1, 1), \ldots, (n, n)</tex>, будет равна <tex>n</tex>. Во избежание таких случаев, полезным оказывается выбирать приоритеты в ключах случайно.
 +
 +
{{Теорема
 +
|statement = Декартово дерево из <tex>n</tex> узлов, ключи <tex>y</tex> которых являются незавимыми непрерывными случайными величинами с одинаковым вероятностным распределением, имеет высоту <tex>O(\log n)</tex>.
 +
|proof=
 +
Замечание: В следующих утверждениях мы будем считать, что <tex>x_1 < x_2 < \ldots x_n</tex>, а каждое <tex>y_i</tex> выбрано случайно и независимо с одинаковым распределением, а также будем называть <tex>i</tex>-м узлом узел с ключом <tex>x_i</tex>.
 +
 +
{{Лемма
 +
|statement = <tex>i</tex>-й узел является прародителем <tex>k</tex>-го узла тогда и только, когда <tex>y_i < y_j</tex> для любого <tex>j</tex> такого, что <tex>i < j \leqslant k</tex> или <tex>k \leqslant j < i</tex>.
 +
|proof=
 +
Рассмотрим случай <tex>i < k</tex>, в случае <tex>i > k</tex> доказательство аналогично.
 +
 +
Необходимость. Допустим, что <tex>y_i < y_j</tex> для всех <tex>i < j \leqslant k</tex>. Тогда по свойствам кучи <tex>i</tex>-й узел не может лежать в поддереве с корнем в <tex>k</tex>-м узле. Более того, не может существовать индекс <tex>j</tex> такой, что <tex>j</tex>-й узел общий прародитель <tex>i</tex>-го и <tex>k</tex>-го узлов, но эти узлы лежат в его разных  поддеревьях. Если он существует, то <tex>x_i < x_j < x_k</tex>, следовательно, <tex>i < j < k</tex>. Но тогда <tex>j</tex>-й не мог быть прародителем <tex>i</tex>-го узла (опять же по свойствам кучи). Остался последний вариант взаимного расположения <tex>i</tex>-го и <tex>k</tex>-го узлов: <tex>i</tex>-й является прародителем <tex>k</tex>-го узла.
 +
 +
Достаточность. Пусть <tex>i</tex>-й узел является предком <tex>k</tex>-го узла. Докажем от противного. Предположим, что существует <tex>j</tex> такое, что <tex>i < j \leqslant k</tex> и <tex>y_j < y_i</tex>. По свойствам кучи <tex>i</tex>-й узел не может быть прародителем <tex>j</tex>-го узла. Если <tex>j</tex>-й узел является прародителем <tex>i</tex>-го узла, то из неравенства <tex>x_i < x_j < x_k</tex> следует, что  <tex>i</tex>-й узел содержится в левом поддереве <tex>j</tex>-го узла, а <tex>k</tex>-й в правом. Это противоречит тому, что <tex>i</tex>-й узел прародитель <tex>k</tex>-го узла. Остается последний вариант взаимного расположения <tex>i</tex>-го и <tex>j</tex>-го узла: некоторый <tex>l</tex>-й узел является их общим прародителям, но они содержатся в его разных поддеревьях. Тогда получаем неравенство <tex>x_i < x_l < x_j \leqslant x_k</tex>, из которого следует, что <tex>k</tex>-й узел содержится в правом поддереве <tex>l</tex>-го узла. Снова противоречие. Значит, наше предположение не верно.
 +
}}
 +
 +
 +
}}
  
 
== Ссылки ==
 
== Ссылки ==

Версия 01:06, 12 апреля 2012

Эта статья про Курево

Описание

Декартово дерево — это структура данных, объединяющая в себе бинарное дерево поиска и бинарную кучу (отсюда и второе её название: treap (tree + heap) и дерамида (дерево + пирамида), так же существует название курево (куча + дерево).

Более строго, это структура данных, которая хранит пары [math] (X,Y) [/math] в виде бинарного дерева таким образом, что она является бинарным деревом поиска по [math]x[/math] и бинарной пирамидой по [math]y[/math]. Предполагая, что все [math]X[/math] и все [math]Y[/math] являются различными, получаем, что если некоторый элемент дерева содержит [math](X_0,Y_0)[/math], то у всех элементов в левом поддереве [math]X \lt X_0[/math], у всех элементов в правом поддереве [math] X \gt X_0[/math], а также и в левом, и в правом поддереве имеем: [math] Y \lt Y_0[/math].

Дерамиды были предложены Сиделем (Siedel) и Арагоном (Aragon) в 1996 г.

Операции в декартовом дереве

Split

Операция split

Операция [math]\mathrm{Split}[/math] (разрезать) позволяет сделать следующее: разрезать декартово дерево [math]T[/math] по ключу [math]x[/math] и получить два других декартовых дерева: [math]T_1[/math] и [math]T_2[/math], причем в [math]T_1[/math] находятся все ключи дерева [math]T[/math], не большие [math]x[/math], а в [math]T_2[/math] — большие [math]x[/math].

[math]\mathrm{Split}(T, x) \to \{T_1, T_2\}[/math].

Эта операция устроена следующим образом.

Рассмотрим случай, в котором требуется разрезать дерево по ключу, большему ключа корня. Посмотрим, как будут устроены результирующие деревья [math]T_1[/math] и [math]T_2[/math]:

  • [math]T_1[/math]: левое поддерево [math]T_1[/math] совпадёт с левым поддеревом [math]T[/math]. Для нахождения правого поддерева [math]T_1[/math], нужно разрезать правое поддерево [math]T[/math] на [math]T^R_1[/math] и [math]T^R_2[/math] по ключу [math]x[/math] и взять [math]T^R_1[/math].
  • [math]T_2[/math] совпадёт с [math]T^R_2[/math].

Случай, в котором требуется разрезать дерево по ключу, меньше либо равному ключа в корне, рассматривается симметрично.

Оценим время работы операции [math]\mathrm{Split}[/math]. Во время выполнения вызывается одна операция [math]\mathrm{Split}[/math] для дерева хотя бы на один меньшей высоты и делается ещё [math]\mathcal{O}(1)[/math] операция. Тогда итоговая трудоёмкость этой операции равна [math]\mathcal{O}(h)[/math], где [math]h[/math] — высота дерева.

Merge

Операция merge

Рассмотрим вторую операцию с декартовыми деревьями — [math]\mathrm{Merge}[/math](слить).

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

[math]\mathrm{Merge}(T_1, T_2) \to T[/math]

Рассмотрим принцип работы этой операции. Пусть нужно слить деревья [math]T_1[/math] и [math]T_2[/math]. Тогда, очевидно, у результирующего дерева [math]T[/math] есть корень. Корнем станет вершина из [math]T_1[/math] или [math]T_2[/math] с наибольшим ключом [math]y[/math]. Но вершина с самым большим [math]y[/math] из всех вершин деревьев [math]T_1[/math] и [math]T_2[/math] может быть только либо корнем [math]T_1[/math], либо корнем [math]T_2[/math]. Рассмотрим случай, в котором корень [math]T_1[/math] имеет больший [math]y[/math], чем корень [math]T_2[/math]. Случай, в котором корень [math]T_2[/math] имеет больший [math]y[/math], чем корень [math]T_1[/math], симметричен этому.

Если [math]y[/math] корня [math]T_1[/math] больше [math]y[/math] корня [math]T_2[/math], то он и будет являться корнем. Тогда левое поддерево [math]T[/math] совпадёт с левым поддеревом [math]T_1[/math]. Справа же нужно подвесить объединение правого поддерева [math]T_1[/math] и дерева [math]T_2[/math].

Рассуждая аналогично операции [math]\mathrm{Split}[/math] приходим к выводу, что трудоёмкость операции [math]\mathrm{Merge}[/math] равна [math]\mathcal{O}(h)[/math], где [math]h[/math] — высота дерева.

Insert

Операция [math]\mathrm{Insert}(T, k)[/math] добавляет в дерево [math]T[/math] элемент [math]k[/math], где [math]k.x[/math] — ключ, а [math]k.y[/math]— приоритет.

  • Реализация №1
  1. Разобьём наше дерево по ключу, который мы хотим добавить, то есть [math]\mathrm{Split}(T, k.x) \to \{T_1, T_2\}[/math].
  2. Сливаем первое дерево с новым элементом, то есть [math]\mathrm{Merge}(T_1, k) \to T_1[/math].
  3. Сливаем получившиеся дерево со вторым, то есть [math]\mathrm{Merge}(T_1, T_2) \to T[/math].
  • Реализация №2
  1. Сначала спускаемся по дереву (как в обычном бинарном дереве поиска по [math]k.x[/math]), но останавливаемся на первом элементе, в котором значение приоритета оказалось меньше [math]k.y[/math].
  2. Теперь вызываем [math]\mathrm{Split }(T, k.x) \to \{T_1, T_2\}[/math] от найденного элемента (от элемента вместе со всем его поддеревом)
  3. Полученные [math]T_1[/math] и [math]T_2[/math] записываем в качестве левого и правого сына добавляемого элемента.
  4. Полученное дерево ставим на место элемента, найденного в первом пункте.

Remove

Операция [math]\mathrm{Remove}(T, x)[/math] удаляет из дерева [math]T[/math] элемент с ключом [math]x[/math].

  • Реализация №1
  1. Разобьём наше дерево по ключу, который мы хотим удалить, то есть [math]\mathrm{Split }(T, k.x) \to \{T_1, T_2\}[/math].
  2. Теперь отделяем от первого дерева элемент [math]x[/math], опять таки разбивая по ключу [math]x[/math], то есть [math]\mathrm{Split }(T_1, k.x - \varepsilon) \to \{T_1, T_3\}[/math].
  3. Сливаем первое дерево со вторым, то есть [math]\mathrm{Merge }(T_1, T_2) \to T[/math].
  • Реализация №2
  1. Спускаемся по дереву (как в обычном бинарном дереве поиска по [math]x[/math]), ища удаляемый элемент.
  2. Найдя элемент, вызываем [math]Merge[/math] его левого и правого сыновей
  3. Возвращаемое значение функции [math]Merge[/math] ставим на место удаляемого элемента.

Высота декартового дерева

Мы уже выяснили, что сложность операций с декартовым деревом линейно зависит от его высоты. В действительности высота декартова дерева может быть линейной относительно его размеров. Например, высота декартова дерева, построенного по набору ключей [math](1, 1), \ldots, (n, n)[/math], будет равна [math]n[/math]. Во избежание таких случаев, полезным оказывается выбирать приоритеты в ключах случайно.

Теорема:
Декартово дерево из [math]n[/math] узлов, ключи [math]y[/math] которых являются незавимыми непрерывными случайными величинами с одинаковым вероятностным распределением, имеет высоту [math]O(\log n)[/math].
Доказательство:
[math]\triangleright[/math]

Замечание: В следующих утверждениях мы будем считать, что [math]x_1 \lt x_2 \lt \ldots x_n[/math], а каждое [math]y_i[/math] выбрано случайно и независимо с одинаковым распределением, а также будем называть [math]i[/math]-м узлом узел с ключом [math]x_i[/math].

Лемма:
[math]i[/math]-й узел является прародителем [math]k[/math]-го узла тогда и только, когда [math]y_i \lt y_j[/math] для любого [math]j[/math] такого, что [math]i \lt j \leqslant k[/math] или [math]k \leqslant j \lt i[/math].
Доказательство:
[math]\triangleright[/math]

Рассмотрим случай [math]i \lt k[/math], в случае [math]i \gt k[/math] доказательство аналогично.

Необходимость. Допустим, что [math]y_i \lt y_j[/math] для всех [math]i \lt j \leqslant k[/math]. Тогда по свойствам кучи [math]i[/math]-й узел не может лежать в поддереве с корнем в [math]k[/math]-м узле. Более того, не может существовать индекс [math]j[/math] такой, что [math]j[/math]-й узел общий прародитель [math]i[/math]-го и [math]k[/math]-го узлов, но эти узлы лежат в его разных поддеревьях. Если он существует, то [math]x_i \lt x_j \lt x_k[/math], следовательно, [math]i \lt j \lt k[/math]. Но тогда [math]j[/math]-й не мог быть прародителем [math]i[/math]-го узла (опять же по свойствам кучи). Остался последний вариант взаимного расположения [math]i[/math]-го и [math]k[/math]-го узлов: [math]i[/math]-й является прародителем [math]k[/math]-го узла.

Достаточность. Пусть [math]i[/math]-й узел является предком [math]k[/math]-го узла. Докажем от противного. Предположим, что существует [math]j[/math] такое, что [math]i \lt j \leqslant k[/math] и [math]y_j \lt y_i[/math]. По свойствам кучи [math]i[/math]-й узел не может быть прародителем [math]j[/math]-го узла. Если [math]j[/math]-й узел является прародителем [math]i[/math]-го узла, то из неравенства [math]x_i \lt x_j \lt x_k[/math] следует, что [math]i[/math]-й узел содержится в левом поддереве [math]j[/math]-го узла, а [math]k[/math]-й в правом. Это противоречит тому, что [math]i[/math]-й узел прародитель [math]k[/math]-го узла. Остается последний вариант взаимного расположения [math]i[/math]-го и [math]j[/math]-го узла: некоторый [math]l[/math]-й узел является их общим прародителям, но они содержатся в его разных поддеревьях. Тогда получаем неравенство [math]x_i \lt x_l \lt x_j \leqslant x_k[/math], из которого следует, что [math]k[/math]-й узел содержится в правом поддереве [math]l[/math]-го узла. Снова противоречие. Значит, наше предположение не верно.
[math]\triangleleft[/math]
[math]\triangleleft[/math]

Ссылки