【问题标题】:Binomial Heap implementation in HaskellHaskell 中的二项式堆实现
【发布时间】:2018-05-14 14:59:57
【问题描述】:

我正在尝试使用“Purely Functional Data Structures” Chris Okasaki 一书在 Haskell 中实现二项式堆。

{- Implemetation of Binomial Heap-}
module BinomialHeap where

 {- Definition of a Binomial Tree -}
 data BTree a = Node Int a ([BTree a]) deriving Show

 {- Definition of a Binomial Heap -}
 data BHeap a = Heap [BTree a] deriving Show

 empty :: BHeap a
 empty = Heap []


 {- Linking function tree -}
    -- w/ larger root is
    --  linked w/ tree w/ lower root  -}
 link :: Ord a => BTree a -> BTree a -> BTree a
 link t1@(Node r x1 c1) t2@(Node _ x2 c2) =
    if x1 < x2 then
        Node (r+1) x1 (t2:c1)
    else
        Node (r+1) x2 (t1:c2)

 root :: BTree a -> a
 root (Node _ x _) = x

 {- Gives the rank of the Binomial Tree-} 
 rank :: BTree a -> Int 
 rank (Node r _ _ ) = r

 {- Insertion in the tree -}
    -- Create a new singl. tree
    -- Step through the existing trees in increasing order
    -- until we find a missing rank
    -- link tree of equal ranks
    -- atm it's O(log n)
 insTree :: Ord a => BTree a -> [BTree a] -> [BTree a]
 insTree t [] = [t]
 insTree t ts1@(t1':ts1') =
     if rank t > rank t1' then
        t:ts1
     else
        insTree (link t t1') ts1'

 insert :: Ord a => BHeap a -> a -> BHeap a
 insert (Heap ts) x = Heap $ insTree (Node 0 x []) ts

 {- Merge of Heaps-}
    --  We step through both list of tree in increasing order
    -- link tree of equal root
 merge :: Ord a => [BTree a] -> [BTree a] -> [BTree a]
 merge [] ts = ts 
 merge ts [] = ts
 merge ts1@(t1:ts1') ts2@(t2:ts2') = 
    if rank t1 < rank t2 then
        t1:merge ts1' ts2
    else if rank t2 < rank t1 then
        t2:merge ts1 ts2'
    else 
        insTree (link t1 t2) (merge ts1' ts2')


 sampleHeap :: BHeap Int
 sampleHeap = foldl insert empty [1, 2, 3]

问题是插入给了我一个不正确的输出:

Heap [Node 1 1 [Node 0 3 [],Node 0 2 []]]

插入原语可能不正确。冈崎 说:

“要向堆中插入一个新元素,我们首先创建一个新的单例树(等级 0)。然后我们按等级递增的顺序逐步遍历现有的树,直到找到缺失的等级,将具有相同等级的树连接为我们走吧。每个链接对应一个二进制算术进位"

您能帮我找出插入原语中可能存在错误的地方吗? 谢谢。

【问题讨论】:

  • 欢迎来到 StackOverflow。请将问题简化为minimal reproducible example,这样我们就不必跳过与问题无关的代码。
  • 你说输出“不正确”;你期望得到什么?

标签: haskell


【解决方案1】:

来自冈崎的论文第 71 页 (https://www.cs.cmu.edu/~rwh/theses/okasaki.pdf):

出于稍后将变得清楚的原因,我们保留以下列表 以递增顺序表示堆的树,但保持 表示节点的子节点的树列表在递减 排名顺序。

让我们根据这个声明来看看你的insTree 函数:

 insTree :: Ord a => BTree a -> [BTree a] -> [BTree a]
 insTree t [] = [t]
 insTree t ts1@(t1':ts1') =
     if rank t > rank t1' then
        t:ts1
     else
        insTree (link t t1') ts1'

注意二叉树列表不为空的情况。那里的代码说如果被插入的树的排名大于列表中下一棵树的排名,则将树添加到列表中。这违反了代表堆的树列表按等级递增顺序组织的假设。在比较中将符号从 &gt; 反转为 &lt; 应该可以解决问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-06
    • 1970-01-01
    • 2013-11-11
    • 1970-01-01
    • 2010-10-19
    • 1970-01-01
    • 2011-09-25
    • 1970-01-01
    相关资源
    最近更新 更多