给出一个Huffman tree和一个比特流,返回一个包含(1) -由位编码的符号字符串(根据霍夫曼树),以及 -(2)一个布尔值,指示输出流是否包含来自 -输入(即,如果剩余任何位,则返回False。)
这是代码,它仅返回树中的第一个符号。有什么问题吗?
data BTree a = Leaf a | Fork (BTree a) (BTree a) deriving (Show, Eq)
traT :: BTree a -> BTree a -> [Bool] -> [a] -> ([a], Bool)
traT (Leaf v) c bs res= (res++[v], True)
traT (Fork left right) c (b:bs) res
| b = traT right c bs res
| otherwise = traT left c bs res
traT _ c [] res = (res, True)
traT _ c bs res = traT c c (bs) res
traT _ c bs res = (res, False)
decode :: BTree a -> [Bool] -> ([a], Bool)
decode (Fork x y) bs = traT (Fork x y) (Fork x y) bs []
decode (Leaf x) bs = traT(Leaf x) (Leaf x) bs []
答案 0 :(得分:2)
好吧,您似乎处在正确的轨道上。
它仅返回树中的第一个符号。
您的主要问题在于这两行:
traT (Leaf v) c bs res= (res++[v], True)
...
traT _ c bs res = traT c c (bs) res
第一个掩盖所有叶节点的第二个。第二个是您唯一可以在叶节点上运行的前向递归调用,因此您唯一的希望是处理任何其他位。
几句话:
res++[v]
表达式会强制代码在每个新符号处重新扫描整个符号列表。另一个(较小的)问题是,在位流的末尾仅返回一个标志以表示“额外”位的存在会丢失信息,因为我们想知道多余的位是什么。在您的核心递归函数中执行此操作有点冒险。当然,完全可以在最后的外部decode
函数中进行操作。
这就是为什么在下面的代码示例中,我使用了额外的symBits
参数来保留已处理但尚未归因于符号的位。我将它们保持相反的顺序,因为Haskell宁愿将项目放在列表的前面,而不是将它们放在最后,而是重新扫描整个列表。因此,在处理的最后阶段调用reverse
。这是一个廉价的reverse
调用,因为它的长度受到霍夫曼树深度的限制。
所以这是一些建议的重做代码,在这里我试图区分4种情况:叶节点或派生节点AND在位流的末尾与否。我还冒昧地将您的c
参数重命名为htop。
data BTree a = Leaf a | Fork (BTree a) (BTree a) deriving (Show, Eq)
type Bit = Bool
-- hnode htop symBits bs
travHT :: BTree a -> BTree a -> [Bit] -> [Bit] -> ([a], [Bit])
-- situations where at least one input bit remains:
travHT (Leaf v) htop symBits (b:rbs) = -- CHANGE: forward recursive call
-- symbol completed, jump from leaf node to top of htree:
let fwdRes = travHT htop htop [] (b:rbs)
nextSyms = fst fwdRes
lastSymBits = snd fwdRes
in (v : nextSyms, lastSymBits)
travHT (Fork left right) htop symBits (b:rbs)
| b = travHT right htop (b:symBits) rbs
| otherwise = travHT left htop (b:symBits) rbs
-- situations where we have reached the end of the bit stream:
travHT (Leaf v) htop symBits [] = ([v],[])
-- no more bits and not at a leaf --> incomplete last symbol:
travHT (Fork left right) htop symBits [] = ([], reverse symBits)
-- homework-mandated interface:
decode :: BTree a -> [Bit] -> ([a], Bool)
decode htree bs =
let pair = travHT htree htree [] bs
(symbols, restOfBits) = pair
weUsedAllBits = null restOfBits
in (symbols, weUsedAllBits)
xyz_code :: BTree Char
xyz_code = Fork (Leaf 'x') (Fork (Leaf 'y') (Leaf 'z'))
-- Bit streams for test purposes:
------ Y Z X X X Y/Z??
bl0 = [True,False, True,True , False, False, False]
bl1 = [True,False, True,True , False, False, False, True]
main = do
let bitList = bl0
let htree = xyz_code
let result = decode htree bitList
putStrLn $ "result = " ++ show result
result = ("yzxxx",True)
希望有帮助。我还将要求具有的功能将[huffman-code]标记添加到您的问题中。标签是帮助人们找到他们感兴趣的问题的好方法。而且我们确实有霍夫曼代码的标签。