Aller au contenu

Codage de Huffman (encodage du texte)

Présentation rapide

Le codage de Huffman est un codage qui permet de compresser des données. Dans le cas d'un texte, codé en UTF-8, chaque caractère prendra la place de un à 4 octets. Dans le cas du codage de Huffman , plus un caractère est fréquent dans le texte, plus court sera son codage en binaire.

Exemple

Le texte : que voulez vous que je vous dise sera codé par : 01111011101110000011011000011010001111000001101010111011110111011110010110111000001101010111100110110010110. Soit \(107\) bits au lieu de \(256\) avec le codage UTF-8. Le caractère espace ' ' sera codé par 111, tandis que le caractère 'l' sera codé par 1 0000.

Série d'exercices

Cet exercice fait partie d'une série :

Les étapes sur un exemple

Prenons pour exemple le texte que voulez vous que je vous dise.

Le nombre d'occurrences de chaque lettre est :

q u e v o l z s j d i
2 5 5 6 3 3 1 1 3 1 1 1

L'arbre de Huffman est un arbre construit progressivement à partir des feuilles.

On commence par créer des nœuds pour tous les caractères. La donnée associée à chaque nœud est un caractère et son poids qui est son nombre d'occurrences.

graph TD
    N7(l:1):::feuille
    N8(z:1):::feuille
    N90(j:1):::feuille
    N10(d:1):::feuille
    N1(i:1):::feuille
    N11(q:2):::feuille
    N5(v:3):::feuille
    N6(o:3):::feuille
    N9(s:3):::feuille
    N2(u:5):::feuille
    N3(e:5):::feuille
    N4(_:6):::feuille
    classDef feuille fill:#F88
graph TD
    N22(( :32)) --> N20(( :12))
    N22 --> N21(( :20))
    N20 --> N16(( :6))
    N20 --> N17(( :6))
    N16 --> N5(v:3):::feuille
    N16 --> N6(o:3):::feuille
    N17 --> N9(s:3):::feuille
    N17 --> N14(( :3))
    N14 --> N1(i:1):::feuille
    N14 --> N11(q:2):::feuille
    N21 --> N18(( :9))
    N18 --> N15(( :4))
    N18 --> N2(u:5):::feuille
    N15 --> N12(( :2))
    N15 --> N13(( :2))
    N12 --> N7(l:1):::feuille
    N12 --> N8(z:1):::feuille
    N13 --> N90(j:1):::feuille
    N13 --> N10(d:1):::feuille
    N21 --> N19( :11)
    N19 --> N3(e:5):::feuille
    N19 --> N4(_:6):::feuille
    classDef feuille fill:#F88

On pourra trouver plus d'explications dans l'exercice sur la construction d'un arbre de Huffman.

Encodage⚓︎

Une fois l'arbre construit, il faut procéder à l'encodage du texte. On va créer un dictionnaire, dont les clés seront les caractères et les valeurs associées, le codage binaire du caractère en utilisant l'arbre construit.

La convention utilisée ici sera la suivante :

Dans l'arbre chaque embranchement à gauche correspond à 0 et chaque embranchement à droite correspond à 1.

Exemple d'arbre et de codes

On obtient l'arbre suivant :

graph TD
    N22(( :32)) --> |0| N20(( :12))
    N22 --> |1| N21(( :20))
    N20 --> |0| N16(( :6))
    N20 --> |1| N17(( :6))
    N16 --> |0| N5(v:3):::feuille
    N16 --> |1| N6(o:3):::feuille
    N17 --> |0| N9(s:3):::feuille
    N17 --> |1| N14(( :3))
    N14 --> |0| N1(i:1):::feuille
    N14 --> |1| N11(q:2):::feuille
    N21 --> |0| N18(( :9))
    N21 --> |1| N19( :11)
    N18 --> |0| N15(( :4))
    N18 --> |1| N2(u:5):::feuille
    N15 --> |0| N12(( :2))
    N15 --> |1| N13(( :2))
    N12 --> |0| N7(l:1):::feuille
    N12 --> |1| N8(z:1):::feuille
    N13 --> |0| N90(j:1):::feuille
    N13 --> |1| N10(d:1):::feuille
    N19 --> |0| N3(e:5):::feuille
    N19 --> |1| N4(_:6):::feuille
    classDef feuille fill:#F88

