编码/解码霍夫曼树Haskell

时间:2018-08-15 19:42:06

标签: haskell huffman-code

我早些时候问过如何制作一棵树的问题,但现在我又陷入了困境。 我想编码和解码我的霍夫曼树

这些是我的类型:

module Types where


type Occurence  = (Number, Value)
type Occurences = [Occurence]
type Number     = Int
type Value      = Char
type Code       = [Directions]
type CodeTable  = [(Value, Code)]


data Directions = L | R deriving (Eq, Ord, Show)


data HTree      = Leaf {frequency :: Number, character:: Value} |
                  Node {frequency:: Number, 
                        leftChild:: HTree,
                        rightChild:: HTree} deriving Show

makeLeaf :: Occurence -> HTree
makeLeaf (n, c) = Leaf n c

这些是我已经编写的功能,并且实际上正在起作用:

makeTree :: Occurences -> HTree
makeTree = makeCodes . toTreeList

toTreeList :: Occurences -> [HTree]
toTreeList = map (uncurry Leaf)

h :: [HTree] -> [HTree]
h (t1:t2:ts) = insertTree (join t1 t2) ts

makeCodes :: [HTree] -> HTree
makeCodes [t] = t
makeCodes ts = makeCodes (h ts)

join :: HTree -> HTree -> HTree
join t1 t2 = Node (freq1+freq2) t1 t2
    where
      freq1 = v t1
      freq2 = v t2

v :: HTree -> Int
v (Leaf n _ ) = n
v (Node n _ _) = n

insertTree :: HTree -> [HTree] -> [HTree]
insertTree t [] = [t]
insertTree t (t1:ts) 
     | v t < v t1 = t:t1:ts
     | otherwise = t1 : insertTree t ts




constructTable :: HTree -> CodeTable
constructTable = convert []
      where
      convert :: Code -> HTree -> CodeTable
      convert hc (Leaf n c) = [(c, hc)]
      convert hc (Node n tl tr) = (convert (hc++[L]) tl) ++ (convert (hc++[R]) tr)

现在我想对解码进行编码...

code :: String -> (Code, CodeTable)

decode :: Code -> CodeTable -> String
decode code table = undefined

我通常会采用这种方式

code :: HTree -> Char -> String
code (Leaf c n) x
| c==x = []
| otherwise = error "!!"
code (Node li n re) x
| member x li = ’L’:code li x
| otherwise = ’R’:code re x
where member a (Leaf c n) = (a==c)
member a (Node li c re) = (member a li) || (member a re)

但是如何使用CodeTable做到这一点?

1 个答案:

答案 0 :(得分:0)

当您知道发生的事时,您知道如何制作一棵树,所以我想您应该找出如何从字符串中进行发生的事。

import Data.Map as M
frequencyTable :: String -> Occurrences
frequencyTable = sort . map (uncurry flip) . M.toList . M.fromListWith (+) . map (\x -> (x,1))

所以现在您可以为字符串制作霍夫曼代码:

codeTable : String -> CodeTable
codeTable = constructTable . makeTree . frequencyTable

您知道拥有霍夫曼代码时如何编码字符串:

code1 [] char = error “not in code table”
code1 ((c1,code)::table) char
  | c1 == char = code
  | otherwise = code1 table char
code s = (s >>= code1 table, table) where
  table = codeTable s

解码比较麻烦,您可能希望将代码表转换为树,以便可以直接做出决定。