File: huffman.ml

package info (click to toggle)
ocaml-doc 3.09-1
  • links: PTS
  • area: non-free
  • in suites: etch, etch-m68k
  • size: 10,428 kB
  • ctags: 4,963
  • sloc: ml: 9,244; makefile: 2,413; ansic: 122; sh: 49; asm: 17
file content (97 lines) | stat: -rw-r--r-- 3,235 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
(***********************************************************************)
(*                                                                     *)
(*                           Objective Caml                            *)
(*                                                                     *)
(*               Pierre Weis, projet Cristal, INRIA Rocquencourt       *)
(*                                                                     *)
(*  Copyright 2001 Institut National de Recherche en Informatique et   *)
(*  en Automatique.  All rights reserved.  This file is distributed    *)
(*  only by permission.                                                *)
(*                                                                     *)
(***********************************************************************)
type table_de_codage =
  { caractre : int list array;
    mutable fin : int list };;

let encode entre sortie codage =
  Esbit.initialise();
  try
    while true do
      let c = input_char entre in
      List.iter (Esbit.crire_bit sortie)
              codage.caractre.(int_of_char c)
    done
  with End_of_file ->           (* fin du fichier d'entre *)
    List.iter (Esbit.crire_bit sortie) codage.fin;
    Esbit.finir sortie;;

type arbre_de_huffman =
  | Lettre of char
  | Fin
  | Noeud of arbre_de_huffman * arbre_de_huffman;;

let dcode entre sortie arbre =
  Esbit.initialise();
  let rec parcours = function
  | Fin -> ()
  | Lettre c ->
      output_char sortie c; parcours arbre
  | Noeud(gauche, droite) ->
      if Esbit.lire_bit entre = 0
      then parcours gauche
      else parcours droite in
  parcours arbre;;

let frquences entre =
  let fr = Array.make 256 0 in
  begin try
    while true do
      let c = int_of_char(input_char entre) in fr.(c) <- fr.(c) + 1
    done
  with End_of_file -> ()
  end;
  fr;;

let construire_arbre frquences =
  let prio = ref (Fileprio.ajoute Fileprio.vide 1 Fin) in
  let nombre_d'arbres = ref 1 in
  for c = 0 to 255 do
    if frquences.(c) > 0 then begin
      prio := Fileprio.ajoute !prio
                frquences.(c) (Lettre(char_of_int c));
      incr nombre_d'arbres
    end
  done;
  for n = !nombre_d'arbres downto 2 do
    let (frq1, arbre1, prio1) = Fileprio.extraire !prio in
    let (frq2, arbre2, prio2) = Fileprio.extraire prio1 in
    prio := Fileprio.ajoute prio2
              (frq1 + frq2) (Noeud(arbre1,arbre2))
  done;
  let (_, arbre, _) = Fileprio.extraire !prio in
  arbre;;

let arbre_vers_codage arbre =
  let codage = { caractre = Array.make 256 []; fin = [] } in
  let rec remplir_codage prfixe = function
  | Lettre c ->
      codage.caractre.(int_of_char c) <- List.rev prfixe
  | Fin ->
      codage.fin <- List.rev prfixe
  | Noeud(arbre1, arbre2) ->
      remplir_codage (0 :: prfixe) arbre1;
      remplir_codage (1 :: prfixe) arbre2 in
  remplir_codage [] arbre;
  codage;;

let compresse entre sortie =
  let frq = frquences entre in
  let arbre = construire_arbre frq in
  let codage = arbre_vers_codage arbre in
  output_value sortie arbre;
  seek_in entre 0;
  encode entre sortie codage;;

let dcompresse entre sortie =
  let arbre = input_value entre in
  dcode entre sortie arbre;;