J'adresse ce topic à ceux qui se demande comment marche la compression de donnés (en l'occurence Huffman), mais surtout à ceux qui savent. Car la question du topic est "Ma méthode est-elle au moins aussi rapide que la traditionnelle manipulation d'arbres ?", à moins que (ça me ferait chier) j'ai une fois de plus réinventé la roue.
Conservez-le réduit dans votre barre des tâches, il vaut mieux le lire hors-connexion

La présentation de l'algorithme d'Huffman passe souvent (toujours ?) par la manipulation d'un arbre binaire. Avec moi elle va passer par la manipulation de tableaux, on oublie complètement les arbres ! On revient exactement à la même chose, mais en plus simple, voir... plus rapide ?
Voyons comment en compressant une suite de 38 octets, car rien ne vaut un exemple.
Claire fut l'éclair
en joli vent d'été
(c'est nul comme jeu de mots, mais on va faire avec)
un espace) f - 1 u - 1 t - 3 ' - 2 c - 1 n - 2 j - 1 o - 1 v - 1 d - 1
On compte la fréquence d'apparition de chaque octet, jusque là, rien de nouveau :C - 1 l - 4 a - 2 i - 3 r - 2 e - 6 (je considère les é comme des e) _ - 6 (je considère le retour à la ligne comme
- 6 _ - 6 l - 4 i - 3 t - 3 a - 2 r - 2 ' - 2 n - 2 C - 1 f - 1 u - 1 c - 1 j - 1 o - 1 v - 1 d - 1Pour plus de clarté, on trie par ordre décroissant d'occurences, mais ce n'est pas obligatoire pour la compression :e
La nouveauté commence ici. On construit 2 tableaux ; un contient les octets surmontés de leur fréquence, l'autre les octets seuls (seuls pour l'instant

) :| 6 | 6 | 4 | 3 | 3 | 2 | 2 | 2 | 2 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | +-------------------------------------------------------------------+ | e | _ | l | i | t | a | r | ' | n | C | f | u | c | j | o | v | d | e - _ - l - i - t - a - r - ' - n - C - f - u - c - j - o - v - d
On cherche les deux plus faibles fréquences. Comme on vient de trier, ce sont forcément les deux dernières colonnes. On déplace la colone de plus faible fréquence vers l'autre. Si elles sont égales, ont choisit de déplacer la plus à droite vers l'autre.
| j | o | v | | | | | | | | | | | | | | | | | d |
Enfin, on additionne leurs fréquences. Regardez la dernière colonne du tableau :| 6 | 6 | 4 | 3 | 3 | 2 | 2 | 2 | 2 | 1 | 1 | 1 | 1 | 1 | 1 | 2 | +---------------------------------------------------------------+ | e | _ | l | i | t | a | r | ' | n | C | f | u | cDans notre deuxième tableau vide, on inscrit un 1 en face des octets déplacés, et un 0 en face de ceux dont la colonne a reçu nos migrants (pour l'instant on n'a qu'un seul octet par colonne

)e - _ - l - i - t - a - r - ' - n - C - f - u - c - j - o - v - 0 d -
- r - ' - n - C - f - u - c - j - 0 o - 1 v - 0 d - 1
On cherche les deux plus petites fréquences, et on recommence la manip :| 6 | 6 | 4 | 3 | 3 | 2 | 2 | 2 | 2 | 1 | 1 | 1 | 1 | 2 | 2 | +-----------------------------------------------------------+ | e | _ | l | i | t | a | r | ' | n | C | f | u | c | j | v | | | | | | | | | | | | | | | o | d | e - _ - l - i - t - a
- 0 c - 1 j - 0 o - 1 v - 0 d - 1
En continuant, on arrive rapidement à :| 6 | 6 | 4 | 3 | 3 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | +---------------------------------------------------+ | e | _ | l | i | t | a | r | ' | n | C | u | j | v | | | | | | | | | | | f | c | o | d | e - _ - l - i - t - a - r - ' - n - C - 0 f - 1 u
Attention, la suite peut paraître moins évidente si vous dormez. | | | | | | | | | | d |
Ce sont bien des colonnes qu'on déplace :| 6 | 6 | 4 | 3 | 3 | 2 | 2 | 2 | 2 | 2 | 2 | 4 | +-----------------------------------------------+ | e | _ | l | i | t | a | r | ' | n | C | u | j | | | | | | | | | | | f | c | o | | | | | | | | | | | | | v | | |Donc ce sont tous les octets des colones concernées par le déplacement qui sont affectés d'un 1 ou d'un 0. Voyez en bas de la liste, j & o ont reçu un 0, v & d un 111
:e - _ - l - i - t - a - r - ' - n - C - 0 f - 1 u - 0 c - 1 j - 00 o - 10 v - 01 d -
C | | f | | u | | c | | j | | o | | v | | d |
La manip se termine lorsqu'il ne reste plus qu'une colonne :| 38 | +----+ | e | | _ | | i | | t | | l | | a | | r | | ' | | n | |- 00111 o - 10111 v - 01111 d - 11111
Les déplacements ont donné cette liste :e - 000 _ - 100 l - 110 i - 0010 t - 1010 a - 0001 r - 1001 ' - 0101 n - 1101 C - 00011 f - 10011 u - 01011 c - 11011 j
Lisez les codes de droite à gauche, c'est magique (la prédécrémentation n'est pas plus lente que la postincrémentation, mais on peut inverser les listes de bits si ça gêne). A chaque octet on a la correspondance binaire compressée

