Ocaml 文本文件的哈夫曼编码

Ocaml 文本文件的哈夫曼编码,ocaml,huffman-code,Ocaml,Huffman Code,这只是使用ocaml生成的huffman树的一部分。该树表示为(char*int list)列表: (char*int list)是代码和相应的编码位流。我想知道这是一棵正确的树还是我理解错了。这样,最长编码的ASC II代码将为255位。原始文件是213.3k,编码后,它变成227k,而在说明中,我被告知它应该在119k周围生成一个文件。我不知道我的问题出在哪里,因为我按照指示做了每件事。有人能告诉我这里怎么了吗 我最大的问题是:如果我使用哈夫曼编码,只有8个最频繁的字符可以节省我的空间,而其

这只是使用ocaml生成的huffman树的一部分。该树表示为(char*int list)列表:

(char*int list)
是代码和相应的编码位流。我想知道这是一棵正确的树还是我理解错了。这样,最长编码的ASC II代码将为255位。原始文件是
213.3k
,编码后,它变成
227k
,而在说明中,我被告知它应该在
119k
周围生成一个文件。我不知道我的问题出在哪里,因为我按照指示做了每件事。有人能告诉我这里怎么了吗

我最大的问题是:如果我使用哈夫曼编码,只有8个最频繁的字符可以节省我的空间,而其他247个字符将花费额外的空间,这是真的吗?如果不是,为什么

我编写的代码遵循此链接中的说明:

这是我的编码函数代码:

type huffmantree = Node of huffmantree*(int*int)*huffmantree 
 | Leaf of char*int | Nil
type encoding = char * (int list)

let look_up (chr: char) (encl : encoding list) : int list =
  let rec look_up_rec encl = 
    match encl with
    | [] -> raise (Failure "Not found")
    | (ch,theL)::tl -> if ch = chr then theL
                       else look_up_rec tl
    in
    look_up_rec encl
;;

let get_codes (hm : huffmantree): encoding list = 
  let rec get_codes_rec aTree word=
  match aTree with
  | Nil -> []
  | Node (Leaf(lKey,lFreq),value,Nil) -> [(lKey,[0])]
  | Node (Leaf(lKey,lFreq),value,Leaf(rKey,rFreq)) ->  
    [(lKey,List.append word [0]);(rKey,List.append word [1])]
  | Node (Leaf(lKey,lFreq),value,rNode) -> 
    (lKey,List.append word [0])::(get_codes_rec rNode (List.append     word [1]))
  in
  get_codes_rec hm []
;;

let encode (text : char list) : huffmantree * int list = 
  let sortedT = List.fast_sort (fun ch1 ch2->   
    if (int_of_char ch1)>=(int_of_char) ch2 then 1 else -1) text
  in
  let rec cre_freq_list aList m = 
    match aList with
    | [] -> []
    | hd::[] -> [(hd,m+1)]
    | hd1::hd2::tl -> if hd1=hd2 then cre_freq_list (hd2::tl) (m+1)
                      else (hd1,(m+1))::(cre_freq_list  (hd2::tl) 0)
  in
  let sortedF = List.fast_sort (fun (ch1,fr1) (ch2,fr2) ->
    if fr1>=fr2 then 1 else -1) (cre_freq_list sortedT 0)
  in
  let rec createHuff sortedF= 
    match sortedF with
    | [] -> Nil
    | (ch,va)::[] -> Node (Leaf (ch,va),(256,va),Nil)
    | (ach,aval)::tl -> 
      let rec creH_rec the_tl sib n freq= 
        match the_tl with
        | (bch,bval)::[] -> Node(Leaf (bch,bval),(n,bval+freq),sib)
        | (bch,bval)::btl -> creH_rec btl 
          (Node (Leaf (bch,bval),(n,bval+freq),sib)) (n+1) 
          (freq+bval)
    in creH_rec tl (Leaf(ach,aval)) 256 aval
  in
  let huff = createHuff sortedF
  in
  let rec make_codes text = 
    match text with
    | [] -> []
    | hd::tl -> List.append (look_up hd (get_codes huff)) 
      (make_codes tl)
  in
  (huff,(make_codes text))

