Vous êtes sur la page 1sur 41

CODAGE DE

HUFFMAN

ANTOINE Thomas
BENMEZIANE Mlina
ERHEL Mathieu
KELLER Florence
MANGIN Yann
ROLLOT Jordan

Atelier Maths en Jeans


Anne scolaire 2007-2008
Lyce Louis Lapicque - pinal
Le codage de Huffman est un processus qui permet de compresser des donnes informatiques afin de librer
de la place dans la mmoire d'un ordinateur. Or tout fichier informatique (qu'il s'agisse d'un fichier texte,
d'une image ou d'une musique) est form d'une suite de caractres. Chacun de ces caractres tant lui-mme
cod par une suite de 0 et de 1. L'ide du codage de Huffman est de reprer les caractres les plus frquents
et de leur attribuer des codes courts (c'est--dire ncessitant moins de 0 et de 1) alors que les caractres les
moins frquents auront des codes longs. Pour dterminer le code de chaque caractre on utilise un arbre
binaire. Cet arbre est galement utilis pour le dcodage.

Nous avons aussi fait des recherches sur un autre procd appel transformation de Burrows Wheeler. Pour
cela il faut construire deux tableaux (une permutation permet de passer de l'un l'autre). On peut alors
procder des regroupements de lettres de faon transformer le texte initial. L'application du codage de
Huffman sur ce texte transform permet alors (en gnral) une compression encore meilleure.

Enfin, nous avons essay de mettre en uvre le codage de Huffman en rdigeant un programme en langage
C permettant de construire l'arbre binaire ncessaire au codage du fichier. Si notre programme ne fournit pas
le codage final, il permet tout de mme de connatre la taille du codage final et de la comparer avec la taille
du codage initial.

2
Table des matires

Introduction......................................................................................................................................................5

1 Exemple de codage de Huffman....................................................................................................................6


1.1 Quelques dfinitions informatiques.......................................................................................................6
1.1.1 Codage d'un caractre....................................................................................................................6
1.1.2 Extensions du codage ASCII.........................................................................................................7
1.1.3 Bits................................................................................................................................................7
1.1.4 Poids..............................................................................................................................................8
1.1.5 Taux de compression.....................................................................................................................8
1.2 Notion d'arbre........................................................................................................................................8
1.2.1 Dfinitions : nuds, branche, racine, feuilles................................................................................8
1.2.2 Arbre binaire..................................................................................................................................9
1.3 Description de l'algorithme du codage de Huffman...............................................................................9
1.4 Exemple...............................................................................................................................................10
1.4.1 Construction du tableau...............................................................................................................10
1.4.2 Construction de l'arbre.................................................................................................................10
1.4.3 Taux de compression...................................................................................................................12
1.5 Dcodage.............................................................................................................................................13

2 Transformation de Burrows Wheeler...........................................................................................................14


2.1 Un premier tableau..............................................................................................................................14
2.1.1 Principe........................................................................................................................................14
2.1.2 Exemple.......................................................................................................................................14
2.2 Un second tableau................................................................................................................................15
2.2.1 Principe........................................................................................................................................15
2.2.2 Exemple.......................................................................................................................................15
2.2.3 Comment passer d'un tableau l'autre.........................................................................................16
2.3 Texte transform..................................................................................................................................17
2.3.1 Codage du texte transform.........................................................................................................17
2.3.2 Comment retrouver le texte initial?..............................................................................................18

3 Dfinitions complmentaires.......................................................................................................................19
3.1 tage et position..................................................................................................................................19
3.1.1 Dfinitions...................................................................................................................................19
3.1.2 Passage de position tage..........................................................................................................20
3.2 Notion de pointeur...............................................................................................................................20
3.2.1 Dfinition.....................................................................................................................................20
3.2.2 Application la reprsentation informatique d'un arbre...............................................................21

4 Programmation en C du codage de Huffman...............................................................................................23


4.1 Diffrentes tapes du programme........................................................................................................23
4.1.1 Fonction principale......................................................................................................................23
4.1.2 Principe gnral...........................................................................................................................23
4.2 Lecture du fichier initial......................................................................................................................24
4.2.1 Tableau des effectifs de chaque caractre....................................................................................24

3
4.2.2 Lecture du tableau des effectifs...................................................................................................25
4.3 Construction de l'arbre.........................................................................................................................25
4.3.1 Obtention de deux minimums......................................................................................................25
4.3.2 Nombre de caractres distincts....................................................................................................26
4.3.3 Cration de l'arbre........................................................................................................................27
4.3.4 Affichage de l'arbre......................................................................................................................29
4.4 tage et position..................................................................................................................................29
4.4.1 criture des positions...................................................................................................................30
4.4.2 Calcul de l'tage en fonction de la position..................................................................................30
4.5 Calcul du taux de compression............................................................................................................30
4.5.1 Obtention de la taille du fichier compress..................................................................................30
4.5.2 Prambule d'un fichier compress................................................................................................31
4.6 Exemple...............................................................................................................................................31

5 Annexe.........................................................................................................................................................34
5.1 Fichier main.c......................................................................................................................................34
5.2 Fichiers Jordan.....................................................................................................................................34
5.2.1 Fichier Jordan.h...........................................................................................................................34
5.2.2 Fichier Jordan.c...........................................................................................................................35
5.3 Fichiers Thomas..................................................................................................................................35
5.3.1 Fichier Thomas.h.........................................................................................................................35
5.3.2 Fichier Thomas.c.........................................................................................................................36
5.4 Fichiers creation_arbre........................................................................................................................37
5.4.1 Fichier creation_arbre.h...............................................................................................................37
5.4.2 Fichier creation_arbre.c...............................................................................................................37

Conclusion......................................................................................................................................................40

4
Introduction
Cet crit est la synthse des recherches effectues dans le cadre de l'atelier Maths en Jeans au lyce Louis
Lapicque d'pinal durant l'anne scolaire 2007-2008.

Cette exprience a commenc en septembre 2007 lors d'une runion avec Monsieur Stphane Gaussent,
chercheur l'institut lie Cartan de Nancy. Il nous a expos les diffrents sujets que l'on pourrait traiter. la
suite de cela, nous avons choisi de travailler sur le codage de Huffman. Ce sujet nous plaisait car
l'informatique nous intresse.

Le codage de Huffman est un algorithme informatique permettant de compresser des donnes (quelles que
soient ces donnes). Il est en particulier utilis pour une compression en mp3 (format d'un fichier son),
jpeg (format d'une image) ou mpeg (format d'une vido).

Notre groupe est spar en deux quipes de trois personnes : d'une part Florence Keller, Jordan Rollot et
Thomas Antoine et d'autre part Mlina Benmeziane, Yann Mangin et Mathieu Erhel. Les deux groupes ont
commenc par crire des arbres la main, puis le premier groupe s'est orient vers une approche
informatique du sujet (dbut du chapitre 1, chapitres 3 et 4) tandis que l'autre a travaill sur le sujet de faon
plus thorique et en tudiant une variante du codage de Huffman (chapitres 1 et 2). Nous avons travaill
chacun de notre ct jusqu'au premier entranement avant le congrs de Paris. Le jour de l'expos Paris qui
a eu lieu la fin du mois de mars 2008, tout le groupe tait plus ou moins tendu, c'tait la premire fois que
l'on exposait nos travaux dans un amphithtre devant une cinquantaine de personnes. Malgr cela tout le
monde en garde un trs bon souvenir, car cette exprience peut nous aider lors d'un oral l'cole (par
exemple).

Les mois d'avril et de mai 2008 ont t consacr la rdaction de ce rapport. Chacune des deux quipes a
travaill de son ct, puis nous avons effectu une synthse.

5
Chapitre 1
Exemple de codage de Huffman

1.1 Quelques dfinitions informatiques

1.1.1 Codage d'un caractre

Tout fichier informatique est constitu de caractres. Un caractre est une lettre (majuscule ou minuscule), un
chiffre, un signe de ponctuation ou un symbole non imprimable (par exemple un retour la ligne, une
tabulation, un signal sonore mis par l'ordinateur...). Cet ensemble de caractres est appel code ASCII et
correspond la liste ci-dessous :

On remarque dans cette liste que chaque caractre est repr par un numro. Ainsi de 0 31 on a les

6
caractres non imprimables, de 32 47 la majorit des signes de ponctuation, de 48 57 les chiffres, de 58
64 d'autres signes de ponctuation, de 65 122 les lettres majuscules puis minuscules. Enfin de 123 127 se
trouvent diffrents symboles.

1.1.2 Extensions du codage ASCII

On constate galement dans la liste prcdente l'absence de caractres accentus. C'est pourquoi, les
ordinateurs actuels utilisent un jeu tendu du code ASCII. En fait, ils en utilisent mme plusieurs. Par
exemple, sous le systme d'exploitation WINDOWS, il y a en a au moins deux : le premier est utilis
lorsqu'on travaille sous MS-DOS, le second lorsqu'on travaille dans l'environnement graphique
WINDOWS. Voici le tableau de tous les caractres qui correspond au code ASCII (parties rose et bleu
fonc) tendu soit dans sa version DOS soit dans sa version WINDOWS (jeu de caractres dit CP1252 ou
ANSI ):

Par exemple, le caractre est numrot 233 sous WINDOWS mais le mme caractre correspond
sous DOS!

1.1.3 Bits

On appelle bit la plus petite unit de stockage en informatique. Il s'agit d'un 0 ou d'un 1. Chaque caractre
(ou plus prcisment chaque numro de caractre selon la table utilise) est cod l'aide de bits.

7
Avec un bit, on peut coder deux numros: 0 ou 1. Avec deux bits, on peut coder quatre numros : 00, 01, 10
et 11. Plus gnralement avec n bits on peut coder 2 n numros. Or une table tendue comporte 256
caractres (de 0 255), on comprend donc pourquoi un caractre est cod sur 8 bits. On parle alors d'un
octet.

1.1.4 Poids

Chaque caractre pesant un poids constant de 8 bits, tout l'intrt d'un algorithme de compression est de faire
en sorte que certains caractres psent moins que 8 bits de sorte que le fichier final pse moins que le fichier
initial.

Par exemple un fichier contenant uniquement les mots lyce lapicque contient 14 caractres et pse donc
112 bits.

1.1.5 Taux de compression

On appelle taux de compression le rapport suivant:


poids du fichier final
taux de compression= poids du fichier initial

Bien entendu le taux de compression est un nombre entre 0 et 1. Plus il est proche de 0 et meilleure est la
compression.

1.2 Notion d'arbre

1.2.1 Dfinitions : nuds, branche, racine, feuilles

Considrons un ensemble de diverses informations (cela peut tre des caractres, des effectifs et mme ces
deux informations la fois). Chacune de ces informations est appele nud.

Entre les diffrents nuds, existent des relations appeles branches et symbolises par des flches et telles
que chaque nud est reli l'ensemble des autres nuds de l'arbre par au moins une branche.

Il existe un nud particulier appel racine : c'est le nud initial d'o partent toutes les branches. Il existe
galement des nuds appels feuilles : ce sont les nuds o arrive une branche sans que d'autres branches
partent de ces nuds. Ce sont les nuds qui terminent l'arbre.

8
1.2.2 Arbre binaire

Sur le schma ci-dessous, on a reprsent un arbre. En rouge se trouve le nud racine, en vert les feuilles, les
autre nuds sont laisss en bleu.

On constatera que de chacun des nuds partent deux branches (on parle d'arbre binaire), exception faite des
feuilles d'o ne part aucune branche. Mais, en pratique, il y a bel et bien deux branches qui partent des
feuilles mais elles ne visent aucun nud (voir le paragraphe sur les pointeurs).

1.3 Description de l'algorithme du codage de


Huffman
Il faut compter tout dabord tous les caractres du fichier coder et affecter chacun dentre eux son
poids dapparition. On obtient alors un tableau o chaque case correspond un caractre et son poids,
tout tant rang dans l'ordre du codage CP1252 .

Avec ce tableau, on va construire un arbre. Chacune des cellules du tableau sera une feuille de cet arbre. Pour
complter cet arbre, il faut associer les caractres ensemble : on va associer les caractres ayant le plus petit
poids pour former un nouveau nud.

Ainsi, on demande l'ordinateur de choisir les deux caractres ayant les poids les plus faibles. En cas
d'galit entre diffrents poids , on choisit en priorit le premier caractre dans l'ordre correspondant au
codage CP1252 . Aprs cela, on ajoute un nud l'arbre o on mmorise la somme des deux poids des
caractres choisis prcdemment. On ritre le processus en considrant l'arbre obtenu (t des deux
caractres prcdemment slectionns mais avec le nud supplmentaire). Ensuite, on refait ainsi pour tous
les caractres suivants jusqu'au dernier.

9
Une fois que tous les caractres sont associs les uns aux autres on a un arbre qui se finit avec 1 seul nud
qui contient le nombre de lettres coder.

Une fois l'arbre termin on va associer un bit aux branches de larbre, c'est--dire que lon va choisir, par
convention, que les branches de gauche correspondent 0 et que les branches de droite correspondent 1.

1.4 Exemple

1.4.1 Construction du tableau

Prenons un exemple. Cherchons coder la phrase : Recherche chat chtain .

Pour simplifier, on ne tient pas compte des espaces, de l'accent circonflexe ni bien sr des guillemets. Ainsi,
on cherche coder la phrase :

recherchechatchatain

On repre la lettre la plus utilise : le c apparat 4 fois, de mme que h.


Puis les lettres a et e apparaissent 3 fois.
Ensuite les lettres t, r apparaissent 2 fois.
Pour finir les lettres i et n apparaissent 1 fois.

On obtient donc le tableau suivant :

caractre a c e h i n r t
poids 3 4 3 4 1 1 2 2

1.4.2 Construction de l'arbre

Ce tableau nous permet de construire les feuilles de l'arbre:

a3 c4 e3 h4 i1 n1 r2 t2

On dtermine ensuite les deux lettres de poids le plus faible : ici les lettres i et n sont de poids 1. On
reprsente deux branches qui se rejoignent et qui relient les deux lettres les moins frquemment utilises:

a3 c4 e3 h4 i1 n1 r2 t2

10
On ritre le processus en constatant que les deux caractres de poids minimum sont r et t :

a3 c4 e3 h4 i1 n1 r2 t2

2 4

Les deux poids minimums sont ceux du nud a et de poids 2 :

c4 e3 h4 i1 n1 r2 t2

2 a3 4

Les deux minimums sont ensuite les nuds dont les caractres sont e et c :

e3 c4 h4 i1 n1 r2 t2

7 2 a3 4

Les deux minimums sont alors les nuds de poids 4 :

e3 c4 i1 n1

r2 t2 7 2 a3

h4 4 5

On relie ensuite les nuds de poids 5 et 7 pour obtenir un nud de poids 12. On arrive ainsi nud final en

11
reliant ces deux derniers nuds :

i1 n1

r2 t2 2 a3 e3 c4

h4 4 5 7

8 12

20

Ensuite , par convention, on place un 0 gauche de chaque branche et un 1 droite de chaque branche :

i1 n1

0 1
r2 t2 2 a3 e3 c4

0 1 0 1 0 1
h4 4 5 7

0 1
0 1
8 12

0 1

20

Ce qui va nous permettre de coder les lettres laide de 0 et 1. Ainsi le codage de r donne 100, celui de e
donne 001 et ainsi de suite. Le codage de recherchechatchatain donne :

0101101110011001011100110111001010111110010101110110001001

1.4.3 Taux de compression

12
La phrase recherchechatchatain contient 20 caractres (voir le nud racine!), chacun tant cod sur 8 bits,
un fichier contenant cette page pse 160 bits. Si on compte le nombre de bits obtenus aprs compression on
en a 58. Ainsi le taux de compression est :
58
taux de compression= 160 =0,3625

1.5 Dcodage
On a vu que l'on obtient le codage suivant :

0101101110011001011100110111001010111110010101110110001001

On se pose naturellement la question suivante : Comment partir du codage qui est l, retrouver la phrase de
dpart ?

En fait, il suffit de prendre le code en entier et de l'enfiler directement par la racine. Reprenons l'exemple
prcdent :

Le code est : 0101101110011001011100110111001010111110010101110110001001

Avec cela on ne sait pas si le code de la lettre est en 3,4,5 ou mme 6 bits mais ce n'est pas un problme. On
regarde bit par bit et on se dirige ainsi dans toutes les branches de l'arbre :

Le premier bit est 0, donc on se dirige vers la gauche, le second est 1, donc on se dirige vers la
droite. Ensuite, le bit est 0 donc on se dirige vers la gauche. On arrive alors une feuille de l'arbre :
celle qui correspond au caractre r.
De mme 110 correspond e et ainsi de suite...

13
Chapitre 2
Transformation de Burrows Wheeler

2.1 Un premier tableau

2.1.1 Principe

Dans ce chapitre, on note T la phrase coder. On utilise un tableau form de 3 colonnes : La premire
colonne est constitue de la suite des lettres de la phrase de dpart, cette suite sera nomme Ti et la premire
lettre sera appele T1, puis la deuxime T2 et ainsi de suite...

Dans la deuxime colonne on indique un numro correspondant lapparition dans T de chaque lettre. Dans
la troisime colonne, on crit la suite S correspondant aux lettres prcdentes. Chaque Si sera gal aux lettres
crites avant le Ti correspondant.

2.1.2 Exemple

Reprenons la phrase recherchechatchatain. On obtient alors le tableau suivant :

Ti i Si
r 1
e 2 r
c 3 er
h 4 cer
e 5 hcer
r 6 ehcer
c 7 rehcer
h 8 crehcer
e 9 hcrehcer

14
c 10 ehcrehcer
h 11 cehcrehcer
a 12 hcehcrehcer
t 13 ahcehcrehcer
c 14 tahcehcrehcer
h 15 ctahcehcrehcer
a 16 hctahcehcrehcer
t 17 ahctahcehcrehcer
a 18 tahctahcehcrehcer
i 19 atahctahcehcrehcer
n 20 iatahctahcehcrehcer

2.2 Un second tableau

2.2.1 Principe

Ensuite laide du premier tableau nous allons construire un autre tableau toujours constitu de 3 colonnes.

Dans la premire colonne que lon appellera Sj, on va classer les Si dans lordre alphabtique. Puis on met en
face dans la deuxime colonne nomme j, lordre dapparition des Sj. Enfin dans la dernire colonne on
inscrira la lettre correspondante au Sj note tj.

2.2.2 Exemple

Sj j tj
1 r
ahcehcrehcer 2 t
ahctahcehcrehcer 3 t
atahctahcehcrehcer 4 i
cehcrehcer 5 h
cer 6 h
crehcer 7 h
ctahcehcrehcer 8 h
ehcer 9 r
ehcrehcer 10 c

15
er 11 c
hcehcrehcer 12 a
hcer 13 e
hcrehcer 14 e
hctahcehcrehcer 15 a
iatahctahcehcrehcer 16 n
r 17 e
rehcer 18 c
tahcehcrehcer 19 c
tahctahcehcrehcer 20 a

2.2.3 Comment passer d'un tableau l'autre

On pourra noter quil ny a aucune perte entre ces deux tableaux, on peut retrouver un des deux tableaux
partir du deuxime. Pour cela on compare lemplacement des j et des i :

T S t s
i Si sj j
1 1
2 r r 17
3 er er 11
4 cer cer 6
5 hcer hcer 13
6 ehcer ehcer 9
7 rehcer rehcer 18
8 crehcer crehcer 7
9 hcrehcer hcrehcer 14
10 ehcrehcer ehcrehcer 10
11 cehcrehcer cehcrehcer 5
12 hcehcrehcer hcehcrehcer 12
13 ahcehcrehcer ahcehcrehcer 2
14 tahcehcrehcer tahcehcrehcer 19
15 ctahcehcrehcer ctahcehcrehcer 8
16 hctahcehcrehcer hctahcehcrehcer 15
17 ahctahcehcrehcer ahctahcehcrehcer 3
18 tahctahcehcrehcer tahctahcehcrehcer 20
19 atahctahcehcrehcer atahctahcehcrehcer 4

16
20 iatahctahcehcrehcer iatahctahcehcrehcer 16

Il est donc question entre les deux premiers tableaux dune permutation de 20 lments. On a reprsent
cette permutation (de j vers i) dans le tableau ci-dessous :

j 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
i 1 13 17 19 11 4 8 15 6 10 3 12 5 9 16 20 2 7 14 18

2.3 Texte transform

2.3.1 Codage du texte transform

Notre second tableau permet d'obtenir un nouveau texte. Il suffit de reprendre tous les tj :

rttihhhhrccaeeanecca

On peut alors coder ce texte par le codage de Huffman. Mieux, on peut le coder en utilisant de nouveaux
caractres : double t not t2, quadruple h not h4 et ainsi de suite :

rt2ih4rc2ae2anec2a

Ainsi le caractre r apparat deux fois, le caractre t2 une fois, le caractre i une fois, le caractre h4 une fois,
le caractre c2 deux fois, le caractre a trois fois, le caractre e2 apparat une fois, le caractre n une fois et le
caractre e une fois galement. On obtient ainsi l'arbre suivant :

2
n1 e2 1 t 1 h4 1

0 1 0 1
2 2 r2 c2 2 e1 i1

0 1 0 1 0 1
4 4 2 a3

0 1 0 1

8 5

0 1
13

On a donc le codage suivant :

0100010101001101001111000111000111000010001111

17
On obtient ici un rsultat de 46 bits, ce qui nous fait alors un gain de 12 bits par rapport au codage de
Huffman sur le texte initial et de 114 bits sur le texte sans compression.

2.3.2 Comment retrouver le texte initial?

Cependant, cela n'est qu'une thorie car la cration du second tableau ncessite la permutation . Or, il faut a
priori mmoriser toute cette permutation pour pouvoir partir du texte transform retrouver le texte initial.

En fait, on nous a expliqu qu'il n'tait pas ncessaire de mmoriser l'ensemble de la permutation mais nous
n'avons pas eu le temps d'tudier cette proprit de la transformation de Burrows-Wheeler.

18
Chapitre 3
Dfinitions complmentaires

3.1 tage et position

3.1.1 Dfinitions

On cherche numroter les nuds d'un arbre. On appelle un tel numro la position du nud. On part du
nud le plus bas (appel racine) qui on affecte la position n = 1 et ensuite, pour le nud suivant gauche,
on multiplie n par 2 (ainsi le nud situ en haut gauche de la racine a pour position n = 2). Pour le nud se
situant droite de la racine, on multiplie n par 2 et on ajoute 1 (ainsi le nud situ en haut gauche de la
racine a pour position n = 3). On ritre le procd ainsi jusqu'aux feuilles :

tage 4 i1 n1
24 25
0 1
tage 3 r2 t2 2 a3 e3 c4
10 11 12 13 14 15
0 1 0 1 0 1
tage 2 h4 4 5 7
4 5 6 7
0 1
0 1
tage 1 8 12
2 3

0 1

tage 0 20
1

Les numros des nuds se situant lextrme gauche s'crivent tous sous la forme 2p. Les autres nuds tant
plus vers la droite, ont une position comprise entre 2p et 2p+1 1. On dit alors que ces nuds sont situs
l'tage p.

19
Or p reprsente le nombre de bits ncessaires pour coder le nud. Donc connaissant l'tage associ chaque
feuille (en fonction de sa position dans l'arbre), on peut dterminer le nombre de bits ncessaires pour coder
un caractre.

3.1.2 Passage de position tage

Cherchons calculer l'tage p connaissant la position i du nud : Pour savoir comment on passe de la
position dun nud ltage o il se trouve dans larbre, il suffit d'utiliser les logarithmes. tant en premire,
nous ne connaissons pas les logarithmes, mais on nous a dit deux choses:

la fonction ln est croissante sur ]0; [


Pour tous rels a>0 et b>0 on a : ln ab = b ln a

On a vu que 2p i < 2p+1 donc :

ln 2p ln i < ln 2p+1 (car la fonction ln est croissante)


p ln 2 ln i < (p+1) ln 2 (d'aprs la seconde proprit)
ln i
p < p+1 (comme on divise par ln 2, il faut que celui-ci soit positif, or
ln 2
d'aprs la calculatrice, ln 2 est gal environ 0,69)

ln i ln i
De l'ingalit < p+1, on dduit -1 < p et donc :
ln 2 ln 2
ln i ln i
-1 < p
ln 2 ln 2

On en dduit que p = E lni


ln 2
(o E dsigne la fonction partie entire).

3.2 Notion de pointeur

3.2.1 Dfinition

Un pointeur est une variable contenant l'adresse d'une autre variable. Par exemple, quand on cre un entier a
cod sur quatre octets, lordinateur attribue quatre octets dans sa mmoire pour stocker cet entier. Le pointeur
relatif a est le numro du premier octet o se trouve a.

Par exemple on peut coder :

inta;

Si on souhaite obtenir la valeur de a et, par exemple, dcider que la valeur de a est 1, on crira :

20
a=1;

On peut aussi avoir besoin du pointeur sur a. On crira alors &a.

En fait, on manipule au moins aussi souvent des pointeurs sur les objets que les objets eux-mmes. Pour
dclarer un pointeur (par exemple sur un entier) on crira :

int*b;

Alors *b dsigne l'entier point par b et b est le pointeur, c'est--dire l'adresse de *b.

Le programme ci-dessous montre comment on manipule les pointeurs :

#include<stdio.h>

intmain(intargc,char*argv[])
{
inta;//aestunentier
a=1;//initialis1
printf("Valeurdea:%i\n",a);
printf("Adressedea:%p\n",&a);

int*b;//bestunpointeur

b=&a;//quipointesura

printf("Valeurdeb:%i\n",*b);
printf("Adressedeb:%p\n",b);
return0;
}

3.2.2 Application la reprsentation informatique d'un arbre

Dans un arbre binaire il y a un ensemble de nuds. Chaque nud est constitu de donnes et de deux
branches vers d'autres nuds. Chacune de ces branches est en fait un pointeur vers un nud. On a donc crer
l'objet tree de la faon suivante : un caractre de type uchar, un poids (il est nomm weight de type
long), une position (de type long) et enfin deux pointeurs *left et *rightsur des objets de type tree.

typedefstructtree{
ucharc;
longweight;
longpos;
structtree*left,*right;
}tree;

Il suffit donc de connatre l'adresse du nud racine pour pouvoir remonter n'importe quel nud ou
n'importe quelle feuille. Remarquons enfin que les feuilles sont des nuds particuliers puisqu'il n'en mane
aucune branche. Ici on aura simplement deux pointeurs qui pointent sur une adresse particulire : l'adresse
NULL. On crira donc, s'il s'agit d'une feuille de l'arbre a:

21
a.left=NULL;
a.right=NULL;

Si bien sur a est un pointeur sur un arbre on aura :

(*a).left=NULL;
(*a).right=NULL;

22
Chapitre 4
Programmation en C du codage de
Huffman

4.1 Diffrentes tapes du programme

4.1.1 Fonction principale

Le point d'entre d'un programme crit en C est la fonction main qui appelle toute les autres fonctions.
Voici cette fonction :

intmain(intargc,char*argv[])
{
FILE*source=fopen("exemple.txt","r+");
long*eff=Jordan(source);
tree*arbre=creer_arbre(eff);
afficher_arbre(arbre);
printf("\n\nTaux de compression : %lf\n", ( ((double)
taille(arbre))/(8*ftell(source))));
fclose(source);
system("PAUSE");
returnEXIT_SUCCESS;
}

Cette fonction renvoie au systme un entier (int) qui permet de savoir si le programme s'est droul
correctement (par returnEXIT_SUCCESS;) ou pas.

4.1.2 Principe gnral

La premire chose effectue est l'ouverture du fichier exemple.txt et sa mise disposition au programme
sous la forme de l'objet source de type FILE*.

23
Cet objet source est ensuite envoy la fonction Jordan. Cette fonction renvoie le tableau des effectifs de
chaque lettre. Il s'agit du tableau d'entiers (de type long) nomm eff.

partir du tableau eff, on cre l'arbre dans la fonction creer_arbre. Ainsi cette fonction renvoie un
arbre (de type tree*) nomm arbre. On l'affiche (fonction afficher_arbre).

L'tape suivante consiste calculer le taux de compression et l'afficher. Pour cela on utilise la fonction
taille (qui utilise comme paramtre l'arbre arbre) et qui permet d'obtenir le poids du fichier final. On utilise
galement ma fonction ftell qui utilise l'objet source et qui permet d'obtenir le poids du fichier initial.

En dernier lieu, on ferme l'objet source qui correspond au fichier compresser et on renvoie au systme
EXIT_SUCCESS.

4.2 Lecture du fichier initial

4.2.1 Tableau des effectifs de chaque caractre

La premire chose faire est de lire le fichier compresser de faon dterminer l'effectif associ chaque
caractre.

C'est ce que fait la fonction Jordan : partir du FILE* nomm source, elle renvoie un tableau de MAX
=256 entiers nomm eff.

Voici le listing de la fonction Jordan :

long*Jordan(FILE*source){

long*eff=malloc(MAX*sizeof(long));
charc;
ucharu;
longi;

for(i=0;i<MAX;eff[i++]=0);

if(source==NULL)printf("fichiersourceintrouvable\n");
else{
while((c=fgetc(source))!=EOF)eff[u=c]++;
}
returneff;
}

Cette fonction cre le tableau eff qui contient 256 entiers de type long numrots de 0 255. Ce tableau
est dans un premier temps initialis : pour tout entier i plus petit que MAX, toutes les cellules du tableau sont
mises 0.

Si aucun fichier nest trouv, on imprime "fichiersourceintrouvable\n"(le caractre \n est un


caractre spcial : il s'agit du retour la ligne).

24
Sinon, tant que le caractre lu dans le fichier est diffrent du caractre de fin de fichier (caractre EOF), on
ajoute 1 la valeur situe dans le tableau eff dont l'indice u reprsente le caractre c.

4.2.2 Lecture du tableau des effectifs

Pour vrifier le bon fonctionnement de la fonction Jordan, il nous a t utile d'imprimer le tableau eff
obtenu. C'est ce que fait la fonction afficher_eff dont voici le listing :

voidafficher_eff(long*eff)
{
longi

for(i=0;i<MAX;i++){
if (eff[i] != 0) printf ("caratere %c, \t code %ld, \t
effectif%ld\n",i,i,eff[i]);
}
}

Pour un entier i plus petit que MAX, toutes les cases du tableau sont lues. Si la case lue correspond un
effectif non nul alors on imprime "caratere %c, \t code %ld, \t effectif
%ld\n",i,i,eff[i], c'est--dire qu'on imprime le caractre (par exemple A, puis son codage sous
DOS, par exemple 65, et enfin l'effectif correspond dans le fichier compresser).

4.3 Construction de l'arbre

4.3.1 Obtention de deux minimums

Une des premire fonctions que nous avons du programmer est la fonction Thomas qui partir du tableau
d'entiers t dont la longueur taille est passe en paramtre, permet d'obtenir les deux minima (strictement
positifs) contenus dans le tableau t. Cette fonction renvoie un tableau nomm resultat constitu de deux
entiers qui sont les 2 minima recherchs. Voici le listing de cette fonction :

long*Thomas(long*t,longtaille)
{
long*resultat=malloc(2*sizeof(long));
longi,i1=0,i2=0,min1,min2;

for(i=0;i<taille;i++){
if(t[i]>0)break;
}
min1=t[resultat[0]=i]; //min1estlepremierentiernonnuldu
tableau

25
for(i=0;i<taille;i++){
if(t[i]>0&&t[i]<min1)min1=t[resultat[0]=i];
}

for(i=0;i<taille;i++){
if(t[i]>0&&i!=resultat[0])break;
}
min2=t[resultat[1]=i]; //min2estlesecondentiernonnuldu
tableau

for(i=0;i<taille;i++){
if(i==resultat[0])continue;
if(t[i]>0&&t[i]<min2)min2=t[resultat[1]=i];
}

returnresultat;
}

Elle cre une boucle pour trouver le premier entier positif non nul dans le tableau t, car si t[i] n'est pas
strictement suprieur 0, l'ordinateur lit la case suivante du tableau. Une fois qu'un indice i tel que t[i] est
strictement positif est obtenu, on sort de la boucle par l'instruction break. On assigne alors
resultat[0] l'entier i obtenu et min1 l'effectif correspondant.

L'analyse du tableau reprend : si la valeur de l'effectif d'indice i est strictement suprieure 0 et infrieur
min1 alors min1 est remplac par cet effectif et resultat[0] est remplac par i.

Une troisime boucle est ncessaire pour dterminer un indice i tel que t[i] est strictement positif sans
que i soit gal resultat[0]. Ds qu'un tel i est obtenu, on sort de la boucle et on assigne
resultat[1] cet entier i et min2 l'effectif correspondant.

Enfin la quatrime et dernire boucle permet de modifier min2 s'il ne correspond pas au second minimum :
pour cela, pour un indice i distinct de resultat[0], on modifie min2 et resultat[1] si l'effectif lu
est strictement positif est strictement infrieur min2.

4.3.2 Nombre de caractres distincts

La fonction nbcarac compte le nombre de caractres diffrents dans le fichier en renvoyant un entier
nomm resultat. Pour cela elle parcourt le tableau des effectifs eff entr en paramtre et ajoute 1
resultat ds qu'un caractre est marqu comme prsent dans le tableau des effectifs (c'est--dire ds que
eff[i] est strictement suprieur 0).

longnbcarac(long*eff)
{
longresultat=0,i=0;
for(i=0;i<MAX;i++){
if(eff[i]>0)resultat++;
}
returnresultat;
}

26
4.3.3 Cration de l'arbre

La fonction creer_arbre permet la construction de l'arbre. Cette fonction utilise le tableau des effectifs
eff cr prcdemment et renvoie un pointeur sur un arbre, c'est--dire un objet du typetree*. On utilise
l'entier n qui est le nombre de caractre diffrents dans le fichier ainsi que tho qui est un tableau de deux
entiers : ces deux entiers sont les deux indices o se trouvent les deux effectifs minimums recherchs dans le
tableau tab qui contient la liste de tous les effectifs. Enfin, tableau_arbre est un tableau de 2n-1
nuds. On utilisera ce tableau pour renvoyer l'adresse du dernier nud qui sera le nud racine.

Voici le listing de cette fonction :

tree*creer_arbre(long*eff)
{
longn=nbcarac(eff);
longi=0,j=0,k=0,min1,min2;
long*tho=(long*)malloc(2*sizeof(long));
tree*tableau_arbre=(tree*)malloc((2*n1)*sizeof(tree));
long*tab=(long*)malloc((2*n1)*sizeof(long));

//INITIALISATION

for(i=0;i<n;i++){
for(j=k;j<MAX;j++)if(eff[j]!=0)break;
k=j+1;
tableau_arbre[i].weight=eff[j];
tableau_arbre[i].pos=0;
tableau_arbre[i].c=(uchar)j;
tableau_arbre[i].left=tableau_arbre[i].right=NULL;
}
for(i=n;i<2*n1;i++){
tableau_arbre[i].weight=tableau_arbre[i].pos=0;
tableau_arbre[i].c=0;
tableau_arbre[i].left=tableau_arbre[i].right=NULL;
}

//CREATIONARBRE

for(i=n;i<2*n1;i++){
for(j=0;j<2*n1;j++)tab[j]=
tableau_arbre[j].weight;
tho=Thomas(tab,2*n1);
tableau_arbre[i].weight=
tableau_arbre[tho[0]].weight+tableau_arbre[tho[1]].weight;
tableau_arbre[i].left=&(tableau_arbre[tho[0]]);
tableau_arbre[i].right=&(tableau_arbre[tho[1]]);
tableau_arbre[tho[0]].weight=
tableau_arbre[tho[0]].weight;
tableau_arbre[tho[1]].weight=
tableau_arbre[tho[1]].weight;
}

27
//REECRITUREDESEFFECTIFSENPOSITIF

for(j=0;j<2*n1;j++){
if(tableau_arbre[j].weight<0)tableau_arbre[j].weight=
tableau_arbre[j].weight;
}

//ECRITUREDESPOSITIONS

completer_position(&(tableau_arbre[2*n2]),1);

return&(tableau_arbre[2*n2]);
}

Comme on le voit il y a plusieurs tapes dans cette fonction :

Initialisation.
Cration de l'arbre
Rcriture des effectifs en positif .
criture des positions.

Commenons par l'initialisation : il s'agit de remplir les n premires cellules (numrotes de 0 n-1) de
tableau_arbre par l'effectif de chaque caractre en assignant eff[j]
tableau_arbre[i].weight et le caractre prsent dans le tableau (j) est assign sous sa forme non
signe tableau_arbre[i].c. Dans l'initialisation les positions sont mises 0 et les pointeurs mis
NULL.
partir de la case n, on met 0 comme caractre, comme effectif et comme position. De mme tous les
pointeurs sont mis NULL.

Passons la seconde tape : les n premires cellules tant compltes lors de l'initialisation, il reste
complter les n-1 suivantes lors de la cration de l'arbre. Pour cela on utilise un entier i qui va de n 2n-2.
A chaque passage dans cette boucle, le tableau tab est reconstruit (on verra que les n poids des caractres
sont modifis chaque tape) .
On dtermine ensuite (par la fonction Thomas) les deux indices de tab o se trouvent les minima. Ces
deux indices, tho[0] et tho[1] permettent d'affecter la case i un poids qui est la somme des deux
poids minimaux par la ligne suivante :

tableau_arbre[i].weight=
tableau_arbre[tho[0]].weight+tableau_arbre[tho[1]].weight;

On affecte galement les deux pointeurs aux cellules qui correspondent tho[0] et tho[1].

Il reste ensuite prciser que les cellules correspondantes tho[0] et tho[1] ne doivent plus tre prises
en compte : pour cela on multiplie les effectifs correspondants par -1 (la fonction Thomas ne cherche que
les minimums positifs). Par exemple pour la cellule correspondante tho[0] :

tableau_arbre[tho[0]].weight=tableau_arbre[tho[0]].weight;

La troisime tape consiste multiplier les effectifs ngatifs par -1 de sorte qu'ils soient nouveau tous
positifs. Il suffit de faire varier un entier j de 0 2n-2 et de tester le signe de
tableau_arbre[j].weight pour ventuellement le multiplier par -1.

28
La dernire tape consiste crire la position de chaque nud : cela s'effectue dans une autre fonction, la
fonction completer_position. Son fonctionnement est dtaill dans le paragraphe 4.4.1.

Enfin, on renvoie l'adresse de la dernire cellule du tableau tableau_arbre qui est l'adresse du nud
racine.

4.3.4 Affichage de l'arbre

Cette fonction utilise comme paramtre le pointeur arbre sur un arbre et ne renvoie aucune valeur. Elle sert
afficher l'cran l'arbre en question. Pour cela, on affiche "AFFICHAGEARBRE ",
puis on appelle la fonction afficher_arbre_rec. Voici le listing de cette fonction :

voidafficher_arbre(tree*arbre)
{
printf("AFFICHAGEARBRE\n");
afficher_arbre_rec(arbre);
printf("\n");
}

La fonction afficher_arbre_rec commence par donner le numro du nud racine avec l'effectif
correspondant. Dans la suite de la fonction on trouve le test suivant :

si le pointeur de gauche et le pointeur de droite pointent sur NULL alors il affiche le caractre, car le
nud observ est en ralit une feuille
si le pointeur de gauche ne pointe pas sur NULL alors elle recommence pour le pointeur de gauche
(c'est--dire que tout se passe comme si le nouveau nud racine tait le nud gauche).
si le pointeur de droite ne pointe pas sur NULL alors elle recommence pour le pointeur de droite
(c'est--dire que tout se passe comme si le nouveau nud racine tait le nud droit).

Voici le listing de cette fonction :

voidafficher_arbre_rec(tree*arbre)
{
printf("\n\nNoeudnumero%ld.\nEffectif%ld\t",(*arbre).pos,
(*arbre).weight);
if((*arbre).left==NULL&&(*arbre).right==NULL)
printf("Caractere%c",(*arbre).c);
if((*arbre).left!=NULL)afficher_arbre_rec((*arbre).left);
if((*arbre).right!=NULL)afficher_arbre_rec(arbre>right);
}

4.4 tage et position

29
4.4.1 criture des positions

La fonction completer_positioncrit les positions des nuds dans larbre. Elle prend en paramtre
un entier i (qui correspond la position de la racine, savoir 1) et l'arbre complter. Voici le listing de
cette fonction :

voidcompleter_position(tree*arbre,longi)
{
(*arbre).pos=i;
if((*arbre).left!=NULL)completer_position(arbre>left,
2*i);
if((*arbre).right!=NULL)completer_position(arbre>right,
2*i+1);
}

La premire fois que la fonction est appele, la position de la racine de l'arbre est gale 1. Ensuite :
si le pointeur de gauche est diffrent de NULL alors la position suivante est double et elle est
affecte au nud situ gauche.
si le pointeur de droite est diffrent de NULL alors la position suivante est double et ajoute 1 et
elle est affecte au nud situ droite.

4.4.2 Calcul de l'tage en fonction de la position

Soit i la position dun nud dans larbre. La fonction etagenous permet de calculer l'tage p en fonction
de i en utilisant les logarithmes. On y voit ainsi l'application du rsultat trouv dans la dmonstration du
paragraphe 3.1.2. :

p=E
lni
ln 2

Dans le listing ci-dessous, log correspond ln, floor la fonction partie entire :

longetage(longi)
{
return((long)floor(log(i)/log(2)));
}

4.5 Calcul du taux de compression

4.5.1 Obtention de la taille du fichier compress

30
Pour obtenir la taille du fichier compress, on utilise la fonction taille qui utilise comme paramtre un
pointeur sur un arbre et renvoie un entier. Cette fonction est trs simple. Voici son listing :

longtaille(tree*arbre)
{
returntaille_rec(arbre,1);
}

Comme on le voit tout se passe dans la fonction taille_rec qui fonctionne de la manire suivante : la
premire fois qu'elle est appele, l'entier i est gal 1 et on teste le nud (initialement le nud racine) pour
savoir s'il s'agit d'une feuille. Si ce n'est pas le cas on calcule la somme de la taille correspondant la branche
gauche et la branche droite grce :

taille_rec((*arbre).left,2*i)+taille_rec(arbre>right,2*i+1)

Comme la branche gauche est affecte de 2*i et la branche droite de 2*i+1, chaque appel de la fonction
taille_rec, on donne la position du nud. Ds que l'on est sur une feuille on calcule etage(i) (c'est-
-dire le nombre de bits ncessaires pour crire le caractre correspondant la feuille) multipli par
(*arbre).weight (c'est--dire le nombre de fois o le caractre est prsent dans le fichier initial).
Comme on a ajout les diffrents tailles, on calcule bien le poids (en bits) du fichier final,

longtaille_rec(tree*arbre,longi)
{
if((*arbre).left!=NULL||(*arbre).right!=NULL)
return(taille_rec((*arbre).left,2*i)+taille_rec(arbre>right,
2*i+1));
if((*arbre).left==NULL&&(*arbre).right==NULL)
return((*arbre).weight*etage(i));
}

4.5.2 Prambule d'un fichier compress

En fait un fichier compress doit contenir, en plus du codage brut (par exemple
0101101110011001011100110111001010111110010101110110001001), un prambule qui dcrit pour chaque
caractre le codage associ.

Si on reprend l'exemple recherchechatchatain on a :

Caractre Codage
r 010
e 110
c 111
h 00
a 101

31
t 011
i 1000
n 1001

Ce prambule doit donc contenir les huit caractres (un caractre pse 8 bits) et tous les codages soit :

3+3+3+2+3+3+4+4 = 25 bits

Ainsi ce prambule contient au minimum 88 + 25 = 89 bits ajouter aux 58 du codage brut. Bien entendu,
cela modifie le taux obtenu. On peut penser que l'on obtiendrait un taux rel de :

taux de compression= 8958


160
=0,9187

4.6 Exemple
Utilisons notre programme pour tester la phrase recherchechatchatain. Comme on l'a vu prcdemment, on
utilise le fichier exemple :

Ce fichier contient 20 caractres, soit une taille initiale de 20 octets comme le confirme la copie d'cran
suivante :

32
Lanons notre programme! On obtient alors :

33
On constate que les positions obtenues par notre programme sont bien les mmes que celles obtenues au
chapitre 1. Ainsi le taux de compression thorique est bien de 0,3625 comme annonc!

34
Chapitre 5
Annexe

5.1 Fichier main.c

intmain(intargc,char*argv[])
{
FILE*source=fopen("exemple.txt","r+");
long*eff=Jordan(source);
tree*arbre=creer_arbre(eff);
afficher_arbre(arbre);
printf("\n\nTauxdecompression:%lf\n",(((double)
taille(arbre))/(8*ftell(source))));
fclose(source);
system("PAUSE");
returnEXIT_SUCCESS;
}

5.2 Fichiers Jordan

5.2.1 Fichier Jordan.h

#ifndef_Jordan
#define_Jordan

#defineMAX256

typedefunsignedcharuchar;

long*Jordan(FILE*);

voidaffiche_eff(long*);

#endif

35
5.2.2 Fichier Jordan.c

#include<stdio.h>
#include<stdlib.h>
#include"Jordan.h"
#include"Thomas.h"

long*Jordan(FILE*source){

long*eff=malloc(MAX*sizeof(long));
charc;
ucharu;
longi;

for(i=0;i<MAX;eff[i++]=0);

if(source==NULL)printf("fichiersourceintrouvable\n");
else{
while((c=fgetc(source))!=EOF)eff[u=c]++;
}
returneff;
}

voidafficher_eff(long*eff)
{
longi;

for(i=0;i<MAX;i++){
if(eff[i]!=0)printf("caratere%c,\tcode%ld,\teffectif
%ld\n",i,i,eff[i]);
}
}

5.3 Fichiers Thomas

5.3.1 Fichier Thomas.h

#ifndef_Thomas
#define_Thomas

typedefstructtree{
ucharc;
longweight;
longpos;
structtree*left,*right;

36
}tree;

long*Thomas(long*,long);

longnbcarac(long*);

#endif

5.3.2 Fichier Thomas.c

#include<stdio.h>
#include<stdlib.h>
#include"Jordan.h"
#include"Thomas.h"

long*Thomas(long*t,longtaille)
{
long*resultat=malloc(2*sizeof(long));
longi,i1=0,i2=0,min1,min2;

for(i=0;i<taille;i++){
if(t[i]>0)break;
}
min1=t[resultat[0]=i];//min1estlepremierentier
nonnuldutableau

for(i=0;i<taille;i++){
if(t[i]>0&&t[i]<min1)min1=t[resultat[0]=i];
}

for(i=0;i<taille;i++){
if(t[i]>0&&i!=resultat[0])break;
}
min2=t[resultat[1]=i];//min2estlesecondentier
nonnuldutableau

for(i=0;i<taille;i++){
if(i==resultat[0])continue;
if(t[i]>0&&t[i]<min2)min2=t[resultat[1]=i];
}

returnresultat;
}

longnbcarac(long*eff)
{
longresultat=0,i=0;
for(i=0;i<MAX;i++){
if(eff[i]>0)resultat++;
}
returnresultat;

37
}

5.4 Fichiers creation_arbre

5.4.1 Fichier creation_arbre.h

#ifndef_creation_arbre
#define_creation_arbre

tree*creer_arbre(long*);

voidafficher_arbre(tree*);

voidafficher_arbre_rec(tree*);

voidcompleter_position(tree*,long);

longetage(long);

longtaille(tree*);

longtaille_rec(tree*,long);

#endif

5.4.2 Fichier creation_arbre.c

#include<stdio.h>
#include<stdlib.h>
#include"Jordan.h"
#include"Thomas.h"
#include"creation_arbre.h"
#include<math.h>

tree*creer_arbre(long*eff)
{
longn=nbcarac(eff);
longi=0,j=0,k=0,min1,min2;
long*tho=(long*)malloc(2*sizeof(long));
tree*tableau_arbre=(tree*)malloc((2*n1)*sizeof(tree));
long*tab=(long*)malloc((2*n1)*sizeof(long));

//INITIALISATION

for(i=0;i<n;i++){

38
for(j=k;j<MAX;j++)if(eff[j]!=0)break;
k=j+1;
tableau_arbre[i].weight=eff[j];
tableau_arbre[i].pos=0;
tableau_arbre[i].c=(uchar)j;
tableau_arbre[i].left=tableau_arbre[i].right=NULL;
}
for(i=n;i<2*n1;i++){
tableau_arbre[i].weight=tableau_arbre[i].pos=0;
tableau_arbre[i].c=0;
tableau_arbre[i].left=tableau_arbre[i].right=NULL;
}

//CREATIONARBRE

for(i=n;i<2*n1;i++){
for(j=0;j<2*n1;j++)tab[j]=
tableau_arbre[j].weight;
tho=Thomas(tab,2*n1);
tableau_arbre[i].weight=
tableau_arbre[tho[0]].weight+tableau_arbre[tho[1]].weight;
tableau_arbre[i].left=&(tableau_arbre[tho[0]]);
tableau_arbre[i].right=&(tableau_arbre[tho[1]]);
tableau_arbre[tho[0]].weight=
tableau_arbre[tho[0]].weight;
tableau_arbre[tho[1]].weight=
tableau_arbre[tho[1]].weight;
}

//REECRITUREDESEFFECTIFSENPOSITIF

for(j=0;j<2*n1;j++){
if(tableau_arbre[j].weight<0)tableau_arbre[j].weight=
tableau_arbre[j].weight;
}

//ECRITUREDESPOSITIONS

completer_position(&(tableau_arbre[2*n2]),1);

return&(tableau_arbre[2*n2]);
}

voidcompleter_position(tree*arbre,longi)
{
(*arbre).pos=i;
if((*arbre).left!=NULL)completer_position(arbre>left,
2*i);
if((*arbre).right!=NULL)completer_position(arbre>right,
2*i+1);
}

voidafficher_arbre(tree*arbre)
{
printf("AFFICHAGEARBRE\n");

39
afficher_arbre_rec(arbre);
printf("\n");
}

voidafficher_arbre_rec(tree*arbre)
{
printf("\n\nNoeudnumero%ld.\nEffectif%ld\t",(*arbre).pos,
(*arbre).weight);
if((*arbre).left==NULL&&(*arbre).right==NULL)
printf("Caractere%c\tcode%ld",(*arbre).c,(*arbre).c);
if((*arbre).left!=NULL)afficher_arbre_rec((*arbre).left);
if((*arbre).right!=NULL)afficher_arbre_rec(arbre>right);
}

longetage(longi)
{
return((long)floor(log(i)/log(2)));
}

longtaille(tree*arbre)
{
returntaille_rec(arbre,1);
}

longtaille_rec(tree*arbre,longi)
{
if((*arbre).left!=NULL||(*arbre).right!=NULL)
return(taille_rec((*arbre).left,2*i)+taille_rec(arbre>right,
2*i+1));
if((*arbre).left==NULL&&(*arbre).right==NULL)
return((*arbre).weight*etage(i));
}

40
Conclusion
L'atelier Math en Jeans nous a apport certains avantages pour la suite de nos tudes et comme amliorations
personnelles. Ainsi, nous avons dvelopp notre esprit d'quipe dans ce travail, en nous rpartissant les
tches quitablement et en s'entraidant. De plus, lors de notre voyage Paris nous avons pu amliorer notre
oral, grce la prsentation de nos recherches devant un public et nous avons galement progress dans nos
aptitudes de rdaction en rdigeant ce rapport.

On peut galement noter que notre sujet nous a aid pour nos cours de mathmatiques grce l'apprentissage
des arbres, que nous avons utilis cette anne dans le chapitre des probabilits. Il y a aussi les logarithmes
qui nous seront utiles l'anne prochaine.

Nous avons dcouvert la programmation qui fut dure comprendre mais nous esprons que cela nous servira
pour l'examen pratique de mathmatique du baccalaurat.

41

Vous aimerez peut-être aussi