Haskell:从其位表示重建二叉树
Haskell: rebuild binary tree from its bits representation
我正在将霍夫曼编码算法重写为 Haskell 新手练习,我正在努力改造我使用以下技术序列化的树:
- 以深度优先预序从根开始遍历树
- 遇到一个节点 put 0 followed by recurse on left then right childs
- 遇到一个 Leaf put 1 后跟符号 byte
我的序列化代码:
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
构造的我自己的数据类型
例如,
上面的树将表示为:
0100000000001000001001000001010100000110100000111
现在要反序列化它,我知道我必须逐位读取流并且:
- 遇到一个 1 用下一个字节做一个叶子
- 遇到 0 使分支在左子树和右子树上递归
但是我的方法失败了,这是我的反序列化代码(这次没有功能):
deserializeHtree :: [Bit] -> HTree a
deserializeHtree (x:xs) = case x of
'O' -> Branch (deserializeHtree xs) (deserializeHtree xs)
'I' -> Leaf (head xs)
感谢支持
您需要编写一个解析器,使用适合递归的类型。
在顶层你确实想要 [Bit] -> HTree a
(可能将 a
限制为某种类型 class,但我会忽略这一点)。但是,要启用递归,您需要
parser :: [Bit] -> (HTree a, [Bit])
-- or, if you need to handle failure
parser :: [Bit] -> Maybe (HTree a, [Bit])
这个想法是 parser
被提供了要解析的位。
然后它尝试解析 first 树,该树表示在这些位的 prefix 中。如果成功,它会 returns 一个 HTree a
和超出(未消耗)位的列表。
返回未消耗的位对于 Branch
需要解析两个子树至关重要。您解析第一个,获取未消耗的位,然后使用它们启动右子树的解析器。
这个主题对于一个 SO 答案来说太广泛了,但是如果你 google 对 "Haskell parser monad" 你应该找到很多例子。
我正在将霍夫曼编码算法重写为 Haskell 新手练习,我正在努力改造我使用以下技术序列化的树:
- 以深度优先预序从根开始遍历树
- 遇到一个节点 put 0 followed by recurse on left then right childs
- 遇到一个 Leaf put 1 后跟符号 byte
我的序列化代码:
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
例如,
上面的树将表示为:
0100000000001000001001000001010100000110100000111
现在要反序列化它,我知道我必须逐位读取流并且:
- 遇到一个 1 用下一个字节做一个叶子
- 遇到 0 使分支在左子树和右子树上递归
但是我的方法失败了,这是我的反序列化代码(这次没有功能):
deserializeHtree :: [Bit] -> HTree a
deserializeHtree (x:xs) = case x of
'O' -> Branch (deserializeHtree xs) (deserializeHtree xs)
'I' -> Leaf (head xs)
感谢支持
您需要编写一个解析器,使用适合递归的类型。
在顶层你确实想要 [Bit] -> HTree a
(可能将 a
限制为某种类型 class,但我会忽略这一点)。但是,要启用递归,您需要
parser :: [Bit] -> (HTree a, [Bit])
-- or, if you need to handle failure
parser :: [Bit] -> Maybe (HTree a, [Bit])
这个想法是 parser
被提供了要解析的位。
然后它尝试解析 first 树,该树表示在这些位的 prefix 中。如果成功,它会 returns 一个 HTree a
和超出(未消耗)位的列表。
返回未消耗的位对于 Branch
需要解析两个子树至关重要。您解析第一个,获取未消耗的位,然后使用它们启动右子树的解析器。
这个主题对于一个 SO 答案来说太广泛了,但是如果你 google 对 "Haskell parser monad" 你应该找到很多例子。