Haskell中优先级队列实现的比较

时间:2011-08-07 23:38:08

标签: haskell

Haskell似乎有几种现成的优先级队列实现。例如,有:

这两者似乎都是纯优先级队列数据结构。前者基于手指树,这是一种我不熟悉的数据结构;后者是Data.Map的包装器。还有

定义了纯功能堆数据结构,从中可以轻松地创建优先级队列。 。还有

它们都使用Brodal / Okasaki数据结构实现纯功能可融合堆,我认为这类似于非纯函数域中的二项式堆数据结构。

(哦,还有

  • Data.PriorityQueue(在hackage的priority-queue-0.2.2中)

我的功能不清楚,但它似乎与monad相关的构建优先级队列相关,而且无论如何它似乎都建立在Data.Map之上。在这个问题中,我关注纯粹的功能优先级队列,所以我认为priority-queue-0.2.2包是无关紧要的。但如果我错了,请纠正我!)

我需要为我正在构建的项目提供纯功能优先级队列数据结构。当我在hackage提供的embarrassment of riches之间做出决定时,我想知道是否有人可以提供任何智慧的话语。具体做法是:

  1. 假设我希望在纯函数/不可变表示中执行除传统优先级队列插入和提取最小值操作之外的功能。上面提到的包的优缺点是什么?有没有人有'愤怒'使用其中任何一个的经验?表现有哪些权衡?可靠性?其他人更广泛地使用哪种? (使用这些可能会让我的代码更容易让其他人阅读,因为他们更有可能熟悉这个库。)在他们之间作出决定之前还有其他我应该知道的事情吗?
  2. 如果我还想要有效合并优先级队列,那么呢? (我不赞成这个项目,但我想添加这个,但会让SO问题对未来的读者更有用。)
  3. 我错过了其他优先级队列包吗?

1 个答案:

答案 0 :(得分:38)

在hackage上有很多优先级队列实现,只是为了完成你的列表:

在那些我发现PSQueue有一个特别好的界面。我想这是第一个实现之一,并且由{RALf Hinze在this paper中很好地介绍了。它可能不是最有效和最完整的实现,但到目前为止它已满足我的所有需求。

Louis Wassermann(他还撰写了issue 16包)在MonadReader(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]

可以在haskell.org here上找到threadhere相当有趣的{{3}}优先队列实施的一些基准。