Фибоначчиева куча — различия между версиями
Warrior (обсуждение | вклад) (→Фибоначчиевы деревья) |
Warrior (обсуждение | вклад) (→Фибоначчиевы деревья) |
||
| Строка 11: | Строка 11: | ||
{{Лемма | {{Лемма | ||
|id=Лемма1 | |id=Лемма1 | ||
| − | |statement=Для всех целых <tex> | + | |statement=Для всех целых <tex> n \geqslant 2</tex> |
| − | <tex> | + | <tex> F_n = 1 + \sum\limits_{i=0}^{n-2} F_i </tex>, |
| − | где <tex> | + | где <tex> F_n </tex> {{---}} <tex> n </tex> число Фибоначчи, определяемое формулой: |
<tex> | <tex> | ||
| − | + | F_n = | |
\begin{cases} | \begin{cases} | ||
| − | 0, & | + | 0, & n = 0 \\ |
| − | 1, & | + | 1, & n = 1 \\ |
| − | F_{ | + | F_{n-1} + F_{n-2}, & n \geqslant 2 |
\end{cases} </tex> | \end{cases} </tex> | ||
|proof= | |proof= | ||
Докажем лемму с помощью математической индукции: | Докажем лемму с помощью математической индукции: | ||
| − | при <tex> | + | при <tex>n = 2</tex> |
<tex>F_2 = 1 + \sum\limits_{i=0}^0 F_i = 1 + 0 = 1</tex>, что действительно верно. | <tex>F_2 = 1 + \sum\limits_{i=0}^0 F_i = 1 + 0 = 1</tex>, что действительно верно. | ||
| − | По индукции предполагаем, что <tex>F_{ | + | По индукции предполагаем, что <tex>F_{n-1} = 1 + \sum\limits_{i=0}^{n-3} F_i </tex>. Тогда |
| − | <tex> | + | <tex>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</tex> |
}} | }} | ||
{{Лемма | {{Лемма | ||
|id=Лемма2 | |id=Лемма2 | ||
| − | |statement= <tex> | + | |statement= <tex>F_n =\Theta(\varphi^n)</tex>, где <tex dpi="160"> \varphi = \frac {1 + \sqrt 5} {2}</tex> |
|proof= | |proof= | ||
| − | Для начала докажем, что <tex> | + | Для начала докажем, что <tex>F_n =</tex> <tex dpi="160">\frac {\varphi^n - (-\varphi)^{-n}} {\sqrt 5}</tex> |
Используем для этого математическую индукцию. | Используем для этого математическую индукцию. | ||
| − | При <tex> | + | При <tex>n = 0</tex> |
<tex>F_0 =</tex> <tex dpi="160">\frac {\varphi^0 - (-\varphi)^0} {\sqrt 5} = \frac {1 - 1} {\sqrt 5} = 0</tex>, что верно. | <tex>F_0 =</tex> <tex dpi="160">\frac {\varphi^0 - (-\varphi)^0} {\sqrt 5} = \frac {1 - 1} {\sqrt 5} = 0</tex>, что верно. | ||
| Строка 49: | Строка 49: | ||
<tex>F_1 =</tex> <tex dpi="160">\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</tex>, что также верно. | <tex>F_1 =</tex> <tex dpi="160">\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</tex>, что также верно. | ||
| − | По индукции предполагаем, что <tex>F_{ | + | По индукции предполагаем, что <tex>F_{n-1} =</tex> <tex dpi="160">\frac {\varphi^{n-1} - (-\varphi)^{1-n}} {\sqrt 5}</tex> и <tex>F_{n-2} =</tex> <tex dpi="160">\frac {\varphi^{n-2} - (-\varphi)^{2-n}} {\sqrt 5}</tex>. Тогда |
| − | <tex> | + | <tex>F_n = F_{n-1} + F_{n-2} =</tex> <tex dpi="160">\frac {\varphi^{n-1} - (-\varphi)^{1-n}} {\sqrt 5} + \frac {\varphi^{n-2} - (-\varphi)^{2-n}} {\sqrt 5} =</tex> |
| − | <tex dpi="160">= \frac {1} {\sqrt 5}</tex> <tex>(\varphi^{ | + | <tex dpi="160">= \frac {1} {\sqrt 5}</tex> <tex>(\varphi^{n-1} - (-\varphi)^{1-n} + \varphi^{n-2} - (-\varphi)^{2-n}) </tex> <tex dpi="160">= \frac {1} {\sqrt 5}</tex> <tex>(\varphi^{n}(\varphi^{-1} + \varphi^{-2}) - (-\varphi)^{-n}(-\varphi + \varphi^{2}))</tex> |
Подставив вместо <tex>\varphi</tex> его значение, нетрудно убедится, что <tex>\varphi^{-1} + \varphi^{-2} = -\varphi + \varphi^{2} = 1</tex> | Подставив вместо <tex>\varphi</tex> его значение, нетрудно убедится, что <tex>\varphi^{-1} + \varphi^{-2} = -\varphi + \varphi^{2} = 1</tex> | ||
| − | Поскольку <tex>\left\vert (-\varphi)^{-1} \right\vert < 1</tex>, то выполняются неравенства <tex dpi="160">\frac {(-\varphi)^{- | + | Поскольку <tex>\left\vert (-\varphi)^{-1} \right\vert < 1</tex>, то выполняются неравенства <tex dpi="160">\frac {(-\varphi)^{-n}} {\sqrt 5} < \frac {1} {\sqrt 5} < \frac {1} {2}</tex>. Таким образом, <tex>n</tex>-е число Фибоначчи равно <tex dpi="160">\frac {\varphi^{n}} {\sqrt 5}</tex>, округленному до ближайшего целого числа. Следовательно, <tex>F_n =\Theta(\varphi^n)</tex>. |
}} | }} | ||
| − | + | {{Лемма | |
| + | |id=Лемма3 | ||
| + | |statement= Фибоначчиево дерево порядка <tex>n</tex> содержит не менее <tex>F_n</tex> вершин. | ||
| + | |proof= | ||
| + | Докажем это утверждение по индукции. | ||
| + | Пусть <tex>s_n</tex> {{---}} минимальный размер фибоначчиева дерева порядка n. | ||
| + | |||
| + | При <tex>n = 0</tex> | ||
| − | + | <tex>s_0 = 1 > F_0</tex>. | |
| − | + | При <tex>n = 1</tex> | |
| − | + | <tex>s_1 = 1 = F_1</tex>. | |
| + | |||
| + | Предположим по индукции, что для всех <tex>i < n \ s_i \geqslant F_i</tex>. | ||
| + | Пусть в нашем дереве удалено поддерево порядка <tex>n - 1</tex>. Тогда | ||
| + | |||
| + | <tex>s_n = 1 + \sum\limits_{i=0}^{n-2} s_i \geqslant 1 + \sum\limits_{i=0}^{n-2} F_i</tex> | ||
| + | |||
| + | Но по [[#Лемма1|лемме]] <tex>1 + \sum\limits_{i=0}^{n-2} F_i = F_n</tex>. Следовательно, <tex>s_n \geqslant F_n</tex> | ||
| + | }} | ||
= Фибоначчиевы кучи = | = Фибоначчиевы кучи = | ||
Версия 19:58, 8 марта 2012
Содержание
Фибоначчиевы деревья
| Определение: |
| Фибоначчиево дерево - биномиальное дерево, где у каждой вершины удалено не более одного ребенка. |
| Определение: |
| Фибоначчиево дерево порядка - биномиальное дерево порядка , из которого оно получено. |
| Лемма: |
Для всех целых
, где — число Фибоначчи, определяемое формулой: |
| Доказательство: |
|
Докажем лемму с помощью математической индукции: при , что действительно верно. По индукции предполагаем, что . Тогда |
| Лемма: |
, где |
| Доказательство: |
|
Для начала докажем, что Используем для этого математическую индукцию. При , что верно. При , что также верно. По индукции предполагаем, что и . Тогда
Подставив вместо его значение, нетрудно убедится, что Поскольку , то выполняются неравенства . Таким образом, -е число Фибоначчи равно , округленному до ближайшего целого числа. Следовательно, . |
| Лемма: |
Фибоначчиево дерево порядка содержит не менее вершин. |
| Доказательство: |
|
Докажем это утверждение по индукции. Пусть — минимальный размер фибоначчиева дерева порядка n. При . При . Предположим по индукции, что для всех . Пусть в нашем дереве удалено поддерево порядка . Тогда Но по лемме . Следовательно, |
Фибоначчиевы кучи
| Определение: |
| Фибоначчиева куча - набор фибоначчиевых деревьев. |
Корни фибоначчиевых деревьев, составляющих фибоначчиеву кучу, также объединены в двусвязный циклический список (корневой список, root list). В отличие от биномиальных куч, в корневом списке может находиться несколько деревьев с одной и той же степенью корня.
Доступ к куче осуществляется с помощью указателя , указывающего на минимальную вершину в куче.
Доказательство времени работы для всех операций с фибоначчиевыми кучами проводим с помощью методов амортизационного анализа.
Операции
Потенциал
Введем потенциал фибоначчиевой кучи , где — количество элементов в корневом списке кучи, а — количество вершин, у которых удален один ребенок (то есть вершин с пометкой ). Подходящую константу выберем позже, на этапе анализа каскадного вырезания. На языке метода предоплаты это выглядит следующим образом: возле каждого корня лежит одна монета, а возле каждой вершины, у которой удалили ребенка, лежит две монеты.
Создание кучи
Создается новый пустой корневой список, в устанавливается значение . Реальное время работы — .
Слияние
Слияние двух фибоначчиевых куч происходит просто: объединяем списки этих куч в один, релаксируем минимум. Реальное время работы — . Амортизированное время работы - также , поскольку, при объединении двух куч в одну, потенциалы обеих куч суммируются, итоговая сумма потенциалов не изменяется, .
Вставка элемента
Вставка элемента в фибоначчиеву кучу также тривиальна: создается новая куча из одного элемента и сливается с текущей. Амортизированная стоимость операции: 1 (создание кучи) + 2 (слияние куч + релаксация минимума) + 1(изменение потенциала) = 4.
Извлечение минимума
Первая рассматриваемая операция, в ходе которой меняется структура кучи. Здесь используется вспомогательная процедура Consolidate ("уплотнение" кучи). Возьмем указатель на , удалим эту вершину. Ее поддеревья (их не более, чем , где — максимальная степень вершины в куче) все положим в корневой список. Теперь вызываем процедуру .
"Уплотнение" (Consolidate)
Данная процедура принимает кучу, и делает из нее кучу, в корневом списке которой вершин.
Для этого возьмем массив списков указателей на корни деревьев , где — максимальная степень вершины в текущем корневом списке. Далее мы увидим, что .
Затем происходит процесс, аналогичный слиянию биномиальных куч : добавляем поочередно каждый корень, смотря на его степень. Пусть она равна . Если в соответствующей ячейке A еще нету вершины, записываем текущую вершину туда. Иначе подвешиваем одно дерево к другому, и пытаемся также добавить дерево, степень корня которого уже равна . Продолжаем, пока не найдем свободную ячейку.
Учетная стоимость равна . Докажем это:
Пусть изначально в корневом списке было вершин. Тогда в ходе операции мы сделали слияний деревьев. Но эти слияний скомпенсируются уменьшением потенциала . Остальных действий будет также . Таким образом, учетная стоимость .
На языке метода предоплаты: Положим у каждой вершины-ребенка удаленной монету. Это действий. Теперь: у каждой вершины в корневом списке лежит монета, потратим ее на то, чтобы провести процедуру . Получили новый корневой список, снова раздаем монеты каждой вершине. Итого действий.
Уменьшение ключа
Основная идея: хотим, чтобы учетная стоимость данной операции была . Было бы хорошо, чтобы вершина не всплывала до корня; тогда дерево не придется сильно перестраивать. Для этого, при удобном случае будем вырезать поддерево полностью и перемещать его в корневой список. Итак, сам алгоритм:
- Проверяем, если новое значение ключа все же не меньше значения ключа родителя, то все хорошо, и мы выходим.
- Иначе, вырезаем дерево с текущей вершиной в корневой список, и производим каскадное вырезание родителя.
Вырезание вершины
При вырезании вершины мы удаляем ее из списка детей своего родителя, уменьшаем степень ее родителя () и снимаем пометку с текущей вершины ().
Каскадное вырезание
Перед вызовом каскадного вырезания нам известно, что перед этим мы удалили ребенка у этой вершины. Если , то мы ставим эту пометку и заканчиваем. В противном случае, вырезаем текущую вершину, и запускаем каскадное вырезание от родителя.
Докажем, что амортизированное время работы операции "уменьшение ключа" есть . Поскольку в процедуре нет циклов, ее время работы определяется лишь количеством рекурсивных вызовов каскадного вырезания.
Пусть мы вызвали процедуру каскадного вырезания раз. Тогда вершин с пометкой стало на меньше, а в корневом списке прибавилось новых вершин. Итого, время работы будет: . Теперь, подбирая соответствующую константу в потенциале, можем добиться того, чтобы амортизированное время работы этой процедуры стало . Теперь также стало ясно, для чего в определении нашего потенциала количество вершин с пометкой учитывается вдвое больше, чем количество вершин в корневом списке.
На языке метода предоплаты: Покажем, что взяв в начале 4 монеты, нам хватит этого для выполнения данной операции. Возьмем 4 монеты перед началом уменьшения ключа. Теперь 1 монету потратим на перенос в корневой список и релаксацию минимума, еще 1 - на то, чтобы положить монету у новой вершины в корневом списке. У нас осталось 2 монеты. Далее производим каскадное вырезание: в случае, когда , кладем 2 монеты к этой вершине, и устанавливаем соответствующую пометку. Инвариант сохраняется.
Иначе, и там лежит 2 монеты. 2 + 2 = 4, и мы можем рекурсивно продолжить данный процесс. Оценка доказана.
На рисунке проиллюстрирован процесс понижения ключа вершины c 10 до 7. Серым помечены вершины с .
Удаление вершины
Удаление вершины реализуется через уменьшение ее ключа до и последующим извлечением минимума. Амортизированное время работы: .
Поскольку, ранее мы показали, что , то соответствующие оценки доказаны.
Ссылки
- Томас Кормен, Чарльз Лейзерсон, Рональд Ривест, Клиффорд Штайн - Алгоритмы: построение и анализ. — М.: Издательский дом «Вильямс», 2005. — С. 1296. — ISBN 5-8459-0857-4
- http://ru.wikipedia.org/wiki/Фибоначчиева_куча
- http://www.intuit.ru/department/algorithms/dscm/7/2.html - INTUIT.ru
- Визуализаторы на rain.ifmo.ru: http://rain.ifmo.ru/cat/view.php/vis/heaps
- http://www.cs.duke.edu/courses/fall05/cps230/L-11.pdf