Plus un symbole est fréquent, plus il est proche de la racine.

graph TD
    N22(( :32)) --> |0| N20(( :12))
    N22 --> |1| N21(( :20))
    N20 --> |0| N16(( :6))
    N20 --> |1| N17(( :6))
    N16 --> |0| N5(v:3):::feuille
    N16 --> |1| N6(o:3):::feuille
    N17 --> |0| N9(s:3):::feuille
    N17 --> |1| N14(( :3))
    N14 --> |0| N1(i:1):::feuille
    N14 --> |1| N11(q:2):::feuille
    N21 --> |0| N18(( :9))
    N21 --> |1| N19( :11)
    N18 --> |0| N15(( :4))
    N18 --> |1| N2(u:5):::feuille
    N15 --> |0| N12(( :2))
    N15 --> |1| N13(( :2))
    N12 --> |0| N7(l:1):::feuille
    N12 --> |1| N8(z:1):::feuille
    N13 --> |0| N90(j:1):::feuille
    N13 --> |1| N10(d:1):::feuille
    N19 --> |0| N3(e:5):::feuille
    N19 --> |1| N4(_:6):::feuille
    N5 o-...-o N32[000]:::binaire
    N1 o-..-o N33[0110]:::binaire
    N4 o-...-o N30[111]:::binaire
    N7 o-.-o N31[1 0000]:::binaire
    classDef feuille fill:#F88
    classDef binaire fill:#FF0

Par exemple, l (peu fréquent) sera codé 1 0000 (5 bits) alors que l'espace (très fréquente) sera codée 111 (3 bits).

Note

Toutes les fonctions crées dans des questions, sont utilisables dans les questions suivantes.

Question 1 : lettre_binaire(arbre)

Principe : on parcourt récursivement l'arbre en profondeur. À chaque fois qu'on arrive sur un nœud,

  • si c'est une feuille, on met à jour le dictionnaire de codage
  • sinon on appelle récursivement le parcours en mettant à jour l'argument code en fonction du sous arbre gauche ou droit.

Compléter la fonction lettre_binaire qui prend comme paramètre un arbre de Huffman et qui renvoie un dictionnaire avec comme clé, les caractères et comme valeurs associées, le codage binaire du caractère.