Le poême compressé :
110000111000010010010000011100111010010100101110100001101101110000100100100100010110011110011101011010011110000101101010011111110100000101000
C'est beau non ?
Si jamais ce n'était pas plus rapide que le travail sur arbres, voyons la décompression, il se pourrait qu'on y gagne, je ne sais pas. Tout en image, la simplicité ne demande pas d'explication :
110000111000010010010000011100111010010100101110100001101101110000100100100100010110011110011101011010011110000101101010011111110100000101000
e - 000
_ - 100
l - 110
i - 0010
t - 1010
a - 0001
r - 1001
' - 0101
n - 1101
C - 00011
f - 10011
u - 01011
c - 11011
j - 00111
o - 10111
v - 01111
d - 11111
110000111000010010010000011100111010010100101110100001101101110000100100100100010110011110011101011010011110000101101010011111110100000101000
e - 000
_ - 100
l - 110
i - 0010
t - 1010
a - 0001
r - 1001
' - 0101
n - 1101
C - 00011
f - 10011
u - 01011
c - 11011
j - 00111
o - 10111
v - 01111
d - 11111
110000111000010010010000011100111010010100101110100001101101110000100100100100010110011110011101011010011110000101101010011111110100000101000
e - 000
_ - 100
l - 110
i - 0010
t - 1010
a - 0001
r - 1001
' - 0101
n - 1101
C - 00011
f - 10011
u - 01011
c - 11011
j - 00111
o - 10111
v - 01111
d - 11111
110000111000010010010000011100111010010100101110100001101101110000100100100100010110011110011101011010011110000101101010011111110100000101000
e - 000
_ - 100
l - 110
i - 0010
t - 1010
a - 0001
r - 1001
' - 0101
n - 1101
C - 00011
f - 10011
u - 01011
c - 11011
j - 00111
o - 10111
v - 01111
d - 11111
110000111000010010010000011100111010010100101110100001101101110000100100100100010110011110011101011010011110000101101010011111110100000101000[pre]e - 000 _ - 100 l - 110 i - 0010 t - 1010 a - 0001 r - 1001 ' - 0101 n - 1101 C - [b]00011[/b] f - 10011 u - 01011 c - 11011 j - 00111 o - 10111 v - 01111 d - 11111 On s'arrête car on est arrivé à la fin d'une liste de bits, ici, la liste du [i]C[/i] : le premier octet est donc un [i]C[/i]. Vous l'avez compris ; on part du haut du tableau, et si le Nième lut ne correspond pas au Nième bit de la liste en face sur laquelle on est, on descend jusqu'à trouver une correspondance. Et ainsi de suite jusqu'à ce qu'on atteigne la fin d'une liste. Qu'est ce que vous pensez de cette méthode ? Si c'est une pauvre merde, argumentez, et puis ben... soyez gentils, expliquez moi ou donnez-moi des ULR sur la structure de donnés à utiliser pour les arbres, et la façon de s'en servir car je n'ai rien compris aux tutoriels que j'ai lu (c'est pour ça que j'ai dû inventer ma propre implémentation). Merci ! [edit]Edité par Thibaut le 26-09-2001 à 18:32:16[/edit]