查看生成的树,似乎没有实现哈夫曼算法。我怀疑“e”在你的文本中比其他任何字母都要频繁。如果没有代码,我只能猜测,但可能在合并两棵最轻的树时,您将结果树插入到要合并的树列表的末尾,而不是根据其权重将其插入正确的位置

在您的代码中,
createHuff
被声明为递归,但没有递归调用。
您的函数
createHuff
从不比较
sortedF
列表中的值您不认为这是个问题吗?这意味着
createHuff
将始终生成相同的树(具有不同的标签,但具有相同的结构)。

将您的代码提供给我们,以便我们可以帮助您。。。。也许还有一些说明……”在从createHuff函数中删除rec关键字后,它仍然会给我相同的结果。”当然。问题是,
createHuff
应该是递归的(这就是为什么你把
rec
放在第一位)。正如我在回答中告诉你的,你的函数
createHuff
不关心频率,那么它怎么能把轻的子树放在底部,重的子树放在顶部呢?你的树没有编译,但它看起来只有一个分支,这显然是错误的。我理解了你的意思,现在正在处理这棵树。昨天我真的不理解哈夫曼树的结构,写了很多毫无意义的东西。所以我删除了它们。谢谢你抽出时间。
type huffmantree = Node of huffmantree*(int*int)*huffmantree 
 | Leaf of char*int | Nil
type encoding = char * (int list)

let look_up (chr: char) (encl : encoding list) : int list =
  let rec look_up_rec encl = 
    match encl with
    | [] -> raise (Failure "Not found")
    | (ch,theL)::tl -> if ch = chr then theL
                       else look_up_rec tl
    in
    look_up_rec encl
;;

let get_codes (hm : huffmantree): encoding list = 
  let rec get_codes_rec aTree word=
  match aTree with
  | Nil -> []
  | Node (Leaf(lKey,lFreq),value,Nil) -> [(lKey,[0])]
  | Node (Leaf(lKey,lFreq),value,Leaf(rKey,rFreq)) ->  
    [(lKey,List.append word [0]);(rKey,List.append word [1])]
  | Node (Leaf(lKey,lFreq),value,rNode) -> 
    (lKey,List.append word [0])::(get_codes_rec rNode (List.append     word [1]))
  in
  get_codes_rec hm []
;;

let encode (text : char list) : huffmantree * int list = 
  let sortedT = List.fast_sort (fun ch1 ch2->   
    if (int_of_char ch1)>=(int_of_char) ch2 then 1 else -1) text
  in
  let rec cre_freq_list aList m = 
    match aList with
    | [] -> []
    | hd::[] -> [(hd,m+1)]
    | hd1::hd2::tl -> if hd1=hd2 then cre_freq_list (hd2::tl) (m+1)
                      else (hd1,(m+1))::(cre_freq_list  (hd2::tl) 0)
  in
  let sortedF = List.fast_sort (fun (ch1,fr1) (ch2,fr2) ->
    if fr1>=fr2 then 1 else -1) (cre_freq_list sortedT 0)
  in
  let rec createHuff sortedF= 
    match sortedF with
    | [] -> Nil
    | (ch,va)::[] -> Node (Leaf (ch,va),(256,va),Nil)
    | (ach,aval)::tl -> 
      let rec creH_rec the_tl sib n freq= 
        match the_tl with
        | (bch,bval)::[] -> Node(Leaf (bch,bval),(n,bval+freq),sib)
        | (bch,bval)::btl -> creH_rec btl 
          (Node (Leaf (bch,bval),(n,bval+freq),sib)) (n+1) 
          (freq+bval)
    in creH_rec tl (Leaf(ach,aval)) 256 aval
  in
  let huff = createHuff sortedF
  in
  let rec make_codes text = 
    match text with
    | [] -> []
    | hd::tl -> List.append (look_up hd (get_codes huff)) 
      (make_codes tl)
  in
  (huff,(make_codes text))