403
правки
Изменения
→Фибоначчиевы кучи
Фибоначчиевы кучи поддерживают тот же набор операций, что и [[Биномиальная куча|биномиальные кучи]], но имеют то преимущество, что операции, в которых не требуется удаление, имеют амортизированное время работы, равное <tex>O(1)</tex>.
С теоретической точки зрения фибоначчиевы кучи особенно полезны в случае, когда количество операций <tex>ExtractMinextractMin</tex> и <tex>Deletedelete</tex> относительно мало по сравнению с количеством других операций. Однако с практической точки зрения программная сложность и высокие значения постоянных множителей в формулах времени работы существенно снижают эффективность применения фибоначчиевых куч, делая их в большинстве случаев менее привлекательными, чем обычные [[Двоичная куча|бинарные кучи]].
{{Определение
== Потенциал ==
Для анализа производительности операций введем потенциал для фибоначчиевой кучи <tex>H</tex> как <tex> \Phi(H) = t[H] + 2m[H] </tex>, где <tex> t[H] </tex> {{---}} количество элементов в корневом списке кучи, а <tex> m[H] </tex> {{---}} количество вершин, у которых удален один ребенок (то есть вершин с пометкой <tex> x.mark == true </tex>). Договоримся, что единицы потенциала достаточно для оплаты константного количества работы. На языке метода предоплаты это выглядит следующим образом: возле каждого корня лежит одна монета, а возле каждой вершины, у которой удалили ребенка, лежит две монеты.
== Операции ==
=== extractMin ===
Первая рассматриваемая операция, в ходе которой меняется структура кучи. Здесь используется вспомогательная процедура Consolidate ("уплотнение" кучи)<tex> consolidate </tex>. Возьмем указатель на <tex> H.min[H] </tex>, удалим эту вершину. Ее поддеревья (их не более, чем <tex> D[H] (n) </tex>, где <tex> D[H] (n) </tex> {{---}} максимальная степень вершины в куче) все положим в корневой списокобъединим с корневым списком. Теперь вызываем процедуру <tex> consolidate </tex>. После этой операции в списке корней остается не более чем <tex> D(n) + 1</tex> узлов, среди которых нужно найти минимальный. Итоговая асимптотика операции <tex>extraxtMin</tex>, учитывая и вспомогательную функцию <tex> consolidate </tex>, время работы которой доказывается ниже, равно: <tex> O(1)+O(D(n))+O(D(n))=O(D(n)) </tex>. Но по доказанной выше [[#Лемма4|лемме]] это <tex>O(\log(n))</tex>.
==== consolidate ====
Данная процедура принимает кучу, и делает из нее кучу, в корневом списке которой не более <tex> OD(D[H]n) </tex> вершин.
Для этого возьмем массив списков указателей на корни деревьев <tex> A[0..D[H]] </tex>, где <tex> D[H] </tex> {{---}} максимальная степень вершины в текущем корневом списке. Далее мы увидим, что <tex> D[H] = O(logN) </tex>.
Затем происходит [[Биномиальная_куча#Union | процесс, аналогичный слиянию биномиальных куч ]]: добавляем поочередно каждый корень, смотря на его степень. Пусть она равна <tex> d </tex>. Если в соответствующей ячейке A еще нету вершины, записываем текущую вершину туда. Иначе подвешиваем одно дерево к другому, и пытаемся также добавить дерево, степень корня которого уже равна <tex> d + 1 </tex>. Продолжаем, пока не найдем свободную ячейку.
Учетная стоимость <tex> Consolidate consolidate </tex> равна <tex> O(D[H](n)) </tex>. Докажем это:
=== decreaseKey ===