Unité d Enseignement M313 : Algorithmique avancée Cours 3 Algorithme de Huffman pour la compression de données Conservatoire National des Arts et Métiers D. Porumbel et E. Soutil
2 UE M313 Algorithmique avancée Plan du cours 1. Récursivité 2. Tris 3. Algorithme de Huffman (compression de données) 4. Preuves d'algorithmes 5. Complexité des algorithmes 6. Recherche de chaînes de caractères 7. Une heuristique de recherche locale
Compression de données : codage de Huffman 3 Compression de données : Gain de place de 2 à 9% (fichiers de texte) C = {caractères} À c i C on associe une chaîne binaire unique, de plus ou moins 8 bits Exemple : C = alphabet d : 1 f :11 m : 11... Codage de dfd = 1111 Mais : mf 1111 (= dfd!)
Codage préfixe 4 Règle à respecter pour un codage non ambigü : aucun code ne doit être préfixe d un autre code. Cette règle rend le décodage facile Exemple : face 1111 face Objectif : concevoir le codage et savoir décoder efficacement
Exemple (suite) : arbre associé 5 Arbre binaire ( sur fils gauche, 1 sur fils droit). Si l arbre est parfait, tous les codes sont de même longueur.
Exemple (suite) : arbre associé 6 Autre possibilité :
Choix d un arbre 7 On établit le tableau des fréquences d'apparition des caractères dans le fichier (c f(c)) h A (c) : hauteur de la branche c = nombre de bits pour c Nombre de bits requis pour encoder un fichier selon l arbre A : B(A) = cc f(c) h A (c)
Exemple 8 a b c d e f fréq. 45 13 12 16 9 5 code A' 1 1 11 1 11 code A'' 1 1 1 1 11 code H 11 1 111 111 11 B(A') = 3 (45+13+12+16+9+5) 3 B(A") = 328 (45 4+13 4+12 3+16 2+9 2+5 2) B(H) = 224 (45 1+13 3+12 3+16 3+9 4+5 4)
Conception des codes de Huffman 9 Idée : associer un code à chaque caractère, dont la longueur dépende de la fréquence d apparition de ce caractère dans le texte (fichier) à compresser : Plus le caractère est fréquent, plus court sera le code qu on lui associe. Une fois que le fichier entier a été encodé, on le redécoupe en séquences de 8 bits formant chacune un octet. Remarque : Il convient d associer un code à la marque de fin de fichier (CTRL-F)
Conception des codes de Huffman 1 Construction de l arbre. Pour concevoir les codes, Huffman en 1952 a l idée de construire un arbre binaire de la façon suivante : Chaque nœud de l arbre comporte deux données : la valeur d un caractère et une valeur numérique correspondant à la notion de fréquence. Initialement, on créée autant de nœuds qu il y a de caractères à encoder (= les lettres apparaissant dans le fichier). La valeur numérique associée à ces nœuds correspond à la fréquence d apparition dans le fichier. Ces nœuds initiaux constitueront les feuilles de l arbre. Puis on associe à chaque fois les deux nœuds de plus faibles valeurs pour donner un nœud père dont la valeur équivaut à la somme des valeurs de ses fils jusqu'à n'en avoir plus qu'un, la racine. On associe ensuite par exemple le code à la branche de gauche et le code 1 à la branche de droite.
11 Algorithme de construction de l arbre de Huffman Algorithme HUFFMAN (C : liste triée de caractères; f : tableau des fréquences des caractères; A: arbre de Huffman): // Utilise la procédure construire(a, z, x, y) qui ajoute à A un nœud z ayant pour fils gauche x et pour fils droit y début liste_ordonnée L ; entier n; n = card(c); L = C; tri de L selon les f(c) croissants; pour i = 1 à n-1 faire x L.min(); L.supprimer_min(); y L.min(); L.supprimer_min(); f(z) f(x) + f(y); construire (A, z,x,y); L.insérer (z); fait ; fin
Exemple d arbre de Huffman 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 Un arbre d exemple avec la phrase "this is an example of a huffman tree" (Source : Wikipedia)
Remarques sur l utilisation de l arbre 13 Codage. Une fois l arbre construit, les codes s obtiennent par un parcours en profondeur du graphe Le décodage s effectue de la façon suivante. Pour obtenir le code binaire de chaque caractère, on descend l'arbre à partir de la racine jusqu'aux feuilles en rajoutant à chaque fois au code un ou un 1 selon la branche suivie ( si on emprunte la branche de gauche, 1 si c est celle de droite).
Conclusions 14 On voit que la connaissance de l arbre est nécessaire pour le décodage. Cela signifie que l arbre doit être connu au moment de décoder : Soit on l inclut dans le fichier compressé, pour que les codes soient optimaux (pour une compression par symboles), mais alors on dégrade les performances car il faut bien stocker l arbre Soit on utilise un (même) arbre donné pour chaque type de fichier, construit en utilisant une distribution de probabilité connue pour le type de fichier (texte, image, ) mais alors on perd l optimalité de la longueur des codes par rapport au fichier à compresser Il existe des algorithmes plus efficaces (Lempel et Ziv) mais plus complexes, basés sur la fréquences non pas des caractères mais des séquences de caractères (on tire alors profit d une autre redondance dans le fichiers).