Les étiquettes des nœuds de l'arbre sont des dictionnaire de la forme {"caractere":…, "poids":…}.

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.128013.3395[tf4{)}+2rFR3,sao iug08àm1]P6pNnl7h.e=cy:v9(wq;US/b_dk050%0N0e0s0v0J0r0u0P0J0s0r0r0O010e0v0G010406050r0w0B0B0s0m0Q040Z0t0J0w0|0t0I0u020s0B0G0X0u0o0N160m0W0w0N0r050!13151719110G041x1E051H0!1H1J1E110%0v0S0;0?0^0`0L0v0x0L0J1X0L0e0 050,0#0J0N1S0@0_011W1Y1!1Y0e1*1,1(0e0#0t0%191)0m1F0e0L0;1c0r0G0s0I0`0l011.1U010f0.0N0I1k0N1(292b2g1:2j1,2m0B2o040a0u0E0m0t0G0t0r0v1f1h0*270m0m0N0P2J1x2q0I1F0!252V0e2322240%2s0`1!0I2l2G1(1P1R0=1/2)0v2+0I1 1Q1(0G2O1F2T2V30122a1h2;2h2_0m160J0 0u0C2S3410332r361:383a3c0l3f2b3h2T2(013m0s3b040u0p3q2U113t3k0`3w3y0u0g3C3s343u3I3c0c3M3E3O3G3v0t393x3c0F3T3i351T3l3Y3n3z0K3%3F3*3H3,3!3z0z3:3V3=3X3Z3J0T3{3j3}3Q040C0y423)2=3~3-0C3e1y3g3U434b450C3p4g3r4i4a373@3y0C3B4o3D3(3P4t0 0C3L4x3N4j4s3 4C3S4F1G2~1x2/2Y0%2$3u0P1 2y0)1Q1F2}0N2 3g3M054V0*4%4H1:0(0 0*0f4)3;4b0V3c4@3|4k0f0 1,1_2O0$0#2@0-2O4|4.0`0~040U594r3l0 170#584M4^2h5c0q3M0u4z3W0I0 4+0s0x0N5f3u0t0 0O5B3W0r2e0401015G3}5p5r5t445w1 5y1v0$3x0G0L0s0#0+5r5s5n1:5D045F5m4}2h0(0P0 0H1g5A5/5a015c0i0R3T0u625)5:4/0 0v4?4F645|5v045x5z0r5X0J5Z5#5%6a6b5g0`5,0O5.306o3u5=5@5_5Q5*6q4`042b0%6A653H5i0m5k5`326B015,0M5N4k0 1v0e0$0f0N0w0.1,6T5o0 0U5 61636.5R6U6e170s2Q0N5l6u6:2h6r6H6c6K6M6(5+0 6S5{6p3v4;1g2+6N4(6P5c6+0d730`5I0 010P6?6^2O5M773u5c0D6-6.626|66042O0e0w0m0I6 785c0h7j796=0m6@0e6_7d3r7A5b0 607t5H0C0 000y007M5c0j7x6v3W4:04687I3P5T0%5V6h5Y5!5$0e5(7V6Q5E6t3g7.3}6x045^2+7*7X7-6/6P6d6f5W7|6l7 6n816~7Z5O0 0h7,4F068f6I017:7=6a816d5j6`7e8y6R7M6d6W6Y6!6$7T2U817g6,8v7y638D5w7p7R8G3r864b8p6{8g718$8R6P8J8q6;0%7b0N8Q4-7J6*0i7i8=2h7l5K7o7P7q2o8c047w8V8W8(377^7`6i6k7~7?3W5c8 6O8y8h8!7S989a8+8I5E9k5S6e5U5z7-817:0N0/8`8S8d9b8W8Y040x0s0w0P0L8`9d745-9y6;8F9I8:758K0 0r0t0w7{6L539P9R9T986+8e8X8,040%2D2I9Y6}9x8C9`9!7M8;9o70049*9,5X9.0N0$9|0t9~901:8T9^7z9`512Zae552m0v8.8{7u6*9(9O9Q9S9#8y5Pa29p9f9CaG5|5,0k9 1:92010y7sa78|045qaj6J9A7_6g9h7}6m9v5|5~am9VaZap53as57aDa+ayaY7NagaiaUaxaWaOaZ8ib18204aNaK78aQ7#98aXa~5uaI8j6ja(8ma*aV0i9D6P7:7D7F7Hb87@a!9g8k9j6a110!4+4$4NbE0!4Q1x0e4SbJ2!2W1~202Y5#1,2V4Q1Daw3W2O0B6Y0s0(ae0L0p0 1p1r1t1v0u7Y321K3h1E0Y2+0u0S6_2H1g0u0sb|0P0u0w1h2a0m4V7F0:2l0u0?0m5z7F0q0u1t0v0u0v1l1!b.0u0%002l2u6_cd1-bD277F2b0ec0c2cx0:0f1eca0u0I0b0w0%0:0Ab{0v2H8#761N4Y2:3}1=1Z1#1%bX3}cv2w2y2A0Z0P0m0}cD0E0Q251g4)4#8{314(bDc)4b7:4=7M6D5sa`0I4 04a:ar56aua@aV5ed88-dga 8U308w9_aHbwa$bya)85a.b5848%9J048tbodrb3bu3W8*8581aQaT4h8x5|8A69blbva4a`a68Ha88M6Z6#0J6%a`8Tb;dO9c9N947Q9sdH3}dJdAa3ada59%dj9{8^dl9l8}9ndYb95J7n9r7r9ta-9E0 br7Gb47Kazd/9698d+7U6P0r7#047%7)d)0 8udodP786dcvb4d@2Udx6d0n2k9?bn9LeF0 eBdWd|be9zcueIeu5ddieR9Zd`eVbddK9`dGeY6)040ieKexdqdQ0 0V1Wd(dTdI6D2_bke%dreOe*9W76f1aZ8M0S0v0*eJem3D9ceM7C6@2@e08rb0d}e)e~aLa1e_9zf0e45CeQftbf9{0NfsenaE8}ebbp67dSfnezedfg8beP04f3fweS0r6Xd#8Pfaa-eybvej8#9U8ofpfIbv95fhd{fOaz8@0I7ceJe3fB5|aQf!7SdNf^aV9ud,fdandF9Bbh9idvd^fC04f@8/dFe8fi4b7veCf(g9a8fm4pfdec049G0rgge+fb10g2e:fJaA9;f$9$9Xd=6;f+fMf4b5fPf~bvaa9-6M0$9:aCeJfXgzbva|e}gl78eD3z9NgIguf2azgPacgRgZgVeLgp9`fAgdfof.d}eTe^fQgh6*eXh09egBgUe#b48hg5gjb6b4aQaS98e-gWg3a8g_d1a0g|gK8Ld9eUgK7gh3gNfxg;h8gGh5gneEf%hdhBaPe6bbeVhieLgqeebtfq6;8i7{bi8l5(bBd0bFbU4ZbB0*0,0.0r04.
Question 2 : encode_texte_codage(texte, codage)

