微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何实现最佳的,纯功能的双端优先级队列?

如何解决如何实现最佳的,纯功能的双端优先级队列?

Okasaki展示了如何使用O(1) insertO(log n) minView编写纯功能优先级队列(某些版本还提供O(log n)甚至{{1} } O(1)。这些想法中的任何一个都可以扩展到双端优先级队列吗?Khoong和Leong(在我没有获得的论文中)提供了一种基于二项式的临时实现。堆,但从他们的论文中我可以看到,这种方法似乎很难持久化,因为它使用了父指针和兄弟指针。

解决方法

如左图所示,可以使用2–3个手指树来完成。特别是用半群注释的人

data MinMax k = MinMax
  { smallest :: !k,largest :: !k }

instance Ord k => Semigroup (MinMax k) where
  MinMax min1 max1 <> MinMax min2 max2 = MinMax (min min1 min2) (max max1 max2)

可以用与fingertree包定义优先级队列基本相同的方式,将这种带注释的手指树做成双端优先级队列(但要稍作调整以避免使用Monoid)。可以使用与minView相同的实现技术来改善maxViewData.Sequence.deleteAt

为什么使用Semigroup而不添加中性元素使其成为Monoid?这样,我们可以将MinMax批注解包到树节点中,并避免在每个步骤中都有额外的间接操作以及额外的分配。

性能界限

  • insert:摊销O(1)(注意:由于谨慎使用惰性,即使面对持久性,此界限也将成立)。最差情况O(log n)。请注意,fingertree包仅声明O(log n)即可插入;这是我报告的文档错误,将在下一版本中予以纠正。
  • minView / maxView:最坏情况下的O(1)可以看到最小值/最大值;最糟糕的情况是O(log n)删除它。
  • meld:最坏情况O(log(min(m,n)),其中mn是队列的大小。

Hinze-Paterson风格的2–3手指树实际上比必要的多。一个手指的版本就可以解决这个问题,位数更少。

{-# options_ghc -funbox-strict-fields #-}

data Node k a
  = Node2 !(MinMax k) !a !a
  | Node3 !(MinMax k) !a !a !a

data Tree k a
  = Empty
    -- the child of a Zero node may
    -- not be empty
  | Zero !(MinMax k) (Tree k (Node k a))
  | One !(MinMax k) !a (Tree k (Node k a))

最近几天我一直在努力充实。幸运的是,它非常简单。不幸的是,它需要大量的代码。根本的挑战是在2至3棵树中进行删除是相当重要的。手指树的版本增加了另一层复杂性。然后,整个内容必须写两次才能处理minViewmaxView

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。