Haskell:从其位表示重建二叉树

时间:2018-04-21 00:55:59

标签: haskell recursion binary-tree huffman-code

我正在将哈夫曼编码算法重写为Haskell新手练习,我正在努力改造我使用以下技术序列化的树:
- 在深度优先预订中从根走树 - 遇到一个节点放0然后递归左边然后右边的孩子
- 遇到一个Leaf放1然后是符号字节

我的序列化代码:

serializeHtree :: (Ord a) => CodeDict a -> HTree a -> [Bit]
serializeHtree dict (Leaf a) = I : (myLpad $ dict M.! a)
serializeHtree dict (Branch l r) = O : (serializeHtree dict r ++ serializeHtree dict l)

其中:
- CodeDict是从a到[Bit]的映射 - myLpad用0填充可变长度的霍夫曼代码,使其成为固定长度的 - 和Bit是我自己的数据类型由O和I构建

例如,
Huffman tree

上面的树将表示为:
 01的 00000000 001的 00000100 1的 00000101 01的 00000110 1的 00000111

现在反序列化它,我知道我必须每位读取流位并且:
- 遇到一个1用下一个字节制作一个叶子 - 遇到一个0使分支在左边和右边的子树上递归

但是我的方法失败了,这是我的反序列化代码(这次不起作用):

deserializeHtree :: [Bit] -> HTree a
deserializeHtree (x:xs) = case x of
    'O' -> Branch (deserializeHtree xs) (deserializeHtree xs)
    'I' -> Leaf (head xs)  

感谢您的支持

1 个答案:

答案 0 :(得分:2)

您需要使用适合递归的类型编写解析器。

在顶级,您确实需要[Bit] -> HTree a(可能会将a限制为某个类型类,但我忽略了这一点。但是,要启用递归,您需要

parser :: [Bit] -> (HTree a, [Bit])
-- or, if you need to handle failure
parser :: [Bit] -> Maybe (HTree a, [Bit])

这个想法是parser被提供了要解析的位。 然后它尝试解析第一个树,该树在这些位的前缀中表示。如果成功,则返回HTree a和超出(非消耗)位的列表。

返回非消耗位对于需要解析两个子树的Branch至关重要。解析第一个,取非消耗的位,然后使用它们启动右子树的解析器。

这个主题对于SO答案来说过于宽泛,但是如果你谷歌为#34; Haskell解析器monad"你应该找到很多例子。