Il faut maintenant encoder le texte initial avec ce code obtenu.

Créer la fonction encode_texte_codage qui prend comme paramètre un texte et qui renvoie une chaîne de caractères contenant le codage binaire du texte.

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.1280135[tf4)2rj3,sao iugxm1]Ppnlh.e=cy:v(wS/b_dk050P0D0d0n0q0A0m0p0F0A0n0m0m0E010d0q0y010406050m0r0u0u0n0i0G040L0o0A0r0+0o0z050M0=0@0_0{0:0y04141b051e0M1e1g1b0:0P0q0I0Z0#0%0)0B0q0s0B0A1u0B0d0.050U0N0A0D1p0$0(011t1v1x1v0d1D1F1B0d0N0o0P0{1C0i1c0d0B0Z0~0m0y0n0z0)0h011H1r010e0W0D0z0n0u0D1B1)1+1:1J1?1F1_1{0.0a0p0x0i0o0y0o0m0q110z0p0S1%0i0i0D0F2g141~0z1c0M1#2t0d1Z1Y1!0P200)1x0z1^2d1B1m1o0!1I2D0q2F0z1V1n1B0y2m1c2r2t2X0;1*2h2L1;2Q0i0^0A0.0v2q2#0/2!1 2%1J2)2+0.0h2/1+2;2r2C012_0n2,040k2}2s0:302@0)33350f382 2#313e0.0b3h1d2V142J2w0P2A310F1V1|1c3s1f3q2Z152:053x0S2W3j3c010Q0.0S0e3o3b1q1J0K0.0p3S3L3U3d0e0.1^3I0D0O0d0D0t3-0O3I0n0s0D3Z2?3#010-040J3_2$3{0z0.3-3/3^3F2~2=412M3|0.0l3h3Y3T4c43043=3@0m0O340y0B0n0N0T40313}0g0H3h060p4D4h3!4j443.3:3*4g4a310o0.0E4M4i2(0N0.1x0m0d4w3M3}0J0g4B4E4F3`4c3O040e0o0i4S4G2(0.0F0_0n2o0D2m4?4,1;0o3W042O504b4^04453-4!3{3}4A48394*4*4N3M4k5b3+4L5h3K511J4P040C5d4H040n0y0y1^0P5y1;4$5G2^4_1V3?0D4o4q4s4u4Z5r5l5e0.0c5J3d4_4{4}4 5U4T1J3}0w4(5r4C4E5V4-0.2m0d0r0i135r4+581J0m1.0401015Z015v5x5)4@5K040j0o566a5t0)5I6h5 5!5a4J5p3y664y4B143*2t2U0D2t3B2u3u142x2w1U1W2w4t1F6A1n2;0M0S0U0W0m04.
Question 3 : encode_Huffman(texte)

Pour encoder un texte, en utilisant le codage de Huffman, il faut :

  • créer l'arbre de Huffman à partir du texte. La fonction arbre_Huffman(chaine) est intégré à l'IDE,
  • en déduire le dictionnaire de codage
  • encoder le texte.

Compléter la fonction encode_Huffman(texte), qui prend en paramètre une chaine de caractères, et renvoie une chaine de caractère, représentant un codage de Huffman du paramètre.

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.1280135tf4)2r3,sao iugxm1Ppnlhe=cy:v(HwS/b_dk050M0z0c0l0o0x0k0n0B0x0l0k0k0A010c0o0v010406050k0p0s0s0l0h0C040I0m0x0p0(0m0w050J0/0;0?0^0-0v041118051b0J1b1d180-0M0o0E0W0Y0!0$0y0o0q0y0x1r0y0c0+050R0K0x0z1m0Z0#011q1s1u1s0c1A1C1y0c0K0m0M0^1z0h190c0y0W0{0k0v0l0w0$0g011E1o010d0T0z0w0l0s0z1y1$1(1-1G1:1C1?1^0+0a0n0u0h0m0v0m0k0o0~0w0n0P1!0h0h0z0B2d111{0w190J1Y2q0c1W1V1X0M1}0$1u0w1=2a1y1j1l0X1F2A0o2C0w1S1k1y0v2j192o2q2U0.1%2e2I1.2N0h0=0x0+0t2n2Y0,2X1|2!1G2$2(0+0g2,1(2.2o2z012?0l2)040i2`2p0-2}2;0$30320e352|2Y2~3b0+0b3e1a2S112G2t0M2x2~0B1S1_193p1c3n2W122-053u0P2T3g39010N0+0P0d3l381n1G0H0+0n3P3I3R3a0d0+1=3F0z0L0G0p0d0d0=103C2{2/2Z3Y010*040F3W2:3@0w0+0B0y0S2C3|3?2J3^0+0f0D3e060n4e3V3Q473 040?0K2j3e4g3X470m0+0A4o3=3h0+4l2j3)3+3-1(452~3_3{3:2p4w3J4j41430z4F3J3_0f4c4f4p3}4i3M0o3u0L3$1S0l0q4Q4J044X461.4s044u4-4/4x041C1M4A0K2L0S4n4-4L3@4H4R3~4y0h4m4,2W4h1.4T4V4f544Z044O2L3(4(0P5c2-4_3J4=4@2U5t58045p3(0c0z0r5D0L3F4*5r3;5e1G56535M3a40425n57473_0j4v5Q2 4!4$5p5J5V5f495h4e5j1.3L042j0c0p0h3/5x5/2=5S4P4%0w3%5K36113%2q2R0z2q3y2r3r112u2t1R1T2t0l1B693o1k2.0J0P0R0T0k04.

Remarques

  1. Pour l'exercice le codage est « textualisé », alors que, dans la réalité, l'opération se passe au niveau des octets et est donc plus difficilement visible.
  2. En pratique, le dictionnaire de codage est transmis dans le fichier avec le texte à décoder.