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

Материал из Викиконспекты
Перейти к: навигация, поиск
м
м
Строка 1: Строка 1:
 
[[Файл:Thin heap examples.png|200x200px|frame|Из [[Биномиальная куча#Биномиальное дерево|биномиального дерева]] ранга 3 получены два тонких дерева. Числа обозначают ранг вершин, черные вершины являются помеченными (не имеют самого левого сына).]]
 
[[Файл:Thin heap examples.png|200x200px|frame|Из [[Биномиальная куча#Биномиальное дерево|биномиального дерева]] ранга 3 получены два тонких дерева. Числа обозначают ранг вершин, черные вершины являются помеченными (не имеют самого левого сына).]]
'''''Тонкая куча''''' {{---}} это структура данных, реализующая приоритетную очередь с теми же асимптотическими оценками, что и [[Фибоначчиева куча|''фибоначчиева куча'']], но имеющая большую практическую ценность из-за меньших констант.
+
'''''Тонкая куча''''' {{---}} это структура данных, реализующая приоритетную очередь с теми же асимптотическими оценками, что и [[Фибоначчиева куча|фибоначчиева куча]], но имеющая большую практическую ценность из-за меньших констант.
  
''Тонкие кучи'', как и многие другие [[Двоичная куча|кучеобразные]] структуры, аналогичны [[Биномиальная куча|''биномиальным кучам'']].
+
Тонкие кучи, как и многие другие [[Двоичная куча|кучеобразные]] структуры, аналогичны [[Биномиальная куча|биномиальным кучам]].
 
= Тонкое дерево =
 
= Тонкое дерево =
  
Строка 25: Строка 25:
 
|id=about_thin_tree
 
|id=about_thin_tree
 
|statement=Тонкое дерево обладает следующими свойствами:
 
|statement=Тонкое дерево обладает следующими свойствами:
# Для любого узла <tex>x</tex> либо <tex>Degree(x)=Rank(x)</tex>, в этом случае говорим, что узел <tex>x</tex> не помечен (полный); либо <tex>Degree(x)=Rank(x)-1</tex>, в этом случае говорим, что узел <tex>x</tex> помечен (неполный).
+
# Для любого узла <tex>x</tex> либо <tex>Degree(x)=Rank(x)</tex>, в этом случае говорим, что узел <tex>x</tex> не помечен (полон); либо <tex>Degree(x)=Rank(x)-1</tex>, в этом случае говорим, что узел <tex>x</tex> помечен (не полон).
# Корень не помечен (полный).
+
# Корень не помечен (полон).
 
# Для любого узла <tex>x</tex> ранги его детей от самого правого к самому левому равны соответственно <tex>0,1,2,...,Degree(x)-1</tex>.
 
# Для любого узла <tex>x</tex> ранги его детей от самого правого к самому левому равны соответственно <tex>0,1,2,...,Degree(x)-1</tex>.
 
# Узел <tex>x</tex> помечен тогда и только тогда, когда его ранг на 2 больше, чем ранг его самого левого сына, или его ранг равен 1, и он не имеет детей.
 
# Узел <tex>x</tex> помечен тогда и только тогда, когда его ранг на 2 больше, чем ранг его самого левого сына, или его ранг равен 1, и он не имеет детей.
Строка 35: Строка 35:
 
{{Определение
 
{{Определение
 
|id=thin_forest_def
 
|id=thin_forest_def
|definition='''Тонкий лес''' (''thin forest'') {{---}} это набор ''тонких деревьев'', ранги которых не обязательно попарно различны.
+
|definition='''Тонкий лес''' (''thin forest'') {{---}} это набор тонких деревьев, ранги которых не обязательно попарно различны.
 
}}
 
}}
  
Строка 41: Строка 41:
 
|id=about_thin_forest_with_n_nodes
 
|id=about_thin_forest_with_n_nodes
 
|statement=Для любого натурального числа <tex>n</tex> существует тонкий лес, который содержит ровно <tex>n</tex> элементов и состоит из тонких деревьев попарно различных рангов.
 
|statement=Для любого натурального числа <tex>n</tex> существует тонкий лес, который содержит ровно <tex>n</tex> элементов и состоит из тонких деревьев попарно различных рангов.
|proof=Действительно, любой [[Биномиальная куча#Биномиальное дерево|биномиальный]] лес является тонким, а для [[Биномиальная куча#Биномиальное дерево|биномиального]] леса рассматриваемое утверждение справедливо.
+
|proof=Действительно, любой [[Биномиальная куча#Биномиальное дерево|биномиальный лес]] является тонким, а для биномиального леса рассматриваемое утверждение справедливо.
 
}}
 
}}
  
 
{{Определение
 
{{Определение
 
|id=thin_heap_def
 
|id=thin_heap_def
|definition='''Тонкая куча''' (''thin heap'') {{---}} это [[Двоичная куча|кучеобразно]] нагруженный ''тонкий лес''.
+
|definition='''Тонкая куча''' (''thin heap'') {{---}} это [[Двоичная куча|кучеобразно]] нагруженный тонкий лес, то есть значение в любой вершине тонкого дерева не превосходит значений в её потомках.
 
}}
 
}}
  
Строка 55: Строка 55:
 
|about=О максимальном ранге узла
 
|about=О максимальном ранге узла
 
|statement=В тонкой куче из <tex>n</tex> элементов <tex>D(n) \leqslant \log_{\Phi} n</tex>, где <tex dpi = "180">\Phi=\frac{1+\sqrt{5}}{2}</tex> {{---}} золотое сечение.
 
|statement=В тонкой куче из <tex>n</tex> элементов <tex>D(n) \leqslant \log_{\Phi} n</tex>, где <tex dpi = "180">\Phi=\frac{1+\sqrt{5}}{2}</tex> {{---}} золотое сечение.
|proof=Сначала покажем, что узел ранга <tex>k</tex> в тонком дереве имеет не менее <tex>F_k \geqslant \Phi^{k-1}</tex> потомков, включая самого себя, где <tex>F_k</tex> — <tex>k</tex>-е число Фибоначчи, определяемое соотношениями <tex>F_0=1</tex>, <tex>F_1=1</tex>, <tex>F_k=F_{k-2}+F_{k-1}</tex> для <tex>k \geqslant 2</tex>.
+
|proof=Сначала покажем, что узел ранга <tex>k</tex> в тонком дереве имеет не менее <tex>F_k \geqslant \Phi^{k-1}</tex> потомков, включая самого себя, где <tex>F_k</tex> — <tex>k</tex>-е число Фибоначчи.
  
Действительно, пусть <tex>T_k</tex> {{---}} минимально возможное число узлов, включая самого себя, в тонком дереве ранга <tex>k</tex>. По свойствам <tex>1</tex> и <tex>3</tex> ''тонкого дерева'' получаем следующие соотношения:
+
Действительно, пусть <tex>T_k</tex> {{---}} минимально возможное число узлов, включая самого себя, в тонком дереве ранга <tex>k</tex>. По свойствам <tex>1</tex> и <tex>3</tex> тонкого дерева получаем следующие соотношения:
  
 
<tex>T_0=1,T_1=1,T_k \geqslant 1+\sum_{i=0}^{k-2}T_i</tex> для <tex>k \geqslant 2</tex>
 
<tex>T_0=1,T_1=1,T_k \geqslant 1+\sum_{i=0}^{k-2}T_i</tex> для <tex>k \geqslant 2</tex>
Строка 63: Строка 63:
 
Числа Фибоначчи удовлетворяют этому же рекуррентному соотношению, причем неравенство можно заменить равенством. Отсюда по индукции следует, что <tex>T_k \geqslant F_k</tex> для любых <tex>k</tex>. Неравенство <tex>F_k \geqslant \Phi^{k-1}</tex> [[Фибоначчиева куча#Лемма3|хорошо известно]].
 
Числа Фибоначчи удовлетворяют этому же рекуррентному соотношению, причем неравенство можно заменить равенством. Отсюда по индукции следует, что <tex>T_k \geqslant F_k</tex> для любых <tex>k</tex>. Неравенство <tex>F_k \geqslant \Phi^{k-1}</tex> [[Фибоначчиева куча#Лемма3|хорошо известно]].
  
Теперь убедимся в том, что максимально возможный ранг <tex>D(n)</tex> ''тонкого дерева'' в тонкой куче, содержащей <tex>n</tex> элементов, не превосходит числа <tex>\log_{\Phi}(n)+1</tex>.  
+
Теперь убедимся в том, что максимально возможный ранг <tex>D(n)</tex> тонкого дерева в тонкой куче, содержащей <tex>n</tex> элементов, не превосходит числа <tex>\log_{\Phi}(n)+1</tex>.  
  
 
Действительно, выберем в тонкой куче дерево максимального ранга. Пусть <tex>n^*</tex> {{---}} количество вершин в этом дереве, тогда <tex>n \geqslant n^* \geqslant \Phi^{D(n)-1}</tex>.
 
Действительно, выберем в тонкой куче дерево максимального ранга. Пусть <tex>n^*</tex> {{---}} количество вершин в этом дереве, тогда <tex>n \geqslant n^* \geqslant \Phi^{D(n)-1}</tex>.
Строка 72: Строка 72:
 
== Представление тонкой кучи ==
 
== Представление тонкой кучи ==
  
''Тонкую кучу'' можно представить как [[Список#Односвязный список|односвязный список]] корней ''тонких деревьев'', причем корень с минимальным ключом должен быть первым в списке.
+
Тонкую кучу можно представить как [[Список#Односвязный список|односвязный список]] корней тонких деревьев, причем корень с минимальным ключом должен быть первым в списке.
  
Поскольку при работе с ''тонкой кучей'' ссылка на родителя требуется только у самого левого его ребенка, можно хранить ее вместо ссылки на левого брата этой вершины.  
+
Поскольку при работе с тонкой кучей ссылка на родителя требуется только у самого левого его ребенка, можно хранить ее вместо ссылки на левого брата этой вершины.  
  
Таким образом, для эффективной работы ''тонкой кучи'' необходимы следующие поля узла:
+
Таким образом, для эффективной работы тонкой кучи необходимы следующие поля узла:
 
*<tex>key</tex> {{---}} ключ (вес) элемента;
 
*<tex>key</tex> {{---}} ключ (вес) элемента;
 
*<tex>child</tex> {{---}} указатель на самого левого ребенка узла;
 
*<tex>child</tex> {{---}} указатель на самого левого ребенка узла;
Строка 83: Строка 83:
 
*<tex>rank</tex> {{---}} ранг узла (количество дочерних узлов данного узла).
 
*<tex>rank</tex> {{---}} ранг узла (количество дочерних узлов данного узла).
  
Для ускорения проверки на ''тонкость'' (''thinness'') можно отдельно хранить помеченность вершины.
+
Для ускорения проверки на тонкость (''thinness'') можно отдельно хранить помеченность вершины.
 
Также в вершине можно хранить любую дополнительную информацию.
 
Также в вершине можно хранить любую дополнительную информацию.
  
Для работы с ''тонкой кучей'' достаточно иметь [[Список#Односвязный список|односвязный список]] ее корней.  
+
Для работы с тонкой кучей достаточно иметь [[Список#Односвязный список|односвязный список]] ее корней.  
  
 
== Операции над тонкой кучей ==
 
== Операции над тонкой кучей ==
  
Рассмотрим операции, которые можно производить над ''тонкой кучей''. Время работы указано в таблице:
+
Рассмотрим операции, которые можно производить над тонкой кучей. Время работы указано в таблице:
 
{| border="1"
 
{| border="1"
 
  |-align="center"
 
  |-align="center"
Строка 115: Строка 115:
 
  |}
 
  |}
  
Многие операции над ''тонкой кучей'' выполняются так же, как и над [[Фибоначчиева куча|''фиббоначиевой'']].
+
Многие операции над тонкой кучей выполняются так же, как и над [[Фибоначчиева куча|фиббоначиевой]].
  
 
Для [[Амортизационный анализ|амортизационного анализа]] операций применим [[Амортизационный анализ#Метод потенциалов|метод потенциалов]].
 
Для [[Амортизационный анализ|амортизационного анализа]] операций применим [[Амортизационный анализ#Метод потенциалов|метод потенциалов]].
  
Пусть функция потенциала определена как <tex>\Phi = n + 2 \cdot m</tex> где <tex>n</tex> {{---}} это количество ''тонких деревьев'' в куче, а <tex>m</tex> {{---}} это количество помеченных вершин.
+
Пусть функция потенциала определена как <tex>\Phi = n + 2 \cdot m</tex> где <tex>n</tex> {{---}} это количество тонких деревьев в куче, а <tex>m</tex> {{---}} это количество помеченных вершин.
  
 
{{Утверждение
 
{{Утверждение
Строка 125: Строка 125:
 
|statement=Определённый таким образом потенциал обладает свойствами:
 
|statement=Определённый таким образом потенциал обладает свойствами:
 
# <tex>\Phi \geqslant 0</tex>.
 
# <tex>\Phi \geqslant 0</tex>.
# Для пустой ''тонкой кучи'' <tex>\Phi = 0</tex>.
+
# Для пустой тонкой кучи <tex>\Phi = 0</tex>.
 
}}
 
}}
 
   
 
   
Строка 166: Строка 166:
 
Пусть мы сделали <tex>ls</tex> связывающих шагов (''linking steps'') во время добавления в массив.
 
Пусть мы сделали <tex>ls</tex> связывающих шагов (''linking steps'') во время добавления в массив.
  
Мы удалили корень из списка за <tex>O(1)</tex>, затем за <tex>O(D(n))</tex> нормализовали детей корня и добавили в корневой список, далее за <tex>O(D(n))+O(ls)</tex> получили новый корневой список, в котором за <tex>O(D(n))</tex> нашли минимальный корень и подвесили список за него.
+
Мы удалили корень из списка за <tex>O(1)</tex>, затем за <tex>O(D(n))</tex> нормализовали детей корня и добавили в корневой список, далее за <tex>O(D(n))+ls</tex> получили новый корневой список, в котором за <tex>O(D(n))</tex> нашли минимальный корень и подвесили список за него.
  
Получили фактическую стоимость <tex>O(D(n))+O(ls)</tex>. С другой стороны, при добавлении детей в список мы увеличили потенциал <tex>\Phi</tex> не более чем на <tex>O(D(n))</tex>, а каждый связывающий шаг уменьшает наш потенциал <tex>\Phi</tex> на <tex>1</tex>.
+
Получили фактическую стоимость <tex>O(D(n))+ls</tex>. С другой стороны, при добавлении детей в список мы увеличили потенциал <tex>\Phi</tex> не более чем на <tex>O(D(n))</tex>, а каждый связывающий шаг уменьшает наш потенциал <tex>\Phi</tex> на <tex>1</tex>.
  
 
Cтоимость <tex>O(D(n))=O(\log(n))</tex>.
 
Cтоимость <tex>O(D(n))=O(\log(n))</tex>.

Версия 14:22, 2 июня 2013

Из биномиального дерева ранга 3 получены два тонких дерева. Числа обозначают ранг вершин, черные вершины являются помеченными (не имеют самого левого сына).

Тонкая куча — это структура данных, реализующая приоритетную очередь с теми же асимптотическими оценками, что и фибоначчиева куча, но имеющая большую практическую ценность из-за меньших констант.

Тонкие кучи, как и многие другие кучеобразные структуры, аналогичны биномиальным кучам.

Тонкое дерево

Определение:
Тонкое дерево (thin tree) [math]T_k[/math] ранга [math]k[/math] — это дерево, которое может быть получено из биномиального дерева [math]B_k[/math] удалением у нескольких внутренних, то есть не являющихся корнем или листом, узлов самого левого сына.


Ограничение на принадлежность внутренним узлам вызвано тем, что у листьев детей нет, а если у корня [math]B_k[/math] удалить самого левого сына, то [math]B_k[/math] превратится в [math]B_{k-1}[/math].

Утверждение:
Ранг тонкого дерева равен количеству детей его корня.

Для любого узла [math]x[/math] в дереве [math]T_k[/math] обозначим:

  • [math]Degree(x)[/math] — количество детей узла [math]x[/math].
  • [math]Rank(x)[/math] — ранг соответствующего узла в биномиальном дереве [math]B_k[/math].

Свойства тонкого дерева

Утверждение:
Тонкое дерево обладает следующими свойствами:
  1. Для любого узла [math]x[/math] либо [math]Degree(x)=Rank(x)[/math], в этом случае говорим, что узел [math]x[/math] не помечен (полон); либо [math]Degree(x)=Rank(x)-1[/math], в этом случае говорим, что узел [math]x[/math] помечен (не полон).
  2. Корень не помечен (полон).
  3. Для любого узла [math]x[/math] ранги его детей от самого правого к самому левому равны соответственно [math]0,1,2,...,Degree(x)-1[/math].
  4. Узел [math]x[/math] помечен тогда и только тогда, когда его ранг на 2 больше, чем ранг его самого левого сына, или его ранг равен 1, и он не имеет детей.

Тонкая куча

Определение:
Тонкий лес (thin forest) — это набор тонких деревьев, ранги которых не обязательно попарно различны.


Утверждение:
Для любого натурального числа [math]n[/math] существует тонкий лес, который содержит ровно [math]n[/math] элементов и состоит из тонких деревьев попарно различных рангов.
[math]\triangleright[/math]
Действительно, любой биномиальный лес является тонким, а для биномиального леса рассматриваемое утверждение справедливо.
[math]\triangleleft[/math]


Определение:
Тонкая куча (thin heap) — это кучеобразно нагруженный тонкий лес, то есть значение в любой вершине тонкого дерева не превосходит значений в её потомках.


Пусть [math]D(n)[/math] — максимально возможный ранг узла в тонкой куче, содержащей [math]n[/math] элементов.

Теорема (О максимальном ранге узла):
В тонкой куче из [math]n[/math] элементов [math]D(n) \leqslant \log_{\Phi} n[/math], где [math]\Phi=\frac{1+\sqrt{5}}{2}[/math] — золотое сечение.
Доказательство:
[math]\triangleright[/math]

Сначала покажем, что узел ранга [math]k[/math] в тонком дереве имеет не менее [math]F_k \geqslant \Phi^{k-1}[/math] потомков, включая самого себя, где [math]F_k[/math][math]k[/math]-е число Фибоначчи.

Действительно, пусть [math]T_k[/math] — минимально возможное число узлов, включая самого себя, в тонком дереве ранга [math]k[/math]. По свойствам [math]1[/math] и [math]3[/math] тонкого дерева получаем следующие соотношения:

[math]T_0=1,T_1=1,T_k \geqslant 1+\sum_{i=0}^{k-2}T_i[/math] для [math]k \geqslant 2[/math]

Числа Фибоначчи удовлетворяют этому же рекуррентному соотношению, причем неравенство можно заменить равенством. Отсюда по индукции следует, что [math]T_k \geqslant F_k[/math] для любых [math]k[/math]. Неравенство [math]F_k \geqslant \Phi^{k-1}[/math] хорошо известно.

Теперь убедимся в том, что максимально возможный ранг [math]D(n)[/math] тонкого дерева в тонкой куче, содержащей [math]n[/math] элементов, не превосходит числа [math]\log_{\Phi}(n)+1[/math].

Действительно, выберем в тонкой куче дерево максимального ранга. Пусть [math]n^*[/math] — количество вершин в этом дереве, тогда [math]n \geqslant n^* \geqslant \Phi^{D(n)-1}[/math].

Отсюда следует, что [math]D(n)\leqslant\log_{\Phi}(n)+1[/math].
[math]\triangleleft[/math]

Представление тонкой кучи

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

Поскольку при работе с тонкой кучей ссылка на родителя требуется только у самого левого его ребенка, можно хранить ее вместо ссылки на левого брата этой вершины.

Таким образом, для эффективной работы тонкой кучи необходимы следующие поля узла:

  • [math]key[/math] — ключ (вес) элемента;
  • [math]child[/math] — указатель на самого левого ребенка узла;
  • [math]right[/math] — указатель на правого брата узла, либо на следующий корень, если текущий узел корень;
  • [math]left[/math] — указатель на левого брата узла, либо на родителя, если текущий узел самый левый, либо null, если это корень;
  • [math]rank[/math] — ранг узла (количество дочерних узлов данного узла).

Для ускорения проверки на тонкость (thinness) можно отдельно хранить помеченность вершины. Также в вершине можно хранить любую дополнительную информацию.

Для работы с тонкой кучей достаточно иметь односвязный список ее корней.

Операции над тонкой кучей

Рассмотрим операции, которые можно производить над тонкой кучей. Время работы указано в таблице:

[math]makeHeap[/math] [math]O(1)[/math]
[math]insert[/math] [math]O(1)[/math]
[math]getMin[/math] [math]O(1)[/math]
[math]meld[/math] [math]O(1)[/math]
[math]extractMin[/math] [math]O(\log(n))[/math]
[math]decreaseKey[/math] [math]O(1)[/math]
[math]delete[/math] [math]O(\log(n))[/math]

Многие операции над тонкой кучей выполняются так же, как и над фиббоначиевой.

Для амортизационного анализа операций применим метод потенциалов.

Пусть функция потенциала определена как [math]\Phi = n + 2 \cdot m[/math] где [math]n[/math] — это количество тонких деревьев в куче, а [math]m[/math] — это количество помеченных вершин.

Утверждение:
Определённый таким образом потенциал обладает свойствами:
  1. [math]\Phi \geqslant 0[/math].
  2. Для пустой тонкой кучи [math]\Phi = 0[/math].

makeHeap

Для создания новой пустой тонкой кучи нужно вернуть ссылку на новый пустой корневой список, его потенциал [math]\Phi=0[/math].

Стоимость [math]O(1)[/math].

insert

Для вставки элемента в тонкую кучу нужно создать новое тонкое дерево из единственного узла с ключом [math]x[/math], добавить его в корневой список на первое место, если этот ключ минимален, иначе на второе. Потенциал [math]\Phi[/math] увеличивается на 1.

Стоимость [math]O(1)[/math].

getMin

Для обращения к минимальному элементу в тонкой куче нужно обратиться к первому корневому узлу списка и вернуть его ключ, потенциал [math]\Phi[/math] не меняется.

Стоимость [math]O(1)[/math].

meld

Для объединения тонких куч нужно слить их корневые списки, ставя первым тот список, у которого ключ первого корня минимален. Суммарный потенциал [math]\Phi[/math] не меняется.

Стоимость [math]O(1)[/math].

extractMin

Чтобы извлечь минимальный элемент из тонкой кучи нужно:

  1. Удалить корень с минимальным ключом из корневого списка.
  2. Уменьшить ранг для всех его помеченных детей.
  3. Cлить детей с корневым списком.
  4. Объединять, пока возможно, тонкие деревья одного ранга.

Это можно сделать, например, с помощью вспомогательного массива размером [math]O(D(n))[/math], в [math]i[/math]-ой ячейке которого хранится корень тонкого дерева [math]T_i[/math] ранга [math]i[/math].

Изначально массив пуст, а мы добавляем в него все деревья нашего корневого списка.

При добавлении нового дерева мы, если дерево такого ранга уже есть в массиве, связываем его с существующим и пытаемся добавить новое дерево с рангом на [math]1[/math] больше.

Пусть мы сделали [math]ls[/math] связывающих шагов (linking steps) во время добавления в массив.

Мы удалили корень из списка за [math]O(1)[/math], затем за [math]O(D(n))[/math] нормализовали детей корня и добавили в корневой список, далее за [math]O(D(n))+ls[/math] получили новый корневой список, в котором за [math]O(D(n))[/math] нашли минимальный корень и подвесили список за него.

Получили фактическую стоимость [math]O(D(n))+ls[/math]. С другой стороны, при добавлении детей в список мы увеличили потенциал [math]\Phi[/math] не более чем на [math]O(D(n))[/math], а каждый связывающий шаг уменьшает наш потенциал [math]\Phi[/math] на [math]1[/math].

Cтоимость [math]O(D(n))=O(\log(n))[/math].

decreaseKey

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

Теперь могут быть нарушены свойства тонкого дерева, будем различать два вида нарушений:

Назовем узел [math]y[/math] узлом локализации братского нарушения среди детей узла [math]z[/math], если ранг узла [math]y[/math] отличается от ранга его ближайшего правого брата на 2, либо он не имеет правого брата и его ранг равен 1.

Назовем узел [math]y[/math] узлом локализации родительского нарушения, если выполнено одно из трех условий:

  1. Ранг узла [math]y[/math] на три больше, чем ранг его самого левого сына.
  2. Ранг узла [math]y[/math] равен двум, и он не имеет детей.
  3. Узел [math]y[/math] есть помеченный корень дерева.

Пусть узел [math]y[/math] — это узел локализации братского нарушения.

  • Узел [math]y[/math] не помечен, тогда помещаем поддерево с корнем в самом левом сыне узла [math]y[/math] на место пропущенного в братском списке. Узел [math]y[/math] становится помеченным, дерево становится корректным, процедура исправления завершается.
  • Узел [math]y[/math] помечен, тогда уменьшаем ранг узла [math]y[/math] на единицу. Теперь узлом локализации нарушения будет либо левый брат узла [math]y[/math], либо его родитель, тогда нарушение станет родительским.

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

Пусть узел [math]y[/math] — это узел локализации родительского нарушения, а узел [math]z[/math] — родитель узла [math]y[/math].

Переместим все поддерево с корнем в [math]y[/math] в корневой список и уменьшим ранг [math]y[/math].

  • Узел [math]z[/math] не был помечен, пометим его, тогда дерево станет корректным.
  • Узел [math]z[/math] был помечен, тогда [math]z[/math] — новый узел локализации родительского нарушения, переходим к нему.

Продолжая эту процедуру, мы или остановимся, или дойдем до корня дерева, тогда достаточно сделать ранг корня на 1 больше ранга его самого левого сына.

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

Стоимость [math]O(1)[/math].

delete

Чтобы удалить элемент из тонкой кучи нужно сначала выполнить [math]decreaseKey[/math] этого элемента до [math]-\infty[/math], а затем выполнить [math]extractMin[/math].

Стоимость [math]O(\log(n))[/math].


Источники