<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=217.66.156.128&amp;*</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=217.66.156.128&amp;*"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/217.66.156.128"/>
		<updated>2026-05-19T17:59:55Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B1%D0%BE%D0%BD%D0%B0%D1%87%D1%87%D0%B8%D0%B5%D0%B2%D0%B0_%D0%BA%D1%83%D1%87%D0%B0&amp;diff=46767</id>
		<title>Фибоначчиева куча</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B1%D0%BE%D0%BD%D0%B0%D1%87%D1%87%D0%B8%D0%B5%D0%B2%D0%B0_%D0%BA%D1%83%D1%87%D0%B0&amp;diff=46767"/>
				<updated>2015-05-21T16:01:18Z</updated>
		
		<summary type="html">&lt;p&gt;217.66.156.128: /* cascadingCut */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Фибоначчиево дерево ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Фибоначчиево дерево''' (англ. ''Fibonacci tree'') {{---}} [[Биномиальная куча#Биномиальное дерево |биномиальное дерево]], где у каждой вершины удалено не более одного ребенка.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Порядок фибоначчиева дерева''' (англ. ''Fibonacci tree rank'') {{---}} порядок соответствующего биномиального дерева, из которого оно получено.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Степень вершины''' (англ. ''degree'')  {{---}} количество дочерних узлов данной вершины.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма1&lt;br /&gt;
|statement=Для всех целых &amp;lt;tex&amp;gt; n \geqslant 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt; F_n = 1 + \sum\limits_{i=0}^{n-2} F_i &amp;lt;/tex&amp;gt;,&lt;br /&gt;
где &amp;lt;tex&amp;gt; F_n &amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt;-ое число Фибоначчи, определяемое формулой:&lt;br /&gt;
&amp;lt;tex&amp;gt;&lt;br /&gt;
F_n =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
 0, &amp;amp; n = 0 \\&lt;br /&gt;
 1, &amp;amp; n = 1 \\&lt;br /&gt;
 F_{n-1} + F_{n-2}, &amp;amp; n \geqslant 2&lt;br /&gt;
\end{cases} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Докажем лемму по индукции:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;tex&amp;gt;n = 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_2 = 1 + \sum\limits_{i=0}^0 F_i = 1 + 0 = 1&amp;lt;/tex&amp;gt;, что действительно верно.&lt;br /&gt;
&lt;br /&gt;
По индукции предполагаем, что &amp;lt;tex&amp;gt;F_{n-1} = 1 + \sum\limits_{i=0}^{n-3} F_i &amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_n = F_{n-1} + F_{n-2} = 1 + \sum\limits_{i=0}^{n-3} F_i + F_{n-2} = 1 + \sum\limits_{i=0}^{n-2} F_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма2&lt;br /&gt;
|statement= Фибоначчиево дерево порядка &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; содержит не менее &amp;lt;tex&amp;gt;F_n&amp;lt;/tex&amp;gt; вершин.&lt;br /&gt;
|proof=&lt;br /&gt;
Докажем это утверждение по индукции.&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;s_n&amp;lt;/tex&amp;gt; {{---}} минимальный размер фибоначчиева дерева порядка &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_0 = 1 &amp;gt; F_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_1 = 1 = F_1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предположим по индукции, что для всех &amp;lt;tex&amp;gt;i &amp;lt; n \ s_i \geqslant F_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Пусть в нашем дереве удалено поддерево порядка &amp;lt;tex&amp;gt;n - 1&amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_n = 1 + \sum\limits_{i=0}^{n-2} s_i \geqslant 1 + \sum\limits_{i=0}^{n-2} F_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Но по предыдущей [[#Лемма1|лемме]] :&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;tex&amp;gt;1 + \sum\limits_{i=0}^{n-2} F_i = F_n&amp;lt;/tex&amp;gt;. Следовательно, &amp;lt;tex&amp;gt;s_n \geqslant F_n&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Фибоначчиева куча ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Фибоначчиева куча''' (англ. ''Fibonacci heap'')   {{---}} набор фибоначчиевых деревьев, корни которых объединены в неупорядоченный [[Список#Циклический список |циклический]] [[Список#Двусвязный список | двусвязный список]]. В отличие от [[Биномиальная куча|биномиальной кучи]], степени корней не обязаны быть попарно различными.&lt;br /&gt;
}}&lt;br /&gt;
Фибоначчиевы кучи поддерживают тот же набор операций, что и биномиальные кучи, но имеют то преимущество, что операции, в которых не требуется удаление, имеют [[Амортизационный анализ|амортизированное]] время работы, равное &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
С теоретической точки зрения фибоначчиевы кучи особенно полезны в случае, когда количество операций &amp;lt;tex&amp;gt;\mathrm {extractMin}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt; относительно мало по сравнению с количеством других операций. Однако с практической точки зрения программная сложность и высокие значения постоянных множителей в формулах времени работы  существенно снижают эффективность применения фибоначчиевых куч, делая их в большинстве случаев менее привлекательными, чем обычные [[Двоичная куча|бинарные кучи]].&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма3&lt;br /&gt;
|statement= &amp;lt;tex&amp;gt;F_n =\Theta(\varphi^n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt; \varphi = \frac {1 + \sqrt 5} {2}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Для начала докажем, что &amp;lt;tex&amp;gt;F_n =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^n - (-\varphi)^{-n}} {\sqrt 5}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Используем для этого математическую индукцию.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_0 =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^0 - (-\varphi)^0} {\sqrt 5} = \frac {1 - 1} {\sqrt 5} = 0&amp;lt;/tex&amp;gt;, что верно.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_1 =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^1 - (-\varphi)^{-1}} {\sqrt 5} = \frac {1} {\sqrt 5}(\frac {1 + \sqrt 5} {2} - \frac {1 - \sqrt 5} {2}) = \frac {2\sqrt 5} {2\sqrt 5} = 1&amp;lt;/tex&amp;gt;, что также верно.&lt;br /&gt;
&lt;br /&gt;
По индукции предполагаем, что &amp;lt;tex&amp;gt;F_{n-1} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-1} - (-\varphi)^{1-n}} {\sqrt 5}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;F_{n-2} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-2} - (-\varphi)^{2-n}} {\sqrt 5}&amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_n = F_{n-1} + F_{n-2} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-1} - (-\varphi)^{1-n}} {\sqrt 5} + \frac {\varphi^{n-2} - (-\varphi)^{2-n}} {\sqrt 5} =&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;= \frac {1} {\sqrt 5}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(\varphi^{n-1} - (-\varphi)^{1-n} + \varphi^{n-2} - (-\varphi)^{2-n}) &amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;= \frac {1} {\sqrt 5}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(\varphi^{n}(\varphi^{-1} + \varphi^{-2}) - (-\varphi)^{-n}(-\varphi + \varphi^{2}))&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подставив вместо &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; его значение, нетрудно убедится, что &amp;lt;tex&amp;gt;\varphi^{-1} + \varphi^{-2} = -\varphi + \varphi^{2} = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Поскольку &amp;lt;tex&amp;gt;\left\vert (-\varphi)^{-1} \right\vert &amp;lt; 1&amp;lt;/tex&amp;gt;, то выполняются неравенства &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {(-\varphi)^{-n}} {\sqrt 5} &amp;lt; \frac {1} {\sqrt 5} &amp;lt; \frac {1} {2}&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;-ое число Фибоначчи равно &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n}} {\sqrt 5}&amp;lt;/tex&amp;gt;, округленному до ближайшего целого числа. Следовательно, &amp;lt;tex&amp;gt;F_n =\Theta(\varphi^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма4&lt;br /&gt;
|statement=Максимальная степень &amp;lt;tex&amp;gt;D(n)&amp;lt;/tex&amp;gt; произвольной вершины в фибоначчиевой куче с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершинами равна &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; {{---}} произвольная вершина в фибоначчиевой куче с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершинами, и пусть &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; {{---}} степень вершины &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;. Тогда по [[#Лемма2|доказанному выше]] в дереве, корень которого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, содержится не менее &amp;lt;tex&amp;gt;F_k&amp;lt;/tex&amp;gt; вершин, что в свою очередь по [[#Лемма3|лемме]] равно &amp;lt;tex&amp;gt;\Theta(\varphi^k)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
То есть&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;n \geqslant \varphi^{k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Логарифмируя по основанию &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt;, получаем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\log_{\varphi}n \geqslant k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом, максимальная степень &amp;lt;tex&amp;gt;D(n)&amp;lt;/tex&amp;gt; произвольной вершины равна &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Структура ===&lt;br /&gt;
====Структура узла====&lt;br /&gt;
Каждый узел &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; в куче &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; содержит следующие указатели и поля:&lt;br /&gt;
 '''struct''' Node&lt;br /&gt;
    '''int''' key &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;     // ключ&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' p &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;      // указатель на родительский узел&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' child &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;  // указатель на один из дочерних узлов&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' left &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;   // указатель  на левый сестринский узел&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' right &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;  // указатель на правый сестринский узел&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''int''' degree &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;  // количество дочерних узлов&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''boolean''' mark &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// флаг, который показывает, удаляли ли мы дочерние узлы данной вершины&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Структура кучи====&lt;br /&gt;
 '''struct''' Heap&lt;br /&gt;
    '''int''' size &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// текущее количество узлов&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' min &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// указатель на корень дерева с минимальным ключом&amp;lt;/span&amp;gt;&lt;br /&gt;
====Структура списка детей====&lt;br /&gt;
[[File:Fibonacci-heap.png|thumb|340px|Пример фибоначчиевой кучи]]&lt;br /&gt;
* Дочерние узлы &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; объединены при помощи указателей &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; в  [[Список#Циклический список |циклический]] [[Список#Двусвязный список | двусвязный список]].&lt;br /&gt;
* Корни всех деревьев в &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; связаны при помощи указателей &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; в [[Список#Циклический список |циклический]] [[Список#Двусвязный список | двусвязный список]] корней.&lt;br /&gt;
&lt;br /&gt;
[[Список#Циклический список |Циклический]] [[Список#Двусвязный список | двусвязный список]] обладает двумя преимуществами для использования в фибоначчиевых кучах. Во-первых, удаление элемента из такого списка выполняется за время &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;. Во-вторых, если имеется два таких списка, их легко объединить в один за время &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Потенциал ===&lt;br /&gt;
&lt;br /&gt;
Для анализа производительности операций введем потенциал для фибоначчиевой кучи &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; как &amp;lt;tex&amp;gt; \Phi(H) = t[H] + 2m[H] &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; t[H] &amp;lt;/tex&amp;gt; {{---}} количество элементов в корневом списке кучи, а &amp;lt;tex&amp;gt; m[H] &amp;lt;/tex&amp;gt; {{---}} количество вершин, у которых удален один ребенок (то есть вершин с пометкой &amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt;). Договоримся, что единицы потенциала достаточно для оплаты константного количества работы.&lt;br /&gt;
&lt;br /&gt;
=== Операции ===&lt;br /&gt;
Рассмотрим операции, которые поддерживают фибоначчиевы кучи. Амортизированное время их работы показано в таблице.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Операция&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Амортизированная сложность&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {makeHeap}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {insert}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {getMin}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {merge}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {extractMin}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(\log n )&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {decreaseKey}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(\log n )&amp;lt;/tex&amp;gt; &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Стоит заметить, что структура фибоначчиевых куч, также как биномиальных и бинарных, не могут обеспечить эффективную реализацию поиска элемента с заданным ключом, поэтому операции &amp;lt;tex&amp;gt;\mathrm {decreaseKey}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt; получают в качестве аргумента указатель на узел, а не значение его ключа.&lt;br /&gt;
&lt;br /&gt;
==== makeHeap ====&lt;br /&gt;
&lt;br /&gt;
Создается новый пустой корневой [[Список#Двусвязный список | список]], в &amp;lt;tex&amp;gt; H.min &amp;lt;/tex&amp;gt; устанавливается значение &amp;lt;tex&amp;gt; null &amp;lt;/tex&amp;gt;. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== insert ====&lt;br /&gt;
&lt;br /&gt;
Вставка элемента в фибоначчиеву кучу также тривиальна: создается новая куча из одного элемента и сливается с текущей. Для оценки амортизированной стоимости операции рассмотрим исходную кучу &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; и получившуюся в результате вставки нового элемента кучу &amp;lt;tex&amp;gt; H' &amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt; t[H'] = t[H] + 1 &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; m[H'] = m[H] &amp;lt;/tex&amp;gt;. Следовательно, увеличение потенциала составляет &amp;lt;tex&amp;gt; (t[H] + 1 + 2m[H]) - (t[H] + 2m[H]) = 1 &amp;lt;/tex&amp;gt;. Так как реальное время работы составляет &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, то амортизированная стоимость данной операции также равна &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== getMin ====&lt;br /&gt;
Возвращает указатель &amp;lt;tex&amp;gt;H.min&amp;lt;/tex&amp;gt;. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== merge ====&lt;br /&gt;
&lt;br /&gt;
Слияние двух фибоначчиевых куч происходит просто: объединяем списки этих куч в один, релаксируем минимум. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Амортизированное время работы также &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, поскольку, при объединении двух куч в одну, потенциалы обеих куч суммируются, итоговая сумма потенциалов не изменяется, &amp;lt;tex&amp;gt; \Phi_{n + 1} - \Phi_n = 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== extractMin ====&lt;br /&gt;
&lt;br /&gt;
Первая рассматриваемая операция, в ходе которой меняется структура кучи. Здесь используется вспомогательная процедура &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;. Возьмем указатель на &amp;lt;tex&amp;gt; H.min &amp;lt;/tex&amp;gt;, удалим эту вершину. Ее поддеревья (их не более, чем &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt; {{---}}  максимальная степень вершины в куче) объединим с корневым списком. Теперь вызываем процедуру &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;. После этой операции в списке корней остается не более чем &amp;lt;tex&amp;gt; D(n) + 1&amp;lt;/tex&amp;gt; узлов, среди которых нужно найти минимальный. Итоговая асимптотика операции &amp;lt;tex&amp;gt;\mathrm {extraxtMin}&amp;lt;/tex&amp;gt;, учитывая и вспомогательную функцию &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;, время работы которой доказывается ниже, равно: &amp;lt;tex&amp;gt; O(1)+O(D(n))+O(D(n))=O(D(n)) &amp;lt;/tex&amp;gt;. По доказанной выше [[#Лемма4|лемме]] &amp;lt;tex&amp;gt;O(D(n)) = O(\log(n))&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===== consolidate =====&lt;br /&gt;
&lt;br /&gt;
Данная процедура принимает кучу и преобразует ее таким образом, что в корневом списке остается не более &amp;lt;tex&amp;gt; D(n) + 1&amp;lt;/tex&amp;gt; вершин.&lt;br /&gt;
&lt;br /&gt;
Для этого возьмем массив списков указателей на корни деревьев &amp;lt;tex&amp;gt; A[0..D[H]] &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; D[H] &amp;lt;/tex&amp;gt; {{---}} максимальная степень вершины в текущем корневом списке.&lt;br /&gt;
&lt;br /&gt;
Затем происходит [[Биномиальная_куча#merge | процесс, аналогичный слиянию биномиальных куч]]: добавляем поочередно каждый корень, смотря на его степень. Пусть она равна &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;. Если в соответствующей ячейке &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; еще нету вершины, записываем текущую вершину туда. Иначе подвешиваем одно дерево к другому, и пытаемся также добавить дерево, степень корня которого уже равна &amp;lt;tex&amp;gt; d + 1 &amp;lt;/tex&amp;gt;. Продолжаем, пока не найдем свободную ячейку.&lt;br /&gt;
&lt;br /&gt;
Учетная стоимость &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt; равна &amp;lt;tex&amp;gt; O(D(n)) &amp;lt;/tex&amp;gt;. Докажем это:&lt;br /&gt;
&lt;br /&gt;
Изначально в корневом списке было не более &amp;lt;tex&amp;gt; D(n) + t[H] - 1 &amp;lt;/tex&amp;gt; вершин, поскольку он состоит из исходного списка корней с &amp;lt;tex&amp;gt;t[H]&amp;lt;/tex&amp;gt; узлами, минус извлеченный узел и плюс дочерние узлы, количество которых не превышает &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt;. В ходе операции &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt; мы сделали &amp;lt;tex&amp;gt; O(D(n) + t[H]) &amp;lt;/tex&amp;gt; слияний деревьев. Потенциал перед извлечением минимума равен &amp;lt;tex&amp;gt; t[H] + 2m[H] &amp;lt;/tex&amp;gt;, а после не превышает &amp;lt;tex&amp;gt; D(n) + 1 + 2m[H] &amp;lt;/tex&amp;gt;, поскольку в корневом списке остается не более  &amp;lt;tex&amp;gt; D(n) + 1 &amp;lt;/tex&amp;gt; узлов, а количество помеченных узлов не изменяется. Таким образом, амортизированная стоимость не превосходит&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; O(D(n) + t[H]) + (D(n) + 1 + 2m[H]) - (t[H] + 2m[H]) = O(D(n)) + O(t[H]) - t[H]&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Поскольку мы договорились, что можем масштабировать единицу потенциала таким образом, чтобы покрывать константное количество работы, то итоговая амортизационная оценка {{---}} &amp;lt;tex&amp;gt; O(D(n)) &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== decreaseKey ====&lt;br /&gt;
&lt;br /&gt;
Основная идея: хотим, чтобы учетная стоимость данной операции была &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Было бы хорошо, чтобы вершина не всплывала до корня, и тогда дерево не придется сильно перестраивать. Для этого при удобном случае будем вырезать поддерево полностью и перемещать его в корневой [[Список |список]]. Итак, сам алгоритм:&lt;br /&gt;
&lt;br /&gt;
# Проверяем, если новое значение ключа все же не меньше значения ключа родителя, то все хорошо, и мы выходим.&lt;br /&gt;
# Иначе, вырезаем дерево с текущей вершиной в корневой [[Список |список]], и производим каскадное вырезание родителя. &lt;br /&gt;
&lt;br /&gt;
===== cut =====&lt;br /&gt;
&lt;br /&gt;
При вырезании вершины мы удаляем ее из списка детей своего родителя, уменьшаем степень ее родителя (&amp;lt;tex&amp;gt; x.p.degree &amp;lt;/tex&amp;gt;) и снимаем пометку с текущей вершины (&amp;lt;tex&amp;gt; x.mark = false &amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
===== cascadingCut =====&lt;br /&gt;
&lt;br /&gt;
[[File:Каскадное вырезание.png|thumb|500px|Пример каскадного вырезания]]&lt;br /&gt;
&lt;br /&gt;
Перед вызовом каскадного вырезания нам известно, удаляли ли ребенка у этой вершины. Если у вершины до этого не удаляли дочерний узел (&amp;lt;tex&amp;gt; x.mark = false &amp;lt;/tex&amp;gt;), то мы помечаем эту вершину (&amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt;) и прекращаем выполнение операции. В противном случае применяем операцию &amp;lt;tex&amp;gt;\mathrm {cut}&amp;lt;/tex&amp;gt; для текущей вершины и запускаем каскадное вырезание от родителя.&lt;br /&gt;
&lt;br /&gt;
'''Пример'''&lt;br /&gt;
&lt;br /&gt;
Рисунок иллюстрирует пример каскадного вырезания:&lt;br /&gt;
&lt;br /&gt;
* Изначально, куча состояла из &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; фибоначчиевых деревьев. У вершины с ключом &amp;lt;tex&amp;gt;24&amp;lt;/tex&amp;gt; отсутствует &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; ребенок.&lt;br /&gt;
* Уменьшаем ключ &amp;lt;tex&amp;gt;26&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; и делаем операцию &amp;lt;tex&amp;gt;\mathrm {cut}&amp;lt;/tex&amp;gt; этого дерева. Получаем кучу с &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt; деревьями и новым минимумом. Но у вершины с ключом &amp;lt;tex&amp;gt;24&amp;lt;/tex&amp;gt; был удален второй ребенок, поэтому запускам операцию &amp;lt;tex&amp;gt;\mathrm {cascadingCut}&amp;lt;/tex&amp;gt; для этой вершины: вырезаем ее, помещаем в корневой [[Список |список]] и помечаем ее родителя.&lt;br /&gt;
* У вершины с ключом &amp;lt;tex&amp;gt;7&amp;lt;/tex&amp;gt; удален лишь один ребенок, поэтому операция &amp;lt;tex&amp;gt;\mathrm {cascadingCut}&amp;lt;/tex&amp;gt; от нее не запускается. В итоге, получаем кучу, состоящую из &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; фибоначчиевых деревьев.&lt;br /&gt;
&lt;br /&gt;
===== Время работы =====&lt;br /&gt;
&lt;br /&gt;
Докажем, что амортизированное время работы операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; есть &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Поскольку в процедуре нет циклов, ее время работы определяется лишь количеством рекурсивных вызовов каскадного вырезания.&lt;br /&gt;
&lt;br /&gt;
Пусть мы вызвали процедуру каскадного вырезания &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; раз. Так как реальное время работы операции &amp;lt;tex&amp;gt; \mathrm {cascadingCut} &amp;lt;/tex&amp;gt; без учета рекурсии составляет &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, то реальное время работы операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt; O(k) &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Рассмотрим, как изменится потенциал в результате выполнения данной операции. Пусть &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; {{---}} фибоначчиева куча до вызова &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt;. Тогда после &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; рекурсивных вызовов операции &amp;lt;tex&amp;gt; \mathrm {cascadingCut} &amp;lt;/tex&amp;gt; вершин с пометкой &amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt; стало как минимум на &amp;lt;tex&amp;gt; k - 2 &amp;lt;/tex&amp;gt; меньше, потому что каждый вызов каскадного вырезания, за исключением последнего, уменьшает количество помеченных вершин на одну, и в результате последнего вызова одну вершину мы можем пометить. В корневом списке прибавилось &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; новых деревьев (&amp;lt;tex&amp;gt; k - 1 &amp;lt;/tex&amp;gt; дерево за счет каскадного вырезания и еще одно из-за самого первого вызова операции &amp;lt;tex&amp;gt; \mathrm {cut} &amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
В итоге, изменение потенциала составляет: &amp;lt;tex&amp;gt; \Phi_i - \Phi_{i - 1} = ((t[H] + k) + 2(m[H] + k - 2)) - (t[H] + 2m[H]) = 4 - k &amp;lt;/tex&amp;gt;. Следовательно, амортизированная стоимость не превышает &amp;lt;tex&amp;gt; O(k) + 4 - k &amp;lt;/tex&amp;gt;. Но поскольку мы можем соответствующим образом масштабировать единицы потенциала, то амортизированная стоимость операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; равна &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== delete ====&lt;br /&gt;
&lt;br /&gt;
Удаление вершины реализуется через уменьшение ее ключа до &amp;lt;tex&amp;gt; -\infty &amp;lt;/tex&amp;gt; и последующим извлечением минимума. Амортизированное время работы: &amp;lt;tex&amp;gt; O(1) + O(D(n)) = O(D(n)) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Поскольку ранее мы показали, что &amp;lt;tex&amp;gt; D(n) = O(\log n ) &amp;lt;/tex&amp;gt;, то соответствующие оценки доказаны.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Левосторонняя куча]]&lt;br /&gt;
* [[Тонкая куча]]&lt;br /&gt;
* [[Толстая куча на избыточном счетчике]]&lt;br /&gt;
* [[Куча Бродала-Окасаки]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
&lt;br /&gt;
* Томас Кормен, Чарльз Лейзерсон, Рональд Ривест, Клиффорд Штайн — Алгоритмы: построение и анализ. — М.: Издательский дом «Вильямс», 2005. — С. 1296. — ISBN 5-8459-0857-4&lt;br /&gt;
* [[wikipedia:ru:Числа Фибоначчи|Числа Фибоначчи {{---}} Википедия]]&lt;br /&gt;
* [[wikipedia:ru:Фибоначчиева куча|Фибоначчиева куча {{---}} Википедия]]&lt;br /&gt;
* [http://www.intuit.ru/department/algorithms/dscm/7/2.html Фибоначчиевы кучи — INTUIT.ru]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/heaps Визуализаторы]&lt;br /&gt;
* [http://www.cs.duke.edu/courses/fall05/cps230/L-11.pdf Fibonacci Heaps]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Приоритетные очереди]]&lt;/div&gt;</summary>
		<author><name>217.66.156.128</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B1%D0%BE%D0%BD%D0%B0%D1%87%D1%87%D0%B8%D0%B5%D0%B2%D0%B0_%D0%BA%D1%83%D1%87%D0%B0&amp;diff=46766</id>
		<title>Фибоначчиева куча</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B1%D0%BE%D0%BD%D0%B0%D1%87%D1%87%D0%B8%D0%B5%D0%B2%D0%B0_%D0%BA%D1%83%D1%87%D0%B0&amp;diff=46766"/>
				<updated>2015-05-21T16:00:46Z</updated>
		
		<summary type="html">&lt;p&gt;217.66.156.128: /* decreaseKey */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Фибоначчиево дерево ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Фибоначчиево дерево''' (англ. ''Fibonacci tree'') {{---}} [[Биномиальная куча#Биномиальное дерево |биномиальное дерево]], где у каждой вершины удалено не более одного ребенка.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Порядок фибоначчиева дерева''' (англ. ''Fibonacci tree rank'') {{---}} порядок соответствующего биномиального дерева, из которого оно получено.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Степень вершины''' (англ. ''degree'')  {{---}} количество дочерних узлов данной вершины.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма1&lt;br /&gt;
|statement=Для всех целых &amp;lt;tex&amp;gt; n \geqslant 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt; F_n = 1 + \sum\limits_{i=0}^{n-2} F_i &amp;lt;/tex&amp;gt;,&lt;br /&gt;
где &amp;lt;tex&amp;gt; F_n &amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt;-ое число Фибоначчи, определяемое формулой:&lt;br /&gt;
&amp;lt;tex&amp;gt;&lt;br /&gt;
F_n =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
 0, &amp;amp; n = 0 \\&lt;br /&gt;
 1, &amp;amp; n = 1 \\&lt;br /&gt;
 F_{n-1} + F_{n-2}, &amp;amp; n \geqslant 2&lt;br /&gt;
\end{cases} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Докажем лемму по индукции:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;tex&amp;gt;n = 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_2 = 1 + \sum\limits_{i=0}^0 F_i = 1 + 0 = 1&amp;lt;/tex&amp;gt;, что действительно верно.&lt;br /&gt;
&lt;br /&gt;
По индукции предполагаем, что &amp;lt;tex&amp;gt;F_{n-1} = 1 + \sum\limits_{i=0}^{n-3} F_i &amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_n = F_{n-1} + F_{n-2} = 1 + \sum\limits_{i=0}^{n-3} F_i + F_{n-2} = 1 + \sum\limits_{i=0}^{n-2} F_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма2&lt;br /&gt;
|statement= Фибоначчиево дерево порядка &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; содержит не менее &amp;lt;tex&amp;gt;F_n&amp;lt;/tex&amp;gt; вершин.&lt;br /&gt;
|proof=&lt;br /&gt;
Докажем это утверждение по индукции.&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;s_n&amp;lt;/tex&amp;gt; {{---}} минимальный размер фибоначчиева дерева порядка &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_0 = 1 &amp;gt; F_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_1 = 1 = F_1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предположим по индукции, что для всех &amp;lt;tex&amp;gt;i &amp;lt; n \ s_i \geqslant F_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Пусть в нашем дереве удалено поддерево порядка &amp;lt;tex&amp;gt;n - 1&amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_n = 1 + \sum\limits_{i=0}^{n-2} s_i \geqslant 1 + \sum\limits_{i=0}^{n-2} F_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Но по предыдущей [[#Лемма1|лемме]] :&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;tex&amp;gt;1 + \sum\limits_{i=0}^{n-2} F_i = F_n&amp;lt;/tex&amp;gt;. Следовательно, &amp;lt;tex&amp;gt;s_n \geqslant F_n&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Фибоначчиева куча ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Фибоначчиева куча''' (англ. ''Fibonacci heap'')   {{---}} набор фибоначчиевых деревьев, корни которых объединены в неупорядоченный [[Список#Циклический список |циклический]] [[Список#Двусвязный список | двусвязный список]]. В отличие от [[Биномиальная куча|биномиальной кучи]], степени корней не обязаны быть попарно различными.&lt;br /&gt;
}}&lt;br /&gt;
Фибоначчиевы кучи поддерживают тот же набор операций, что и биномиальные кучи, но имеют то преимущество, что операции, в которых не требуется удаление, имеют [[Амортизационный анализ|амортизированное]] время работы, равное &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
С теоретической точки зрения фибоначчиевы кучи особенно полезны в случае, когда количество операций &amp;lt;tex&amp;gt;\mathrm {extractMin}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt; относительно мало по сравнению с количеством других операций. Однако с практической точки зрения программная сложность и высокие значения постоянных множителей в формулах времени работы  существенно снижают эффективность применения фибоначчиевых куч, делая их в большинстве случаев менее привлекательными, чем обычные [[Двоичная куча|бинарные кучи]].&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма3&lt;br /&gt;
|statement= &amp;lt;tex&amp;gt;F_n =\Theta(\varphi^n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt; \varphi = \frac {1 + \sqrt 5} {2}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Для начала докажем, что &amp;lt;tex&amp;gt;F_n =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^n - (-\varphi)^{-n}} {\sqrt 5}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Используем для этого математическую индукцию.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_0 =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^0 - (-\varphi)^0} {\sqrt 5} = \frac {1 - 1} {\sqrt 5} = 0&amp;lt;/tex&amp;gt;, что верно.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_1 =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^1 - (-\varphi)^{-1}} {\sqrt 5} = \frac {1} {\sqrt 5}(\frac {1 + \sqrt 5} {2} - \frac {1 - \sqrt 5} {2}) = \frac {2\sqrt 5} {2\sqrt 5} = 1&amp;lt;/tex&amp;gt;, что также верно.&lt;br /&gt;
&lt;br /&gt;
По индукции предполагаем, что &amp;lt;tex&amp;gt;F_{n-1} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-1} - (-\varphi)^{1-n}} {\sqrt 5}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;F_{n-2} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-2} - (-\varphi)^{2-n}} {\sqrt 5}&amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_n = F_{n-1} + F_{n-2} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-1} - (-\varphi)^{1-n}} {\sqrt 5} + \frac {\varphi^{n-2} - (-\varphi)^{2-n}} {\sqrt 5} =&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;= \frac {1} {\sqrt 5}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(\varphi^{n-1} - (-\varphi)^{1-n} + \varphi^{n-2} - (-\varphi)^{2-n}) &amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;= \frac {1} {\sqrt 5}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(\varphi^{n}(\varphi^{-1} + \varphi^{-2}) - (-\varphi)^{-n}(-\varphi + \varphi^{2}))&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подставив вместо &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; его значение, нетрудно убедится, что &amp;lt;tex&amp;gt;\varphi^{-1} + \varphi^{-2} = -\varphi + \varphi^{2} = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Поскольку &amp;lt;tex&amp;gt;\left\vert (-\varphi)^{-1} \right\vert &amp;lt; 1&amp;lt;/tex&amp;gt;, то выполняются неравенства &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {(-\varphi)^{-n}} {\sqrt 5} &amp;lt; \frac {1} {\sqrt 5} &amp;lt; \frac {1} {2}&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;-ое число Фибоначчи равно &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n}} {\sqrt 5}&amp;lt;/tex&amp;gt;, округленному до ближайшего целого числа. Следовательно, &amp;lt;tex&amp;gt;F_n =\Theta(\varphi^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма4&lt;br /&gt;
|statement=Максимальная степень &amp;lt;tex&amp;gt;D(n)&amp;lt;/tex&amp;gt; произвольной вершины в фибоначчиевой куче с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершинами равна &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; {{---}} произвольная вершина в фибоначчиевой куче с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершинами, и пусть &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; {{---}} степень вершины &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;. Тогда по [[#Лемма2|доказанному выше]] в дереве, корень которого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, содержится не менее &amp;lt;tex&amp;gt;F_k&amp;lt;/tex&amp;gt; вершин, что в свою очередь по [[#Лемма3|лемме]] равно &amp;lt;tex&amp;gt;\Theta(\varphi^k)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
То есть&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;n \geqslant \varphi^{k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Логарифмируя по основанию &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt;, получаем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\log_{\varphi}n \geqslant k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом, максимальная степень &amp;lt;tex&amp;gt;D(n)&amp;lt;/tex&amp;gt; произвольной вершины равна &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Структура ===&lt;br /&gt;
====Структура узла====&lt;br /&gt;
Каждый узел &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; в куче &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; содержит следующие указатели и поля:&lt;br /&gt;
 '''struct''' Node&lt;br /&gt;
    '''int''' key &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;     // ключ&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' p &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;      // указатель на родительский узел&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' child &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;  // указатель на один из дочерних узлов&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' left &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;   // указатель  на левый сестринский узел&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' right &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;  // указатель на правый сестринский узел&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''int''' degree &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;  // количество дочерних узлов&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''boolean''' mark &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// флаг, который показывает, удаляли ли мы дочерние узлы данной вершины&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Структура кучи====&lt;br /&gt;
 '''struct''' Heap&lt;br /&gt;
    '''int''' size &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// текущее количество узлов&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' min &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// указатель на корень дерева с минимальным ключом&amp;lt;/span&amp;gt;&lt;br /&gt;
====Структура списка детей====&lt;br /&gt;
[[File:Fibonacci-heap.png|thumb|340px|Пример фибоначчиевой кучи]]&lt;br /&gt;
* Дочерние узлы &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; объединены при помощи указателей &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; в  [[Список#Циклический список |циклический]] [[Список#Двусвязный список | двусвязный список]].&lt;br /&gt;
* Корни всех деревьев в &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; связаны при помощи указателей &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; в [[Список#Циклический список |циклический]] [[Список#Двусвязный список | двусвязный список]] корней.&lt;br /&gt;
&lt;br /&gt;
[[Список#Циклический список |Циклический]] [[Список#Двусвязный список | двусвязный список]] обладает двумя преимуществами для использования в фибоначчиевых кучах. Во-первых, удаление элемента из такого списка выполняется за время &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;. Во-вторых, если имеется два таких списка, их легко объединить в один за время &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Потенциал ===&lt;br /&gt;
&lt;br /&gt;
Для анализа производительности операций введем потенциал для фибоначчиевой кучи &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; как &amp;lt;tex&amp;gt; \Phi(H) = t[H] + 2m[H] &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; t[H] &amp;lt;/tex&amp;gt; {{---}} количество элементов в корневом списке кучи, а &amp;lt;tex&amp;gt; m[H] &amp;lt;/tex&amp;gt; {{---}} количество вершин, у которых удален один ребенок (то есть вершин с пометкой &amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt;). Договоримся, что единицы потенциала достаточно для оплаты константного количества работы.&lt;br /&gt;
&lt;br /&gt;
=== Операции ===&lt;br /&gt;
Рассмотрим операции, которые поддерживают фибоначчиевы кучи. Амортизированное время их работы показано в таблице.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Операция&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Амортизированная сложность&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {makeHeap}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {insert}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {getMin}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {merge}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {extractMin}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(\log n )&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {decreaseKey}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(\log n )&amp;lt;/tex&amp;gt; &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Стоит заметить, что структура фибоначчиевых куч, также как биномиальных и бинарных, не могут обеспечить эффективную реализацию поиска элемента с заданным ключом, поэтому операции &amp;lt;tex&amp;gt;\mathrm {decreaseKey}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt; получают в качестве аргумента указатель на узел, а не значение его ключа.&lt;br /&gt;
&lt;br /&gt;
==== makeHeap ====&lt;br /&gt;
&lt;br /&gt;
Создается новый пустой корневой [[Список#Двусвязный список | список]], в &amp;lt;tex&amp;gt; H.min &amp;lt;/tex&amp;gt; устанавливается значение &amp;lt;tex&amp;gt; null &amp;lt;/tex&amp;gt;. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== insert ====&lt;br /&gt;
&lt;br /&gt;
Вставка элемента в фибоначчиеву кучу также тривиальна: создается новая куча из одного элемента и сливается с текущей. Для оценки амортизированной стоимости операции рассмотрим исходную кучу &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; и получившуюся в результате вставки нового элемента кучу &amp;lt;tex&amp;gt; H' &amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt; t[H'] = t[H] + 1 &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; m[H'] = m[H] &amp;lt;/tex&amp;gt;. Следовательно, увеличение потенциала составляет &amp;lt;tex&amp;gt; (t[H] + 1 + 2m[H]) - (t[H] + 2m[H]) = 1 &amp;lt;/tex&amp;gt;. Так как реальное время работы составляет &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, то амортизированная стоимость данной операции также равна &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== getMin ====&lt;br /&gt;
Возвращает указатель &amp;lt;tex&amp;gt;H.min&amp;lt;/tex&amp;gt;. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== merge ====&lt;br /&gt;
&lt;br /&gt;
Слияние двух фибоначчиевых куч происходит просто: объединяем списки этих куч в один, релаксируем минимум. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Амортизированное время работы также &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, поскольку, при объединении двух куч в одну, потенциалы обеих куч суммируются, итоговая сумма потенциалов не изменяется, &amp;lt;tex&amp;gt; \Phi_{n + 1} - \Phi_n = 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== extractMin ====&lt;br /&gt;
&lt;br /&gt;
Первая рассматриваемая операция, в ходе которой меняется структура кучи. Здесь используется вспомогательная процедура &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;. Возьмем указатель на &amp;lt;tex&amp;gt; H.min &amp;lt;/tex&amp;gt;, удалим эту вершину. Ее поддеревья (их не более, чем &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt; {{---}}  максимальная степень вершины в куче) объединим с корневым списком. Теперь вызываем процедуру &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;. После этой операции в списке корней остается не более чем &amp;lt;tex&amp;gt; D(n) + 1&amp;lt;/tex&amp;gt; узлов, среди которых нужно найти минимальный. Итоговая асимптотика операции &amp;lt;tex&amp;gt;\mathrm {extraxtMin}&amp;lt;/tex&amp;gt;, учитывая и вспомогательную функцию &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;, время работы которой доказывается ниже, равно: &amp;lt;tex&amp;gt; O(1)+O(D(n))+O(D(n))=O(D(n)) &amp;lt;/tex&amp;gt;. По доказанной выше [[#Лемма4|лемме]] &amp;lt;tex&amp;gt;O(D(n)) = O(\log(n))&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===== consolidate =====&lt;br /&gt;
&lt;br /&gt;
Данная процедура принимает кучу и преобразует ее таким образом, что в корневом списке остается не более &amp;lt;tex&amp;gt; D(n) + 1&amp;lt;/tex&amp;gt; вершин.&lt;br /&gt;
&lt;br /&gt;
Для этого возьмем массив списков указателей на корни деревьев &amp;lt;tex&amp;gt; A[0..D[H]] &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; D[H] &amp;lt;/tex&amp;gt; {{---}} максимальная степень вершины в текущем корневом списке.&lt;br /&gt;
&lt;br /&gt;
Затем происходит [[Биномиальная_куча#merge | процесс, аналогичный слиянию биномиальных куч]]: добавляем поочередно каждый корень, смотря на его степень. Пусть она равна &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;. Если в соответствующей ячейке &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; еще нету вершины, записываем текущую вершину туда. Иначе подвешиваем одно дерево к другому, и пытаемся также добавить дерево, степень корня которого уже равна &amp;lt;tex&amp;gt; d + 1 &amp;lt;/tex&amp;gt;. Продолжаем, пока не найдем свободную ячейку.&lt;br /&gt;
&lt;br /&gt;
Учетная стоимость &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt; равна &amp;lt;tex&amp;gt; O(D(n)) &amp;lt;/tex&amp;gt;. Докажем это:&lt;br /&gt;
&lt;br /&gt;
Изначально в корневом списке было не более &amp;lt;tex&amp;gt; D(n) + t[H] - 1 &amp;lt;/tex&amp;gt; вершин, поскольку он состоит из исходного списка корней с &amp;lt;tex&amp;gt;t[H]&amp;lt;/tex&amp;gt; узлами, минус извлеченный узел и плюс дочерние узлы, количество которых не превышает &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt;. В ходе операции &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt; мы сделали &amp;lt;tex&amp;gt; O(D(n) + t[H]) &amp;lt;/tex&amp;gt; слияний деревьев. Потенциал перед извлечением минимума равен &amp;lt;tex&amp;gt; t[H] + 2m[H] &amp;lt;/tex&amp;gt;, а после не превышает &amp;lt;tex&amp;gt; D(n) + 1 + 2m[H] &amp;lt;/tex&amp;gt;, поскольку в корневом списке остается не более  &amp;lt;tex&amp;gt; D(n) + 1 &amp;lt;/tex&amp;gt; узлов, а количество помеченных узлов не изменяется. Таким образом, амортизированная стоимость не превосходит&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; O(D(n) + t[H]) + (D(n) + 1 + 2m[H]) - (t[H] + 2m[H]) = O(D(n)) + O(t[H]) - t[H]&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Поскольку мы договорились, что можем масштабировать единицу потенциала таким образом, чтобы покрывать константное количество работы, то итоговая амортизационная оценка {{---}} &amp;lt;tex&amp;gt; O(D(n)) &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== decreaseKey ====&lt;br /&gt;
&lt;br /&gt;
Основная идея: хотим, чтобы учетная стоимость данной операции была &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Было бы хорошо, чтобы вершина не всплывала до корня, и тогда дерево не придется сильно перестраивать. Для этого при удобном случае будем вырезать поддерево полностью и перемещать его в корневой [[Список |список]]. Итак, сам алгоритм:&lt;br /&gt;
&lt;br /&gt;
# Проверяем, если новое значение ключа все же не меньше значения ключа родителя, то все хорошо, и мы выходим.&lt;br /&gt;
# Иначе, вырезаем дерево с текущей вершиной в корневой [[Список |список]], и производим каскадное вырезание родителя. &lt;br /&gt;
&lt;br /&gt;
===== cut =====&lt;br /&gt;
&lt;br /&gt;
При вырезании вершины мы удаляем ее из списка детей своего родителя, уменьшаем степень ее родителя (&amp;lt;tex&amp;gt; x.p.degree &amp;lt;/tex&amp;gt;) и снимаем пометку с текущей вершины (&amp;lt;tex&amp;gt; x.mark = false &amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
===== cascadingCut =====&lt;br /&gt;
&lt;br /&gt;
[[File:Каскадное вырезание.png|thumb|500px|Пример каскадного вырезания]]&lt;br /&gt;
&lt;br /&gt;
Перед вызовом каскадного вырезания нам известно, удаляли ли ребенка у этой вершины. Если у вершины до этого не удаляли дочерний узел (&amp;lt;tex&amp;gt; x.mark = false &amp;lt;/tex&amp;gt;), то мы помечаем эту вершину (&amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt;) и прекращаем выполнение операции. В противном случае применяем операцию &amp;lt;tex&amp;gt;\mathrm {cut}&amp;lt;/tex&amp;gt; для текущей вершины и запускаем каскадное вырезание от родителя.&lt;br /&gt;
&lt;br /&gt;
'''Пример'''&lt;br /&gt;
&lt;br /&gt;
Рисунок иллюстрирует пример каскадного вырезания:&lt;br /&gt;
&lt;br /&gt;
* Изначально, куча состояла из &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; фибоначчиевых деревьев. У вершины с ключом &amp;lt;tex&amp;gt;24&amp;lt;/tex&amp;gt; отсутствует &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; ребенок.&lt;br /&gt;
* Уменьшаем ключ &amp;lt;tex&amp;gt;26&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; и делаем операцию &amp;lt;tex&amp;gt;\mathrm {cut}&amp;lt;/tex&amp;gt; этого дерева. Получаем кучу с &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt; деревьями и новым минимумом. Но у вершины с ключом &amp;lt;tex&amp;gt;24&amp;lt;/tex&amp;gt; был удален второй ребенок, поэтому запускам операцию &amp;lt;tex&amp;gt;\mathrm {cascadingCut}&amp;lt;/tex&amp;gt; для этой вершины: вырезаем ее, помещаем в корневой список и помечаем ее родителя.&lt;br /&gt;
* У вершины с ключом &amp;lt;tex&amp;gt;7&amp;lt;/tex&amp;gt; удален лишь один ребенок, поэтому операция &amp;lt;tex&amp;gt;\mathrm {cascadingCut}&amp;lt;/tex&amp;gt; от нее не запускается. В итоге, получаем кучу, состоящую из &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; фибоначчиевых деревьев.&lt;br /&gt;
&lt;br /&gt;
===== Время работы =====&lt;br /&gt;
&lt;br /&gt;
Докажем, что амортизированное время работы операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; есть &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Поскольку в процедуре нет циклов, ее время работы определяется лишь количеством рекурсивных вызовов каскадного вырезания.&lt;br /&gt;
&lt;br /&gt;
Пусть мы вызвали процедуру каскадного вырезания &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; раз. Так как реальное время работы операции &amp;lt;tex&amp;gt; \mathrm {cascadingCut} &amp;lt;/tex&amp;gt; без учета рекурсии составляет &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, то реальное время работы операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt; O(k) &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Рассмотрим, как изменится потенциал в результате выполнения данной операции. Пусть &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; {{---}} фибоначчиева куча до вызова &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt;. Тогда после &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; рекурсивных вызовов операции &amp;lt;tex&amp;gt; \mathrm {cascadingCut} &amp;lt;/tex&amp;gt; вершин с пометкой &amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt; стало как минимум на &amp;lt;tex&amp;gt; k - 2 &amp;lt;/tex&amp;gt; меньше, потому что каждый вызов каскадного вырезания, за исключением последнего, уменьшает количество помеченных вершин на одну, и в результате последнего вызова одну вершину мы можем пометить. В корневом списке прибавилось &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; новых деревьев (&amp;lt;tex&amp;gt; k - 1 &amp;lt;/tex&amp;gt; дерево за счет каскадного вырезания и еще одно из-за самого первого вызова операции &amp;lt;tex&amp;gt; \mathrm {cut} &amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
В итоге, изменение потенциала составляет: &amp;lt;tex&amp;gt; \Phi_i - \Phi_{i - 1} = ((t[H] + k) + 2(m[H] + k - 2)) - (t[H] + 2m[H]) = 4 - k &amp;lt;/tex&amp;gt;. Следовательно, амортизированная стоимость не превышает &amp;lt;tex&amp;gt; O(k) + 4 - k &amp;lt;/tex&amp;gt;. Но поскольку мы можем соответствующим образом масштабировать единицы потенциала, то амортизированная стоимость операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; равна &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== delete ====&lt;br /&gt;
&lt;br /&gt;
Удаление вершины реализуется через уменьшение ее ключа до &amp;lt;tex&amp;gt; -\infty &amp;lt;/tex&amp;gt; и последующим извлечением минимума. Амортизированное время работы: &amp;lt;tex&amp;gt; O(1) + O(D(n)) = O(D(n)) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Поскольку ранее мы показали, что &amp;lt;tex&amp;gt; D(n) = O(\log n ) &amp;lt;/tex&amp;gt;, то соответствующие оценки доказаны.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Левосторонняя куча]]&lt;br /&gt;
* [[Тонкая куча]]&lt;br /&gt;
* [[Толстая куча на избыточном счетчике]]&lt;br /&gt;
* [[Куча Бродала-Окасаки]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
&lt;br /&gt;
* Томас Кормен, Чарльз Лейзерсон, Рональд Ривест, Клиффорд Штайн — Алгоритмы: построение и анализ. — М.: Издательский дом «Вильямс», 2005. — С. 1296. — ISBN 5-8459-0857-4&lt;br /&gt;
* [[wikipedia:ru:Числа Фибоначчи|Числа Фибоначчи {{---}} Википедия]]&lt;br /&gt;
* [[wikipedia:ru:Фибоначчиева куча|Фибоначчиева куча {{---}} Википедия]]&lt;br /&gt;
* [http://www.intuit.ru/department/algorithms/dscm/7/2.html Фибоначчиевы кучи — INTUIT.ru]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/heaps Визуализаторы]&lt;br /&gt;
* [http://www.cs.duke.edu/courses/fall05/cps230/L-11.pdf Fibonacci Heaps]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Приоритетные очереди]]&lt;/div&gt;</summary>
		<author><name>217.66.156.128</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B1%D0%BE%D0%BD%D0%B0%D1%87%D1%87%D0%B8%D0%B5%D0%B2%D0%B0_%D0%BA%D1%83%D1%87%D0%B0&amp;diff=46765</id>
		<title>Фибоначчиева куча</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B1%D0%BE%D0%BD%D0%B0%D1%87%D1%87%D0%B8%D0%B5%D0%B2%D0%B0_%D0%BA%D1%83%D1%87%D0%B0&amp;diff=46765"/>
				<updated>2015-05-21T15:59:44Z</updated>
		
		<summary type="html">&lt;p&gt;217.66.156.128: /* makeHeap */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Фибоначчиево дерево ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Фибоначчиево дерево''' (англ. ''Fibonacci tree'') {{---}} [[Биномиальная куча#Биномиальное дерево |биномиальное дерево]], где у каждой вершины удалено не более одного ребенка.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Порядок фибоначчиева дерева''' (англ. ''Fibonacci tree rank'') {{---}} порядок соответствующего биномиального дерева, из которого оно получено.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Степень вершины''' (англ. ''degree'')  {{---}} количество дочерних узлов данной вершины.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма1&lt;br /&gt;
|statement=Для всех целых &amp;lt;tex&amp;gt; n \geqslant 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt; F_n = 1 + \sum\limits_{i=0}^{n-2} F_i &amp;lt;/tex&amp;gt;,&lt;br /&gt;
где &amp;lt;tex&amp;gt; F_n &amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt;-ое число Фибоначчи, определяемое формулой:&lt;br /&gt;
&amp;lt;tex&amp;gt;&lt;br /&gt;
F_n =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
 0, &amp;amp; n = 0 \\&lt;br /&gt;
 1, &amp;amp; n = 1 \\&lt;br /&gt;
 F_{n-1} + F_{n-2}, &amp;amp; n \geqslant 2&lt;br /&gt;
\end{cases} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Докажем лемму по индукции:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;tex&amp;gt;n = 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_2 = 1 + \sum\limits_{i=0}^0 F_i = 1 + 0 = 1&amp;lt;/tex&amp;gt;, что действительно верно.&lt;br /&gt;
&lt;br /&gt;
По индукции предполагаем, что &amp;lt;tex&amp;gt;F_{n-1} = 1 + \sum\limits_{i=0}^{n-3} F_i &amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_n = F_{n-1} + F_{n-2} = 1 + \sum\limits_{i=0}^{n-3} F_i + F_{n-2} = 1 + \sum\limits_{i=0}^{n-2} F_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма2&lt;br /&gt;
|statement= Фибоначчиево дерево порядка &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; содержит не менее &amp;lt;tex&amp;gt;F_n&amp;lt;/tex&amp;gt; вершин.&lt;br /&gt;
|proof=&lt;br /&gt;
Докажем это утверждение по индукции.&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;s_n&amp;lt;/tex&amp;gt; {{---}} минимальный размер фибоначчиева дерева порядка &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_0 = 1 &amp;gt; F_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_1 = 1 = F_1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предположим по индукции, что для всех &amp;lt;tex&amp;gt;i &amp;lt; n \ s_i \geqslant F_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Пусть в нашем дереве удалено поддерево порядка &amp;lt;tex&amp;gt;n - 1&amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_n = 1 + \sum\limits_{i=0}^{n-2} s_i \geqslant 1 + \sum\limits_{i=0}^{n-2} F_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Но по предыдущей [[#Лемма1|лемме]] :&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;tex&amp;gt;1 + \sum\limits_{i=0}^{n-2} F_i = F_n&amp;lt;/tex&amp;gt;. Следовательно, &amp;lt;tex&amp;gt;s_n \geqslant F_n&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Фибоначчиева куча ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Фибоначчиева куча''' (англ. ''Fibonacci heap'')   {{---}} набор фибоначчиевых деревьев, корни которых объединены в неупорядоченный [[Список#Циклический список |циклический]] [[Список#Двусвязный список | двусвязный список]]. В отличие от [[Биномиальная куча|биномиальной кучи]], степени корней не обязаны быть попарно различными.&lt;br /&gt;
}}&lt;br /&gt;
Фибоначчиевы кучи поддерживают тот же набор операций, что и биномиальные кучи, но имеют то преимущество, что операции, в которых не требуется удаление, имеют [[Амортизационный анализ|амортизированное]] время работы, равное &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
С теоретической точки зрения фибоначчиевы кучи особенно полезны в случае, когда количество операций &amp;lt;tex&amp;gt;\mathrm {extractMin}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt; относительно мало по сравнению с количеством других операций. Однако с практической точки зрения программная сложность и высокие значения постоянных множителей в формулах времени работы  существенно снижают эффективность применения фибоначчиевых куч, делая их в большинстве случаев менее привлекательными, чем обычные [[Двоичная куча|бинарные кучи]].&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма3&lt;br /&gt;
|statement= &amp;lt;tex&amp;gt;F_n =\Theta(\varphi^n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt; \varphi = \frac {1 + \sqrt 5} {2}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Для начала докажем, что &amp;lt;tex&amp;gt;F_n =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^n - (-\varphi)^{-n}} {\sqrt 5}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Используем для этого математическую индукцию.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_0 =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^0 - (-\varphi)^0} {\sqrt 5} = \frac {1 - 1} {\sqrt 5} = 0&amp;lt;/tex&amp;gt;, что верно.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_1 =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^1 - (-\varphi)^{-1}} {\sqrt 5} = \frac {1} {\sqrt 5}(\frac {1 + \sqrt 5} {2} - \frac {1 - \sqrt 5} {2}) = \frac {2\sqrt 5} {2\sqrt 5} = 1&amp;lt;/tex&amp;gt;, что также верно.&lt;br /&gt;
&lt;br /&gt;
По индукции предполагаем, что &amp;lt;tex&amp;gt;F_{n-1} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-1} - (-\varphi)^{1-n}} {\sqrt 5}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;F_{n-2} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-2} - (-\varphi)^{2-n}} {\sqrt 5}&amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_n = F_{n-1} + F_{n-2} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-1} - (-\varphi)^{1-n}} {\sqrt 5} + \frac {\varphi^{n-2} - (-\varphi)^{2-n}} {\sqrt 5} =&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;= \frac {1} {\sqrt 5}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(\varphi^{n-1} - (-\varphi)^{1-n} + \varphi^{n-2} - (-\varphi)^{2-n}) &amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;= \frac {1} {\sqrt 5}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(\varphi^{n}(\varphi^{-1} + \varphi^{-2}) - (-\varphi)^{-n}(-\varphi + \varphi^{2}))&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подставив вместо &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; его значение, нетрудно убедится, что &amp;lt;tex&amp;gt;\varphi^{-1} + \varphi^{-2} = -\varphi + \varphi^{2} = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Поскольку &amp;lt;tex&amp;gt;\left\vert (-\varphi)^{-1} \right\vert &amp;lt; 1&amp;lt;/tex&amp;gt;, то выполняются неравенства &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {(-\varphi)^{-n}} {\sqrt 5} &amp;lt; \frac {1} {\sqrt 5} &amp;lt; \frac {1} {2}&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;-ое число Фибоначчи равно &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n}} {\sqrt 5}&amp;lt;/tex&amp;gt;, округленному до ближайшего целого числа. Следовательно, &amp;lt;tex&amp;gt;F_n =\Theta(\varphi^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма4&lt;br /&gt;
|statement=Максимальная степень &amp;lt;tex&amp;gt;D(n)&amp;lt;/tex&amp;gt; произвольной вершины в фибоначчиевой куче с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершинами равна &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; {{---}} произвольная вершина в фибоначчиевой куче с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершинами, и пусть &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; {{---}} степень вершины &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;. Тогда по [[#Лемма2|доказанному выше]] в дереве, корень которого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, содержится не менее &amp;lt;tex&amp;gt;F_k&amp;lt;/tex&amp;gt; вершин, что в свою очередь по [[#Лемма3|лемме]] равно &amp;lt;tex&amp;gt;\Theta(\varphi^k)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
То есть&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;n \geqslant \varphi^{k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Логарифмируя по основанию &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt;, получаем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\log_{\varphi}n \geqslant k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом, максимальная степень &amp;lt;tex&amp;gt;D(n)&amp;lt;/tex&amp;gt; произвольной вершины равна &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Структура ===&lt;br /&gt;
====Структура узла====&lt;br /&gt;
Каждый узел &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; в куче &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; содержит следующие указатели и поля:&lt;br /&gt;
 '''struct''' Node&lt;br /&gt;
    '''int''' key &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;     // ключ&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' p &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;      // указатель на родительский узел&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' child &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;  // указатель на один из дочерних узлов&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' left &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;   // указатель  на левый сестринский узел&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' right &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;  // указатель на правый сестринский узел&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''int''' degree &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;  // количество дочерних узлов&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''boolean''' mark &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// флаг, который показывает, удаляли ли мы дочерние узлы данной вершины&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Структура кучи====&lt;br /&gt;
 '''struct''' Heap&lt;br /&gt;
    '''int''' size &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// текущее количество узлов&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' min &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// указатель на корень дерева с минимальным ключом&amp;lt;/span&amp;gt;&lt;br /&gt;
====Структура списка детей====&lt;br /&gt;
[[File:Fibonacci-heap.png|thumb|340px|Пример фибоначчиевой кучи]]&lt;br /&gt;
* Дочерние узлы &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; объединены при помощи указателей &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; в  [[Список#Циклический список |циклический]] [[Список#Двусвязный список | двусвязный список]].&lt;br /&gt;
* Корни всех деревьев в &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; связаны при помощи указателей &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; в [[Список#Циклический список |циклический]] [[Список#Двусвязный список | двусвязный список]] корней.&lt;br /&gt;
&lt;br /&gt;
[[Список#Циклический список |Циклический]] [[Список#Двусвязный список | двусвязный список]] обладает двумя преимуществами для использования в фибоначчиевых кучах. Во-первых, удаление элемента из такого списка выполняется за время &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;. Во-вторых, если имеется два таких списка, их легко объединить в один за время &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Потенциал ===&lt;br /&gt;
&lt;br /&gt;
Для анализа производительности операций введем потенциал для фибоначчиевой кучи &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; как &amp;lt;tex&amp;gt; \Phi(H) = t[H] + 2m[H] &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; t[H] &amp;lt;/tex&amp;gt; {{---}} количество элементов в корневом списке кучи, а &amp;lt;tex&amp;gt; m[H] &amp;lt;/tex&amp;gt; {{---}} количество вершин, у которых удален один ребенок (то есть вершин с пометкой &amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt;). Договоримся, что единицы потенциала достаточно для оплаты константного количества работы.&lt;br /&gt;
&lt;br /&gt;
=== Операции ===&lt;br /&gt;
Рассмотрим операции, которые поддерживают фибоначчиевы кучи. Амортизированное время их работы показано в таблице.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Операция&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Амортизированная сложность&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {makeHeap}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {insert}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {getMin}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {merge}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {extractMin}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(\log n )&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {decreaseKey}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(\log n )&amp;lt;/tex&amp;gt; &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Стоит заметить, что структура фибоначчиевых куч, также как биномиальных и бинарных, не могут обеспечить эффективную реализацию поиска элемента с заданным ключом, поэтому операции &amp;lt;tex&amp;gt;\mathrm {decreaseKey}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt; получают в качестве аргумента указатель на узел, а не значение его ключа.&lt;br /&gt;
&lt;br /&gt;
==== makeHeap ====&lt;br /&gt;
&lt;br /&gt;
Создается новый пустой корневой [[Список#Двусвязный список | список]], в &amp;lt;tex&amp;gt; H.min &amp;lt;/tex&amp;gt; устанавливается значение &amp;lt;tex&amp;gt; null &amp;lt;/tex&amp;gt;. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== insert ====&lt;br /&gt;
&lt;br /&gt;
Вставка элемента в фибоначчиеву кучу также тривиальна: создается новая куча из одного элемента и сливается с текущей. Для оценки амортизированной стоимости операции рассмотрим исходную кучу &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; и получившуюся в результате вставки нового элемента кучу &amp;lt;tex&amp;gt; H' &amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt; t[H'] = t[H] + 1 &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; m[H'] = m[H] &amp;lt;/tex&amp;gt;. Следовательно, увеличение потенциала составляет &amp;lt;tex&amp;gt; (t[H] + 1 + 2m[H]) - (t[H] + 2m[H]) = 1 &amp;lt;/tex&amp;gt;. Так как реальное время работы составляет &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, то амортизированная стоимость данной операции также равна &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== getMin ====&lt;br /&gt;
Возвращает указатель &amp;lt;tex&amp;gt;H.min&amp;lt;/tex&amp;gt;. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== merge ====&lt;br /&gt;
&lt;br /&gt;
Слияние двух фибоначчиевых куч происходит просто: объединяем списки этих куч в один, релаксируем минимум. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Амортизированное время работы также &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, поскольку, при объединении двух куч в одну, потенциалы обеих куч суммируются, итоговая сумма потенциалов не изменяется, &amp;lt;tex&amp;gt; \Phi_{n + 1} - \Phi_n = 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== extractMin ====&lt;br /&gt;
&lt;br /&gt;
Первая рассматриваемая операция, в ходе которой меняется структура кучи. Здесь используется вспомогательная процедура &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;. Возьмем указатель на &amp;lt;tex&amp;gt; H.min &amp;lt;/tex&amp;gt;, удалим эту вершину. Ее поддеревья (их не более, чем &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt; {{---}}  максимальная степень вершины в куче) объединим с корневым списком. Теперь вызываем процедуру &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;. После этой операции в списке корней остается не более чем &amp;lt;tex&amp;gt; D(n) + 1&amp;lt;/tex&amp;gt; узлов, среди которых нужно найти минимальный. Итоговая асимптотика операции &amp;lt;tex&amp;gt;\mathrm {extraxtMin}&amp;lt;/tex&amp;gt;, учитывая и вспомогательную функцию &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;, время работы которой доказывается ниже, равно: &amp;lt;tex&amp;gt; O(1)+O(D(n))+O(D(n))=O(D(n)) &amp;lt;/tex&amp;gt;. По доказанной выше [[#Лемма4|лемме]] &amp;lt;tex&amp;gt;O(D(n)) = O(\log(n))&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===== consolidate =====&lt;br /&gt;
&lt;br /&gt;
Данная процедура принимает кучу и преобразует ее таким образом, что в корневом списке остается не более &amp;lt;tex&amp;gt; D(n) + 1&amp;lt;/tex&amp;gt; вершин.&lt;br /&gt;
&lt;br /&gt;
Для этого возьмем массив списков указателей на корни деревьев &amp;lt;tex&amp;gt; A[0..D[H]] &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; D[H] &amp;lt;/tex&amp;gt; {{---}} максимальная степень вершины в текущем корневом списке.&lt;br /&gt;
&lt;br /&gt;
Затем происходит [[Биномиальная_куча#merge | процесс, аналогичный слиянию биномиальных куч]]: добавляем поочередно каждый корень, смотря на его степень. Пусть она равна &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;. Если в соответствующей ячейке &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; еще нету вершины, записываем текущую вершину туда. Иначе подвешиваем одно дерево к другому, и пытаемся также добавить дерево, степень корня которого уже равна &amp;lt;tex&amp;gt; d + 1 &amp;lt;/tex&amp;gt;. Продолжаем, пока не найдем свободную ячейку.&lt;br /&gt;
&lt;br /&gt;
Учетная стоимость &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt; равна &amp;lt;tex&amp;gt; O(D(n)) &amp;lt;/tex&amp;gt;. Докажем это:&lt;br /&gt;
&lt;br /&gt;
Изначально в корневом списке было не более &amp;lt;tex&amp;gt; D(n) + t[H] - 1 &amp;lt;/tex&amp;gt; вершин, поскольку он состоит из исходного списка корней с &amp;lt;tex&amp;gt;t[H]&amp;lt;/tex&amp;gt; узлами, минус извлеченный узел и плюс дочерние узлы, количество которых не превышает &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt;. В ходе операции &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt; мы сделали &amp;lt;tex&amp;gt; O(D(n) + t[H]) &amp;lt;/tex&amp;gt; слияний деревьев. Потенциал перед извлечением минимума равен &amp;lt;tex&amp;gt; t[H] + 2m[H] &amp;lt;/tex&amp;gt;, а после не превышает &amp;lt;tex&amp;gt; D(n) + 1 + 2m[H] &amp;lt;/tex&amp;gt;, поскольку в корневом списке остается не более  &amp;lt;tex&amp;gt; D(n) + 1 &amp;lt;/tex&amp;gt; узлов, а количество помеченных узлов не изменяется. Таким образом, амортизированная стоимость не превосходит&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; O(D(n) + t[H]) + (D(n) + 1 + 2m[H]) - (t[H] + 2m[H]) = O(D(n)) + O(t[H]) - t[H]&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Поскольку мы договорились, что можем масштабировать единицу потенциала таким образом, чтобы покрывать константное количество работы, то итоговая амортизационная оценка {{---}} &amp;lt;tex&amp;gt; O(D(n)) &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== decreaseKey ====&lt;br /&gt;
&lt;br /&gt;
Основная идея: хотим, чтобы учетная стоимость данной операции была &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Было бы хорошо, чтобы вершина не всплывала до корня, и тогда дерево не придется сильно перестраивать. Для этого при удобном случае будем вырезать поддерево полностью и перемещать его в корневой список. Итак, сам алгоритм:&lt;br /&gt;
&lt;br /&gt;
# Проверяем, если новое значение ключа все же не меньше значения ключа родителя, то все хорошо, и мы выходим.&lt;br /&gt;
# Иначе, вырезаем дерево с текущей вершиной в корневой список, и производим каскадное вырезание родителя. &lt;br /&gt;
&lt;br /&gt;
===== cut =====&lt;br /&gt;
&lt;br /&gt;
При вырезании вершины мы удаляем ее из списка детей своего родителя, уменьшаем степень ее родителя (&amp;lt;tex&amp;gt; x.p.degree &amp;lt;/tex&amp;gt;) и снимаем пометку с текущей вершины (&amp;lt;tex&amp;gt; x.mark = false &amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
===== cascadingCut =====&lt;br /&gt;
&lt;br /&gt;
[[File:Каскадное вырезание.png|thumb|500px|Пример каскадного вырезания]]&lt;br /&gt;
&lt;br /&gt;
Перед вызовом каскадного вырезания нам известно, удаляли ли ребенка у этой вершины. Если у вершины до этого не удаляли дочерний узел (&amp;lt;tex&amp;gt; x.mark = false &amp;lt;/tex&amp;gt;), то мы помечаем эту вершину (&amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt;) и прекращаем выполнение операции. В противном случае применяем операцию &amp;lt;tex&amp;gt;\mathrm {cut}&amp;lt;/tex&amp;gt; для текущей вершины и запускаем каскадное вырезание от родителя.&lt;br /&gt;
&lt;br /&gt;
'''Пример'''&lt;br /&gt;
&lt;br /&gt;
Рисунок иллюстрирует пример каскадного вырезания:&lt;br /&gt;
&lt;br /&gt;
* Изначально, куча состояла из &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; фибоначчиевых деревьев. У вершины с ключом &amp;lt;tex&amp;gt;24&amp;lt;/tex&amp;gt; отсутствует &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; ребенок.&lt;br /&gt;
* Уменьшаем ключ &amp;lt;tex&amp;gt;26&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; и делаем операцию &amp;lt;tex&amp;gt;\mathrm {cut}&amp;lt;/tex&amp;gt; этого дерева. Получаем кучу с &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt; деревьями и новым минимумом. Но у вершины с ключом &amp;lt;tex&amp;gt;24&amp;lt;/tex&amp;gt; был удален второй ребенок, поэтому запускам операцию &amp;lt;tex&amp;gt;\mathrm {cascadingCut}&amp;lt;/tex&amp;gt; для этой вершины: вырезаем ее, помещаем в корневой список и помечаем ее родителя.&lt;br /&gt;
* У вершины с ключом &amp;lt;tex&amp;gt;7&amp;lt;/tex&amp;gt; удален лишь один ребенок, поэтому операция &amp;lt;tex&amp;gt;\mathrm {cascadingCut}&amp;lt;/tex&amp;gt; от нее не запускается. В итоге, получаем кучу, состоящую из &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; фибоначчиевых деревьев.&lt;br /&gt;
&lt;br /&gt;
===== Время работы =====&lt;br /&gt;
&lt;br /&gt;
Докажем, что амортизированное время работы операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; есть &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Поскольку в процедуре нет циклов, ее время работы определяется лишь количеством рекурсивных вызовов каскадного вырезания.&lt;br /&gt;
&lt;br /&gt;
Пусть мы вызвали процедуру каскадного вырезания &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; раз. Так как реальное время работы операции &amp;lt;tex&amp;gt; \mathrm {cascadingCut} &amp;lt;/tex&amp;gt; без учета рекурсии составляет &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, то реальное время работы операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt; O(k) &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Рассмотрим, как изменится потенциал в результате выполнения данной операции. Пусть &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; {{---}} фибоначчиева куча до вызова &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt;. Тогда после &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; рекурсивных вызовов операции &amp;lt;tex&amp;gt; \mathrm {cascadingCut} &amp;lt;/tex&amp;gt; вершин с пометкой &amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt; стало как минимум на &amp;lt;tex&amp;gt; k - 2 &amp;lt;/tex&amp;gt; меньше, потому что каждый вызов каскадного вырезания, за исключением последнего, уменьшает количество помеченных вершин на одну, и в результате последнего вызова одну вершину мы можем пометить. В корневом списке прибавилось &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; новых деревьев (&amp;lt;tex&amp;gt; k - 1 &amp;lt;/tex&amp;gt; дерево за счет каскадного вырезания и еще одно из-за самого первого вызова операции &amp;lt;tex&amp;gt; \mathrm {cut} &amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
В итоге, изменение потенциала составляет: &amp;lt;tex&amp;gt; \Phi_i - \Phi_{i - 1} = ((t[H] + k) + 2(m[H] + k - 2)) - (t[H] + 2m[H]) = 4 - k &amp;lt;/tex&amp;gt;. Следовательно, амортизированная стоимость не превышает &amp;lt;tex&amp;gt; O(k) + 4 - k &amp;lt;/tex&amp;gt;. Но поскольку мы можем соответствующим образом масштабировать единицы потенциала, то амортизированная стоимость операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; равна &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== delete ====&lt;br /&gt;
&lt;br /&gt;
Удаление вершины реализуется через уменьшение ее ключа до &amp;lt;tex&amp;gt; -\infty &amp;lt;/tex&amp;gt; и последующим извлечением минимума. Амортизированное время работы: &amp;lt;tex&amp;gt; O(1) + O(D(n)) = O(D(n)) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Поскольку ранее мы показали, что &amp;lt;tex&amp;gt; D(n) = O(\log n ) &amp;lt;/tex&amp;gt;, то соответствующие оценки доказаны.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Левосторонняя куча]]&lt;br /&gt;
* [[Тонкая куча]]&lt;br /&gt;
* [[Толстая куча на избыточном счетчике]]&lt;br /&gt;
* [[Куча Бродала-Окасаки]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
&lt;br /&gt;
* Томас Кормен, Чарльз Лейзерсон, Рональд Ривест, Клиффорд Штайн — Алгоритмы: построение и анализ. — М.: Издательский дом «Вильямс», 2005. — С. 1296. — ISBN 5-8459-0857-4&lt;br /&gt;
* [[wikipedia:ru:Числа Фибоначчи|Числа Фибоначчи {{---}} Википедия]]&lt;br /&gt;
* [[wikipedia:ru:Фибоначчиева куча|Фибоначчиева куча {{---}} Википедия]]&lt;br /&gt;
* [http://www.intuit.ru/department/algorithms/dscm/7/2.html Фибоначчиевы кучи — INTUIT.ru]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/heaps Визуализаторы]&lt;br /&gt;
* [http://www.cs.duke.edu/courses/fall05/cps230/L-11.pdf Fibonacci Heaps]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Приоритетные очереди]]&lt;/div&gt;</summary>
		<author><name>217.66.156.128</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B1%D0%BE%D0%BD%D0%B0%D1%87%D1%87%D0%B8%D0%B5%D0%B2%D0%B0_%D0%BA%D1%83%D1%87%D0%B0&amp;diff=46764</id>
		<title>Фибоначчиева куча</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B1%D0%BE%D0%BD%D0%B0%D1%87%D1%87%D0%B8%D0%B5%D0%B2%D0%B0_%D0%BA%D1%83%D1%87%D0%B0&amp;diff=46764"/>
				<updated>2015-05-21T15:58:45Z</updated>
		
		<summary type="html">&lt;p&gt;217.66.156.128: /* Структура списка детей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Фибоначчиево дерево ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Фибоначчиево дерево''' (англ. ''Fibonacci tree'') {{---}} [[Биномиальная куча#Биномиальное дерево |биномиальное дерево]], где у каждой вершины удалено не более одного ребенка.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Порядок фибоначчиева дерева''' (англ. ''Fibonacci tree rank'') {{---}} порядок соответствующего биномиального дерева, из которого оно получено.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Степень вершины''' (англ. ''degree'')  {{---}} количество дочерних узлов данной вершины.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма1&lt;br /&gt;
|statement=Для всех целых &amp;lt;tex&amp;gt; n \geqslant 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt; F_n = 1 + \sum\limits_{i=0}^{n-2} F_i &amp;lt;/tex&amp;gt;,&lt;br /&gt;
где &amp;lt;tex&amp;gt; F_n &amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt;-ое число Фибоначчи, определяемое формулой:&lt;br /&gt;
&amp;lt;tex&amp;gt;&lt;br /&gt;
F_n =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
 0, &amp;amp; n = 0 \\&lt;br /&gt;
 1, &amp;amp; n = 1 \\&lt;br /&gt;
 F_{n-1} + F_{n-2}, &amp;amp; n \geqslant 2&lt;br /&gt;
\end{cases} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Докажем лемму по индукции:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;tex&amp;gt;n = 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_2 = 1 + \sum\limits_{i=0}^0 F_i = 1 + 0 = 1&amp;lt;/tex&amp;gt;, что действительно верно.&lt;br /&gt;
&lt;br /&gt;
По индукции предполагаем, что &amp;lt;tex&amp;gt;F_{n-1} = 1 + \sum\limits_{i=0}^{n-3} F_i &amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_n = F_{n-1} + F_{n-2} = 1 + \sum\limits_{i=0}^{n-3} F_i + F_{n-2} = 1 + \sum\limits_{i=0}^{n-2} F_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма2&lt;br /&gt;
|statement= Фибоначчиево дерево порядка &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; содержит не менее &amp;lt;tex&amp;gt;F_n&amp;lt;/tex&amp;gt; вершин.&lt;br /&gt;
|proof=&lt;br /&gt;
Докажем это утверждение по индукции.&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;s_n&amp;lt;/tex&amp;gt; {{---}} минимальный размер фибоначчиева дерева порядка &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_0 = 1 &amp;gt; F_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_1 = 1 = F_1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предположим по индукции, что для всех &amp;lt;tex&amp;gt;i &amp;lt; n \ s_i \geqslant F_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Пусть в нашем дереве удалено поддерево порядка &amp;lt;tex&amp;gt;n - 1&amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_n = 1 + \sum\limits_{i=0}^{n-2} s_i \geqslant 1 + \sum\limits_{i=0}^{n-2} F_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Но по предыдущей [[#Лемма1|лемме]] :&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;tex&amp;gt;1 + \sum\limits_{i=0}^{n-2} F_i = F_n&amp;lt;/tex&amp;gt;. Следовательно, &amp;lt;tex&amp;gt;s_n \geqslant F_n&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Фибоначчиева куча ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Фибоначчиева куча''' (англ. ''Fibonacci heap'')   {{---}} набор фибоначчиевых деревьев, корни которых объединены в неупорядоченный [[Список#Циклический список |циклический]] [[Список#Двусвязный список | двусвязный список]]. В отличие от [[Биномиальная куча|биномиальной кучи]], степени корней не обязаны быть попарно различными.&lt;br /&gt;
}}&lt;br /&gt;
Фибоначчиевы кучи поддерживают тот же набор операций, что и биномиальные кучи, но имеют то преимущество, что операции, в которых не требуется удаление, имеют [[Амортизационный анализ|амортизированное]] время работы, равное &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
С теоретической точки зрения фибоначчиевы кучи особенно полезны в случае, когда количество операций &amp;lt;tex&amp;gt;\mathrm {extractMin}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt; относительно мало по сравнению с количеством других операций. Однако с практической точки зрения программная сложность и высокие значения постоянных множителей в формулах времени работы  существенно снижают эффективность применения фибоначчиевых куч, делая их в большинстве случаев менее привлекательными, чем обычные [[Двоичная куча|бинарные кучи]].&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма3&lt;br /&gt;
|statement= &amp;lt;tex&amp;gt;F_n =\Theta(\varphi^n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt; \varphi = \frac {1 + \sqrt 5} {2}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Для начала докажем, что &amp;lt;tex&amp;gt;F_n =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^n - (-\varphi)^{-n}} {\sqrt 5}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Используем для этого математическую индукцию.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_0 =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^0 - (-\varphi)^0} {\sqrt 5} = \frac {1 - 1} {\sqrt 5} = 0&amp;lt;/tex&amp;gt;, что верно.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_1 =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^1 - (-\varphi)^{-1}} {\sqrt 5} = \frac {1} {\sqrt 5}(\frac {1 + \sqrt 5} {2} - \frac {1 - \sqrt 5} {2}) = \frac {2\sqrt 5} {2\sqrt 5} = 1&amp;lt;/tex&amp;gt;, что также верно.&lt;br /&gt;
&lt;br /&gt;
По индукции предполагаем, что &amp;lt;tex&amp;gt;F_{n-1} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-1} - (-\varphi)^{1-n}} {\sqrt 5}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;F_{n-2} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-2} - (-\varphi)^{2-n}} {\sqrt 5}&amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_n = F_{n-1} + F_{n-2} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-1} - (-\varphi)^{1-n}} {\sqrt 5} + \frac {\varphi^{n-2} - (-\varphi)^{2-n}} {\sqrt 5} =&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;= \frac {1} {\sqrt 5}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(\varphi^{n-1} - (-\varphi)^{1-n} + \varphi^{n-2} - (-\varphi)^{2-n}) &amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;= \frac {1} {\sqrt 5}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(\varphi^{n}(\varphi^{-1} + \varphi^{-2}) - (-\varphi)^{-n}(-\varphi + \varphi^{2}))&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подставив вместо &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; его значение, нетрудно убедится, что &amp;lt;tex&amp;gt;\varphi^{-1} + \varphi^{-2} = -\varphi + \varphi^{2} = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Поскольку &amp;lt;tex&amp;gt;\left\vert (-\varphi)^{-1} \right\vert &amp;lt; 1&amp;lt;/tex&amp;gt;, то выполняются неравенства &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {(-\varphi)^{-n}} {\sqrt 5} &amp;lt; \frac {1} {\sqrt 5} &amp;lt; \frac {1} {2}&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;-ое число Фибоначчи равно &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n}} {\sqrt 5}&amp;lt;/tex&amp;gt;, округленному до ближайшего целого числа. Следовательно, &amp;lt;tex&amp;gt;F_n =\Theta(\varphi^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма4&lt;br /&gt;
|statement=Максимальная степень &amp;lt;tex&amp;gt;D(n)&amp;lt;/tex&amp;gt; произвольной вершины в фибоначчиевой куче с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершинами равна &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; {{---}} произвольная вершина в фибоначчиевой куче с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершинами, и пусть &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; {{---}} степень вершины &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;. Тогда по [[#Лемма2|доказанному выше]] в дереве, корень которого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, содержится не менее &amp;lt;tex&amp;gt;F_k&amp;lt;/tex&amp;gt; вершин, что в свою очередь по [[#Лемма3|лемме]] равно &amp;lt;tex&amp;gt;\Theta(\varphi^k)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
То есть&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;n \geqslant \varphi^{k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Логарифмируя по основанию &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt;, получаем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\log_{\varphi}n \geqslant k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом, максимальная степень &amp;lt;tex&amp;gt;D(n)&amp;lt;/tex&amp;gt; произвольной вершины равна &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Структура ===&lt;br /&gt;
====Структура узла====&lt;br /&gt;
Каждый узел &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; в куче &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; содержит следующие указатели и поля:&lt;br /&gt;
 '''struct''' Node&lt;br /&gt;
    '''int''' key &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;     // ключ&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' p &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;      // указатель на родительский узел&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' child &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;  // указатель на один из дочерних узлов&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' left &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;   // указатель  на левый сестринский узел&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' right &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;  // указатель на правый сестринский узел&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''int''' degree &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;  // количество дочерних узлов&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''boolean''' mark &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// флаг, который показывает, удаляли ли мы дочерние узлы данной вершины&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Структура кучи====&lt;br /&gt;
 '''struct''' Heap&lt;br /&gt;
    '''int''' size &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// текущее количество узлов&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' min &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// указатель на корень дерева с минимальным ключом&amp;lt;/span&amp;gt;&lt;br /&gt;
====Структура списка детей====&lt;br /&gt;
[[File:Fibonacci-heap.png|thumb|340px|Пример фибоначчиевой кучи]]&lt;br /&gt;
* Дочерние узлы &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; объединены при помощи указателей &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; в  [[Список#Циклический список |циклический]] [[Список#Двусвязный список | двусвязный список]].&lt;br /&gt;
* Корни всех деревьев в &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; связаны при помощи указателей &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; в [[Список#Циклический список |циклический]] [[Список#Двусвязный список | двусвязный список]] корней.&lt;br /&gt;
&lt;br /&gt;
[[Список#Циклический список |Циклический]] [[Список#Двусвязный список | двусвязный список]] обладает двумя преимуществами для использования в фибоначчиевых кучах. Во-первых, удаление элемента из такого списка выполняется за время &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;. Во-вторых, если имеется два таких списка, их легко объединить в один за время &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Потенциал ===&lt;br /&gt;
&lt;br /&gt;
Для анализа производительности операций введем потенциал для фибоначчиевой кучи &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; как &amp;lt;tex&amp;gt; \Phi(H) = t[H] + 2m[H] &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; t[H] &amp;lt;/tex&amp;gt; {{---}} количество элементов в корневом списке кучи, а &amp;lt;tex&amp;gt; m[H] &amp;lt;/tex&amp;gt; {{---}} количество вершин, у которых удален один ребенок (то есть вершин с пометкой &amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt;). Договоримся, что единицы потенциала достаточно для оплаты константного количества работы.&lt;br /&gt;
&lt;br /&gt;
=== Операции ===&lt;br /&gt;
Рассмотрим операции, которые поддерживают фибоначчиевы кучи. Амортизированное время их работы показано в таблице.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Операция&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Амортизированная сложность&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {makeHeap}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {insert}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {getMin}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {merge}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {extractMin}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(\log n )&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {decreaseKey}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(\log n )&amp;lt;/tex&amp;gt; &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Стоит заметить, что структура фибоначчиевых куч, также как биномиальных и бинарных, не могут обеспечить эффективную реализацию поиска элемента с заданным ключом, поэтому операции &amp;lt;tex&amp;gt;\mathrm {decreaseKey}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt; получают в качестве аргумента указатель на узел, а не значение его ключа.&lt;br /&gt;
&lt;br /&gt;
==== makeHeap ====&lt;br /&gt;
&lt;br /&gt;
Создается новый пустой корневой список, в &amp;lt;tex&amp;gt; H.min &amp;lt;/tex&amp;gt; устанавливается значение &amp;lt;tex&amp;gt; null &amp;lt;/tex&amp;gt;. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== insert ====&lt;br /&gt;
&lt;br /&gt;
Вставка элемента в фибоначчиеву кучу также тривиальна: создается новая куча из одного элемента и сливается с текущей. Для оценки амортизированной стоимости операции рассмотрим исходную кучу &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; и получившуюся в результате вставки нового элемента кучу &amp;lt;tex&amp;gt; H' &amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt; t[H'] = t[H] + 1 &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; m[H'] = m[H] &amp;lt;/tex&amp;gt;. Следовательно, увеличение потенциала составляет &amp;lt;tex&amp;gt; (t[H] + 1 + 2m[H]) - (t[H] + 2m[H]) = 1 &amp;lt;/tex&amp;gt;. Так как реальное время работы составляет &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, то амортизированная стоимость данной операции также равна &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== getMin ====&lt;br /&gt;
Возвращает указатель &amp;lt;tex&amp;gt;H.min&amp;lt;/tex&amp;gt;. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== merge ====&lt;br /&gt;
&lt;br /&gt;
Слияние двух фибоначчиевых куч происходит просто: объединяем списки этих куч в один, релаксируем минимум. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Амортизированное время работы также &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, поскольку, при объединении двух куч в одну, потенциалы обеих куч суммируются, итоговая сумма потенциалов не изменяется, &amp;lt;tex&amp;gt; \Phi_{n + 1} - \Phi_n = 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== extractMin ====&lt;br /&gt;
&lt;br /&gt;
Первая рассматриваемая операция, в ходе которой меняется структура кучи. Здесь используется вспомогательная процедура &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;. Возьмем указатель на &amp;lt;tex&amp;gt; H.min &amp;lt;/tex&amp;gt;, удалим эту вершину. Ее поддеревья (их не более, чем &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt; {{---}}  максимальная степень вершины в куче) объединим с корневым списком. Теперь вызываем процедуру &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;. После этой операции в списке корней остается не более чем &amp;lt;tex&amp;gt; D(n) + 1&amp;lt;/tex&amp;gt; узлов, среди которых нужно найти минимальный. Итоговая асимптотика операции &amp;lt;tex&amp;gt;\mathrm {extraxtMin}&amp;lt;/tex&amp;gt;, учитывая и вспомогательную функцию &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;, время работы которой доказывается ниже, равно: &amp;lt;tex&amp;gt; O(1)+O(D(n))+O(D(n))=O(D(n)) &amp;lt;/tex&amp;gt;. По доказанной выше [[#Лемма4|лемме]] &amp;lt;tex&amp;gt;O(D(n)) = O(\log(n))&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===== consolidate =====&lt;br /&gt;
&lt;br /&gt;
Данная процедура принимает кучу и преобразует ее таким образом, что в корневом списке остается не более &amp;lt;tex&amp;gt; D(n) + 1&amp;lt;/tex&amp;gt; вершин.&lt;br /&gt;
&lt;br /&gt;
Для этого возьмем массив списков указателей на корни деревьев &amp;lt;tex&amp;gt; A[0..D[H]] &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; D[H] &amp;lt;/tex&amp;gt; {{---}} максимальная степень вершины в текущем корневом списке.&lt;br /&gt;
&lt;br /&gt;
Затем происходит [[Биномиальная_куча#merge | процесс, аналогичный слиянию биномиальных куч]]: добавляем поочередно каждый корень, смотря на его степень. Пусть она равна &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;. Если в соответствующей ячейке &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; еще нету вершины, записываем текущую вершину туда. Иначе подвешиваем одно дерево к другому, и пытаемся также добавить дерево, степень корня которого уже равна &amp;lt;tex&amp;gt; d + 1 &amp;lt;/tex&amp;gt;. Продолжаем, пока не найдем свободную ячейку.&lt;br /&gt;
&lt;br /&gt;
Учетная стоимость &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt; равна &amp;lt;tex&amp;gt; O(D(n)) &amp;lt;/tex&amp;gt;. Докажем это:&lt;br /&gt;
&lt;br /&gt;
Изначально в корневом списке было не более &amp;lt;tex&amp;gt; D(n) + t[H] - 1 &amp;lt;/tex&amp;gt; вершин, поскольку он состоит из исходного списка корней с &amp;lt;tex&amp;gt;t[H]&amp;lt;/tex&amp;gt; узлами, минус извлеченный узел и плюс дочерние узлы, количество которых не превышает &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt;. В ходе операции &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt; мы сделали &amp;lt;tex&amp;gt; O(D(n) + t[H]) &amp;lt;/tex&amp;gt; слияний деревьев. Потенциал перед извлечением минимума равен &amp;lt;tex&amp;gt; t[H] + 2m[H] &amp;lt;/tex&amp;gt;, а после не превышает &amp;lt;tex&amp;gt; D(n) + 1 + 2m[H] &amp;lt;/tex&amp;gt;, поскольку в корневом списке остается не более  &amp;lt;tex&amp;gt; D(n) + 1 &amp;lt;/tex&amp;gt; узлов, а количество помеченных узлов не изменяется. Таким образом, амортизированная стоимость не превосходит&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; O(D(n) + t[H]) + (D(n) + 1 + 2m[H]) - (t[H] + 2m[H]) = O(D(n)) + O(t[H]) - t[H]&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Поскольку мы договорились, что можем масштабировать единицу потенциала таким образом, чтобы покрывать константное количество работы, то итоговая амортизационная оценка {{---}} &amp;lt;tex&amp;gt; O(D(n)) &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== decreaseKey ====&lt;br /&gt;
&lt;br /&gt;
Основная идея: хотим, чтобы учетная стоимость данной операции была &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Было бы хорошо, чтобы вершина не всплывала до корня, и тогда дерево не придется сильно перестраивать. Для этого при удобном случае будем вырезать поддерево полностью и перемещать его в корневой список. Итак, сам алгоритм:&lt;br /&gt;
&lt;br /&gt;
# Проверяем, если новое значение ключа все же не меньше значения ключа родителя, то все хорошо, и мы выходим.&lt;br /&gt;
# Иначе, вырезаем дерево с текущей вершиной в корневой список, и производим каскадное вырезание родителя. &lt;br /&gt;
&lt;br /&gt;
===== cut =====&lt;br /&gt;
&lt;br /&gt;
При вырезании вершины мы удаляем ее из списка детей своего родителя, уменьшаем степень ее родителя (&amp;lt;tex&amp;gt; x.p.degree &amp;lt;/tex&amp;gt;) и снимаем пометку с текущей вершины (&amp;lt;tex&amp;gt; x.mark = false &amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
===== cascadingCut =====&lt;br /&gt;
&lt;br /&gt;
[[File:Каскадное вырезание.png|thumb|500px|Пример каскадного вырезания]]&lt;br /&gt;
&lt;br /&gt;
Перед вызовом каскадного вырезания нам известно, удаляли ли ребенка у этой вершины. Если у вершины до этого не удаляли дочерний узел (&amp;lt;tex&amp;gt; x.mark = false &amp;lt;/tex&amp;gt;), то мы помечаем эту вершину (&amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt;) и прекращаем выполнение операции. В противном случае применяем операцию &amp;lt;tex&amp;gt;\mathrm {cut}&amp;lt;/tex&amp;gt; для текущей вершины и запускаем каскадное вырезание от родителя.&lt;br /&gt;
&lt;br /&gt;
'''Пример'''&lt;br /&gt;
&lt;br /&gt;
Рисунок иллюстрирует пример каскадного вырезания:&lt;br /&gt;
&lt;br /&gt;
* Изначально, куча состояла из &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; фибоначчиевых деревьев. У вершины с ключом &amp;lt;tex&amp;gt;24&amp;lt;/tex&amp;gt; отсутствует &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; ребенок.&lt;br /&gt;
* Уменьшаем ключ &amp;lt;tex&amp;gt;26&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; и делаем операцию &amp;lt;tex&amp;gt;\mathrm {cut}&amp;lt;/tex&amp;gt; этого дерева. Получаем кучу с &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt; деревьями и новым минимумом. Но у вершины с ключом &amp;lt;tex&amp;gt;24&amp;lt;/tex&amp;gt; был удален второй ребенок, поэтому запускам операцию &amp;lt;tex&amp;gt;\mathrm {cascadingCut}&amp;lt;/tex&amp;gt; для этой вершины: вырезаем ее, помещаем в корневой список и помечаем ее родителя.&lt;br /&gt;
* У вершины с ключом &amp;lt;tex&amp;gt;7&amp;lt;/tex&amp;gt; удален лишь один ребенок, поэтому операция &amp;lt;tex&amp;gt;\mathrm {cascadingCut}&amp;lt;/tex&amp;gt; от нее не запускается. В итоге, получаем кучу, состоящую из &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; фибоначчиевых деревьев.&lt;br /&gt;
&lt;br /&gt;
===== Время работы =====&lt;br /&gt;
&lt;br /&gt;
Докажем, что амортизированное время работы операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; есть &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Поскольку в процедуре нет циклов, ее время работы определяется лишь количеством рекурсивных вызовов каскадного вырезания.&lt;br /&gt;
&lt;br /&gt;
Пусть мы вызвали процедуру каскадного вырезания &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; раз. Так как реальное время работы операции &amp;lt;tex&amp;gt; \mathrm {cascadingCut} &amp;lt;/tex&amp;gt; без учета рекурсии составляет &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, то реальное время работы операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt; O(k) &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Рассмотрим, как изменится потенциал в результате выполнения данной операции. Пусть &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; {{---}} фибоначчиева куча до вызова &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt;. Тогда после &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; рекурсивных вызовов операции &amp;lt;tex&amp;gt; \mathrm {cascadingCut} &amp;lt;/tex&amp;gt; вершин с пометкой &amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt; стало как минимум на &amp;lt;tex&amp;gt; k - 2 &amp;lt;/tex&amp;gt; меньше, потому что каждый вызов каскадного вырезания, за исключением последнего, уменьшает количество помеченных вершин на одну, и в результате последнего вызова одну вершину мы можем пометить. В корневом списке прибавилось &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; новых деревьев (&amp;lt;tex&amp;gt; k - 1 &amp;lt;/tex&amp;gt; дерево за счет каскадного вырезания и еще одно из-за самого первого вызова операции &amp;lt;tex&amp;gt; \mathrm {cut} &amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
В итоге, изменение потенциала составляет: &amp;lt;tex&amp;gt; \Phi_i - \Phi_{i - 1} = ((t[H] + k) + 2(m[H] + k - 2)) - (t[H] + 2m[H]) = 4 - k &amp;lt;/tex&amp;gt;. Следовательно, амортизированная стоимость не превышает &amp;lt;tex&amp;gt; O(k) + 4 - k &amp;lt;/tex&amp;gt;. Но поскольку мы можем соответствующим образом масштабировать единицы потенциала, то амортизированная стоимость операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; равна &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== delete ====&lt;br /&gt;
&lt;br /&gt;
Удаление вершины реализуется через уменьшение ее ключа до &amp;lt;tex&amp;gt; -\infty &amp;lt;/tex&amp;gt; и последующим извлечением минимума. Амортизированное время работы: &amp;lt;tex&amp;gt; O(1) + O(D(n)) = O(D(n)) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Поскольку ранее мы показали, что &amp;lt;tex&amp;gt; D(n) = O(\log n ) &amp;lt;/tex&amp;gt;, то соответствующие оценки доказаны.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Левосторонняя куча]]&lt;br /&gt;
* [[Тонкая куча]]&lt;br /&gt;
* [[Толстая куча на избыточном счетчике]]&lt;br /&gt;
* [[Куча Бродала-Окасаки]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
&lt;br /&gt;
* Томас Кормен, Чарльз Лейзерсон, Рональд Ривест, Клиффорд Штайн — Алгоритмы: построение и анализ. — М.: Издательский дом «Вильямс», 2005. — С. 1296. — ISBN 5-8459-0857-4&lt;br /&gt;
* [[wikipedia:ru:Числа Фибоначчи|Числа Фибоначчи {{---}} Википедия]]&lt;br /&gt;
* [[wikipedia:ru:Фибоначчиева куча|Фибоначчиева куча {{---}} Википедия]]&lt;br /&gt;
* [http://www.intuit.ru/department/algorithms/dscm/7/2.html Фибоначчиевы кучи — INTUIT.ru]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/heaps Визуализаторы]&lt;br /&gt;
* [http://www.cs.duke.edu/courses/fall05/cps230/L-11.pdf Fibonacci Heaps]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Приоритетные очереди]]&lt;/div&gt;</summary>
		<author><name>217.66.156.128</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B1%D0%BE%D0%BD%D0%B0%D1%87%D1%87%D0%B8%D0%B5%D0%B2%D0%B0_%D0%BA%D1%83%D1%87%D0%B0&amp;diff=46763</id>
		<title>Фибоначчиева куча</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B1%D0%BE%D0%BD%D0%B0%D1%87%D1%87%D0%B8%D0%B5%D0%B2%D0%B0_%D0%BA%D1%83%D1%87%D0%B0&amp;diff=46763"/>
				<updated>2015-05-21T15:54:52Z</updated>
		
		<summary type="html">&lt;p&gt;217.66.156.128: /* Структура узла */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Фибоначчиево дерево ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Фибоначчиево дерево''' (англ. ''Fibonacci tree'') {{---}} [[Биномиальная куча#Биномиальное дерево |биномиальное дерево]], где у каждой вершины удалено не более одного ребенка.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Порядок фибоначчиева дерева''' (англ. ''Fibonacci tree rank'') {{---}} порядок соответствующего биномиального дерева, из которого оно получено.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Степень вершины''' (англ. ''degree'')  {{---}} количество дочерних узлов данной вершины.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма1&lt;br /&gt;
|statement=Для всех целых &amp;lt;tex&amp;gt; n \geqslant 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt; F_n = 1 + \sum\limits_{i=0}^{n-2} F_i &amp;lt;/tex&amp;gt;,&lt;br /&gt;
где &amp;lt;tex&amp;gt; F_n &amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt;-ое число Фибоначчи, определяемое формулой:&lt;br /&gt;
&amp;lt;tex&amp;gt;&lt;br /&gt;
F_n =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
 0, &amp;amp; n = 0 \\&lt;br /&gt;
 1, &amp;amp; n = 1 \\&lt;br /&gt;
 F_{n-1} + F_{n-2}, &amp;amp; n \geqslant 2&lt;br /&gt;
\end{cases} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Докажем лемму по индукции:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;tex&amp;gt;n = 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_2 = 1 + \sum\limits_{i=0}^0 F_i = 1 + 0 = 1&amp;lt;/tex&amp;gt;, что действительно верно.&lt;br /&gt;
&lt;br /&gt;
По индукции предполагаем, что &amp;lt;tex&amp;gt;F_{n-1} = 1 + \sum\limits_{i=0}^{n-3} F_i &amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_n = F_{n-1} + F_{n-2} = 1 + \sum\limits_{i=0}^{n-3} F_i + F_{n-2} = 1 + \sum\limits_{i=0}^{n-2} F_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма2&lt;br /&gt;
|statement= Фибоначчиево дерево порядка &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; содержит не менее &amp;lt;tex&amp;gt;F_n&amp;lt;/tex&amp;gt; вершин.&lt;br /&gt;
|proof=&lt;br /&gt;
Докажем это утверждение по индукции.&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;s_n&amp;lt;/tex&amp;gt; {{---}} минимальный размер фибоначчиева дерева порядка &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_0 = 1 &amp;gt; F_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_1 = 1 = F_1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предположим по индукции, что для всех &amp;lt;tex&amp;gt;i &amp;lt; n \ s_i \geqslant F_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Пусть в нашем дереве удалено поддерево порядка &amp;lt;tex&amp;gt;n - 1&amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_n = 1 + \sum\limits_{i=0}^{n-2} s_i \geqslant 1 + \sum\limits_{i=0}^{n-2} F_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Но по предыдущей [[#Лемма1|лемме]] :&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;tex&amp;gt;1 + \sum\limits_{i=0}^{n-2} F_i = F_n&amp;lt;/tex&amp;gt;. Следовательно, &amp;lt;tex&amp;gt;s_n \geqslant F_n&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Фибоначчиева куча ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Фибоначчиева куча''' (англ. ''Fibonacci heap'')   {{---}} набор фибоначчиевых деревьев, корни которых объединены в неупорядоченный [[Список#Циклический список |циклический]] [[Список#Двусвязный список | двусвязный список]]. В отличие от [[Биномиальная куча|биномиальной кучи]], степени корней не обязаны быть попарно различными.&lt;br /&gt;
}}&lt;br /&gt;
Фибоначчиевы кучи поддерживают тот же набор операций, что и биномиальные кучи, но имеют то преимущество, что операции, в которых не требуется удаление, имеют [[Амортизационный анализ|амортизированное]] время работы, равное &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
С теоретической точки зрения фибоначчиевы кучи особенно полезны в случае, когда количество операций &amp;lt;tex&amp;gt;\mathrm {extractMin}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt; относительно мало по сравнению с количеством других операций. Однако с практической точки зрения программная сложность и высокие значения постоянных множителей в формулах времени работы  существенно снижают эффективность применения фибоначчиевых куч, делая их в большинстве случаев менее привлекательными, чем обычные [[Двоичная куча|бинарные кучи]].&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма3&lt;br /&gt;
|statement= &amp;lt;tex&amp;gt;F_n =\Theta(\varphi^n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt; \varphi = \frac {1 + \sqrt 5} {2}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Для начала докажем, что &amp;lt;tex&amp;gt;F_n =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^n - (-\varphi)^{-n}} {\sqrt 5}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Используем для этого математическую индукцию.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_0 =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^0 - (-\varphi)^0} {\sqrt 5} = \frac {1 - 1} {\sqrt 5} = 0&amp;lt;/tex&amp;gt;, что верно.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_1 =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^1 - (-\varphi)^{-1}} {\sqrt 5} = \frac {1} {\sqrt 5}(\frac {1 + \sqrt 5} {2} - \frac {1 - \sqrt 5} {2}) = \frac {2\sqrt 5} {2\sqrt 5} = 1&amp;lt;/tex&amp;gt;, что также верно.&lt;br /&gt;
&lt;br /&gt;
По индукции предполагаем, что &amp;lt;tex&amp;gt;F_{n-1} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-1} - (-\varphi)^{1-n}} {\sqrt 5}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;F_{n-2} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-2} - (-\varphi)^{2-n}} {\sqrt 5}&amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_n = F_{n-1} + F_{n-2} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-1} - (-\varphi)^{1-n}} {\sqrt 5} + \frac {\varphi^{n-2} - (-\varphi)^{2-n}} {\sqrt 5} =&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;= \frac {1} {\sqrt 5}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(\varphi^{n-1} - (-\varphi)^{1-n} + \varphi^{n-2} - (-\varphi)^{2-n}) &amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;= \frac {1} {\sqrt 5}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(\varphi^{n}(\varphi^{-1} + \varphi^{-2}) - (-\varphi)^{-n}(-\varphi + \varphi^{2}))&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подставив вместо &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; его значение, нетрудно убедится, что &amp;lt;tex&amp;gt;\varphi^{-1} + \varphi^{-2} = -\varphi + \varphi^{2} = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Поскольку &amp;lt;tex&amp;gt;\left\vert (-\varphi)^{-1} \right\vert &amp;lt; 1&amp;lt;/tex&amp;gt;, то выполняются неравенства &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {(-\varphi)^{-n}} {\sqrt 5} &amp;lt; \frac {1} {\sqrt 5} &amp;lt; \frac {1} {2}&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;-ое число Фибоначчи равно &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n}} {\sqrt 5}&amp;lt;/tex&amp;gt;, округленному до ближайшего целого числа. Следовательно, &amp;lt;tex&amp;gt;F_n =\Theta(\varphi^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма4&lt;br /&gt;
|statement=Максимальная степень &amp;lt;tex&amp;gt;D(n)&amp;lt;/tex&amp;gt; произвольной вершины в фибоначчиевой куче с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершинами равна &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; {{---}} произвольная вершина в фибоначчиевой куче с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершинами, и пусть &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; {{---}} степень вершины &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;. Тогда по [[#Лемма2|доказанному выше]] в дереве, корень которого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, содержится не менее &amp;lt;tex&amp;gt;F_k&amp;lt;/tex&amp;gt; вершин, что в свою очередь по [[#Лемма3|лемме]] равно &amp;lt;tex&amp;gt;\Theta(\varphi^k)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
То есть&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;n \geqslant \varphi^{k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Логарифмируя по основанию &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt;, получаем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\log_{\varphi}n \geqslant k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом, максимальная степень &amp;lt;tex&amp;gt;D(n)&amp;lt;/tex&amp;gt; произвольной вершины равна &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Структура ===&lt;br /&gt;
====Структура узла====&lt;br /&gt;
Каждый узел &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; в куче &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; содержит следующие указатели и поля:&lt;br /&gt;
 '''struct''' Node&lt;br /&gt;
    '''int''' key &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;     // ключ&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' p &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;      // указатель на родительский узел&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' child &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;  // указатель на один из дочерних узлов&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' left &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;   // указатель  на левый сестринский узел&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' right &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;  // указатель на правый сестринский узел&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''int''' degree &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;  // количество дочерних узлов&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''boolean''' mark &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// флаг, который показывает, удаляли ли мы дочерние узлы данной вершины&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Структура кучи====&lt;br /&gt;
 '''struct''' Heap&lt;br /&gt;
    '''int''' size &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// текущее количество узлов&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' min &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// указатель на корень дерева с минимальным ключом&amp;lt;/span&amp;gt;&lt;br /&gt;
====Структура списка детей====&lt;br /&gt;
[[File:Fibonacci-heap.png|thumb|340px|Пример фибоначчиевой кучи]]&lt;br /&gt;
* Дочерние узлы &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; объединены при помощи указателей &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; в  циклический двусвязный список.&lt;br /&gt;
* Корни всех деревьев в &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; связаны при помощи указателей &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; в циклический двусвязный список корней.&lt;br /&gt;
&lt;br /&gt;
Циклический двусвязный список обладает двумя преимуществами для использования в фибоначчиевых кучах. Во-первых, удаление элемента из такого списка выполняется за время &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;. Во-вторых, если имеется два таких списка, их легко объединить в один за время &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Потенциал ===&lt;br /&gt;
&lt;br /&gt;
Для анализа производительности операций введем потенциал для фибоначчиевой кучи &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; как &amp;lt;tex&amp;gt; \Phi(H) = t[H] + 2m[H] &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; t[H] &amp;lt;/tex&amp;gt; {{---}} количество элементов в корневом списке кучи, а &amp;lt;tex&amp;gt; m[H] &amp;lt;/tex&amp;gt; {{---}} количество вершин, у которых удален один ребенок (то есть вершин с пометкой &amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt;). Договоримся, что единицы потенциала достаточно для оплаты константного количества работы.&lt;br /&gt;
&lt;br /&gt;
=== Операции ===&lt;br /&gt;
Рассмотрим операции, которые поддерживают фибоначчиевы кучи. Амортизированное время их работы показано в таблице.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Операция&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Амортизированная сложность&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {makeHeap}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {insert}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {getMin}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {merge}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {extractMin}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(\log n )&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {decreaseKey}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(\log n )&amp;lt;/tex&amp;gt; &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Стоит заметить, что структура фибоначчиевых куч, также как биномиальных и бинарных, не могут обеспечить эффективную реализацию поиска элемента с заданным ключом, поэтому операции &amp;lt;tex&amp;gt;\mathrm {decreaseKey}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt; получают в качестве аргумента указатель на узел, а не значение его ключа.&lt;br /&gt;
&lt;br /&gt;
==== makeHeap ====&lt;br /&gt;
&lt;br /&gt;
Создается новый пустой корневой список, в &amp;lt;tex&amp;gt; H.min &amp;lt;/tex&amp;gt; устанавливается значение &amp;lt;tex&amp;gt; null &amp;lt;/tex&amp;gt;. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== insert ====&lt;br /&gt;
&lt;br /&gt;
Вставка элемента в фибоначчиеву кучу также тривиальна: создается новая куча из одного элемента и сливается с текущей. Для оценки амортизированной стоимости операции рассмотрим исходную кучу &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; и получившуюся в результате вставки нового элемента кучу &amp;lt;tex&amp;gt; H' &amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt; t[H'] = t[H] + 1 &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; m[H'] = m[H] &amp;lt;/tex&amp;gt;. Следовательно, увеличение потенциала составляет &amp;lt;tex&amp;gt; (t[H] + 1 + 2m[H]) - (t[H] + 2m[H]) = 1 &amp;lt;/tex&amp;gt;. Так как реальное время работы составляет &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, то амортизированная стоимость данной операции также равна &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== getMin ====&lt;br /&gt;
Возвращает указатель &amp;lt;tex&amp;gt;H.min&amp;lt;/tex&amp;gt;. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== merge ====&lt;br /&gt;
&lt;br /&gt;
Слияние двух фибоначчиевых куч происходит просто: объединяем списки этих куч в один, релаксируем минимум. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Амортизированное время работы также &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, поскольку, при объединении двух куч в одну, потенциалы обеих куч суммируются, итоговая сумма потенциалов не изменяется, &amp;lt;tex&amp;gt; \Phi_{n + 1} - \Phi_n = 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== extractMin ====&lt;br /&gt;
&lt;br /&gt;
Первая рассматриваемая операция, в ходе которой меняется структура кучи. Здесь используется вспомогательная процедура &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;. Возьмем указатель на &amp;lt;tex&amp;gt; H.min &amp;lt;/tex&amp;gt;, удалим эту вершину. Ее поддеревья (их не более, чем &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt; {{---}}  максимальная степень вершины в куче) объединим с корневым списком. Теперь вызываем процедуру &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;. После этой операции в списке корней остается не более чем &amp;lt;tex&amp;gt; D(n) + 1&amp;lt;/tex&amp;gt; узлов, среди которых нужно найти минимальный. Итоговая асимптотика операции &amp;lt;tex&amp;gt;\mathrm {extraxtMin}&amp;lt;/tex&amp;gt;, учитывая и вспомогательную функцию &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;, время работы которой доказывается ниже, равно: &amp;lt;tex&amp;gt; O(1)+O(D(n))+O(D(n))=O(D(n)) &amp;lt;/tex&amp;gt;. По доказанной выше [[#Лемма4|лемме]] &amp;lt;tex&amp;gt;O(D(n)) = O(\log(n))&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===== consolidate =====&lt;br /&gt;
&lt;br /&gt;
Данная процедура принимает кучу и преобразует ее таким образом, что в корневом списке остается не более &amp;lt;tex&amp;gt; D(n) + 1&amp;lt;/tex&amp;gt; вершин.&lt;br /&gt;
&lt;br /&gt;
Для этого возьмем массив списков указателей на корни деревьев &amp;lt;tex&amp;gt; A[0..D[H]] &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; D[H] &amp;lt;/tex&amp;gt; {{---}} максимальная степень вершины в текущем корневом списке.&lt;br /&gt;
&lt;br /&gt;
Затем происходит [[Биномиальная_куча#merge | процесс, аналогичный слиянию биномиальных куч]]: добавляем поочередно каждый корень, смотря на его степень. Пусть она равна &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;. Если в соответствующей ячейке &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; еще нету вершины, записываем текущую вершину туда. Иначе подвешиваем одно дерево к другому, и пытаемся также добавить дерево, степень корня которого уже равна &amp;lt;tex&amp;gt; d + 1 &amp;lt;/tex&amp;gt;. Продолжаем, пока не найдем свободную ячейку.&lt;br /&gt;
&lt;br /&gt;
Учетная стоимость &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt; равна &amp;lt;tex&amp;gt; O(D(n)) &amp;lt;/tex&amp;gt;. Докажем это:&lt;br /&gt;
&lt;br /&gt;
Изначально в корневом списке было не более &amp;lt;tex&amp;gt; D(n) + t[H] - 1 &amp;lt;/tex&amp;gt; вершин, поскольку он состоит из исходного списка корней с &amp;lt;tex&amp;gt;t[H]&amp;lt;/tex&amp;gt; узлами, минус извлеченный узел и плюс дочерние узлы, количество которых не превышает &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt;. В ходе операции &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt; мы сделали &amp;lt;tex&amp;gt; O(D(n) + t[H]) &amp;lt;/tex&amp;gt; слияний деревьев. Потенциал перед извлечением минимума равен &amp;lt;tex&amp;gt; t[H] + 2m[H] &amp;lt;/tex&amp;gt;, а после не превышает &amp;lt;tex&amp;gt; D(n) + 1 + 2m[H] &amp;lt;/tex&amp;gt;, поскольку в корневом списке остается не более  &amp;lt;tex&amp;gt; D(n) + 1 &amp;lt;/tex&amp;gt; узлов, а количество помеченных узлов не изменяется. Таким образом, амортизированная стоимость не превосходит&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; O(D(n) + t[H]) + (D(n) + 1 + 2m[H]) - (t[H] + 2m[H]) = O(D(n)) + O(t[H]) - t[H]&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Поскольку мы договорились, что можем масштабировать единицу потенциала таким образом, чтобы покрывать константное количество работы, то итоговая амортизационная оценка {{---}} &amp;lt;tex&amp;gt; O(D(n)) &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== decreaseKey ====&lt;br /&gt;
&lt;br /&gt;
Основная идея: хотим, чтобы учетная стоимость данной операции была &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Было бы хорошо, чтобы вершина не всплывала до корня, и тогда дерево не придется сильно перестраивать. Для этого при удобном случае будем вырезать поддерево полностью и перемещать его в корневой список. Итак, сам алгоритм:&lt;br /&gt;
&lt;br /&gt;
# Проверяем, если новое значение ключа все же не меньше значения ключа родителя, то все хорошо, и мы выходим.&lt;br /&gt;
# Иначе, вырезаем дерево с текущей вершиной в корневой список, и производим каскадное вырезание родителя. &lt;br /&gt;
&lt;br /&gt;
===== cut =====&lt;br /&gt;
&lt;br /&gt;
При вырезании вершины мы удаляем ее из списка детей своего родителя, уменьшаем степень ее родителя (&amp;lt;tex&amp;gt; x.p.degree &amp;lt;/tex&amp;gt;) и снимаем пометку с текущей вершины (&amp;lt;tex&amp;gt; x.mark = false &amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
===== cascadingCut =====&lt;br /&gt;
&lt;br /&gt;
[[File:Каскадное вырезание.png|thumb|500px|Пример каскадного вырезания]]&lt;br /&gt;
&lt;br /&gt;
Перед вызовом каскадного вырезания нам известно, удаляли ли ребенка у этой вершины. Если у вершины до этого не удаляли дочерний узел (&amp;lt;tex&amp;gt; x.mark = false &amp;lt;/tex&amp;gt;), то мы помечаем эту вершину (&amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt;) и прекращаем выполнение операции. В противном случае применяем операцию &amp;lt;tex&amp;gt;\mathrm {cut}&amp;lt;/tex&amp;gt; для текущей вершины и запускаем каскадное вырезание от родителя.&lt;br /&gt;
&lt;br /&gt;
'''Пример'''&lt;br /&gt;
&lt;br /&gt;
Рисунок иллюстрирует пример каскадного вырезания:&lt;br /&gt;
&lt;br /&gt;
* Изначально, куча состояла из &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; фибоначчиевых деревьев. У вершины с ключом &amp;lt;tex&amp;gt;24&amp;lt;/tex&amp;gt; отсутствует &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; ребенок.&lt;br /&gt;
* Уменьшаем ключ &amp;lt;tex&amp;gt;26&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; и делаем операцию &amp;lt;tex&amp;gt;\mathrm {cut}&amp;lt;/tex&amp;gt; этого дерева. Получаем кучу с &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt; деревьями и новым минимумом. Но у вершины с ключом &amp;lt;tex&amp;gt;24&amp;lt;/tex&amp;gt; был удален второй ребенок, поэтому запускам операцию &amp;lt;tex&amp;gt;\mathrm {cascadingCut}&amp;lt;/tex&amp;gt; для этой вершины: вырезаем ее, помещаем в корневой список и помечаем ее родителя.&lt;br /&gt;
* У вершины с ключом &amp;lt;tex&amp;gt;7&amp;lt;/tex&amp;gt; удален лишь один ребенок, поэтому операция &amp;lt;tex&amp;gt;\mathrm {cascadingCut}&amp;lt;/tex&amp;gt; от нее не запускается. В итоге, получаем кучу, состоящую из &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; фибоначчиевых деревьев.&lt;br /&gt;
&lt;br /&gt;
===== Время работы =====&lt;br /&gt;
&lt;br /&gt;
Докажем, что амортизированное время работы операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; есть &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Поскольку в процедуре нет циклов, ее время работы определяется лишь количеством рекурсивных вызовов каскадного вырезания.&lt;br /&gt;
&lt;br /&gt;
Пусть мы вызвали процедуру каскадного вырезания &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; раз. Так как реальное время работы операции &amp;lt;tex&amp;gt; \mathrm {cascadingCut} &amp;lt;/tex&amp;gt; без учета рекурсии составляет &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, то реальное время работы операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt; O(k) &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Рассмотрим, как изменится потенциал в результате выполнения данной операции. Пусть &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; {{---}} фибоначчиева куча до вызова &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt;. Тогда после &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; рекурсивных вызовов операции &amp;lt;tex&amp;gt; \mathrm {cascadingCut} &amp;lt;/tex&amp;gt; вершин с пометкой &amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt; стало как минимум на &amp;lt;tex&amp;gt; k - 2 &amp;lt;/tex&amp;gt; меньше, потому что каждый вызов каскадного вырезания, за исключением последнего, уменьшает количество помеченных вершин на одну, и в результате последнего вызова одну вершину мы можем пометить. В корневом списке прибавилось &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; новых деревьев (&amp;lt;tex&amp;gt; k - 1 &amp;lt;/tex&amp;gt; дерево за счет каскадного вырезания и еще одно из-за самого первого вызова операции &amp;lt;tex&amp;gt; \mathrm {cut} &amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
В итоге, изменение потенциала составляет: &amp;lt;tex&amp;gt; \Phi_i - \Phi_{i - 1} = ((t[H] + k) + 2(m[H] + k - 2)) - (t[H] + 2m[H]) = 4 - k &amp;lt;/tex&amp;gt;. Следовательно, амортизированная стоимость не превышает &amp;lt;tex&amp;gt; O(k) + 4 - k &amp;lt;/tex&amp;gt;. Но поскольку мы можем соответствующим образом масштабировать единицы потенциала, то амортизированная стоимость операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; равна &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== delete ====&lt;br /&gt;
&lt;br /&gt;
Удаление вершины реализуется через уменьшение ее ключа до &amp;lt;tex&amp;gt; -\infty &amp;lt;/tex&amp;gt; и последующим извлечением минимума. Амортизированное время работы: &amp;lt;tex&amp;gt; O(1) + O(D(n)) = O(D(n)) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Поскольку ранее мы показали, что &amp;lt;tex&amp;gt; D(n) = O(\log n ) &amp;lt;/tex&amp;gt;, то соответствующие оценки доказаны.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Левосторонняя куча]]&lt;br /&gt;
* [[Тонкая куча]]&lt;br /&gt;
* [[Толстая куча на избыточном счетчике]]&lt;br /&gt;
* [[Куча Бродала-Окасаки]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
&lt;br /&gt;
* Томас Кормен, Чарльз Лейзерсон, Рональд Ривест, Клиффорд Штайн — Алгоритмы: построение и анализ. — М.: Издательский дом «Вильямс», 2005. — С. 1296. — ISBN 5-8459-0857-4&lt;br /&gt;
* [[wikipedia:ru:Числа Фибоначчи|Числа Фибоначчи {{---}} Википедия]]&lt;br /&gt;
* [[wikipedia:ru:Фибоначчиева куча|Фибоначчиева куча {{---}} Википедия]]&lt;br /&gt;
* [http://www.intuit.ru/department/algorithms/dscm/7/2.html Фибоначчиевы кучи — INTUIT.ru]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/heaps Визуализаторы]&lt;br /&gt;
* [http://www.cs.duke.edu/courses/fall05/cps230/L-11.pdf Fibonacci Heaps]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Приоритетные очереди]]&lt;/div&gt;</summary>
		<author><name>217.66.156.128</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B1%D0%BE%D0%BD%D0%B0%D1%87%D1%87%D0%B8%D0%B5%D0%B2%D0%B0_%D0%BA%D1%83%D1%87%D0%B0&amp;diff=46735</id>
		<title>Фибоначчиева куча</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B1%D0%BE%D0%BD%D0%B0%D1%87%D1%87%D0%B8%D0%B5%D0%B2%D0%B0_%D0%BA%D1%83%D1%87%D0%B0&amp;diff=46735"/>
				<updated>2015-05-20T17:55:50Z</updated>
		
		<summary type="html">&lt;p&gt;217.66.156.128: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Фибоначчиево дерево ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Фибоначчиево дерево''' (англ. ''Fibonacci tree'') {{---}} [[Биномиальная куча#Биномиальное дерево |биномиальное дерево]], где у каждой вершины удалено не более одного ребенка.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Порядок фибоначчиева дерева''' (англ. ''Fibonacci tree order'') {{---}} порядок соответствующего биномиального дерева, из которого оно получено.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Степень вершины''' (англ. ''degree'')  {{---}} количество дочерних узлов данной вершины.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма1&lt;br /&gt;
|statement=Для всех целых &amp;lt;tex&amp;gt; n \geqslant 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt; F_n = 1 + \sum\limits_{i=0}^{n-2} F_i &amp;lt;/tex&amp;gt;,&lt;br /&gt;
где &amp;lt;tex&amp;gt; F_n &amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt;-ое число Фибоначчи, определяемое формулой:&lt;br /&gt;
&amp;lt;tex&amp;gt;&lt;br /&gt;
F_n =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
 0, &amp;amp; n = 0 \\&lt;br /&gt;
 1, &amp;amp; n = 1 \\&lt;br /&gt;
 F_{n-1} + F_{n-2}, &amp;amp; n \geqslant 2&lt;br /&gt;
\end{cases} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Докажем лемму по индукции:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;tex&amp;gt;n = 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_2 = 1 + \sum\limits_{i=0}^0 F_i = 1 + 0 = 1&amp;lt;/tex&amp;gt;, что действительно верно.&lt;br /&gt;
&lt;br /&gt;
По индукции предполагаем, что &amp;lt;tex&amp;gt;F_{n-1} = 1 + \sum\limits_{i=0}^{n-3} F_i &amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_n = F_{n-1} + F_{n-2} = 1 + \sum\limits_{i=0}^{n-3} F_i + F_{n-2} = 1 + \sum\limits_{i=0}^{n-2} F_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма2&lt;br /&gt;
|statement= Фибоначчиево дерево порядка &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; содержит не менее &amp;lt;tex&amp;gt;F_n&amp;lt;/tex&amp;gt; вершин.&lt;br /&gt;
|proof=&lt;br /&gt;
Докажем это утверждение по индукции.&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;s_n&amp;lt;/tex&amp;gt; {{---}} минимальный размер фибоначчиева дерева порядка &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_0 = 1 &amp;gt; F_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_1 = 1 = F_1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предположим по индукции, что для всех &amp;lt;tex&amp;gt;i &amp;lt; n \ s_i \geqslant F_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Пусть в нашем дереве удалено поддерево порядка &amp;lt;tex&amp;gt;n - 1&amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_n = 1 + \sum\limits_{i=0}^{n-2} s_i \geqslant 1 + \sum\limits_{i=0}^{n-2} F_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Но по предыдущей [[#Лемма1|лемме]] :&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;tex&amp;gt;1 + \sum\limits_{i=0}^{n-2} F_i = F_n&amp;lt;/tex&amp;gt;. Следовательно, &amp;lt;tex&amp;gt;s_n \geqslant F_n&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Фибоначчиева куча ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Фибоначчиева куча''' (англ. ''Fibonacci heap'')   {{---}} набор фибоначчиевых деревьев, корни которых объединены в неупорядоченный [[Список#Циклический список |циклический]] [[Список#Двусвязный список | двусвязный список]]. В отличие от [[Биномиальная куча|биномиальной кучи]], степени корней не обязаны быть попарно различными.&lt;br /&gt;
}}&lt;br /&gt;
Фибоначчиевы кучи поддерживают тот же набор операций, что и биномиальные кучи, но имеют то преимущество, что операции, в которых не требуется удаление, имеют [[Амортизационный анализ|амортизированное]] время работы, равное &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
С теоретической точки зрения фибоначчиевы кучи особенно полезны в случае, когда количество операций &amp;lt;tex&amp;gt;\mathrm {extractMin}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt; относительно мало по сравнению с количеством других операций. Однако с практической точки зрения программная сложность и высокие значения постоянных множителей в формулах времени работы  существенно снижают эффективность применения фибоначчиевых куч, делая их в большинстве случаев менее привлекательными, чем обычные [[Двоичная куча|бинарные кучи]].&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма3&lt;br /&gt;
|statement= &amp;lt;tex&amp;gt;F_n =\Theta(\varphi^n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt; \varphi = \frac {1 + \sqrt 5} {2}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Для начала докажем, что &amp;lt;tex&amp;gt;F_n =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^n - (-\varphi)^{-n}} {\sqrt 5}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Используем для этого математическую индукцию.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_0 =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^0 - (-\varphi)^0} {\sqrt 5} = \frac {1 - 1} {\sqrt 5} = 0&amp;lt;/tex&amp;gt;, что верно.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_1 =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^1 - (-\varphi)^{-1}} {\sqrt 5} = \frac {1} {\sqrt 5}(\frac {1 + \sqrt 5} {2} - \frac {1 - \sqrt 5} {2}) = \frac {2\sqrt 5} {2\sqrt 5} = 1&amp;lt;/tex&amp;gt;, что также верно.&lt;br /&gt;
&lt;br /&gt;
По индукции предполагаем, что &amp;lt;tex&amp;gt;F_{n-1} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-1} - (-\varphi)^{1-n}} {\sqrt 5}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;F_{n-2} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-2} - (-\varphi)^{2-n}} {\sqrt 5}&amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_n = F_{n-1} + F_{n-2} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-1} - (-\varphi)^{1-n}} {\sqrt 5} + \frac {\varphi^{n-2} - (-\varphi)^{2-n}} {\sqrt 5} =&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;= \frac {1} {\sqrt 5}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(\varphi^{n-1} - (-\varphi)^{1-n} + \varphi^{n-2} - (-\varphi)^{2-n}) &amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;= \frac {1} {\sqrt 5}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(\varphi^{n}(\varphi^{-1} + \varphi^{-2}) - (-\varphi)^{-n}(-\varphi + \varphi^{2}))&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подставив вместо &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; его значение, нетрудно убедится, что &amp;lt;tex&amp;gt;\varphi^{-1} + \varphi^{-2} = -\varphi + \varphi^{2} = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Поскольку &amp;lt;tex&amp;gt;\left\vert (-\varphi)^{-1} \right\vert &amp;lt; 1&amp;lt;/tex&amp;gt;, то выполняются неравенства &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {(-\varphi)^{-n}} {\sqrt 5} &amp;lt; \frac {1} {\sqrt 5} &amp;lt; \frac {1} {2}&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;-ое число Фибоначчи равно &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n}} {\sqrt 5}&amp;lt;/tex&amp;gt;, округленному до ближайшего целого числа. Следовательно, &amp;lt;tex&amp;gt;F_n =\Theta(\varphi^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма4&lt;br /&gt;
|statement=Максимальная степень &amp;lt;tex&amp;gt;D(n)&amp;lt;/tex&amp;gt; произвольной вершины в фибоначчиевой куче с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершинами равна &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; {{---}} произвольная вершина в фибоначчиевой куче с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершинами, и пусть &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; {{---}} степень вершины &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;. Тогда по [[#Лемма2|доказанному выше]] в дереве, корень которого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, содержится не менее &amp;lt;tex&amp;gt;F_k&amp;lt;/tex&amp;gt; вершин, что в свою очередь по [[#Лемма3|лемме]] равно &amp;lt;tex&amp;gt;\Theta(\varphi^k)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
То есть&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;n \geqslant \varphi^{k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Логарифмируя по основанию &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt;, получаем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\log_{\varphi}n \geqslant k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом, максимальная степень &amp;lt;tex&amp;gt;D(n)&amp;lt;/tex&amp;gt; произвольной вершины равна &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Структура ===&lt;br /&gt;
====Структура узла====&lt;br /&gt;
Каждый узел &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; в куче &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; содержит следующие указатели и поля:&lt;br /&gt;
 '''struct''' Node&lt;br /&gt;
    '''int''' key &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// ключ&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' p &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// указатель на родительский узел&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' child &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// указатель на один из дочерних узлов&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' left &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// указатель  на левый сестринский узел&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' right &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// указатель на правый сестринский узел&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''int''' degree &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// количество дочерних узлов&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''boolean''' mark &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// флаг, который показывает, удаляли ли мы дочерние узлы данной вершины&amp;lt;/span&amp;gt;&lt;br /&gt;
====Структура списка детей====&lt;br /&gt;
[[File:Fibonacci-heap.png|thumb|340px|Пример фибоначчиевой кучи]]&lt;br /&gt;
* Дочерние узлы &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; объединены при помощи указателей &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; в  циклический двусвязный список.&lt;br /&gt;
* Корни всех деревьев в &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; связаны при помощи указателей &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; в циклический двусвязный список корней.&lt;br /&gt;
* Обращение к &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; выполняется посредством указателя &amp;lt;tex&amp;gt;H.min&amp;lt;/tex&amp;gt; на корень дерева с минимальным ключом. Этот узел называется минимальным узлом &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Текущее количество узлов в &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; хранится в &amp;lt;tex&amp;gt;H.size&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Циклический двусвязный список обладает двумя преимуществами для использования в фибоначчиевых кучах. Во-первых, удаление элемента из такого списка выполняется за время &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;. Во-вторых, если имеется два таких списка, их легко объединить в один за время &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Потенциал ===&lt;br /&gt;
&lt;br /&gt;
Для анализа производительности операций введем потенциал для фибоначчиевой кучи &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; как &amp;lt;tex&amp;gt; \Phi(H) = t[H] + 2m[H] &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; t[H] &amp;lt;/tex&amp;gt; {{---}} количество элементов в корневом списке кучи, а &amp;lt;tex&amp;gt; m[H] &amp;lt;/tex&amp;gt; {{---}} количество вершин, у которых удален один ребенок (то есть вершин с пометкой &amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt;). Договоримся, что единицы потенциала достаточно для оплаты константного количества работы.&lt;br /&gt;
&lt;br /&gt;
=== Операции ===&lt;br /&gt;
Рассмотрим операции, которые поддерживают фибоначчиевы кучи. Амортизированное время их работы показано в таблице.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Операция&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Амортизированная сложность&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {makeHeap}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {insert}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {getMin}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {merge}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {extractMin}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(\log n )&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {decreaseKey}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(\log n )&amp;lt;/tex&amp;gt; &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Стоит заметить, что структура фибоначчиевых куч, также как биномиальных и бинарных, не могут обеспечить эффективную реализацию поиска элемента с заданным ключом, поэтому операции &amp;lt;tex&amp;gt;\mathrm {decreaseKey}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt; получают в качестве аргумента указатель на узел, а не значение его ключа.&lt;br /&gt;
&lt;br /&gt;
==== makeHeap ====&lt;br /&gt;
&lt;br /&gt;
Создается новый пустой корневой список, в &amp;lt;tex&amp;gt; H.min &amp;lt;/tex&amp;gt; устанавливается значение &amp;lt;tex&amp;gt; null &amp;lt;/tex&amp;gt;. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== insert ====&lt;br /&gt;
&lt;br /&gt;
Вставка элемента в фибоначчиеву кучу также тривиальна: создается новая куча из одного элемента и сливается с текущей. Для оценки амортизированной стоимости операции рассмотрим исходную кучу &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; и получившуюся в результате вставки нового элемента кучу &amp;lt;tex&amp;gt; H' &amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt; t[H'] = t[H] + 1 &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; m[H'] = m[H] &amp;lt;/tex&amp;gt;. Следовательно, увеличение потенциала составляет &amp;lt;tex&amp;gt; (t[H] + 1 + 2m[H]) - (t[H] + 2m[H]) = 1 &amp;lt;/tex&amp;gt;. Так как реальное время работы составляет &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, то амортизированная стоимость данной операции также равна &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== getMin ====&lt;br /&gt;
Возвращает указатель &amp;lt;tex&amp;gt;H.min&amp;lt;/tex&amp;gt;. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== merge ====&lt;br /&gt;
&lt;br /&gt;
Слияние двух фибоначчиевых куч происходит просто: объединяем списки этих куч в один, релаксируем минимум. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Амортизированное время работы также &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, поскольку, при объединении двух куч в одну, потенциалы обеих куч суммируются, итоговая сумма потенциалов не изменяется, &amp;lt;tex&amp;gt; \Phi_{n + 1} - \Phi_n = 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== extractMin ====&lt;br /&gt;
&lt;br /&gt;
Первая рассматриваемая операция, в ходе которой меняется структура кучи. Здесь используется вспомогательная процедура &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;. Возьмем указатель на &amp;lt;tex&amp;gt; H.min &amp;lt;/tex&amp;gt;, удалим эту вершину. Ее поддеревья (их не более, чем &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt; {{---}}  максимальная степень вершины в куче) объединим с корневым списком. Теперь вызываем процедуру &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;. После этой операции в списке корней остается не более чем &amp;lt;tex&amp;gt; D(n) + 1&amp;lt;/tex&amp;gt; узлов, среди которых нужно найти минимальный. Итоговая асимптотика операции &amp;lt;tex&amp;gt;\mathrm {extraxtMin}&amp;lt;/tex&amp;gt;, учитывая и вспомогательную функцию &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;, время работы которой доказывается ниже, равно: &amp;lt;tex&amp;gt; O(1)+O(D(n))+O(D(n))=O(D(n)) &amp;lt;/tex&amp;gt;. По доказанной выше [[#Лемма4|лемме]] &amp;lt;tex&amp;gt;O(D(n)) = O(\log(n))&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===== consolidate =====&lt;br /&gt;
&lt;br /&gt;
Данная процедура принимает кучу и преобразует ее таким образом, что в корневом списке остается не более &amp;lt;tex&amp;gt; D(n) + 1&amp;lt;/tex&amp;gt; вершин.&lt;br /&gt;
&lt;br /&gt;
Для этого возьмем массив списков указателей на корни деревьев &amp;lt;tex&amp;gt; A[0..D[H]] &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; D[H] &amp;lt;/tex&amp;gt; {{---}} максимальная степень вершины в текущем корневом списке.&lt;br /&gt;
&lt;br /&gt;
Затем происходит [[Биномиальная_куча#merge | процесс, аналогичный слиянию биномиальных куч]]: добавляем поочередно каждый корень, смотря на его степень. Пусть она равна &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;. Если в соответствующей ячейке &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; еще нету вершины, записываем текущую вершину туда. Иначе подвешиваем одно дерево к другому, и пытаемся также добавить дерево, степень корня которого уже равна &amp;lt;tex&amp;gt; d + 1 &amp;lt;/tex&amp;gt;. Продолжаем, пока не найдем свободную ячейку.&lt;br /&gt;
&lt;br /&gt;
Учетная стоимость &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt; равна &amp;lt;tex&amp;gt; O(D(n)) &amp;lt;/tex&amp;gt;. Докажем это:&lt;br /&gt;
&lt;br /&gt;
Изначально в корневом списке было не более &amp;lt;tex&amp;gt; D(n) + t[H] - 1 &amp;lt;/tex&amp;gt; вершин, поскольку он состоит из исходного списка корней с &amp;lt;tex&amp;gt;t[H]&amp;lt;/tex&amp;gt; узлами, минус извлеченный узел и плюс дочерние узлы, количество которых не превышает &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt;. В ходе операции &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt; мы сделали &amp;lt;tex&amp;gt; O(D(n) + t[H]) &amp;lt;/tex&amp;gt; слияний деревьев. Потенциал перед извлечением минимума равен &amp;lt;tex&amp;gt; t[H] + 2m[H] &amp;lt;/tex&amp;gt;, а после не превышает &amp;lt;tex&amp;gt; D(n) + 1 + 2m[H] &amp;lt;/tex&amp;gt;, поскольку в корневом списке остается не более  &amp;lt;tex&amp;gt; D(n) + 1 &amp;lt;/tex&amp;gt; узлов, а количество помеченных узлов не изменяется. Таким образом, амортизированная стоимость не превосходит&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; O(D(n) + t[H]) + (D(n) + 1 + 2m[H]) - (t[H] + 2m[H]) = O(D(n)) + O(t[H]) - t[H]&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Поскольку мы договорились, что можем масштабировать единицу потенциала таким образом, чтобы покрывать константное количество работы, то итоговая амортизационная оценка {{---}} &amp;lt;tex&amp;gt; O(D(n)) &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== decreaseKey ====&lt;br /&gt;
&lt;br /&gt;
Основная идея: хотим, чтобы учетная стоимость данной операции была &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Было бы хорошо, чтобы вершина не всплывала до корня, и тогда дерево не придется сильно перестраивать. Для этого при удобном случае будем вырезать поддерево полностью и перемещать его в корневой список. Итак, сам алгоритм:&lt;br /&gt;
&lt;br /&gt;
# Проверяем, если новое значение ключа все же не меньше значения ключа родителя, то все хорошо, и мы выходим.&lt;br /&gt;
# Иначе, вырезаем дерево с текущей вершиной в корневой список, и производим каскадное вырезание родителя. &lt;br /&gt;
&lt;br /&gt;
===== cut =====&lt;br /&gt;
&lt;br /&gt;
При вырезании вершины мы удаляем ее из списка детей своего родителя, уменьшаем степень ее родителя (&amp;lt;tex&amp;gt; x.p.degree &amp;lt;/tex&amp;gt;) и снимаем пометку с текущей вершины (&amp;lt;tex&amp;gt; x.mark = false &amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
===== cascadingCut =====&lt;br /&gt;
&lt;br /&gt;
[[File:Каскадное вырезание.png|thumb|500px|Пример каскадного вырезания]]&lt;br /&gt;
&lt;br /&gt;
Перед вызовом каскадного вырезания нам известно, удаляли ли ребенка у этой вершины. Если у вершины до этого не удаляли дочерний узел (&amp;lt;tex&amp;gt; x.mark = false &amp;lt;/tex&amp;gt;), то мы помечаем эту вершину (&amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt;) и прекращаем выполнение операции. В противном случае применяем операцию &amp;lt;tex&amp;gt;\mathrm {cut}&amp;lt;/tex&amp;gt; для текущей вершины и запускаем каскадное вырезание от родителя.&lt;br /&gt;
&lt;br /&gt;
'''Пример'''&lt;br /&gt;
&lt;br /&gt;
Рисунок иллюстрирует пример каскадного вырезания:&lt;br /&gt;
&lt;br /&gt;
* Изначально, куча состояла из &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; фибоначчиевых деревьев. У вершины с ключом &amp;lt;tex&amp;gt;24&amp;lt;/tex&amp;gt; отсутствует &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; ребенок.&lt;br /&gt;
* Уменьшаем ключ &amp;lt;tex&amp;gt;26&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; и делаем операцию &amp;lt;tex&amp;gt;\mathrm {cut}&amp;lt;/tex&amp;gt; этого дерева. Получаем кучу с &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt; деревьями и новым минимумом. Но у вершины с ключом &amp;lt;tex&amp;gt;24&amp;lt;/tex&amp;gt; был удален второй ребенок, поэтому запускам операцию &amp;lt;tex&amp;gt;\mathrm {cascadingCut}&amp;lt;/tex&amp;gt; для этой вершины: вырезаем ее, помещаем в корневой список и помечаем ее родителя.&lt;br /&gt;
* У вершины с ключом &amp;lt;tex&amp;gt;7&amp;lt;/tex&amp;gt; удален лишь один ребенок, поэтому операция &amp;lt;tex&amp;gt;\mathrm {cascadingCut}&amp;lt;/tex&amp;gt; от нее не запускается. В итоге, получаем кучу, состоящую из &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; фибоначчиевых деревьев.&lt;br /&gt;
&lt;br /&gt;
===== Время работы =====&lt;br /&gt;
&lt;br /&gt;
Докажем, что амортизированное время работы операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; есть &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Поскольку в процедуре нет циклов, ее время работы определяется лишь количеством рекурсивных вызовов каскадного вырезания.&lt;br /&gt;
&lt;br /&gt;
Пусть мы вызвали процедуру каскадного вырезания &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; раз. Так как реальное время работы операции &amp;lt;tex&amp;gt; \mathrm {cascadingCut} &amp;lt;/tex&amp;gt; без учета рекурсии составляет &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, то реальное время работы операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt; O(k) &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Рассмотрим, как изменится потенциал в результате выполнения данной операции. Пусть &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; {{---}} фибоначчиева куча до вызова &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt;. Тогда после &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; рекурсивных вызовов операции &amp;lt;tex&amp;gt; \mathrm {cascadingCut} &amp;lt;/tex&amp;gt; вершин с пометкой &amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt; стало как минимум на &amp;lt;tex&amp;gt; k - 2 &amp;lt;/tex&amp;gt; меньше, потому что каждый вызов каскадного вырезания, за исключением последнего, уменьшает количество помеченных вершин на одну, и в результате последнего вызова одну вершину мы можем пометить. В корневом списке прибавилось &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; новых деревьев (&amp;lt;tex&amp;gt; k - 1 &amp;lt;/tex&amp;gt; дерево за счет каскадного вырезания и еще одно из-за самого первого вызова операции &amp;lt;tex&amp;gt; \mathrm {cut} &amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
В итоге, изменение потенциала составляет: &amp;lt;tex&amp;gt; \Phi_i - \Phi_{i - 1} = ((t[H] + k) + 2(m[H] + k - 2)) - (t[H] + 2m[H]) = 4 - k &amp;lt;/tex&amp;gt;. Следовательно, амортизированная стоимость не превышает &amp;lt;tex&amp;gt; O(k) + 4 - k &amp;lt;/tex&amp;gt;. Но поскольку мы можем соответствующим образом масштабировать единицы потенциала, то амортизированная стоимость операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; равна &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== delete ====&lt;br /&gt;
&lt;br /&gt;
Удаление вершины реализуется через уменьшение ее ключа до &amp;lt;tex&amp;gt; -\infty &amp;lt;/tex&amp;gt; и последующим извлечением минимума. Амортизированное время работы: &amp;lt;tex&amp;gt; O(1) + O(D(n)) = O(D(n)) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Поскольку ранее мы показали, что &amp;lt;tex&amp;gt; D(n) = O(\log n ) &amp;lt;/tex&amp;gt;, то соответствующие оценки доказаны.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Левосторонняя куча]]&lt;br /&gt;
* [[Тонкая куча]]&lt;br /&gt;
* [[Толстая куча на избыточном счетчике]]&lt;br /&gt;
* [[Куча Бродала-Окасаки]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
&lt;br /&gt;
* Томас Кормен, Чарльз Лейзерсон, Рональд Ривест, Клиффорд Штайн — Алгоритмы: построение и анализ. — М.: Издательский дом «Вильямс», 2005. — С. 1296. — ISBN 5-8459-0857-4&lt;br /&gt;
* [[wikipedia:ru:Числа Фибоначчи|Числа Фибоначчи {{---}} Википедия]]&lt;br /&gt;
* [[wikipedia:ru:Фибоначчиева куча|Фибоначчиева куча {{---}} Википедия]]&lt;br /&gt;
* [http://www.intuit.ru/department/algorithms/dscm/7/2.html Фибоначчиевы кучи — INTUIT.ru]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/heaps Визуализаторы]&lt;br /&gt;
* [http://www.cs.duke.edu/courses/fall05/cps230/L-11.pdf Fibonacci Heaps]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Приоритетные очереди]]&lt;/div&gt;</summary>
		<author><name>217.66.156.128</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B1%D0%BE%D0%BD%D0%B0%D1%87%D1%87%D0%B8%D0%B5%D0%B2%D0%B0_%D0%BA%D1%83%D1%87%D0%B0&amp;diff=46734</id>
		<title>Фибоначчиева куча</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B1%D0%BE%D0%BD%D0%B0%D1%87%D1%87%D0%B8%D0%B5%D0%B2%D0%B0_%D0%BA%D1%83%D1%87%D0%B0&amp;diff=46734"/>
				<updated>2015-05-20T17:43:06Z</updated>
		
		<summary type="html">&lt;p&gt;217.66.156.128: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Фибоначчиево дерево ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Фибоначчиево дерево''' (англ. ''Fibonacci tree'') {{---}} [[Биномиальная куча#Биномиальное дерево |биномиальное дерево]], где у каждой вершины удалено не более одного ребенка.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Порядок фибоначчиева дерева''' (англ. ''Fibonacci tree order'') {{---}} порядок соответствующего биномиального дерева, из которого оно получено.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Степень вершины''' (англ. ''degree'')  {{---}} количество дочерних узлов данной вершины.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма1&lt;br /&gt;
|statement=Для всех целых &amp;lt;tex&amp;gt; n \geqslant 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt; F_n = 1 + \sum\limits_{i=0}^{n-2} F_i &amp;lt;/tex&amp;gt;,&lt;br /&gt;
где &amp;lt;tex&amp;gt; F_n &amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt;-ое число Фибоначчи, определяемое формулой:&lt;br /&gt;
&amp;lt;tex&amp;gt;&lt;br /&gt;
F_n =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
 0, &amp;amp; n = 0 \\&lt;br /&gt;
 1, &amp;amp; n = 1 \\&lt;br /&gt;
 F_{n-1} + F_{n-2}, &amp;amp; n \geqslant 2&lt;br /&gt;
\end{cases} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Докажем лемму по индукции:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;tex&amp;gt;n = 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_2 = 1 + \sum\limits_{i=0}^0 F_i = 1 + 0 = 1&amp;lt;/tex&amp;gt;, что действительно верно.&lt;br /&gt;
&lt;br /&gt;
По индукции предполагаем, что &amp;lt;tex&amp;gt;F_{n-1} = 1 + \sum\limits_{i=0}^{n-3} F_i &amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_n = F_{n-1} + F_{n-2} = 1 + \sum\limits_{i=0}^{n-3} F_i + F_{n-2} = 1 + \sum\limits_{i=0}^{n-2} F_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма2&lt;br /&gt;
|statement= Фибоначчиево дерево порядка &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; содержит не менее &amp;lt;tex&amp;gt;F_n&amp;lt;/tex&amp;gt; вершин.&lt;br /&gt;
|proof=&lt;br /&gt;
Докажем это утверждение по индукции.&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;s_n&amp;lt;/tex&amp;gt; {{---}} минимальный размер фибоначчиева дерева порядка &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_0 = 1 &amp;gt; F_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_1 = 1 = F_1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предположим по индукции, что для всех &amp;lt;tex&amp;gt;i &amp;lt; n \ s_i \geqslant F_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Пусть в нашем дереве удалено поддерево порядка &amp;lt;tex&amp;gt;n - 1&amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_n = 1 + \sum\limits_{i=0}^{n-2} s_i \geqslant 1 + \sum\limits_{i=0}^{n-2} F_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Но по предыдущей [[#Лемма1|лемме]] :&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;tex&amp;gt;1 + \sum\limits_{i=0}^{n-2} F_i = F_n&amp;lt;/tex&amp;gt;. Следовательно, &amp;lt;tex&amp;gt;s_n \geqslant F_n&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Фибоначчиева куча ==&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Фибоначчиева куча''' (англ. ''Fibonacci heap'')   {{---}} набор фибоначчиевых деревьев, корни которых объединены в неупорядоченный [[Список#Циклический список |циклический]] [[Список#Двусвязный список | двусвязный список]]. В отличие от [[Биномиальная куча|биномиальной кучи]], степени корней не обязаны быть попарно различными.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Фибоначчиевы кучи поддерживают тот же набор операций, что и биномиальные кучи, но имеют то преимущество, что операции, в которых не требуется удаление, имеют [[Амортизационный анализ|амортизированное]] время работы, равное &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
С теоретической точки зрения фибоначчиевы кучи особенно полезны в случае, когда количество операций &amp;lt;tex&amp;gt;\mathrm {extractMin}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt; относительно мало по сравнению с количеством других операций. Однако с практической точки зрения программная сложность и высокие значения постоянных множителей в формулах времени работы  существенно снижают эффективность применения фибоначчиевых куч, делая их в большинстве случаев менее привлекательными, чем обычные [[Двоичная куча|бинарные кучи]].&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма3&lt;br /&gt;
|statement= &amp;lt;tex&amp;gt;F_n =\Theta(\varphi^n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt; \varphi = \frac {1 + \sqrt 5} {2}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Для начала докажем, что &amp;lt;tex&amp;gt;F_n =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^n - (-\varphi)^{-n}} {\sqrt 5}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Используем для этого математическую индукцию.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_0 =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^0 - (-\varphi)^0} {\sqrt 5} = \frac {1 - 1} {\sqrt 5} = 0&amp;lt;/tex&amp;gt;, что верно.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_1 =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^1 - (-\varphi)^{-1}} {\sqrt 5} = \frac {1} {\sqrt 5}(\frac {1 + \sqrt 5} {2} - \frac {1 - \sqrt 5} {2}) = \frac {2\sqrt 5} {2\sqrt 5} = 1&amp;lt;/tex&amp;gt;, что также верно.&lt;br /&gt;
&lt;br /&gt;
По индукции предполагаем, что &amp;lt;tex&amp;gt;F_{n-1} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-1} - (-\varphi)^{1-n}} {\sqrt 5}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;F_{n-2} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-2} - (-\varphi)^{2-n}} {\sqrt 5}&amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_n = F_{n-1} + F_{n-2} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-1} - (-\varphi)^{1-n}} {\sqrt 5} + \frac {\varphi^{n-2} - (-\varphi)^{2-n}} {\sqrt 5} =&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;= \frac {1} {\sqrt 5}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(\varphi^{n-1} - (-\varphi)^{1-n} + \varphi^{n-2} - (-\varphi)^{2-n}) &amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;= \frac {1} {\sqrt 5}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(\varphi^{n}(\varphi^{-1} + \varphi^{-2}) - (-\varphi)^{-n}(-\varphi + \varphi^{2}))&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подставив вместо &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; его значение, нетрудно убедится, что &amp;lt;tex&amp;gt;\varphi^{-1} + \varphi^{-2} = -\varphi + \varphi^{2} = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Поскольку &amp;lt;tex&amp;gt;\left\vert (-\varphi)^{-1} \right\vert &amp;lt; 1&amp;lt;/tex&amp;gt;, то выполняются неравенства &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {(-\varphi)^{-n}} {\sqrt 5} &amp;lt; \frac {1} {\sqrt 5} &amp;lt; \frac {1} {2}&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;-ое число Фибоначчи равно &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n}} {\sqrt 5}&amp;lt;/tex&amp;gt;, округленному до ближайшего целого числа. Следовательно, &amp;lt;tex&amp;gt;F_n =\Theta(\varphi^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма4&lt;br /&gt;
|statement=Максимальная степень &amp;lt;tex&amp;gt;D(n)&amp;lt;/tex&amp;gt; произвольной вершины в фибоначчиевой куче с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершинами равна &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; {{---}} произвольная вершина в фибоначчиевой куче с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершинами, и пусть &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; {{---}} степень вершины &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;. Тогда по [[#Лемма2|доказанному выше]] в дереве, корень которого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, содержится не менее &amp;lt;tex&amp;gt;F_k&amp;lt;/tex&amp;gt; вершин, что в свою очередь по [[#Лемма3|лемме]] равно &amp;lt;tex&amp;gt;\Theta(\varphi^k)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
То есть&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;n \geqslant \varphi^{k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Логарифмируя по основанию &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt;, получаем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\log_{\varphi}n \geqslant k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом, максимальная степень &amp;lt;tex&amp;gt;D(n)&amp;lt;/tex&amp;gt; произвольной вершины равна &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Структура ===&lt;br /&gt;
[[File:Fibonacci-heap.png|thumb|340px|Пример фибоначчиевой кучи]]&lt;br /&gt;
====Структура узла====&lt;br /&gt;
Каждый узел &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; в куче &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; содержит следующие указатели и поля:&lt;br /&gt;
 '''struct''' Node&lt;br /&gt;
    '''int''' key &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// ключ&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' p &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// указатель на родительский узел&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' child &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// указатель на один из дочерних узлов&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' left &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// указатель  на левый сестринский узел&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' right &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// указатель на правый сестринский узел&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''int''' degree &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// количество дочерних узлов&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''boolean''' mark &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// флаг, который показывает, удаляли ли мы дочерние узлы данной вершины&amp;lt;/span&amp;gt;&lt;br /&gt;
====Структура списка детей====&lt;br /&gt;
* Дочерние узлы &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; объединены при помощи указателей &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; в  циклический двусвязный список.&lt;br /&gt;
* Корни всех деревьев в &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; связаны при помощи указателей &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; в циклический двусвязный список корней.&lt;br /&gt;
* Обращение к &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; выполняется посредством указателя &amp;lt;tex&amp;gt;H.min&amp;lt;/tex&amp;gt; на корень дерева с минимальным ключом. Этот узел называется минимальным узлом &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Текущее количество узлов в &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; хранится в &amp;lt;tex&amp;gt;H.size&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Циклический двусвязный список обладает двумя преимуществами для использования в фибоначчиевых кучах. Во-первых, удаление элемента из такого списка выполняется за время &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;. Во-вторых, если имеется два таких списка, их легко объединить в один за время &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Потенциал ===&lt;br /&gt;
&lt;br /&gt;
Для анализа производительности операций введем потенциал для фибоначчиевой кучи &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; как &amp;lt;tex&amp;gt; \Phi(H) = t[H] + 2m[H] &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; t[H] &amp;lt;/tex&amp;gt; {{---}} количество элементов в корневом списке кучи, а &amp;lt;tex&amp;gt; m[H] &amp;lt;/tex&amp;gt; {{---}} количество вершин, у которых удален один ребенок (то есть вершин с пометкой &amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt;). Договоримся, что единицы потенциала достаточно для оплаты константного количества работы.&lt;br /&gt;
&lt;br /&gt;
=== Операции ===&lt;br /&gt;
Рассмотрим операции, которые поддерживают фибоначчиевы кучи. Амортизированное время их работы показано в таблице.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Операция&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Амортизированная сложность&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {makeHeap}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {insert}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {getMin}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {merge}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {extractMin}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(\log n )&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {decreaseKey}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(\log n )&amp;lt;/tex&amp;gt; &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Стоит заметить, что структура фибоначчиевых куч, также как биномиальных и бинарных, не могут обеспечить эффективную реализацию поиска элемента с заданным ключом, поэтому операции &amp;lt;tex&amp;gt;\mathrm {decreaseKey}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt; получают в качестве аргумента указатель на узел, а не значение его ключа.&lt;br /&gt;
&lt;br /&gt;
==== makeHeap ====&lt;br /&gt;
&lt;br /&gt;
Создается новый пустой корневой список, в &amp;lt;tex&amp;gt; H.min &amp;lt;/tex&amp;gt; устанавливается значение &amp;lt;tex&amp;gt; null &amp;lt;/tex&amp;gt;. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== insert ====&lt;br /&gt;
&lt;br /&gt;
Вставка элемента в фибоначчиеву кучу также тривиальна: создается новая куча из одного элемента и сливается с текущей. Для оценки амортизированной стоимости операции рассмотрим исходную кучу &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; и получившуюся в результате вставки нового элемента кучу &amp;lt;tex&amp;gt; H' &amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt; t[H'] = t[H] + 1 &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; m[H'] = m[H] &amp;lt;/tex&amp;gt;. Следовательно, увеличение потенциала составляет &amp;lt;tex&amp;gt; (t[H] + 1 + 2m[H]) - (t[H] + 2m[H]) = 1 &amp;lt;/tex&amp;gt;. Так как реальное время работы составляет &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, то амортизированная стоимость данной операции также равна &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== getMin ====&lt;br /&gt;
Возвращает указатель &amp;lt;tex&amp;gt;H.min&amp;lt;/tex&amp;gt;. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== merge ====&lt;br /&gt;
&lt;br /&gt;
Слияние двух фибоначчиевых куч происходит просто: объединяем списки этих куч в один, релаксируем минимум. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Амортизированное время работы также &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, поскольку, при объединении двух куч в одну, потенциалы обеих куч суммируются, итоговая сумма потенциалов не изменяется, &amp;lt;tex&amp;gt; \Phi_{n + 1} - \Phi_n = 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== extractMin ====&lt;br /&gt;
&lt;br /&gt;
Первая рассматриваемая операция, в ходе которой меняется структура кучи. Здесь используется вспомогательная процедура &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;. Возьмем указатель на &amp;lt;tex&amp;gt; H.min &amp;lt;/tex&amp;gt;, удалим эту вершину. Ее поддеревья (их не более, чем &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt; {{---}}  максимальная степень вершины в куче) объединим с корневым списком. Теперь вызываем процедуру &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;. После этой операции в списке корней остается не более чем &amp;lt;tex&amp;gt; D(n) + 1&amp;lt;/tex&amp;gt; узлов, среди которых нужно найти минимальный. Итоговая асимптотика операции &amp;lt;tex&amp;gt;\mathrm {extraxtMin}&amp;lt;/tex&amp;gt;, учитывая и вспомогательную функцию &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;, время работы которой доказывается ниже, равно: &amp;lt;tex&amp;gt; O(1)+O(D(n))+O(D(n))=O(D(n)) &amp;lt;/tex&amp;gt;. По доказанной выше [[#Лемма4|лемме]] &amp;lt;tex&amp;gt;O(D(n)) = O(\log(n))&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===== consolidate =====&lt;br /&gt;
&lt;br /&gt;
Данная процедура принимает кучу и преобразует ее таким образом, что в корневом списке остается не более &amp;lt;tex&amp;gt; D(n) + 1&amp;lt;/tex&amp;gt; вершин.&lt;br /&gt;
&lt;br /&gt;
Для этого возьмем массив списков указателей на корни деревьев &amp;lt;tex&amp;gt; A[0..D[H]] &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; D[H] &amp;lt;/tex&amp;gt; {{---}} максимальная степень вершины в текущем корневом списке.&lt;br /&gt;
&lt;br /&gt;
Затем происходит [[Биномиальная_куча#merge | процесс, аналогичный слиянию биномиальных куч]]: добавляем поочередно каждый корень, смотря на его степень. Пусть она равна &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;. Если в соответствующей ячейке &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; еще нету вершины, записываем текущую вершину туда. Иначе подвешиваем одно дерево к другому, и пытаемся также добавить дерево, степень корня которого уже равна &amp;lt;tex&amp;gt; d + 1 &amp;lt;/tex&amp;gt;. Продолжаем, пока не найдем свободную ячейку.&lt;br /&gt;
&lt;br /&gt;
Учетная стоимость &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt; равна &amp;lt;tex&amp;gt; O(D(n)) &amp;lt;/tex&amp;gt;. Докажем это:&lt;br /&gt;
&lt;br /&gt;
Изначально в корневом списке было не более &amp;lt;tex&amp;gt; D(n) + t[H] - 1 &amp;lt;/tex&amp;gt; вершин, поскольку он состоит из исходного списка корней с &amp;lt;tex&amp;gt;t[H]&amp;lt;/tex&amp;gt; узлами, минус извлеченный узел и плюс дочерние узлы, количество которых не превышает &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt;. В ходе операции &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt; мы сделали &amp;lt;tex&amp;gt; O(D(n) + t[H]) &amp;lt;/tex&amp;gt; слияний деревьев. Потенциал перед извлечением минимума равен &amp;lt;tex&amp;gt; t[H] + 2m[H] &amp;lt;/tex&amp;gt;, а после не превышает &amp;lt;tex&amp;gt; D(n) + 1 + 2m[H] &amp;lt;/tex&amp;gt;, поскольку в корневом списке остается не более  &amp;lt;tex&amp;gt; D(n) + 1 &amp;lt;/tex&amp;gt; узлов, а количество помеченных узлов не изменяется. Таким образом, амортизированная стоимость не превосходит&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; O(D(n) + t[H]) + (D(n) + 1 + 2m[H]) - (t[H] + 2m[H]) = O(D(n)) + O(t[H]) - t[H]&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Поскольку мы договорились, что можем масштабировать единицу потенциала таким образом, чтобы покрывать константное количество работы, то итоговая амортизационная оценка {{---}} &amp;lt;tex&amp;gt; O(D(n)) &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== decreaseKey ====&lt;br /&gt;
&lt;br /&gt;
Основная идея: хотим, чтобы учетная стоимость данной операции была &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Было бы хорошо, чтобы вершина не всплывала до корня, и тогда дерево не придется сильно перестраивать. Для этого при удобном случае будем вырезать поддерево полностью и перемещать его в корневой список. Итак, сам алгоритм:&lt;br /&gt;
&lt;br /&gt;
# Проверяем, если новое значение ключа все же не меньше значения ключа родителя, то все хорошо, и мы выходим.&lt;br /&gt;
# Иначе, вырезаем дерево с текущей вершиной в корневой список, и производим каскадное вырезание родителя. &lt;br /&gt;
&lt;br /&gt;
===== cut =====&lt;br /&gt;
&lt;br /&gt;
При вырезании вершины мы удаляем ее из списка детей своего родителя, уменьшаем степень ее родителя (&amp;lt;tex&amp;gt; x.p.degree &amp;lt;/tex&amp;gt;) и снимаем пометку с текущей вершины (&amp;lt;tex&amp;gt; x.mark = false &amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
===== cascadingCut =====&lt;br /&gt;
&lt;br /&gt;
[[File:Каскадное вырезание.png|thumb|500px|Пример каскадного вырезания]]&lt;br /&gt;
&lt;br /&gt;
Перед вызовом каскадного вырезания нам известно, удаляли ли ребенка у этой вершины. Если у вершины до этого не удаляли дочерний узел (&amp;lt;tex&amp;gt; x.mark = false &amp;lt;/tex&amp;gt;), то мы помечаем эту вершину (&amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt;) и прекращаем выполнение операции. В противном случае применяем операцию &amp;lt;tex&amp;gt;\mathrm {cut}&amp;lt;/tex&amp;gt; для текущей вершины и запускаем каскадное вырезание от родителя.&lt;br /&gt;
&lt;br /&gt;
'''Пример'''&lt;br /&gt;
&lt;br /&gt;
Рисунок иллюстрирует пример каскадного вырезания:&lt;br /&gt;
&lt;br /&gt;
* Изначально, куча состояла из &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; фибоначчиевых деревьев. У вершины с ключом &amp;lt;tex&amp;gt;24&amp;lt;/tex&amp;gt; отсутствует &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; ребенок.&lt;br /&gt;
* Уменьшаем ключ &amp;lt;tex&amp;gt;26&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; и делаем операцию &amp;lt;tex&amp;gt;\mathrm {cut}&amp;lt;/tex&amp;gt; этого дерева. Получаем кучу с &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt; деревьями и новым минимумом. Но у вершины с ключом &amp;lt;tex&amp;gt;24&amp;lt;/tex&amp;gt; был удален второй ребенок, поэтому запускам операцию &amp;lt;tex&amp;gt;\mathrm {cascadingCut}&amp;lt;/tex&amp;gt; для этой вершины: вырезаем ее, помещаем в корневой список и помечаем ее родителя.&lt;br /&gt;
* У вершины с ключом &amp;lt;tex&amp;gt;7&amp;lt;/tex&amp;gt; удален лишь один ребенок, поэтому операция &amp;lt;tex&amp;gt;\mathrm {cascadingCut}&amp;lt;/tex&amp;gt; от нее не запускается. В итоге, получаем кучу, состоящую из &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; фибоначчиевых деревьев.&lt;br /&gt;
&lt;br /&gt;
===== Время работы =====&lt;br /&gt;
&lt;br /&gt;
Докажем, что амортизированное время работы операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; есть &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Поскольку в процедуре нет циклов, ее время работы определяется лишь количеством рекурсивных вызовов каскадного вырезания.&lt;br /&gt;
&lt;br /&gt;
Пусть мы вызвали процедуру каскадного вырезания &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; раз. Так как реальное время работы операции &amp;lt;tex&amp;gt; \mathrm {cascadingCut} &amp;lt;/tex&amp;gt; без учета рекурсии составляет &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, то реальное время работы операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt; O(k) &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Рассмотрим, как изменится потенциал в результате выполнения данной операции. Пусть &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; {{---}} фибоначчиева куча до вызова &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt;. Тогда после &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; рекурсивных вызовов операции &amp;lt;tex&amp;gt; \mathrm {cascadingCut} &amp;lt;/tex&amp;gt; вершин с пометкой &amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt; стало как минимум на &amp;lt;tex&amp;gt; k - 2 &amp;lt;/tex&amp;gt; меньше, потому что каждый вызов каскадного вырезания, за исключением последнего, уменьшает количество помеченных вершин на одну, и в результате последнего вызова одну вершину мы можем пометить. В корневом списке прибавилось &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; новых деревьев (&amp;lt;tex&amp;gt; k - 1 &amp;lt;/tex&amp;gt; дерево за счет каскадного вырезания и еще одно из-за самого первого вызова операции &amp;lt;tex&amp;gt; \mathrm {cut} &amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
В итоге, изменение потенциала составляет: &amp;lt;tex&amp;gt; \Phi_i - \Phi_{i - 1} = ((t[H] + k) + 2(m[H] + k - 2)) - (t[H] + 2m[H]) = 4 - k &amp;lt;/tex&amp;gt;. Следовательно, амортизированная стоимость не превышает &amp;lt;tex&amp;gt; O(k) + 4 - k &amp;lt;/tex&amp;gt;. Но поскольку мы можем соответствующим образом масштабировать единицы потенциала, то амортизированная стоимость операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; равна &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== delete ====&lt;br /&gt;
&lt;br /&gt;
Удаление вершины реализуется через уменьшение ее ключа до &amp;lt;tex&amp;gt; -\infty &amp;lt;/tex&amp;gt; и последующим извлечением минимума. Амортизированное время работы: &amp;lt;tex&amp;gt; O(1) + O(D(n)) = O(D(n)) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Поскольку ранее мы показали, что &amp;lt;tex&amp;gt; D(n) = O(\log n ) &amp;lt;/tex&amp;gt;, то соответствующие оценки доказаны.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Левосторонняя куча]]&lt;br /&gt;
* [[Тонкая куча]]&lt;br /&gt;
* [[Толстая куча на избыточном счетчике]]&lt;br /&gt;
* [[Куча Бродала-Окасаки]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
&lt;br /&gt;
* Томас Кормен, Чарльз Лейзерсон, Рональд Ривест, Клиффорд Штайн — Алгоритмы: построение и анализ. — М.: Издательский дом «Вильямс», 2005. — С. 1296. — ISBN 5-8459-0857-4&lt;br /&gt;
* [[wikipedia:ru:Числа Фибоначчи|Числа Фибоначчи {{---}} Википедия]]&lt;br /&gt;
* [[wikipedia:ru:Фибоначчиева куча|Фибоначчиева куча {{---}} Википедия]]&lt;br /&gt;
* [http://www.intuit.ru/department/algorithms/dscm/7/2.html Фибоначчиевы кучи — INTUIT.ru]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/heaps Визуализаторы]&lt;br /&gt;
* [http://www.cs.duke.edu/courses/fall05/cps230/L-11.pdf Fibonacci Heaps]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Приоритетные очереди]]&lt;/div&gt;</summary>
		<author><name>217.66.156.128</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B1%D0%BE%D0%BD%D0%B0%D1%87%D1%87%D0%B8%D0%B5%D0%B2%D0%B0_%D0%BA%D1%83%D1%87%D0%B0&amp;diff=46733</id>
		<title>Фибоначчиева куча</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B1%D0%BE%D0%BD%D0%B0%D1%87%D1%87%D0%B8%D0%B5%D0%B2%D0%B0_%D0%BA%D1%83%D1%87%D0%B0&amp;diff=46733"/>
				<updated>2015-05-20T17:37:40Z</updated>
		
		<summary type="html">&lt;p&gt;217.66.156.128: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Фибоначчиево дерево ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Фибоначчиево дерево''' (англ. ''Fibonacci tree'') {{---}} [[Биномиальная куча#Биномиальное дерево |биномиальное дерево]], где у каждой вершины удалено не более одного ребенка.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Порядок фибоначчиева дерева''' (англ. ''Fibonacci tree order'') {{---}} порядок соответствующего биномиального дерева, из которого оно получено.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Степень вершины''' (англ. ''degree'')  {{---}} количество дочерних узлов данной вершины.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма1&lt;br /&gt;
|statement=Для всех целых &amp;lt;tex&amp;gt; n \geqslant 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt; F_n = 1 + \sum\limits_{i=0}^{n-2} F_i &amp;lt;/tex&amp;gt;,&lt;br /&gt;
где &amp;lt;tex&amp;gt; F_n &amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt;-ое число Фибоначчи, определяемое формулой:&lt;br /&gt;
&amp;lt;tex&amp;gt;&lt;br /&gt;
F_n =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
 0, &amp;amp; n = 0 \\&lt;br /&gt;
 1, &amp;amp; n = 1 \\&lt;br /&gt;
 F_{n-1} + F_{n-2}, &amp;amp; n \geqslant 2&lt;br /&gt;
\end{cases} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Докажем лемму по индукции:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;tex&amp;gt;n = 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_2 = 1 + \sum\limits_{i=0}^0 F_i = 1 + 0 = 1&amp;lt;/tex&amp;gt;, что действительно верно.&lt;br /&gt;
&lt;br /&gt;
По индукции предполагаем, что &amp;lt;tex&amp;gt;F_{n-1} = 1 + \sum\limits_{i=0}^{n-3} F_i &amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_n = F_{n-1} + F_{n-2} = 1 + \sum\limits_{i=0}^{n-3} F_i + F_{n-2} = 1 + \sum\limits_{i=0}^{n-2} F_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма2&lt;br /&gt;
|statement= Фибоначчиево дерево порядка &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; содержит не менее &amp;lt;tex&amp;gt;F_n&amp;lt;/tex&amp;gt; вершин.&lt;br /&gt;
|proof=&lt;br /&gt;
Докажем это утверждение по индукции.&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;s_n&amp;lt;/tex&amp;gt; {{---}} минимальный размер фибоначчиева дерева порядка &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_0 = 1 &amp;gt; F_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_1 = 1 = F_1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предположим по индукции, что для всех &amp;lt;tex&amp;gt;i &amp;lt; n \ s_i \geqslant F_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Пусть в нашем дереве удалено поддерево порядка &amp;lt;tex&amp;gt;n - 1&amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_n = 1 + \sum\limits_{i=0}^{n-2} s_i \geqslant 1 + \sum\limits_{i=0}^{n-2} F_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Но по предыдущей [[#Лемма1|лемме]] :&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;tex&amp;gt;1 + \sum\limits_{i=0}^{n-2} F_i = F_n&amp;lt;/tex&amp;gt;. Следовательно, &amp;lt;tex&amp;gt;s_n \geqslant F_n&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Фибоначчиева куча ==&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Фибоначчиева куча''' (англ. ''Fibonacci heap'')   {{---}} набор фибоначчиевых деревьев, корни которых объединены в неупорядоченный [[Список#Циклический список |циклический]] [[Список#Двусвязный список | двусвязный список]]. В отличие от [[Биномиальная куча|биномиальной кучи]], степени корней не обязаны быть попарно различными.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Фибоначчиевы кучи поддерживают тот же набор операций, что и биномиальные кучи, но имеют то преимущество, что операции, в которых не требуется удаление, имеют [[Амортизационный анализ|амортизированное]] время работы, равное &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
С теоретической точки зрения фибоначчиевы кучи особенно полезны в случае, когда количество операций &amp;lt;tex&amp;gt;\mathrm {extractMin}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt; относительно мало по сравнению с количеством других операций. Однако с практической точки зрения программная сложность и высокие значения постоянных множителей в формулах времени работы  существенно снижают эффективность применения фибоначчиевых куч, делая их в большинстве случаев менее привлекательными, чем обычные [[Двоичная куча|бинарные кучи]].&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма3&lt;br /&gt;
|statement= &amp;lt;tex&amp;gt;F_n =\Theta(\varphi^n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt; \varphi = \frac {1 + \sqrt 5} {2}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Для начала докажем, что &amp;lt;tex&amp;gt;F_n =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^n - (-\varphi)^{-n}} {\sqrt 5}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Используем для этого математическую индукцию.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_0 =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^0 - (-\varphi)^0} {\sqrt 5} = \frac {1 - 1} {\sqrt 5} = 0&amp;lt;/tex&amp;gt;, что верно.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_1 =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^1 - (-\varphi)^{-1}} {\sqrt 5} = \frac {1} {\sqrt 5}(\frac {1 + \sqrt 5} {2} - \frac {1 - \sqrt 5} {2}) = \frac {2\sqrt 5} {2\sqrt 5} = 1&amp;lt;/tex&amp;gt;, что также верно.&lt;br /&gt;
&lt;br /&gt;
По индукции предполагаем, что &amp;lt;tex&amp;gt;F_{n-1} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-1} - (-\varphi)^{1-n}} {\sqrt 5}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;F_{n-2} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-2} - (-\varphi)^{2-n}} {\sqrt 5}&amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_n = F_{n-1} + F_{n-2} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-1} - (-\varphi)^{1-n}} {\sqrt 5} + \frac {\varphi^{n-2} - (-\varphi)^{2-n}} {\sqrt 5} =&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;= \frac {1} {\sqrt 5}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(\varphi^{n-1} - (-\varphi)^{1-n} + \varphi^{n-2} - (-\varphi)^{2-n}) &amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;= \frac {1} {\sqrt 5}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(\varphi^{n}(\varphi^{-1} + \varphi^{-2}) - (-\varphi)^{-n}(-\varphi + \varphi^{2}))&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подставив вместо &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; его значение, нетрудно убедится, что &amp;lt;tex&amp;gt;\varphi^{-1} + \varphi^{-2} = -\varphi + \varphi^{2} = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Поскольку &amp;lt;tex&amp;gt;\left\vert (-\varphi)^{-1} \right\vert &amp;lt; 1&amp;lt;/tex&amp;gt;, то выполняются неравенства &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {(-\varphi)^{-n}} {\sqrt 5} &amp;lt; \frac {1} {\sqrt 5} &amp;lt; \frac {1} {2}&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;-ое число Фибоначчи равно &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n}} {\sqrt 5}&amp;lt;/tex&amp;gt;, округленному до ближайшего целого числа. Следовательно, &amp;lt;tex&amp;gt;F_n =\Theta(\varphi^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма4&lt;br /&gt;
|statement=Максимальная степень &amp;lt;tex&amp;gt;D(n)&amp;lt;/tex&amp;gt; произвольной вершины в фибоначчиевой куче с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершинами равна &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; {{---}} произвольная вершина в фибоначчиевой куче с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершинами, и пусть &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; {{---}} степень вершины &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;. Тогда по [[#Лемма2|доказанному выше]] в дереве, корень которого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, содержится не менее &amp;lt;tex&amp;gt;F_k&amp;lt;/tex&amp;gt; вершин, что в свою очередь по [[#Лемма3|лемме]] равно &amp;lt;tex&amp;gt;\Theta(\varphi^k)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
То есть&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;n \geqslant \varphi^{k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Логарифмируя по основанию &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt;, получаем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\log_{\varphi}n \geqslant k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом, максимальная степень &amp;lt;tex&amp;gt;D(n)&amp;lt;/tex&amp;gt; произвольной вершины равна &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Структура ===&lt;br /&gt;
[[File:Fibonacci-heap.png|thumb|340px|Пример фибоначчиевой кучи]]&lt;br /&gt;
====Структура узла====&lt;br /&gt;
Каждый узел &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; в куче &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; содержит следующие указатели и поля:&lt;br /&gt;
 '''struct''' Node&lt;br /&gt;
    '''int''' key &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// ключ&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' p &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// указатель на родительский узел&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' child &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// указатель на один из дочерних узлов&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' left &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// указатель  на левый сестринский узел&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' right &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// указатель на правый сестринский узел&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''int''' degree &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// количество дочерних узлов&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''boolean''' mark &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// флаг, который показывает, удаляли ли мы дочерние узлы данной вершины&amp;lt;/span&amp;gt;&lt;br /&gt;
====Структура списка детей====&lt;br /&gt;
* Дочерние узлы &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; объединены при помощи указателей &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; в  циклический двусвязный список.&lt;br /&gt;
* Корни всех деревьев в &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; связаны при помощи указателей &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; в циклический двусвязный список корней.&lt;br /&gt;
* Обращение к &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; выполняется посредством указателя &amp;lt;tex&amp;gt;H.min&amp;lt;/tex&amp;gt; на корень дерева с минимальным ключом. Этот узел называется минимальным узлом &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Текущее количество узлов в &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; хранится в &amp;lt;tex&amp;gt;H.size&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Циклический двусвязный список обладает двумя преимуществами для использования в фибоначчиевых кучах. Во-первых, удаление элемента из такого списка выполняется за время &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;. Во-вторых, если имеется два таких списка, их легко объединить в один за время &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Потенциал ===&lt;br /&gt;
&lt;br /&gt;
Для анализа производительности операций введем потенциал для фибоначчиевой кучи &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; как &amp;lt;tex&amp;gt; \Phi(H) = t[H] + 2m[H] &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; t[H] &amp;lt;/tex&amp;gt; {{---}} количество элементов в корневом списке кучи, а &amp;lt;tex&amp;gt; m[H] &amp;lt;/tex&amp;gt; {{---}} количество вершин, у которых удален один ребенок (то есть вершин с пометкой &amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt;). Договоримся, что единицы потенциала достаточно для оплаты константного количества работы.&lt;br /&gt;
&lt;br /&gt;
=== Операции ===&lt;br /&gt;
Рассмотрим операции, которые поддерживают фибоначчиевы кучи. Амортизированное время их работы показано в таблице.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Операция&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Амортизированная сложность&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {makeHeap}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {insert}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {getMin}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {merge}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {extractMin}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(\log n )&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {decreaseKey}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(\log n )&amp;lt;/tex&amp;gt; &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Стоит заметить, что структура фибоначчиевых куч, также как биномиальных и бинарных, не могут обеспечить эффективную реализацию поиска элемента с заданным ключом, поэтому операции &amp;lt;tex&amp;gt;\mathrm {decreaseKey}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt; получают в качестве аргумента указатель на узел, а не значение его ключа.&lt;br /&gt;
&lt;br /&gt;
==== makeHeap ====&lt;br /&gt;
&lt;br /&gt;
Создается новый пустой корневой список, в &amp;lt;tex&amp;gt; H.min &amp;lt;/tex&amp;gt; устанавливается значение &amp;lt;tex&amp;gt; null &amp;lt;/tex&amp;gt;. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== insert ====&lt;br /&gt;
&lt;br /&gt;
Вставка элемента в фибоначчиеву кучу также тривиальна: создается новая куча из одного элемента и сливается с текущей. Для оценки амортизированной стоимости операции рассмотрим исходную кучу &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; и получившуюся в результате вставки нового элемента кучу &amp;lt;tex&amp;gt; H' &amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt; t[H'] = t[H] + 1 &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; m[H'] = m[H] &amp;lt;/tex&amp;gt;. Следовательно, увеличение потенциала составляет &amp;lt;tex&amp;gt; (t[H] + 1 + 2m[H]) - (t[H] + 2m[H]) = 1 &amp;lt;/tex&amp;gt;. Так как реальное время работы составляет &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, то амортизированная стоимость данной операции также равна &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== getMin ====&lt;br /&gt;
Возвращает указатель &amp;lt;tex&amp;gt;H.min&amp;lt;/tex&amp;gt;. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== merge ====&lt;br /&gt;
&lt;br /&gt;
Слияние двух фибоначчиевых куч происходит просто: объединяем списки этих куч в один, релаксируем минимум. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Амортизированное время работы также &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, поскольку, при объединении двух куч в одну, потенциалы обеих куч суммируются, итоговая сумма потенциалов не изменяется, &amp;lt;tex&amp;gt; \Phi_{n + 1} - \Phi_n = 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== extractMin ====&lt;br /&gt;
&lt;br /&gt;
Первая рассматриваемая операция, в ходе которой меняется структура кучи. Здесь используется вспомогательная процедура &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;. Возьмем указатель на &amp;lt;tex&amp;gt; H.min &amp;lt;/tex&amp;gt;, удалим эту вершину. Ее поддеревья (их не более, чем &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt; {{---}}  максимальная степень вершины в куче) объединим с корневым списком. Теперь вызываем процедуру &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;. После этой операции в списке корней остается не более чем &amp;lt;tex&amp;gt; D(n) + 1&amp;lt;/tex&amp;gt; узлов, среди которых нужно найти минимальный. Итоговая асимптотика операции &amp;lt;tex&amp;gt;\mathrm {extraxtMin}&amp;lt;/tex&amp;gt;, учитывая и вспомогательную функцию &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;, время работы которой доказывается ниже, равно: &amp;lt;tex&amp;gt; O(1)+O(D(n))+O(D(n))=O(D(n)) &amp;lt;/tex&amp;gt;. По доказанной выше [[#Лемма4|лемме]] &amp;lt;tex&amp;gt;O(D(n)) = O(\log(n))&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===== consolidate =====&lt;br /&gt;
&lt;br /&gt;
Данная процедура принимает кучу и преобразует ее таким образом, что в корневом списке остается не более &amp;lt;tex&amp;gt; D(n) + 1&amp;lt;/tex&amp;gt; вершин.&lt;br /&gt;
&lt;br /&gt;
Для этого возьмем массив списков указателей на корни деревьев &amp;lt;tex&amp;gt; A[0..D[H]] &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; D[H] &amp;lt;/tex&amp;gt; {{---}} максимальная степень вершины в текущем корневом списке.&lt;br /&gt;
&lt;br /&gt;
Затем происходит [[Биномиальная_куча#merge | процесс, аналогичный слиянию биномиальных куч]]: добавляем поочередно каждый корень, смотря на его степень. Пусть она равна &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;. Если в соответствующей ячейке &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; еще нету вершины, записываем текущую вершину туда. Иначе подвешиваем одно дерево к другому, и пытаемся также добавить дерево, степень корня которого уже равна &amp;lt;tex&amp;gt; d + 1 &amp;lt;/tex&amp;gt;. Продолжаем, пока не найдем свободную ячейку.&lt;br /&gt;
&lt;br /&gt;
Учетная стоимость &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt; равна &amp;lt;tex&amp;gt; O(D(n)) &amp;lt;/tex&amp;gt;. Докажем это:&lt;br /&gt;
&lt;br /&gt;
Изначально в корневом списке было не более &amp;lt;tex&amp;gt; D(n) + t[H] - 1 &amp;lt;/tex&amp;gt; вершин, поскольку он состоит из исходного списка корней с &amp;lt;tex&amp;gt;t[H]&amp;lt;/tex&amp;gt; узлами, минус извлеченный узел и плюс дочерние узлы, количество которых не превышает &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt;. В ходе операции &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt; мы сделали &amp;lt;tex&amp;gt; O(D(n) + t[H]) &amp;lt;/tex&amp;gt; слияний деревьев. Потенциал перед извлечением минимума равен &amp;lt;tex&amp;gt; t[H] + 2m[H] &amp;lt;/tex&amp;gt;, а после не превышает &amp;lt;tex&amp;gt; D(n) + 1 + 2m[H] &amp;lt;/tex&amp;gt;, поскольку в корневом списке остается не более  &amp;lt;tex&amp;gt; D(n) + 1 &amp;lt;/tex&amp;gt; узлов, а количество помеченных узлов не изменяется. Таким образом, амортизированная стоимость не превосходит&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; O(D(n) + t[H]) + (D(n) + 1 + 2m[H]) - (t[H] + 2m[H]) = O(D(n)) + O(t[H]) - t[H]&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Поскольку мы договорились, что можем масштабировать единицу потенциала таким образом, чтобы покрывать константное количество работы, то итоговая амортизационная оценка {{---}} &amp;lt;tex&amp;gt; O(D(n)) &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== decreaseKey ====&lt;br /&gt;
&lt;br /&gt;
Основная идея: хотим, чтобы учетная стоимость данной операции была &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Было бы хорошо, чтобы вершина не всплывала до корня, и тогда дерево не придется сильно перестраивать. Для этого при удобном случае будем вырезать поддерево полностью и перемещать его в корневой список. Итак, сам алгоритм:&lt;br /&gt;
&lt;br /&gt;
# Проверяем, если новое значение ключа все же не меньше значения ключа родителя, то все хорошо, и мы выходим.&lt;br /&gt;
# Иначе, вырезаем дерево с текущей вершиной в корневой список, и производим каскадное вырезание родителя. &lt;br /&gt;
&lt;br /&gt;
===== cut =====&lt;br /&gt;
&lt;br /&gt;
При вырезании вершины мы удаляем ее из списка детей своего родителя, уменьшаем степень ее родителя (&amp;lt;tex&amp;gt; x.p.degree &amp;lt;/tex&amp;gt;) и снимаем пометку с текущей вершины (&amp;lt;tex&amp;gt; x.mark = false &amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
===== cascadingCut =====&lt;br /&gt;
&lt;br /&gt;
[[File:Каскадное вырезание.png|thumb|500px|Пример каскадного вырезания]]&lt;br /&gt;
&lt;br /&gt;
Перед вызовом каскадного вырезания нам известно, удаляли ли ребенка у этой вершины. Если у вершины до этого не удаляли дочерний узел (&amp;lt;tex&amp;gt; x.mark = false &amp;lt;/tex&amp;gt;), то мы помечаем эту вершину (&amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt;) и прекращаем выполнение операции. В противном случае применяем операцию &amp;lt;tex&amp;gt;\mathrm {cut}&amp;lt;/tex&amp;gt; для текущей вершины и запускаем каскадное вырезание от родителя.&lt;br /&gt;
&lt;br /&gt;
'''Пример'''&lt;br /&gt;
&lt;br /&gt;
Рисунок иллюстрирует пример каскадного вырезания:&lt;br /&gt;
&lt;br /&gt;
* Изначально, куча состояла из &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; фибоначчиевых деревьев. У вершины с ключом &amp;lt;tex&amp;gt;24&amp;lt;/tex&amp;gt; отсутствует &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; ребенок.&lt;br /&gt;
* Уменьшаем ключ &amp;lt;tex&amp;gt;26&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; и делаем операцию &amp;lt;tex&amp;gt;\mathrm {cut}&amp;lt;/tex&amp;gt; этого дерева. Получаем кучу с &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt; деревьями и новым минимумом. Но у вершины с ключом &amp;lt;tex&amp;gt;24&amp;lt;/tex&amp;gt; был удален второй ребенок, поэтому запускам операцию &amp;lt;tex&amp;gt;\mathrm {cascadingCut}&amp;lt;/tex&amp;gt; для этой вершины: вырезаем ее, помещаем в корневой список и помечаем ее родителя.&lt;br /&gt;
* У вершины с ключом &amp;lt;tex&amp;gt;7&amp;lt;/tex&amp;gt; удален лишь один ребенок, поэтому операция &amp;lt;tex&amp;gt;\mathrm {cascadingCut}&amp;lt;/tex&amp;gt; от нее не запускается. В итоге, получаем кучу, состоящую из &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; фибоначчиевых деревьев.&lt;br /&gt;
&lt;br /&gt;
===== Время работы =====&lt;br /&gt;
&lt;br /&gt;
Докажем, что амортизированное время работы операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; есть &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Поскольку в процедуре нет циклов, ее время работы определяется лишь количеством рекурсивных вызовов каскадного вырезания.&lt;br /&gt;
&lt;br /&gt;
Пусть мы вызвали процедуру каскадного вырезания &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; раз. Так как реальное время работы операции &amp;lt;tex&amp;gt; \mathrm {cascadingCut} &amp;lt;/tex&amp;gt; без учета рекурсии составляет &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, то реальное время работы операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt; O(k) &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Рассмотрим, как изменится потенциал в результате выполнения данной операции. Пусть &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; {{---}} фибоначчиева куча до вызова &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt;. Тогда после &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; рекурсивных вызовов операции &amp;lt;tex&amp;gt; \mathrm {cascadingCut} &amp;lt;/tex&amp;gt; вершин с пометкой &amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt; стало как минимум на &amp;lt;tex&amp;gt; k - 2 &amp;lt;/tex&amp;gt; меньше, потому что каждый вызов каскадного вырезания, за исключением последнего, уменьшает количество помеченных вершин на одну, и в результате последнего вызова одну вершину мы можем пометить. В корневом списке прибавилось &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; новых деревьев (&amp;lt;tex&amp;gt; k - 1 &amp;lt;/tex&amp;gt; дерево за счет каскадного вырезания и еще одно из-за самого первого вызова операции &amp;lt;tex&amp;gt; \mathrm {cut} &amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
В итоге, изменение потенциала составляет: &amp;lt;tex&amp;gt; \Phi_i - \Phi_{i - 1} = ((t[H] + k) + 2(m[H] + k - 2)) - (t[H] + 2m[H]) = 4 - k &amp;lt;/tex&amp;gt;. Следовательно, амортизированная стоимость не превышает &amp;lt;tex&amp;gt; O(k) + 4 - k &amp;lt;/tex&amp;gt;. Но поскольку мы можем соответствующим образом масштабировать единицы потенциала, то амортизированная стоимость операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; равна &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== delete ====&lt;br /&gt;
&lt;br /&gt;
Удаление вершины реализуется через уменьшение ее ключа до &amp;lt;tex&amp;gt; -\infty &amp;lt;/tex&amp;gt; и последующим извлечением минимума. Амортизированное время работы: &amp;lt;tex&amp;gt; O(1) + O(D(n)) = O(D(n)) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Поскольку ранее мы показали, что &amp;lt;tex&amp;gt; D(n) = O(\log n ) &amp;lt;/tex&amp;gt;, то соответствующие оценки доказаны.&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
&lt;br /&gt;
* Томас Кормен, Чарльз Лейзерсон, Рональд Ривест, Клиффорд Штайн — Алгоритмы: построение и анализ. — М.: Издательский дом «Вильямс», 2005. — С. 1296. — ISBN 5-8459-0857-4&lt;br /&gt;
* [[wikipedia:ru:Числа Фибоначчи|Числа Фибоначчи {{---}} Википедия]]&lt;br /&gt;
* [[wikipedia:ru:Фибоначчиева куча|Фибоначчиева куча {{---}} Википедия]]&lt;br /&gt;
* [http://www.intuit.ru/department/algorithms/dscm/7/2.html Фибоначчиевы кучи — INTUIT.ru]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/heaps Визуализаторы]&lt;br /&gt;
* [http://www.cs.duke.edu/courses/fall05/cps230/L-11.pdf Fibonacci Heaps]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Приоритетные очереди]]&lt;/div&gt;</summary>
		<author><name>217.66.156.128</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B1%D0%BE%D0%BD%D0%B0%D1%87%D1%87%D0%B8%D0%B5%D0%B2%D0%B0_%D0%BA%D1%83%D1%87%D0%B0&amp;diff=46732</id>
		<title>Фибоначчиева куча</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B1%D0%BE%D0%BD%D0%B0%D1%87%D1%87%D0%B8%D0%B5%D0%B2%D0%B0_%D0%BA%D1%83%D1%87%D0%B0&amp;diff=46732"/>
				<updated>2015-05-20T17:28:15Z</updated>
		
		<summary type="html">&lt;p&gt;217.66.156.128: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Фибоначчиево дерево ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Фибоначчиево дерево''' (англ. ''Fibonacci tree'') {{---}} [[Биномиальная куча#Биномиальное дерево |биномиальное дерево]], где у каждой вершины удалено не более одного ребенка.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Порядок фибоначчиева дерева''' (англ. ''Fibonacci tree order'') {{---}} порядок соответствующего биномиального дерева, из которого оно получено.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Степень вершины''' (англ. ''degree'')  {{---}} количество дочерних узлов данной вершины.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма1&lt;br /&gt;
|statement=Для всех целых &amp;lt;tex&amp;gt; n \geqslant 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt; F_n = 1 + \sum\limits_{i=0}^{n-2} F_i &amp;lt;/tex&amp;gt;,&lt;br /&gt;
где &amp;lt;tex&amp;gt; F_n &amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt;-ое число Фибоначчи, определяемое формулой:&lt;br /&gt;
&amp;lt;tex&amp;gt;&lt;br /&gt;
F_n =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
 0, &amp;amp; n = 0 \\&lt;br /&gt;
 1, &amp;amp; n = 1 \\&lt;br /&gt;
 F_{n-1} + F_{n-2}, &amp;amp; n \geqslant 2&lt;br /&gt;
\end{cases} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Докажем лемму по индукции:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;tex&amp;gt;n = 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_2 = 1 + \sum\limits_{i=0}^0 F_i = 1 + 0 = 1&amp;lt;/tex&amp;gt;, что действительно верно.&lt;br /&gt;
&lt;br /&gt;
По индукции предполагаем, что &amp;lt;tex&amp;gt;F_{n-1} = 1 + \sum\limits_{i=0}^{n-3} F_i &amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_n = F_{n-1} + F_{n-2} = 1 + \sum\limits_{i=0}^{n-3} F_i + F_{n-2} = 1 + \sum\limits_{i=0}^{n-2} F_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма2&lt;br /&gt;
|statement= Фибоначчиево дерево порядка &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; содержит не менее &amp;lt;tex&amp;gt;F_n&amp;lt;/tex&amp;gt; вершин.&lt;br /&gt;
|proof=&lt;br /&gt;
Докажем это утверждение по индукции.&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;s_n&amp;lt;/tex&amp;gt; {{---}} минимальный размер фибоначчиева дерева порядка &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_0 = 1 &amp;gt; F_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_1 = 1 = F_1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предположим по индукции, что для всех &amp;lt;tex&amp;gt;i &amp;lt; n \ s_i \geqslant F_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Пусть в нашем дереве удалено поддерево порядка &amp;lt;tex&amp;gt;n - 1&amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_n = 1 + \sum\limits_{i=0}^{n-2} s_i \geqslant 1 + \sum\limits_{i=0}^{n-2} F_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Но по предыдущей [[#Лемма1|лемме]] :&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;tex&amp;gt;1 + \sum\limits_{i=0}^{n-2} F_i = F_n&amp;lt;/tex&amp;gt;. Следовательно, &amp;lt;tex&amp;gt;s_n \geqslant F_n&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Фибоначчиева куча ==&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Фибоначчиева куча''' (англ. ''Fibonacci heap'')   {{---}} набор фибоначчиевых деревьев, корни которых объединены в неупорядоченный [[Список#Циклический список |циклический]] [[Список#Двусвязный список | двусвязный список]]. В отличие от [[Биномиальная куча|биномиальной кучи]], степени корней не обязаны быть попарно различными.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Фибоначчиевы кучи поддерживают тот же набор операций, что и биномиальные кучи, но имеют то преимущество, что операции, в которых не требуется удаление, имеют [[Амортизационный анализ|амортизированное]] время работы, равное &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
С теоретической точки зрения фибоначчиевы кучи особенно полезны в случае, когда количество операций &amp;lt;tex&amp;gt;\mathrm {extractMin}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt; относительно мало по сравнению с количеством других операций. Однако с практической точки зрения программная сложность и высокие значения постоянных множителей в формулах времени работы  существенно снижают эффективность применения фибоначчиевых куч, делая их в большинстве случаев менее привлекательными, чем обычные [[Двоичная куча|бинарные кучи]].&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма3&lt;br /&gt;
|statement= &amp;lt;tex&amp;gt;F_n =\Theta(\varphi^n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt; \varphi = \frac {1 + \sqrt 5} {2}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Для начала докажем, что &amp;lt;tex&amp;gt;F_n =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^n - (-\varphi)^{-n}} {\sqrt 5}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Используем для этого математическую индукцию.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_0 =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^0 - (-\varphi)^0} {\sqrt 5} = \frac {1 - 1} {\sqrt 5} = 0&amp;lt;/tex&amp;gt;, что верно.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_1 =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^1 - (-\varphi)^{-1}} {\sqrt 5} = \frac {1} {\sqrt 5}(\frac {1 + \sqrt 5} {2} - \frac {1 - \sqrt 5} {2}) = \frac {2\sqrt 5} {2\sqrt 5} = 1&amp;lt;/tex&amp;gt;, что также верно.&lt;br /&gt;
&lt;br /&gt;
По индукции предполагаем, что &amp;lt;tex&amp;gt;F_{n-1} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-1} - (-\varphi)^{1-n}} {\sqrt 5}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;F_{n-2} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-2} - (-\varphi)^{2-n}} {\sqrt 5}&amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_n = F_{n-1} + F_{n-2} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-1} - (-\varphi)^{1-n}} {\sqrt 5} + \frac {\varphi^{n-2} - (-\varphi)^{2-n}} {\sqrt 5} =&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;= \frac {1} {\sqrt 5}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(\varphi^{n-1} - (-\varphi)^{1-n} + \varphi^{n-2} - (-\varphi)^{2-n}) &amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;= \frac {1} {\sqrt 5}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(\varphi^{n}(\varphi^{-1} + \varphi^{-2}) - (-\varphi)^{-n}(-\varphi + \varphi^{2}))&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подставив вместо &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; его значение, нетрудно убедится, что &amp;lt;tex&amp;gt;\varphi^{-1} + \varphi^{-2} = -\varphi + \varphi^{2} = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Поскольку &amp;lt;tex&amp;gt;\left\vert (-\varphi)^{-1} \right\vert &amp;lt; 1&amp;lt;/tex&amp;gt;, то выполняются неравенства &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {(-\varphi)^{-n}} {\sqrt 5} &amp;lt; \frac {1} {\sqrt 5} &amp;lt; \frac {1} {2}&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;-ое число Фибоначчи равно &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n}} {\sqrt 5}&amp;lt;/tex&amp;gt;, округленному до ближайшего целого числа. Следовательно, &amp;lt;tex&amp;gt;F_n =\Theta(\varphi^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма4&lt;br /&gt;
|statement=Максимальная степень &amp;lt;tex&amp;gt;D(n)&amp;lt;/tex&amp;gt; произвольной вершины в фибоначчиевой куче с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершинами равна &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; {{---}} произвольная вершина в фибоначчиевой куче с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершинами, и пусть &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; {{---}} степень вершины &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;. Тогда по [[#Лемма2|доказанному выше]] в дереве, корень которого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, содержится не менее &amp;lt;tex&amp;gt;F_k&amp;lt;/tex&amp;gt; вершин, что в свою очередь по [[#Лемма3|лемме]] равно &amp;lt;tex&amp;gt;\Theta(\varphi^k)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
То есть&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;n \geqslant \varphi^{k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Логарифмируя по основанию &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt;, получаем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\log_{\varphi}n \geqslant k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом, максимальная степень &amp;lt;tex&amp;gt;D(n)&amp;lt;/tex&amp;gt; произвольной вершины равна &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Структура ===&lt;br /&gt;
[[File:Fibonacci-heap.png|thumb|340px|Пример фибоначчиевой кучи]]&lt;br /&gt;
* Каждый узел &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; в куче &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; содержит следующие указатели и поля:&lt;br /&gt;
 '''struct''' Node&lt;br /&gt;
    '''int''' key &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// ключ&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' p &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// указатель на родительский узел&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' child &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// указатель на один из дочерних узлов&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' left &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// указатель  на левый сестринский узел&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''Node''' right &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// указатель на правый сестринский узел&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''int''' degree &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// количество дочерних узлов&amp;lt;/span&amp;gt;&lt;br /&gt;
    '''boolean''' mark &amp;lt;span style=&amp;quot;color:#008000&amp;quot;&amp;gt;// флаг, который показывает, удаляли ли мы дочерние узлы данной вершины&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Дочерние узлы &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; объединены при помощи указателей &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; в  циклический двусвязный список.&lt;br /&gt;
* Корни всех деревьев в &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; связаны при помощи указателей &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; в циклический двусвязный список корней.&lt;br /&gt;
* Обращение к &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; выполняется посредством указателя &amp;lt;tex&amp;gt;H.min&amp;lt;/tex&amp;gt; на корень дерева с минимальным ключом. Этот узел называется минимальным узлом &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Текущее количество узлов в &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; хранится в &amp;lt;tex&amp;gt;H.size&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Циклический двусвязный список обладает двумя преимуществами для использования в фибоначчиевых кучах. Во-первых, удаление элемента из такого списка выполняется за время &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;. Во-вторых, если имеется два таких списка, их легко объединить в один за время &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Потенциал ===&lt;br /&gt;
&lt;br /&gt;
Для анализа производительности операций введем потенциал для фибоначчиевой кучи &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; как &amp;lt;tex&amp;gt; \Phi(H) = t[H] + 2m[H] &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; t[H] &amp;lt;/tex&amp;gt; {{---}} количество элементов в корневом списке кучи, а &amp;lt;tex&amp;gt; m[H] &amp;lt;/tex&amp;gt; {{---}} количество вершин, у которых удален один ребенок (то есть вершин с пометкой &amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt;). Договоримся, что единицы потенциала достаточно для оплаты константного количества работы.&lt;br /&gt;
&lt;br /&gt;
=== Операции ===&lt;br /&gt;
Рассмотрим операции, которые поддерживают фибоначчиевы кучи. Амортизированное время их работы показано в таблице.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Операция&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Амортизированная сложность&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {makeHeap}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {insert}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {getMin}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {merge}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {extractMin}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(\log n )&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {decreaseKey}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(\log n )&amp;lt;/tex&amp;gt; &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Стоит заметить, что структура фибоначчиевых куч, также как биномиальных и бинарных, не могут обеспечить эффективную реализацию поиска элемента с заданным ключом, поэтому операции &amp;lt;tex&amp;gt;\mathrm {decreaseKey}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt; получают в качестве аргумента указатель на узел, а не значение его ключа.&lt;br /&gt;
&lt;br /&gt;
==== makeHeap ====&lt;br /&gt;
&lt;br /&gt;
Создается новый пустой корневой список, в &amp;lt;tex&amp;gt; H.min &amp;lt;/tex&amp;gt; устанавливается значение &amp;lt;tex&amp;gt; null &amp;lt;/tex&amp;gt;. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== insert ====&lt;br /&gt;
&lt;br /&gt;
Вставка элемента в фибоначчиеву кучу также тривиальна: создается новая куча из одного элемента и сливается с текущей. Для оценки амортизированной стоимости операции рассмотрим исходную кучу &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; и получившуюся в результате вставки нового элемента кучу &amp;lt;tex&amp;gt; H' &amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt; t[H'] = t[H] + 1 &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; m[H'] = m[H] &amp;lt;/tex&amp;gt;. Следовательно, увеличение потенциала составляет &amp;lt;tex&amp;gt; (t[H] + 1 + 2m[H]) - (t[H] + 2m[H]) = 1 &amp;lt;/tex&amp;gt;. Так как реальное время работы составляет &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, то амортизированная стоимость данной операции также равна &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== getMin ====&lt;br /&gt;
Возвращает указатель &amp;lt;tex&amp;gt;H.min&amp;lt;/tex&amp;gt;. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== merge ====&lt;br /&gt;
&lt;br /&gt;
Слияние двух фибоначчиевых куч происходит просто: объединяем списки этих куч в один, релаксируем минимум. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Амортизированное время работы также &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, поскольку, при объединении двух куч в одну, потенциалы обеих куч суммируются, итоговая сумма потенциалов не изменяется, &amp;lt;tex&amp;gt; \Phi_{n + 1} - \Phi_n = 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== extractMin ====&lt;br /&gt;
&lt;br /&gt;
Первая рассматриваемая операция, в ходе которой меняется структура кучи. Здесь используется вспомогательная процедура &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;. Возьмем указатель на &amp;lt;tex&amp;gt; H.min &amp;lt;/tex&amp;gt;, удалим эту вершину. Ее поддеревья (их не более, чем &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt; {{---}}  максимальная степень вершины в куче) объединим с корневым списком. Теперь вызываем процедуру &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;. После этой операции в списке корней остается не более чем &amp;lt;tex&amp;gt; D(n) + 1&amp;lt;/tex&amp;gt; узлов, среди которых нужно найти минимальный. Итоговая асимптотика операции &amp;lt;tex&amp;gt;\mathrm {extraxtMin}&amp;lt;/tex&amp;gt;, учитывая и вспомогательную функцию &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;, время работы которой доказывается ниже, равно: &amp;lt;tex&amp;gt; O(1)+O(D(n))+O(D(n))=O(D(n)) &amp;lt;/tex&amp;gt;. По доказанной выше [[#Лемма4|лемме]] &amp;lt;tex&amp;gt;O(D(n)) = O(\log(n))&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===== consolidate =====&lt;br /&gt;
&lt;br /&gt;
Данная процедура принимает кучу и преобразует ее таким образом, что в корневом списке остается не более &amp;lt;tex&amp;gt; D(n) + 1&amp;lt;/tex&amp;gt; вершин.&lt;br /&gt;
&lt;br /&gt;
Для этого возьмем массив списков указателей на корни деревьев &amp;lt;tex&amp;gt; A[0..D[H]] &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; D[H] &amp;lt;/tex&amp;gt; {{---}} максимальная степень вершины в текущем корневом списке.&lt;br /&gt;
&lt;br /&gt;
Затем происходит [[Биномиальная_куча#merge | процесс, аналогичный слиянию биномиальных куч]]: добавляем поочередно каждый корень, смотря на его степень. Пусть она равна &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;. Если в соответствующей ячейке &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; еще нету вершины, записываем текущую вершину туда. Иначе подвешиваем одно дерево к другому, и пытаемся также добавить дерево, степень корня которого уже равна &amp;lt;tex&amp;gt; d + 1 &amp;lt;/tex&amp;gt;. Продолжаем, пока не найдем свободную ячейку.&lt;br /&gt;
&lt;br /&gt;
Учетная стоимость &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt; равна &amp;lt;tex&amp;gt; O(D(n)) &amp;lt;/tex&amp;gt;. Докажем это:&lt;br /&gt;
&lt;br /&gt;
Изначально в корневом списке было не более &amp;lt;tex&amp;gt; D(n) + t[H] - 1 &amp;lt;/tex&amp;gt; вершин, поскольку он состоит из исходного списка корней с &amp;lt;tex&amp;gt;t[H]&amp;lt;/tex&amp;gt; узлами, минус извлеченный узел и плюс дочерние узлы, количество которых не превышает &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt;. В ходе операции &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt; мы сделали &amp;lt;tex&amp;gt; O(D(n) + t[H]) &amp;lt;/tex&amp;gt; слияний деревьев. Потенциал перед извлечением минимума равен &amp;lt;tex&amp;gt; t[H] + 2m[H] &amp;lt;/tex&amp;gt;, а после не превышает &amp;lt;tex&amp;gt; D(n) + 1 + 2m[H] &amp;lt;/tex&amp;gt;, поскольку в корневом списке остается не более  &amp;lt;tex&amp;gt; D(n) + 1 &amp;lt;/tex&amp;gt; узлов, а количество помеченных узлов не изменяется. Таким образом, амортизированная стоимость не превосходит&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; O(D(n) + t[H]) + (D(n) + 1 + 2m[H]) - (t[H] + 2m[H]) = O(D(n)) + O(t[H]) - t[H]&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Поскольку мы договорились, что можем масштабировать единицу потенциала таким образом, чтобы покрывать константное количество работы, то итоговая амортизационная оценка {{---}} &amp;lt;tex&amp;gt; O(D(n)) &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== decreaseKey ====&lt;br /&gt;
&lt;br /&gt;
Основная идея: хотим, чтобы учетная стоимость данной операции была &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Было бы хорошо, чтобы вершина не всплывала до корня, и тогда дерево не придется сильно перестраивать. Для этого при удобном случае будем вырезать поддерево полностью и перемещать его в корневой список. Итак, сам алгоритм:&lt;br /&gt;
&lt;br /&gt;
# Проверяем, если новое значение ключа все же не меньше значения ключа родителя, то все хорошо, и мы выходим.&lt;br /&gt;
# Иначе, вырезаем дерево с текущей вершиной в корневой список, и производим каскадное вырезание родителя. &lt;br /&gt;
&lt;br /&gt;
===== cut =====&lt;br /&gt;
&lt;br /&gt;
При вырезании вершины мы удаляем ее из списка детей своего родителя, уменьшаем степень ее родителя (&amp;lt;tex&amp;gt; x.p.degree &amp;lt;/tex&amp;gt;) и снимаем пометку с текущей вершины (&amp;lt;tex&amp;gt; x.mark = false &amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
===== cascadingCut =====&lt;br /&gt;
&lt;br /&gt;
[[File:Каскадное вырезание.png|thumb|500px|Пример каскадного вырезания]]&lt;br /&gt;
&lt;br /&gt;
Перед вызовом каскадного вырезания нам известно, удаляли ли ребенка у этой вершины. Если у вершины до этого не удаляли дочерний узел (&amp;lt;tex&amp;gt; x.mark = false &amp;lt;/tex&amp;gt;), то мы помечаем эту вершину (&amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt;) и прекращаем выполнение операции. В противном случае применяем операцию &amp;lt;tex&amp;gt;\mathrm {cut}&amp;lt;/tex&amp;gt; для текущей вершины и запускаем каскадное вырезание от родителя.&lt;br /&gt;
&lt;br /&gt;
'''Пример'''&lt;br /&gt;
&lt;br /&gt;
Рисунок иллюстрирует пример каскадного вырезания:&lt;br /&gt;
&lt;br /&gt;
* Изначально, куча состояла из &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; фибоначчиевых деревьев. У вершины с ключом &amp;lt;tex&amp;gt;24&amp;lt;/tex&amp;gt; отсутствует &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; ребенок.&lt;br /&gt;
* Уменьшаем ключ &amp;lt;tex&amp;gt;26&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; и делаем операцию &amp;lt;tex&amp;gt;\mathrm {cut}&amp;lt;/tex&amp;gt; этого дерева. Получаем кучу с &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt; деревьями и новым минимумом. Но у вершины с ключом &amp;lt;tex&amp;gt;24&amp;lt;/tex&amp;gt; был удален второй ребенок, поэтому запускам операцию &amp;lt;tex&amp;gt;\mathrm {cascadingCut}&amp;lt;/tex&amp;gt; для этой вершины: вырезаем ее, помещаем в корневой список и помечаем ее родителя.&lt;br /&gt;
* У вершины с ключом &amp;lt;tex&amp;gt;7&amp;lt;/tex&amp;gt; удален лишь один ребенок, поэтому операция &amp;lt;tex&amp;gt;\mathrm {cascadingCut}&amp;lt;/tex&amp;gt; от нее не запускается. В итоге, получаем кучу, состоящую из &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; фибоначчиевых деревьев.&lt;br /&gt;
&lt;br /&gt;
===== Время работы =====&lt;br /&gt;
&lt;br /&gt;
Докажем, что амортизированное время работы операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; есть &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Поскольку в процедуре нет циклов, ее время работы определяется лишь количеством рекурсивных вызовов каскадного вырезания.&lt;br /&gt;
&lt;br /&gt;
Пусть мы вызвали процедуру каскадного вырезания &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; раз. Так как реальное время работы операции &amp;lt;tex&amp;gt; \mathrm {cascadingCut} &amp;lt;/tex&amp;gt; без учета рекурсии составляет &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, то реальное время работы операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt; O(k) &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Рассмотрим, как изменится потенциал в результате выполнения данной операции. Пусть &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; {{---}} фибоначчиева куча до вызова &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt;. Тогда после &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; рекурсивных вызовов операции &amp;lt;tex&amp;gt; \mathrm {cascadingCut} &amp;lt;/tex&amp;gt; вершин с пометкой &amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt; стало как минимум на &amp;lt;tex&amp;gt; k - 2 &amp;lt;/tex&amp;gt; меньше, потому что каждый вызов каскадного вырезания, за исключением последнего, уменьшает количество помеченных вершин на одну, и в результате последнего вызова одну вершину мы можем пометить. В корневом списке прибавилось &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; новых деревьев (&amp;lt;tex&amp;gt; k - 1 &amp;lt;/tex&amp;gt; дерево за счет каскадного вырезания и еще одно из-за самого первого вызова операции &amp;lt;tex&amp;gt; \mathrm {cut} &amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
В итоге, изменение потенциала составляет: &amp;lt;tex&amp;gt; \Phi_i - \Phi_{i - 1} = ((t[H] + k) + 2(m[H] + k - 2)) - (t[H] + 2m[H]) = 4 - k &amp;lt;/tex&amp;gt;. Следовательно, амортизированная стоимость не превышает &amp;lt;tex&amp;gt; O(k) + 4 - k &amp;lt;/tex&amp;gt;. Но поскольку мы можем соответствующим образом масштабировать единицы потенциала, то амортизированная стоимость операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; равна &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== delete ====&lt;br /&gt;
&lt;br /&gt;
Удаление вершины реализуется через уменьшение ее ключа до &amp;lt;tex&amp;gt; -\infty &amp;lt;/tex&amp;gt; и последующим извлечением минимума. Амортизированное время работы: &amp;lt;tex&amp;gt; O(1) + O(D(n)) = O(D(n)) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Поскольку ранее мы показали, что &amp;lt;tex&amp;gt; D(n) = O(\log n ) &amp;lt;/tex&amp;gt;, то соответствующие оценки доказаны.&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
&lt;br /&gt;
* Томас Кормен, Чарльз Лейзерсон, Рональд Ривест, Клиффорд Штайн — Алгоритмы: построение и анализ. — М.: Издательский дом «Вильямс», 2005. — С. 1296. — ISBN 5-8459-0857-4&lt;br /&gt;
* [[wikipedia:ru:Числа Фибоначчи|Числа Фибоначчи {{---}} Википедия]]&lt;br /&gt;
* [[wikipedia:ru:Фибоначчиева куча|Фибоначчиева куча {{---}} Википедия]]&lt;br /&gt;
* [http://www.intuit.ru/department/algorithms/dscm/7/2.html Фибоначчиевы кучи — INTUIT.ru]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/heaps Визуализаторы]&lt;br /&gt;
* [http://www.cs.duke.edu/courses/fall05/cps230/L-11.pdf Fibonacci Heaps]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Приоритетные очереди]]&lt;/div&gt;</summary>
		<author><name>217.66.156.128</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B1%D0%BE%D0%BD%D0%B0%D1%87%D1%87%D0%B8%D0%B5%D0%B2%D0%B0_%D0%BA%D1%83%D1%87%D0%B0&amp;diff=46731</id>
		<title>Фибоначчиева куча</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B1%D0%BE%D0%BD%D0%B0%D1%87%D1%87%D0%B8%D0%B5%D0%B2%D0%B0_%D0%BA%D1%83%D1%87%D0%B0&amp;diff=46731"/>
				<updated>2015-05-20T17:19:53Z</updated>
		
		<summary type="html">&lt;p&gt;217.66.156.128: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Фибоначчиево дерево ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Фибоначчиево дерево''' (англ. ''Fibonacci tree'') {{---}} [[Биномиальная куча#Биномиальное дерево |биномиальное дерево]], где у каждой вершины удалено не более одного ребенка.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Порядок фибоначчиева дерева''' (англ. ''Fibonacci tree order'') {{---}} порядок соответствующего биномиального дерева, из которого оно получено.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Степень вершины''' (англ. ''degree'')  {{---}} количество дочерних узлов данной вершины.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма1&lt;br /&gt;
|statement=Для всех целых &amp;lt;tex&amp;gt; n \geqslant 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt; F_n = 1 + \sum\limits_{i=0}^{n-2} F_i &amp;lt;/tex&amp;gt;,&lt;br /&gt;
где &amp;lt;tex&amp;gt; F_n &amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt;-ое число Фибоначчи, определяемое формулой:&lt;br /&gt;
&amp;lt;tex&amp;gt;&lt;br /&gt;
F_n =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
 0, &amp;amp; n = 0 \\&lt;br /&gt;
 1, &amp;amp; n = 1 \\&lt;br /&gt;
 F_{n-1} + F_{n-2}, &amp;amp; n \geqslant 2&lt;br /&gt;
\end{cases} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Докажем лемму по индукции:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;tex&amp;gt;n = 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_2 = 1 + \sum\limits_{i=0}^0 F_i = 1 + 0 = 1&amp;lt;/tex&amp;gt;, что действительно верно.&lt;br /&gt;
&lt;br /&gt;
По индукции предполагаем, что &amp;lt;tex&amp;gt;F_{n-1} = 1 + \sum\limits_{i=0}^{n-3} F_i &amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_n = F_{n-1} + F_{n-2} = 1 + \sum\limits_{i=0}^{n-3} F_i + F_{n-2} = 1 + \sum\limits_{i=0}^{n-2} F_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма2&lt;br /&gt;
|statement= Фибоначчиево дерево порядка &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; содержит не менее &amp;lt;tex&amp;gt;F_n&amp;lt;/tex&amp;gt; вершин.&lt;br /&gt;
|proof=&lt;br /&gt;
Докажем это утверждение по индукции.&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;s_n&amp;lt;/tex&amp;gt; {{---}} минимальный размер фибоначчиева дерева порядка &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_0 = 1 &amp;gt; F_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_1 = 1 = F_1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предположим по индукции, что для всех &amp;lt;tex&amp;gt;i &amp;lt; n \ s_i \geqslant F_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Пусть в нашем дереве удалено поддерево порядка &amp;lt;tex&amp;gt;n - 1&amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;s_n = 1 + \sum\limits_{i=0}^{n-2} s_i \geqslant 1 + \sum\limits_{i=0}^{n-2} F_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Но по предыдущей [[#Лемма1|лемме]] :&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;tex&amp;gt;1 + \sum\limits_{i=0}^{n-2} F_i = F_n&amp;lt;/tex&amp;gt;. Следовательно, &amp;lt;tex&amp;gt;s_n \geqslant F_n&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Фибоначчиева куча ==&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Фибоначчиева куча''' (англ. ''Fibonacci heap'')   {{---}} набор фибоначчиевых деревьев, корни которых объединены в неупорядоченный [[Список#Циклический список |циклический]] [[Список#Двусвязный список | двусвязный список]]. В отличие от [[Биномиальная куча|биномиальной кучи]], степени корней не обязаны быть попарно различными.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Фибоначчиевы кучи поддерживают тот же набор операций, что и биномиальные кучи, но имеют то преимущество, что операции, в которых не требуется удаление, имеют [[Амортизационный анализ|амортизированное]] время работы, равное &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
С теоретической точки зрения фибоначчиевы кучи особенно полезны в случае, когда количество операций &amp;lt;tex&amp;gt;\mathrm {extractMin}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt; относительно мало по сравнению с количеством других операций. Однако с практической точки зрения программная сложность и высокие значения постоянных множителей в формулах времени работы  существенно снижают эффективность применения фибоначчиевых куч, делая их в большинстве случаев менее привлекательными, чем обычные [[Двоичная куча|бинарные кучи]].&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма3&lt;br /&gt;
|statement= &amp;lt;tex&amp;gt;F_n =\Theta(\varphi^n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt; \varphi = \frac {1 + \sqrt 5} {2}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Для начала докажем, что &amp;lt;tex&amp;gt;F_n =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^n - (-\varphi)^{-n}} {\sqrt 5}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Используем для этого математическую индукцию.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_0 =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^0 - (-\varphi)^0} {\sqrt 5} = \frac {1 - 1} {\sqrt 5} = 0&amp;lt;/tex&amp;gt;, что верно.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_1 =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^1 - (-\varphi)^{-1}} {\sqrt 5} = \frac {1} {\sqrt 5}(\frac {1 + \sqrt 5} {2} - \frac {1 - \sqrt 5} {2}) = \frac {2\sqrt 5} {2\sqrt 5} = 1&amp;lt;/tex&amp;gt;, что также верно.&lt;br /&gt;
&lt;br /&gt;
По индукции предполагаем, что &amp;lt;tex&amp;gt;F_{n-1} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-1} - (-\varphi)^{1-n}} {\sqrt 5}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;F_{n-2} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-2} - (-\varphi)^{2-n}} {\sqrt 5}&amp;lt;/tex&amp;gt;. Тогда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;F_n = F_{n-1} + F_{n-2} =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n-1} - (-\varphi)^{1-n}} {\sqrt 5} + \frac {\varphi^{n-2} - (-\varphi)^{2-n}} {\sqrt 5} =&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;= \frac {1} {\sqrt 5}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(\varphi^{n-1} - (-\varphi)^{1-n} + \varphi^{n-2} - (-\varphi)^{2-n}) &amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;= \frac {1} {\sqrt 5}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(\varphi^{n}(\varphi^{-1} + \varphi^{-2}) - (-\varphi)^{-n}(-\varphi + \varphi^{2}))&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подставив вместо &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; его значение, нетрудно убедится, что &amp;lt;tex&amp;gt;\varphi^{-1} + \varphi^{-2} = -\varphi + \varphi^{2} = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Поскольку &amp;lt;tex&amp;gt;\left\vert (-\varphi)^{-1} \right\vert &amp;lt; 1&amp;lt;/tex&amp;gt;, то выполняются неравенства &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {(-\varphi)^{-n}} {\sqrt 5} &amp;lt; \frac {1} {\sqrt 5} &amp;lt; \frac {1} {2}&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;-ое число Фибоначчи равно &amp;lt;tex dpi=&amp;quot;160&amp;quot;&amp;gt;\frac {\varphi^{n}} {\sqrt 5}&amp;lt;/tex&amp;gt;, округленному до ближайшего целого числа. Следовательно, &amp;lt;tex&amp;gt;F_n =\Theta(\varphi^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=Лемма4&lt;br /&gt;
|statement=Максимальная степень &amp;lt;tex&amp;gt;D(n)&amp;lt;/tex&amp;gt; произвольной вершины в фибоначчиевой куче с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершинами равна &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; {{---}} произвольная вершина в фибоначчиевой куче с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершинами, и пусть &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; {{---}} степень вершины &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;. Тогда по [[#Лемма2|доказанному выше]] в дереве, корень которого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, содержится не менее &amp;lt;tex&amp;gt;F_k&amp;lt;/tex&amp;gt; вершин, что в свою очередь по [[#Лемма3|лемме]] равно &amp;lt;tex&amp;gt;\Theta(\varphi^k)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
То есть&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;n \geqslant \varphi^{k}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Логарифмируя по основанию &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt;, получаем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\log_{\varphi}n \geqslant k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом, максимальная степень &amp;lt;tex&amp;gt;D(n)&amp;lt;/tex&amp;gt; произвольной вершины равна &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Структура ===&lt;br /&gt;
[[File:Fibonacci-heap.png|thumb|340px|Пример фибоначчиевой кучи]]&lt;br /&gt;
* Каждый узел &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; в куче &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; содержит следующие указатели и поля:&lt;br /&gt;
 '''Node'''&lt;br /&gt;
    int key; //ключ&lt;br /&gt;
    Node* p; //указатель на родительский узел&lt;br /&gt;
    Node* child; //указатель на один из дочерних узлов&lt;br /&gt;
    Node* left; //указатель  на левый сестринский узел&lt;br /&gt;
    Node* right; //указатель на правый сестринский узел&lt;br /&gt;
    int degree; //количество дочерних узлов&lt;br /&gt;
    boolean mark; //флаг, который показывает, удаляли ли мы дочерние узлы данной вершины&lt;br /&gt;
&lt;br /&gt;
* Дочерние узлы &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; объединены при помощи указателей &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; в  циклический двусвязный список.&lt;br /&gt;
* Корни всех деревьев в &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; связаны при помощи указателей &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; в циклический двусвязный список корней.&lt;br /&gt;
* Обращение к &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; выполняется посредством указателя &amp;lt;tex&amp;gt;H.min&amp;lt;/tex&amp;gt; на корень дерева с минимальным ключом. Этот узел называется минимальным узлом &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Текущее количество узлов в &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; хранится в &amp;lt;tex&amp;gt;H.size&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Циклический двусвязный список обладает двумя преимуществами для использования в фибоначчиевых кучах. Во-первых, удаление элемента из такого списка выполняется за время &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;. Во-вторых, если имеется два таких списка, их легко объединить в один за время &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Потенциал ===&lt;br /&gt;
&lt;br /&gt;
Для анализа производительности операций введем потенциал для фибоначчиевой кучи &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; как &amp;lt;tex&amp;gt; \Phi(H) = t[H] + 2m[H] &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; t[H] &amp;lt;/tex&amp;gt; {{---}} количество элементов в корневом списке кучи, а &amp;lt;tex&amp;gt; m[H] &amp;lt;/tex&amp;gt; {{---}} количество вершин, у которых удален один ребенок (то есть вершин с пометкой &amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt;). Договоримся, что единицы потенциала достаточно для оплаты константного количества работы.&lt;br /&gt;
&lt;br /&gt;
=== Операции ===&lt;br /&gt;
Рассмотрим операции, которые поддерживают фибоначчиевы кучи. Амортизированное время их работы показано в таблице.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Операция&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Амортизированная сложность&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {makeHeap}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {insert}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {getMin}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {merge}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {extractMin}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(\log n )&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {decreaseKey}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| &amp;lt;tex&amp;gt;O(\log n )&amp;lt;/tex&amp;gt; &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Стоит заметить, что структура фибоначчиевых куч, также как биномиальных и бинарных, не могут обеспечить эффективную реализацию поиска элемента с заданным ключом, поэтому операции &amp;lt;tex&amp;gt;\mathrm {decreaseKey}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathrm {delete}&amp;lt;/tex&amp;gt; получают в качестве аргумента указатель на узел, а не значение его ключа.&lt;br /&gt;
&lt;br /&gt;
==== makeHeap ====&lt;br /&gt;
&lt;br /&gt;
Создается новый пустой корневой список, в &amp;lt;tex&amp;gt; H.min &amp;lt;/tex&amp;gt; устанавливается значение &amp;lt;tex&amp;gt; null &amp;lt;/tex&amp;gt;. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== insert ====&lt;br /&gt;
&lt;br /&gt;
Вставка элемента в фибоначчиеву кучу также тривиальна: создается новая куча из одного элемента и сливается с текущей. Для оценки амортизированной стоимости операции рассмотрим исходную кучу &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; и получившуюся в результате вставки нового элемента кучу &amp;lt;tex&amp;gt; H' &amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt; t[H'] = t[H] + 1 &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; m[H'] = m[H] &amp;lt;/tex&amp;gt;. Следовательно, увеличение потенциала составляет &amp;lt;tex&amp;gt; (t[H] + 1 + 2m[H]) - (t[H] + 2m[H]) = 1 &amp;lt;/tex&amp;gt;. Так как реальное время работы составляет &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, то амортизированная стоимость данной операции также равна &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== getMin ====&lt;br /&gt;
Возвращает указатель &amp;lt;tex&amp;gt;H.min&amp;lt;/tex&amp;gt;. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== merge ====&lt;br /&gt;
&lt;br /&gt;
Слияние двух фибоначчиевых куч происходит просто: объединяем списки этих куч в один, релаксируем минимум. Реальное время работы {{---}} &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Амортизированное время работы также &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, поскольку, при объединении двух куч в одну, потенциалы обеих куч суммируются, итоговая сумма потенциалов не изменяется, &amp;lt;tex&amp;gt; \Phi_{n + 1} - \Phi_n = 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== extractMin ====&lt;br /&gt;
&lt;br /&gt;
Первая рассматриваемая операция, в ходе которой меняется структура кучи. Здесь используется вспомогательная процедура &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;. Возьмем указатель на &amp;lt;tex&amp;gt; H.min &amp;lt;/tex&amp;gt;, удалим эту вершину. Ее поддеревья (их не более, чем &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt; {{---}}  максимальная степень вершины в куче) объединим с корневым списком. Теперь вызываем процедуру &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;. После этой операции в списке корней остается не более чем &amp;lt;tex&amp;gt; D(n) + 1&amp;lt;/tex&amp;gt; узлов, среди которых нужно найти минимальный. Итоговая асимптотика операции &amp;lt;tex&amp;gt;\mathrm {extraxtMin}&amp;lt;/tex&amp;gt;, учитывая и вспомогательную функцию &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt;, время работы которой доказывается ниже, равно: &amp;lt;tex&amp;gt; O(1)+O(D(n))+O(D(n))=O(D(n)) &amp;lt;/tex&amp;gt;. По доказанной выше [[#Лемма4|лемме]] &amp;lt;tex&amp;gt;O(D(n)) = O(\log(n))&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===== consolidate =====&lt;br /&gt;
&lt;br /&gt;
Данная процедура принимает кучу и преобразует ее таким образом, что в корневом списке остается не более &amp;lt;tex&amp;gt; D(n) + 1&amp;lt;/tex&amp;gt; вершин.&lt;br /&gt;
&lt;br /&gt;
Для этого возьмем массив списков указателей на корни деревьев &amp;lt;tex&amp;gt; A[0..D[H]] &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; D[H] &amp;lt;/tex&amp;gt; {{---}} максимальная степень вершины в текущем корневом списке.&lt;br /&gt;
&lt;br /&gt;
Затем происходит [[Биномиальная_куча#merge | процесс, аналогичный слиянию биномиальных куч]]: добавляем поочередно каждый корень, смотря на его степень. Пусть она равна &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt;. Если в соответствующей ячейке &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; еще нету вершины, записываем текущую вершину туда. Иначе подвешиваем одно дерево к другому, и пытаемся также добавить дерево, степень корня которого уже равна &amp;lt;tex&amp;gt; d + 1 &amp;lt;/tex&amp;gt;. Продолжаем, пока не найдем свободную ячейку.&lt;br /&gt;
&lt;br /&gt;
Учетная стоимость &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt; равна &amp;lt;tex&amp;gt; O(D(n)) &amp;lt;/tex&amp;gt;. Докажем это:&lt;br /&gt;
&lt;br /&gt;
Изначально в корневом списке было не более &amp;lt;tex&amp;gt; D(n) + t[H] - 1 &amp;lt;/tex&amp;gt; вершин, поскольку он состоит из исходного списка корней с &amp;lt;tex&amp;gt;t[H]&amp;lt;/tex&amp;gt; узлами, минус извлеченный узел и плюс дочерние узлы, количество которых не превышает &amp;lt;tex&amp;gt; D(n) &amp;lt;/tex&amp;gt;. В ходе операции &amp;lt;tex&amp;gt; \mathrm {consolidate} &amp;lt;/tex&amp;gt; мы сделали &amp;lt;tex&amp;gt; O(D(n) + t[H]) &amp;lt;/tex&amp;gt; слияний деревьев. Потенциал перед извлечением минимума равен &amp;lt;tex&amp;gt; t[H] + 2m[H] &amp;lt;/tex&amp;gt;, а после не превышает &amp;lt;tex&amp;gt; D(n) + 1 + 2m[H] &amp;lt;/tex&amp;gt;, поскольку в корневом списке остается не более  &amp;lt;tex&amp;gt; D(n) + 1 &amp;lt;/tex&amp;gt; узлов, а количество помеченных узлов не изменяется. Таким образом, амортизированная стоимость не превосходит&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; O(D(n) + t[H]) + (D(n) + 1 + 2m[H]) - (t[H] + 2m[H]) = O(D(n)) + O(t[H]) - t[H]&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Поскольку мы договорились, что можем масштабировать единицу потенциала таким образом, чтобы покрывать константное количество работы, то итоговая амортизационная оценка {{---}} &amp;lt;tex&amp;gt; O(D(n)) &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== decreaseKey ====&lt;br /&gt;
&lt;br /&gt;
Основная идея: хотим, чтобы учетная стоимость данной операции была &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Было бы хорошо, чтобы вершина не всплывала до корня, и тогда дерево не придется сильно перестраивать. Для этого при удобном случае будем вырезать поддерево полностью и перемещать его в корневой список. Итак, сам алгоритм:&lt;br /&gt;
&lt;br /&gt;
# Проверяем, если новое значение ключа все же не меньше значения ключа родителя, то все хорошо, и мы выходим.&lt;br /&gt;
# Иначе, вырезаем дерево с текущей вершиной в корневой список, и производим каскадное вырезание родителя. &lt;br /&gt;
&lt;br /&gt;
===== cut =====&lt;br /&gt;
&lt;br /&gt;
При вырезании вершины мы удаляем ее из списка детей своего родителя, уменьшаем степень ее родителя (&amp;lt;tex&amp;gt; x.p.degree &amp;lt;/tex&amp;gt;) и снимаем пометку с текущей вершины (&amp;lt;tex&amp;gt; x.mark = false &amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
===== cascadingCut =====&lt;br /&gt;
&lt;br /&gt;
[[File:Каскадное вырезание.png|thumb|500px|Пример каскадного вырезания]]&lt;br /&gt;
&lt;br /&gt;
Перед вызовом каскадного вырезания нам известно, удаляли ли ребенка у этой вершины. Если у вершины до этого не удаляли дочерний узел (&amp;lt;tex&amp;gt; x.mark = false &amp;lt;/tex&amp;gt;), то мы помечаем эту вершину (&amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt;) и прекращаем выполнение операции. В противном случае применяем операцию &amp;lt;tex&amp;gt;\mathrm {cut}&amp;lt;/tex&amp;gt; для текущей вершины и запускаем каскадное вырезание от родителя.&lt;br /&gt;
&lt;br /&gt;
'''Пример'''&lt;br /&gt;
&lt;br /&gt;
Рисунок иллюстрирует пример каскадного вырезания:&lt;br /&gt;
&lt;br /&gt;
* Изначально, куча состояла из &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; фибоначчиевых деревьев. У вершины с ключом &amp;lt;tex&amp;gt;24&amp;lt;/tex&amp;gt; отсутствует &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; ребенок.&lt;br /&gt;
* Уменьшаем ключ &amp;lt;tex&amp;gt;26&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; и делаем операцию &amp;lt;tex&amp;gt;\mathrm {cut}&amp;lt;/tex&amp;gt; этого дерева. Получаем кучу с &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt; деревьями и новым минимумом. Но у вершины с ключом &amp;lt;tex&amp;gt;24&amp;lt;/tex&amp;gt; был удален второй ребенок, поэтому запускам операцию &amp;lt;tex&amp;gt;\mathrm {cascadingCut}&amp;lt;/tex&amp;gt; для этой вершины: вырезаем ее, помещаем в корневой список и помечаем ее родителя.&lt;br /&gt;
* У вершины с ключом &amp;lt;tex&amp;gt;7&amp;lt;/tex&amp;gt; удален лишь один ребенок, поэтому операция &amp;lt;tex&amp;gt;\mathrm {cascadingCut}&amp;lt;/tex&amp;gt; от нее не запускается. В итоге, получаем кучу, состоящую из &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; фибоначчиевых деревьев.&lt;br /&gt;
&lt;br /&gt;
===== Время работы =====&lt;br /&gt;
&lt;br /&gt;
Докажем, что амортизированное время работы операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; есть &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;. Поскольку в процедуре нет циклов, ее время работы определяется лишь количеством рекурсивных вызовов каскадного вырезания.&lt;br /&gt;
&lt;br /&gt;
Пусть мы вызвали процедуру каскадного вырезания &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; раз. Так как реальное время работы операции &amp;lt;tex&amp;gt; \mathrm {cascadingCut} &amp;lt;/tex&amp;gt; без учета рекурсии составляет &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;, то реальное время работы операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt; O(k) &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Рассмотрим, как изменится потенциал в результате выполнения данной операции. Пусть &amp;lt;tex&amp;gt; H &amp;lt;/tex&amp;gt; {{---}} фибоначчиева куча до вызова &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt;. Тогда после &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; рекурсивных вызовов операции &amp;lt;tex&amp;gt; \mathrm {cascadingCut} &amp;lt;/tex&amp;gt; вершин с пометкой &amp;lt;tex&amp;gt; x.mark = true &amp;lt;/tex&amp;gt; стало как минимум на &amp;lt;tex&amp;gt; k - 2 &amp;lt;/tex&amp;gt; меньше, потому что каждый вызов каскадного вырезания, за исключением последнего, уменьшает количество помеченных вершин на одну, и в результате последнего вызова одну вершину мы можем пометить. В корневом списке прибавилось &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; новых деревьев (&amp;lt;tex&amp;gt; k - 1 &amp;lt;/tex&amp;gt; дерево за счет каскадного вырезания и еще одно из-за самого первого вызова операции &amp;lt;tex&amp;gt; \mathrm {cut} &amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
В итоге, изменение потенциала составляет: &amp;lt;tex&amp;gt; \Phi_i - \Phi_{i - 1} = ((t[H] + k) + 2(m[H] + k - 2)) - (t[H] + 2m[H]) = 4 - k &amp;lt;/tex&amp;gt;. Следовательно, амортизированная стоимость не превышает &amp;lt;tex&amp;gt; O(k) + 4 - k &amp;lt;/tex&amp;gt;. Но поскольку мы можем соответствующим образом масштабировать единицы потенциала, то амортизированная стоимость операции &amp;lt;tex&amp;gt; \mathrm {decreaseKey} &amp;lt;/tex&amp;gt; равна &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== delete ====&lt;br /&gt;
&lt;br /&gt;
Удаление вершины реализуется через уменьшение ее ключа до &amp;lt;tex&amp;gt; -\infty &amp;lt;/tex&amp;gt; и последующим извлечением минимума. Амортизированное время работы: &amp;lt;tex&amp;gt; O(1) + O(D(n)) = O(D(n)) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Поскольку ранее мы показали, что &amp;lt;tex&amp;gt; D(n) = O(\log n ) &amp;lt;/tex&amp;gt;, то соответствующие оценки доказаны.&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
&lt;br /&gt;
* Томас Кормен, Чарльз Лейзерсон, Рональд Ривест, Клиффорд Штайн — Алгоритмы: построение и анализ. — М.: Издательский дом «Вильямс», 2005. — С. 1296. — ISBN 5-8459-0857-4&lt;br /&gt;
* [[wikipedia:ru:Числа Фибоначчи|Числа Фибоначчи {{---}} Википедия]]&lt;br /&gt;
* [[wikipedia:ru:Фибоначчиева куча|Фибоначчиева куча {{---}} Википедия]]&lt;br /&gt;
* [http://www.intuit.ru/department/algorithms/dscm/7/2.html Фибоначчиевы кучи — INTUIT.ru]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/heaps Визуализаторы]&lt;br /&gt;
* [http://www.cs.duke.edu/courses/fall05/cps230/L-11.pdf Fibonacci Heaps]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Приоритетные очереди]]&lt;/div&gt;</summary>
		<author><name>217.66.156.128</name></author>	</entry>

	</feed>