我早些时候问过如何制作一棵树的问题,但现在我又陷入了困境。 我想编码和解码我的霍夫曼树
这些是我的类型:
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做到这一点?
答案 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
解码比较麻烦,您可能希望将代码表转换为树,以便可以直接做出决定。