Сравнение реализаций очереди приоритетов в Haskell
там, кажется, есть несколько приоритетных реализаций очереди, доступных в готовом виде для Haskell. Например, здесь:
- данные.PriorityQueue.FingerTree (in fingertree-0.0.1.0 на hackage)
- данные.PurePriorityQueue (in pure-priority-queue-0.14 на hackage)
оба из которых кажутся чистыми приоритетными структурами данных очереди. Первый основан на пальцевых деревьях, структуре данных, с которой я незнакомый; последний является оболочкой вокруг данных.Карта. Там же
- данные.Куча (в куча-1.0.0 на hackage)
который определяет чисто функциональные структуры данных кучи, из которых можно тривиально сделать приоритетные очереди. . Есть еще
- данные.Куча (в куч-0.2 на hackage)
- данные.MeldableHeap (in meldable-heap-2.0.3 на hackage)
, который обе реализуйте чисто функциональные плавящиеся кучи, используя структуру данных Brodal/Okasaki, которая, как я считаю, аналогична биномиальной структуре данных кучи в нечистой функциональной земле.
(О, и еще
- данные.PriorityQueue (in priority-queue-0.2.2 on hackage)
чья функция мне непонятна, но которая, похоже, связана с построением очередей приоритетов, прикрепленных к монаде, и которая, похоже, построена поверх данных.Карта в любом случае. В этом вопрос, я занимаюсь чисто функциональными очередями приоритетов, поэтому я думаю, что пакет priority-queue-0.2.2 не имеет значения. Но поправьте меня, если я ошибаюсь!)
Мне нужна чистая функциональная структура данных очереди приоритетов для проекта, который я строю. Мне было интересно, может ли кто-нибудь предоставить какие-либо слова мудрости, когда я решаю между слишком много предоставлены здесь. В частности:
- предположим, я хочу сделать функции помимо традиционных приоритетные операции вставки очереди и извлечения-min, в чисто функциональном / неизменяемом представлении. Каковы плюсы и минусы упомянутых выше пакетов? У кого-нибудь есть опыт использования любого из них "в гневе"? Каковы компромиссы в производительности? Надежность? Которые используются более широко другими? (Используя их, вы можете сделать мой код более легким для чтения другими, так как они, скорее всего, будут знакомы с библиотекой.) Есть какие-то другие вещи, которые я должен знать, прежде чем принимать решение между ними?
- Если я также хочу эффективного слияния очередей приоритетов, что тогда? (Я не для этого проекта, но я думал добавить это, но сделал бы так вопрос более полезным для будущих читателей.)
- есть ли другие приоритетные пакеты очереди там, что я пропустил?
1 ответ:
существует множество реализаций очереди приоритетов, которые можно найти на hackage, просто чтобы завершить ваш список:
- http://hackage.haskell.org/package/PSQueue
- http://hackage.haskell.org/package/pqueue
- http://hackage.haskell.org/package/queuelike
- http://hackage.haskell.org/package/priority-queue
- http://hackage.haskell.org/package/pure-priority-queue
- http://hackage.haskell.org/package/fingertree-psqueue
из из них я обнаружил, что PSQueue имеет особенно приятный интерфейс. Я думаю, что это была одна из первых реализаций и красиво покрыта этой статье Ральф Гинц. Возможно, это не самая эффективная и полная реализация, но до сих пор она удовлетворяла все мои потребности.
в MonadReader есть очень хорошая статья (выпуск 16) Луи Вассерман (который также написал pqueue пакет). В своей статье Луи дает множество различных приоритетные реализации очереди, а также включает в себя алгоритмические сложности для каждого.
В качестве яркого примера простоты некоторых внутренних приоритетов очереди он включает в себя некоторые интересные небольшие реализации. Мой любимый (взятый из его статьи):data SkewHeap a = Empty | SkewNode a (SkewHeap a) (SkewHeap a) deriving (Show) (+++) :: Ord a => SkewHeap a -> SkewHeap a -> SkewHeap a heap1@(SkewNode x1 l1 r1) +++ heap2@(SkewNode x2 l2 r2) | x1 <= x2 = SkewNode x1 (heap2 +++ r1) l1 | otherwise = SkewNode x2 (heap1 +++ r2) l2 Empty +++ heap = heap heap +++ Empty = heap extractMin Empty = Nothing extractMin (SkewNode x l r ) = Just (x , l +++ r )
прохладно мало реализации...короткий пример использования:
test = foldl (\acc x->acc +++ x) Empty nodes where nodes = map (\x-> SkewNode x Empty Empty) [3,5,1,9,7,2]
можно найти некоторые критерии реализации приоритетных очередей здесь и в довольно интересном thread on haskell.org здесь.