Кто-нибудь на самом деле реализовал Фибоначчи-кучу эффективно?


кто-нибудь из вас когда-нибудь реализован Фибоначчи-Кучи? Я сделал это несколько лет назад, но это было на несколько порядков медленнее, чем использование массивных двоичных файлов.

тогда я думал об этом как о ценном уроке в том, как исследования не всегда так хороши, как это утверждает. Однако многие исследовательские работы утверждают, что время работы их алгоритмов основано на использовании кучи Фибоначчи.

вам когда-нибудь удавалось создать эффективную реализацию? Или вы работали с наборами данных настолько большими, что куча Фибоначчи была более эффективной? Если да,то некоторые детали будут оценены.

4 141

4 ответа:

The Boost C++ библиотеки включить реализацию куч Фибоначчи в boost/pending/fibonacci_heap.hpp. Этот файл, по-видимому, был в pending/ в течение многих лет и по моим прогнозам никогда не будет принято. Кроме того, в этой реализации были ошибки, которые были исправлены моим знакомым и все вокруг крутым парнем Аароном Виндзором. К сожалению, большинство версий этого файла, которые я мог найти в интернете (и в пакете libboost-dev Ubuntu), все еще имели ошибки; мне пришлось тянуть чистая версия из репозитория Subversion.

начиная с версии 1.49Boost C++ библиотеки добавлено много новых структур куч, включая кучу Фибоначчи.

мне удалось скомпилировать dijkstra_heap_performance.cpp против измененной версии dijkstra_shortest_paths.ГЭС для сравнения куч Фибоначчи и двоичных куч. (В строке typedef relaxed_heap<Vertex, IndirectCmp, IndexMap> MutableQueue, изменения relaxed до fibonacci.) Я первый забыл скомпилировать с оптимизациями, в этом случае Фибоначчи и двоичные кучи выполняют примерно то же самое, причем кучи Фибоначчи обычно превосходят незначительную величину. После того, как я скомпилировал с очень сильными оптимизациями, бинарные кучи получили огромный импульс. В моих тестах кучи Фибоначчи только превосходили двоичные кучи, когда график был невероятно большим и плотным, например:

Generating graph...10000 vertices, 20000000 edges.
Running Dijkstra's with binary heap...1.46 seconds.
Running Dijkstra's with Fibonacci heap...1.31 seconds.
Speedup = 1.1145.

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

поэтому, чтобы извлечь выгоду из кучи Фибоначчи на практике, вы должны использовать их в приложении, где decrease_keys невероятно часто. В терминах Дейкстры это означает, что лежащий в основе граф плотен. Некоторые приложения могут быть внутренне decrease_key-intense; я хотел попробовать алгоритм минимального разреза Нагомочи-Ибараки потому что, по-видимому, он генерирует много decrease_keys, но это было слишком много усилий, чтобы получить сравнение времени работы.

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

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

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

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

кнут сделал сравнение между кучей Фибоначчи и бинарными кучами для минимальных остовных деревьев еще в 1993 году для своей книги Stanford Graphbase. Он обнаружил, что Фибоначчи от 30 до 60 проц медленнее, чем двоичные кучи при размерах графа, которые он тестировал, 128 вершин с разной плотностью.

Элемент исходный код находится в C (или, скорее, CWEB, который является крестом между C, math и TeX) в разделе MILES_SPAN.

отказ от ответственности

Я знаю, что результаты очень похожи и "похоже, что во время работы полностью доминирует что-то другое, чем куча" (@Alpedar). Но я не смог найти никаких доказательств этого в коде. Код открыт, так что если вы можете найти что-нибудь, что может повлиять на результат теста, пожалуйста, скажите мне.


может быть, я сделал что-то не так, но я написал тест на основе A. Rex ответить сравнение:

  • Фибоначчи-Кучи
  • D-Ary-heap (4)
  • Binary-Heap
  • Услуги-Кучи

время выполнения (только для полных графиков) для всех куч было очень близко. Тест был сделан для полных графов с 1000,2000,3000,4000,5000,6000,7000 и 8000 вершин. Для каждого теста было сгенерировано 50 случайных графиков, а на выходе-среднее время каждой кучи:

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


вот результаты (в секундах):

heap result table

Я также сделал небольшой эксперимент с кучей Фибоначчи. Вот ссылка для деталей: экспериментируя с-dijkstras-алгоритмом. Я просто погуглил термины "Fibonacci heap java" и попробовал несколько существующих реализаций с открытым исходным кодом кучи Фибоначчи. Кажется, что некоторые из них имеют некоторые проблемы с производительностью, но есть некоторые, которые довольно хороши. По крайней мере, они бьют наивную и двоичную производительность PQ кучи в моем тесте. Может быть, они могут помочь реализовать эффективный один.