Vous êtes sur la page 1sur 23

Master SII

Recherche
dans un
arbre
binaire
Algorithmes de recherche dun lment
dans un arbre binaire

Yassmine ANNI, Hajar ELMALKI et Mohamed


Amine ERRACHIDI encadrs par Abderrahim
Tragha

Table des matires


Introduction..................................................................................................2
Chapitre I : Etude thorique.........................................................................4
Structure de donnes...............................................................................4
Algorithmes de parcours...........................................................................5
Parcours en profondeur.........................................................................5
Parcours en largeur................................................................................7
Complexit des algorithmes.....................................................................8
Chapitre II : Etude pratique........................................................................10
Implmentation en langage C.................................................................10
Caractristiques du langage C.............................................................10
Implmentation de la structure de donnes........................................11
Implmentation des algorithmes.........................................................11
Techniques de calcul du temps dexcution........................................13
Accs aux fichiers................................................................................13
Comparaison des temps dexcution......................................................14
Conclusion..................................................................................................18
Rfrences.................................................................................................19

Sommaire des tables


Tableau 1 : Comparation du temps d'execution des algorithmes de
recherche...................................................................................................14

Sommaire des figures


Figure 1: Exemple d'arbre binaire avec des nuds tiquets.....................7
Figure 2: Dcoupage en niveau d'un arbre binaire......................................7
Figure 3: Diagramme comparatif du temps d'execution des algorithmes..17

Introduction
Dans les domaines de mathmatiques et informatique, un
algorithme est une rponse un problme. Il est compos d'un ensemble
d'tapes simples ncessaires la rsolution, dont le nombre varie en
fonction du nombre d'lments traiter. D'autre part, plusieurs
algorithmes peuvent rpondre un mme problme. Pour savoir quelle
mthode est plus efficace il faut les comparer.
Ainsi, intervient la thorie de la complexit, qui est un domaine des
mathmatiques et plus prcisment de linformatique thorique, qui
tudie formellement la quantit de ressources (en temps et en espace)
ncessaire pour la rsolution de problmes, dit algorithmiques, au moyen
de l'excution d'un algorithme. Il s'agit donc d'tudier la difficult
intrinsque de problmes poss mathmatiquement.
Pour dfinir la thorie de la complexit, il faut prsenter les concepts
de problmes algorithmiques, de rponses algorithmiques aux problmes,
et la complexit des problmes algorithmiques. Cette thorie tudie
principalement (mais pas uniquement) les problmes de dcisions, qui
posent une question dont la rponse est oui ou non.
Lorsque ltude se focalise sur un algorithme en particulier plutt
que la difficult intrinsque des problmes, nous parlons de lanalyse de la
complexit de cet algorithme. Cette analyse a pour but la comparaison
entre deux algorithmes comme cit prcdemment.
La ncessit de comparaison entre deux algorithmes est parue
lorsque les scientifiques ont voulu noncer formellement et
rigoureusement ce qu'est l'efficacit d'un algorithme ou au contraire
sa complexit, ils se sont rendu compte que les outils pour le faire
l'poque taient primitifs. Dans la prhistoire de l'informatique (les annes
1950), la mesure publie, si elle existait, tait souvent dpendante
du processeur utilis, des temps d'accs la mmoire vive et de masse,
du langage de programmation et du compilateur utilis.
Une approche indpendante des facteurs matriels tait donc
ncessaire pour valuer l'efficacit des algorithmes. Donald Knuth fut un
des premiers l'appliquer systmatiquement ds les premiers volumes de
sa srie The Art of Computer Programming. Il compltait cette analyse de
considrations propres la thorie de l'information : celle-ci par exemple,
combine la formule de Stirling, montre que, dans le pire des cas, il n'est
pas possible d'effectuer, sur un ordinateur classique, un tri gnral (c'est-dire uniquement par comparaisons) de N lments en un temps
croissant avec N moins rapidement que N ln N.
Ils existent plusieurs approches pour analyser la complexit dun
algorithme. La plus classique est donc de calculer le temps de calcul dans

le pire des cas. Il existe galement au moins trois alternatives cette


dernire. La complexit en moyenne des algorithmes, partir d'une
rpartition probabiliste des tailles de donnes, tente d'valuer le temps
moyen que l'on peut attendre de l'valuation d'un algorithme sur une
donne d'une certaine taille. La complexit amortie des structures de
donnes consiste dterminer le cot de suites d'oprations. L'analyse
lisse d'algorithme, plus rcente, se veut plus proche des situations relles
en calculant la complexit dans le pire des cas sur des instances
lgrement bruites.
Dans notre rapport, nous allons analyser la complexit des
algorithmes de recherche laide dun arbre binaire comme cas particulier.
Pour mener termes cette analyse, nous allons suivre un plan bien prcis.
En premier lieu, nous allons entamer une tude thorique pour dfinir la
structure de donnes que nous allons tudier, dfinir chaque algorithme
de parcours et calculer thoriquement sa complexit. Notre tude de
complexit se focalisera sur une analyse de la complexit en temps dans
une approche du pire des cas. En second lieu et pour en finir, nous allons
essayer, dans une tude de cas pratique, de reprsenter la comparaison
entre les algorithmes de parcours. Cette comparaison va sappuyer sur
deux variables : le temps dexcution et le nombre de donnes en ente.

Chapitre I : Etude thorique


Dans ce chapitre, nous allons nous concentrer sur ltude thorique
de la problmatique qui est la comparaison entre les diffrents
algorithmes de parcours et recherche dans un arbre binaire. Mais avant
tout, il faudrait prsenter la structure de donnes que nous allons utiliser
qui est larbre binaire. Ensuite, nous allons prsenter un un chaque
algorithme de parcours qui se rpartissent sur deux types : les parcours en
profondeur et les parcours en largeur. Cette tude va se terminer par le
calcul thorique de la complexit en temps dans une approche du pire des
cas comme prcdemment nonc.

Structure de donnes
Dans notre tude la structure de donnes choisie a t larbre
binaire. Dans un premier lieu dfinissons quest-ce un arbre ? Puis, quest
ce qui le rend rajoute la facult de binarit. En thorie des graphes,
un arbre est un graphe non orient, acyclique et connexe. Sa forme
voque en effet la ramification des branches d'un arbre. Un ensemble
d'arbres est appel une fort.
Il existe plusieurs dfinitions quivalentes d'un arbre, en plus de
celle donne en introduction. Pour deux dfinitions bases sur la diffrence
entre le nombre d'artes et le nombre de sommets :

Un arbre est un graphe connexe non orient dont le nombre de


sommets excde le nombre d'artes d'une unit exactement.
Un arbre est un graphe non orient sans cycles dont le nombre de
sommets excde le nombre d'artes d'une unit exactement.

Pour une dfinition inductive : Un sommet est un arbre.


Si

est un arbre, alors

est un arbre avec :

tant un lment quelconque n'appartenant pas

et

un sommet

de
. Aucun autre graphe n'est un arbre. Si nous choisissons un
sommet r quelconque dans un arbre, il est possible d'enraciner l'arbre

en r, c'est--dire orienter toutes les artes de sorte qu'il existe un chemin


de r tous les autres nuds. Nous obtiendrons alors un arbre enracin.
En informatique, un arbre enracin est galement une structure de
donnes rcursive utilise pour reprsenter ce type de graphes. Nous
distinguons deux types de sommets dans un arbre :

Les feuilles (ou nuds externes) dont le degr est 1 donc ne


possdant pas de fils dans larbre.
Les nuds internes dont le degr est suprieur 1 donc possdant
des fils (sous-branches).

La racine de l'arbre, cit auparavant, est l'unique nud ne


possdant pas de parent. Les nuds (les pres avec leurs fils) sont relis
entre eux par une arte. Selon le contexte, un nud peut dsigner soit un
nud interne, soit un nud interne ou externe (feuille) de l'arbre. Nous
parlons galement de profondeur d'un nud qui est la distance, alors le
nombre d'artes, de la racine au nud ou mme la hauteur d'un arbre qui
est la plus grande profondeur d'une feuille de l'arbre. La taille d'un arbre
est son nombre de nuds (en comptant les feuilles ou non), la longueur
de cheminement est la somme des profondeurs de chacune des feuilles.
Les arbres peuvent tre tiquets. Dans ce cas, chaque nud
possde une tiquette, qui est en quelque sorte le contenu du nud.
L'tiquette peut tre trs simple : un nombre entier, par exemple. Elle peut
galement tre aussi complexe que l'on veut : un objet, une instance
d'une structure de donnes, un pointeur, etc. Il est presque toujours
obligatoire de pouvoir comparer les tiquettes selon une relation d'ordre
total, afin d'implanter les algorithmes sur les arbres.
Les arbres sont en fait rarement utiliss en tant que tels, mais de
nombreux types d'arbres avec une structure plus restrictive existent et
sont couramment utiliss en algorithmique, notamment pour grer
des bases de donnes, ou pour l'indexation de fichiers. Ils permettent alors
des recherches rapides et efficaces.
Nous vous en donnons ici le principal exemple qui est les arbres
binaires dont chaque nud a au plus deux fils au niveau infrieur
habituellement appels gauche et droit. Du point de vue de ces lments
fils, l'lment dont ils sont issus au niveau suprieur est appel pre.
Comme larbre binaire est galement enracin, au niveau le plus lev il y
a donc un nud racine. Au niveau directement infrieur, il y a au plus
deux nud
s fils. En continuant descendre aux niveaux infrieurs, on peut en
avoir quatre, puis huit, seize, etc. c'est--dire la suite des puissances de deux.
Les arbres binaires peuvent notamment tre utiliss en tant qu'arbre
binaire de recherche ou en tant que tas binaire.

Larbre binaire de recherche est un arbre binaire dans lequel chaque


nud possde une cl, telle que chaque nud du sous arbre gauche ait
une cl infrieure ou gale celle du nud considr, et que chaque
nud du sous arbre droit possde une cl suprieure ou gale celle-ci.
Tandis quun tas binaire vrifie deux contraintes quil soit en premier
un arbre binaire parfait et la deuxime quil soit un tas. Un arbre binaire
parfait est un arbre o tous les niveaux except le dernier doivent tre
totalement remplis et si le dernier n'est pas totalement rempli alors il doit
tre rempli de gauche droite. Un tas est un arbre o l'tiquette de
chaque nud doit tre suprieure ou gale (infrieure ou gale) aux
tiquettes de chacun de ses fils.

Algorithmes de parcours
Souvent, il est souhaitable de visiter chacun des nuds dans un
arbre et d'y examiner la valeur par exemple pour une impression ou pour
une recherche dun lment. Il existe plusieurs faons et ordres dans
lesquels les nuds peuvent tre visits, et chacun a des proprits utiles
qui sont exploites par les algorithmes bass sur les arbres binaires.

Parcours en profondeur
Avec ce parcours, nous tentons toujours de visiter le nud le plus
loign de la racine que nous pouvons, la condition qu'il soit le fils d'un
nud que nous avons dj visit. Les parcours prfixe , infixe et
postfixe sont des cas particuliers de ce type de parcours.
Pour effectuer ce parcours, il est ncessaire de conserver une liste
des lments en attente de traitement. Dans le cas du parcours en
profondeur, il faut que cette liste ait une structure de pile (de type
LIFO, Last In, First Out autrement dit : dernier entr, premier sorti ).
Dans cette implmentation, on choisira galement d'ajouter les fils d'un
nud de droite gauche.
ParcoursProfondeur(Arbre A) {
S = Pilevide
ajouter(Racine(A), S)
Tant que (S != Pilevide) {
nud = premier(S)
retirer(S)
Visiter(nud) //On choisit de faire une opration
Si (droite(nud) != null) Alors
ajouter(droite(nud), S)
Si (gauche(nud) != null) Alors
ajouter(gauche(nud), S)
}
}

Dans les trois algorithmes suivants (postfixe, infixe et prfixe), nous


allons nous contenter du pseudocode et le principe de son fonctionnement
puisquils sont des cas spciaux du parcours en profondeur.
Parcours postfixe
visiterPostfixe(Arbre A) :
Si nonVide(gauche(A))
visiterPostfixe(gauche(A))
Si nonVide(droite(A))
visiterPostfixe(droite(A))
visiter(A)

Dans un parcours postfixe ou suffixe, nous


affichons chaque nud aprs avoir affich
chacun de ses fils de gauche droite.
Parcours infixe
visiterInfixe(Arbre A) :
Si nonVide(gauche(A))
visiterInfixe(gauche(A))
visiter(A)
Si nonVide(droite(A))
visiterInfixe(droite(A))

Un parcours infixe, comme ci-dessus, visite chaque nud entre les


nuds de son sous arbre de gauche et les nuds de son sous arbre de
droite. C'est une manire assez commune de parcourir un arbre binaire de
recherche, car il donne les valeurs dans l'ordre croissant.
Parcours prfixe
visiterPrfixe(Arbre A) :
visiter(A)
Si nonVide(gauche(A))
visiterPrfixe(gauche(A))
Si nonVide(droite(A))
visiterPrfixe(droite(A))

Cet algorithme affiche les valeurs de l'arbre en ordre prfixe. Dans


cet ordre, chaque nud est visit ainsi que chacun de ses fils partant de
celui de gauche celui de droite.
Dans cet arbre binaire,

Rendu du parcours infixe : 4, 2, 7, 5, 8, 1, 3, 9, 6

Rendu du parcours postfixe : 4, 7, 8, 5, 2, 9, 6, 3, 1

Rendu du parcours prfixe : 1, 2, 4, 5, 7, 8, 3, 6, 9


Figure 1: Exemple d'arbre binaire avec des
nuds tiquets.

Parcours en largeur
Le parcours en largeur (ou BFS, pour Breadth First Search)
correspond un parcours par niveau de nuds de l'arbre. Un niveau est
un ensemble de nuds internes ou de feuilles situes la mme
profondeur on parle aussi de nud ou de feuille de mme hauteur dans
l'arbre considr. L'ordre de parcours d'un niveau donn est
habituellement confr, de manire rcursive, par l'ordre de parcours des
nuds parents nuds du niveau immdiatement suprieur.
partir d'un sommet S, le parcours en largeur liste d'abord les
voisins de S pour ensuite les explorer un par un. Ce mode de
fonctionnement utilise donc une file dans laquelle il prend le premier
sommet et place en dernier ses voisins non encore explors. Ainsi, si
l'arbre gauche est utilis, le parcours sera A, B, C, D, E, F puis G.
L'implmentation est quasiment identique celle du parcours en
profondeur ce dtail prs qu'on doit cette fois utiliser une structure
Figure 2: Dcoupage en
de file d'atten
te (de type FIFO, First in, first
niveau d'un arbre binaire.
out autremen
t dit premier entr, premier
sorti ), ce qui induit que l'ordre de sortie n'est pas le mme (i.e. on
permute gauche et droite dans notre traitement).

Maintenant, prsentons le pseudocode


reprsente cet algorithme.

qui

ParcoursLargeur(Arbre A) {
f = FileVide
enfiler(Racine(A), f)
Tant que (f != FileVide) {
nud = defiler(f)
Visiter(nud)
//On choisit de faire une opration telle un affichage ou un test
dgalit.
Si (gauche(nud) != null) Alors
enfiler(gauche(nud), f)

Si (droite(nud) != null) Alors


enfiler(droite(nud), f)
}
}

Complexit des algorithmes


La complexit d'un algorithme value son nombre d'oprations en
fonction de la taille de l'entre. D'une manire gnrale, elle nous donne
une ide sur les performances d'un algorithme et sur l'volution de ces
dernires en fonction de la taille de l'entre.
Notre sujet se concentre sur la recherche dans une liste de donnes
reprsente laide dun arbre binaire. En premier lieu, calculons la
complexit de la construction de cet arbre. Puisque la construction signifie
linsertion de toutes les donnes dans larbre, nous allons nous pencher
sur le calcul de complexit de lalgorithme dinsertion. Dans le meilleur
des cas et en moyenne, nous liminons une moiti darbre chaque
comparaison jusqu tomber sur un emplacement libre. Pour simplifier,
nous allons dire que l'arbre comporte autant de nuds que d'lments
insrer. Si nous liminons chaque itration la moiti des valeurs de
l'arbre l'algorithme d'insertion est donc en O (log(n)) alors il s'agit d'une
complexit logarithmique. Pour insrer chaque lment dans l'arbre, nous
avons donc logiquement du O (n*log(n)) ou une complexit quasi-linaire.
Dans le pire des cas, l'arbre est totalement balanc d'un ct et nous
obtiendrons une liste chane. Pour l'insertion, cela impose donc un
parcours de tous les lments et une complexit pour l'insertion en O(n).
La construction de l'arbre se fera donc en O (n) (une complexit
quadratique).
Avec un parcours en profondeur, nous visitons chaque lment de
l'arbre une et une seule fois. L'algorithme est dans les pires des cas en
complexit O(n) mais dans les meilleurs des cas, la complexit sera de
lordre O(1) si llment recherch se trouve dans la racine. Nous parlons
cette fois-ci d'une complexit linaire. Pour un parcours en largeur et en
considrant que les oprations sur la file s'effectuent en O(1) : O(n) o n
est le nombre de nuds de l'arbre.
Pour un algorithme de recherche dun lment dans un arbre, nous
pourrons nous baser sur ce qui a t dit sur les algorithmes de parcours.
L'ide serait de comparer l'lment cherch l'lment en cours. Encore
une fois, nous liminons, en moyenne et dans le meilleur des cas, la moiti
des valeurs. On a donc un algorithme en O (log(n)). Dans le pire des cas,
c'est comme pour l'insertion, on se retrouve avec du O(n).
Comme vous avez pu le constater, les arbres binaires sont des
arbres trs puissants, permettant un stockage ordonn et logique des

donnes. Cette structure permet l'application d'algorithme souvent en


complexit logarithmique (insertion, recherche, etc.).

Chapitre II : Etude pratique


Dans ce deuxime chapitre, nous allons passer la pratique cest-dire mettre en vedette les diffrents algorithmes noncs prcdemment

en utilisant la structure de donnes choisie qui est larbre binaire. Pour


cela nous allons dvelopper des programmes qui permettront de calculer
le temps dexcution de la recherche dune donne au sein dun groupe de
donnes pour chaque implmentation dun algorithme. Limplmentation a
t ralise en utilisant le langage C. Ainsi pour permettre ce calcul, nous
allons prsenter limplmentation de la structure de donnes, des
algorithmes mais aussi les techniques de calcul de temps dexcution et
daccs aux fichiers pour permettre la lecture automatique des valeurs de
donnes en paramtre.

Implmentation en langage C
Vu que nous avons besoin de calculer le temps dexcution de
chaque algorithme, nous avons besoin den implmenter en utilisant un
langage de programmation. Dans notre tude nous allons utiliser C comme
langage de programmation. Alors dans ce qui suivra, nous allons prsenter
en premier lieu les caractristiques du langage C, puis nous allons dfinir
la structure de donnes Arbre binaire- dans ce dernier et enfin nous
allons prsenter limplmentation de chaque algorithme de recherche.

Caractristiques du langage C
C est un langage de programmation impratif et gnraliste. Il
est qualifi de langage de bas niveau dans le sens o chaque instruction
du langage est conue pour tre compile en un nombre d'instructions
machine assez prvisible en termes d'occupation mmoire et de charge de
calcul. En outre, il propose un ventail de types entiers et flottants conus
pour pouvoir correspondre directement aux types de donne supports
par le processeur. Enfin, il fait un usage intensif des calculs d'adresse
mmoire avec la notion de pointeur.
Hormis les types de base, C supporte les types numrs, composs,
et opaques. Il ne propose en revanche aucune opration qui traite
directement des objets de plus haut niveau (fichier informatique, chane
de caractres, liste). Ces types plus volus doivent tre traits en
manipulant des pointeurs et des types composs
Ces caractristiques en font un langage privilgi quand on cherche
matriser les ressources matrielles utilises, le langage machine et les
donnes binaires gnres par les compilateurs tant relativement
prvisibles. Ce langage est donc extrmement utilis dans des domaines
o la rapidit de traitement est importante. Il constitue une bonne
alternative au langage d'assemblage dans ces domaines, avec les
avantages d'une syntaxe plus expressive et de la portabilit du code
source.
En contrepartie, la mise au point de programmes en C, surtout s'ils
utilisent des structures de donnes complexes, est plus difficile qu'avec
des langages de plus haut niveau. En effet, dans un souci de performance,
le langage C impose l'utilisateur de programmer certains traitements

(libration de la mmoire, vrification de la validit des indices sur les


tableaux) qui sont pris en charge automatiquement dans les langages de
haut niveau.
Dpouill des commodits apportes par sa bibliothque standard,
C est un langage simple, et son compilateur l'est galement.

Implmentation de la structure de donnes


Alors, nous avons parl dans le chapitre prcdent des arbres
comme notre structure de choix. Dans cette partie-l, nous allons
prsenter limplmentation en langage C. Un arbre binaire est compos
dune suite de nuds dont une racine qui na pas de pre. Un nud a au
plus deux fils : droit et gauche. Donc chaque nud devra prsenter un
membre de stockage de la valeur quil porte, dans notre cas un nud
porte une variable dentier. En plus, le nud devra avoir deux membres
qui indiquent les fils droit et gauche laide de pointeur pointant sur une
valeur de type nud.

typedef struct Noeud {


Element contenu;
struct Noeud *filsG;
struct Noeud *filsD;
}*Arbre;

Implmentation des algorithmes


Dans ce sous-titre, nous allons prsenter les implmentations de
chaque algorithme en langage C galement. Les algorithmes implments
sont le parcours en profondeur (avec les cas spciaux infixe, postfixe et
prfixe) et le parcours en largeur. Les algorithmes de parcours seront
utiliss pour rechercher un lment x dans un arbre a . La rponse
alors serait 0 sil ny as pas dlment gale x dans larbre a
et 1 sinon. Pour le cas dun parcours en largeur nous aurons besoin dune
file pour mmoriser lensemble des nuds de chaque niveau et ainsi que
de ses mthodes de gestion et de manipulation.
Parcours infixe
int ParcoursInfixe(Arbre a, int x) {
if (a != NULL) {
ParcoursInfixe(a->filsG);
if (a->contenu==x) return 1;
ParcoursInfixe(a->filsD);
}

return 0 ;
}
Parcours postfixe
int ParcoursPostfixe(Arbre a, int x) {
if (a != NULL) {
ParcoursPostfixe(a->filsG);
ParcoursPostfixe(a->filsD);
if (a->contenu==x) return 1;
}
return 0 ;
}
Parcours prfixe
int ParcoursPrefixe(Arbre a, int x) {
if (a != NULL) {
if (a->contenu==x) return 1;
ParcoursPrefixe(a->filsG);
ParcoursPrefixe(a->filsD);
}
return 0 ;
}
Parcours en largeur
int parcours_en_largeur(Arbre a,int x) {
Queue q;
Arbre g, d;
if (a !=NULL) {
q= init_queue();
enqueue(q, a);
do {
a = arbre(sortir(q));
if(a->contenu==x) return 1 ;
g = gauche(a);

d = droit(a);
if (g !=NULL) enqueue (f, g);
if (d ! =NULL) enqueue (f, d);
} while (!queue_empty(f));
}
return 0 ;
}

Techniques de calcul du temps dexcution


Puisque nous avons introduit dans les sous titres prcdents les
diffrents algorithmes de parcours pour pouvoir rechercher un lment
dans un arbre, nous allons maintenant, aprs bien sr avoir prsent
galement les implmentations de ces diffrents algorithmes, prsenter
les techniques de calcul du temps dexcution dun programme. La gestion
du temps en C passe par la bibliothque time.h . Cette
bibliothque offre la structure tm qui permet la manipulation du temps
selon une manire comprhensible suivant diffrents units et
informations (anne, mois, jour du mois, jour de la semaine, jour de
l'anne, heure, minute, seconde et si nous sommes en heure d't ou
d'hiver). En outre, elle offre la possibilit de situer son programme dans le
temps travers la fonction clock() .
Son prototype est : clock_t clock(void);
De son prototype, nous remarquons que cette fonction ne prend
donc aucun paramtre et renvoie un nombre sous un type : le clock_t .
Le type clock_t permet d'exprimer un nombre de clock ticks .
Le clock tick (ou battement en franais) est une unit de mesure du temps
interne de lordinateur. En fait, cette valeur dpend du systme
d'exploitation et du processeur utiliss. time.h possde une macro
permettant de savoir combien de clock ticks par seconde le systme gre.
Il s'agit de la macro CLOCKS_PER_SEC.
difftime() est une autre fonction utile que nous offre la bibliothque
time.h . Elle permet davoir la diffrence entre deux moments. Cette
fonction accepte deux paramtres de type time_t qui est une structure
reprsentant le nombre de secondes couls depuis le 1er janvier 1970.
Son prototype est : double difftime (time_t arrivee, time_t depart) ;

Accs aux fichiers


Pour comparer le temps dexcution des diffrents algorithmes il
faudrait les appliquer un nombre de donnes assez lev. Pour cela,
nous avons pens utiliser la lecture depuis des fichiers pour automatiser
la saisie des donnes en paramtre. Ainsi, dans cette partie-l nous allons

prsenter les diffrentes possibilits de manipulation de fichiers travers


le langage C.
Pour lire et crire dans des fichiers, nous allons nous servir de
fonctions situes dans la bibliothque stdio qui est couramment
utilise. La procdure de manipulation dun fichier en langage C se rsume
en quatre tapes.
1. Nous appelons la fonction d'ouverture de fichier fopen qui nous
renvoie un pointeur sur le fichier.
2. Nous vrifions si l'ouverture a russi (c'est--dire si le fichier existait)
en testant la valeur du pointeur que nous avons reu. Si le pointeur
vaut NULL, c'est que l'ouverture du fichier n'a pas fonctionn
3. Si l'ouverture a fonctionn (si le pointeur est diffrent
de NULL donc), alors nous pouvons lire ou bien crire dans le
fichier travers des fonctions que nous verrons aprs.
4. Une fois que nous avons termin de travailler sur le fichier, il faut
penser le fermer avec la fonction fclose .
Fonction fopen
Cette fonction attend deux paramtres : le nom du fichier ouvrir et
le mode d'ouverture du fichier. Bien sr, nous allons ouvrir le fichier pour
consultation de son contenu, donc pour un mode de lecture seule w .
FILE* fopen(const char* nomDuFichier, const char* modeOuverture);
Fonction fclose
Une fois que nous avons fini de travailler avec le fichier, il faudra le
fermer . Nous utilisons pour cela la fonction fclose qui a pour rle de
librer la mmoire, c'est--dire supprimer le fichier charg dans la
mmoire vive. Cette fonction renvoie un entier qui indique si la fermeture
sest bien passe.
int fclose(FILE* pointeurSurFichier);
Fonction fscanf
Pour lire une ligne du fichier, nous utilisons la fonction fscanf qui
permet de lire cette ligne selon un format prcis et la stocker dans une
variable.
int fscanf(const
variable);

char*

nomDuFichier,

char*

formatDeLecture,

char*

Comparaison des temps dexcution


Maintenant que nous avons dfini limplmentation de la structure
de donnes qui est larbre binaire et les diffrentes implmentations des
algorithmes de parcours en profondeur et en largeur en langage C, nous
allons passer au calcul des temps dexcution selon le nombre de donnes
dentre.

Tableau 1 : Comparation du temps d'execution des algorithmes de recherche.

Algorithme

Parcours
Infixe

Nombre
donnes
entre
10
100
500
1000
2500
5000
7500
10000

Parcours
Postfixe

10
100
500
1000
2500
5000
7500

de Position
en
Au dbut
Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut

Temps
dexcution en
secondes
0.02217
0.01208
0.01749
0.02468
0.01744
0.03696
0.02492
0.04902
0.06338
0.02322
0.07145
0.1308
0.04087
0.1567
0.3069
0.1316
0.319
0.6789
0.2727
0.552
1.073
0.4377
0.9759
1.609
0.5856
0.6083
0.5536
0.5404
0.5699
0.5874
0.5707
0.5957
0.6124
0.6287
0.6458
0.6608
0.7775
0.603
0.7659
1.045
0.848
1.071
1.418

10000
Parcours
Prfixe

10
100
500
1000
2500
5000
7500
10000

Parcours
Largeur

en 10
100
500
1000
2500
5000
7500

Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut
Au milieu
A la fin
Au dbut

1.227
1.409
1.683
1.532
1.697
0.544
0.5358
0.4026
0.5517
0.5588
0.3978
0.698
0.5925
0.4368
0.5626
0.6438
0.485
0.7421
0.6797
0.6148
0.6505
0.8595
1.027
0.7728
1.116
1.48
1.005
1.397
1.683
0.5347
0.4063
1.367
0.4137
0.443
1.418
0.4716
0.5009
1.407
0.4189
0.5154
1.44
0.4652
0.5389
1.565
0.5251
0.7489
1.83
0.6497

10000

Au milieu
A la fin
Au dbut
Au milieu
A la fin

1.01
1.467
0.817
1.293
1.562

Dans le diagramme suivant, nous avons ralis une comparaison


entre les diffrents algorithmes de recherche par rapport la complexit
thorique n*log(n) en fonction des nombres de donnes en entre. Puisque
la complexit en temps de chaque algorithme retourne le nombre
doprations et la reprsentation des temps dexcution sont exprims en
secondes, il fallait convertir le nombre doprations en secondes. Pour
cela, nous allons reprsenter la fonction n*log(n)/100000.
Justifions cette division par cent milles. Alors, nous avons utilis les
mthodes de situation du programme par rapport au temps pour collecter
les temps dexcution de chaque implmentation dalgorithme selon
diffrents cas : meilleur, moyen et pire des cas. Ces temps dexcution
concernaient le CPU Time et non le User Time . La diffrence entre
ces deux temps dexcution rside que dans le cas o un programme ne
fonctionne pas seul sur une machine, le temps dexcution utilisateur ne
refltera pas ainsi le temps quas pris le systme pour raliser seul le
programme dsir mais aussi les autres programmes en cours. Au
contraire, le temps dexcution processeur reprsente le temps pass par
un programme sur le processeur. Ce temps est une constante : il ne
dpend pas de la charge de travail dune machine.
Le temps dexcution processeur est exprim en jiffy ou coups
dhorloge
et
pour
les
deux
architectures
principales
des
processeurs (RISC et CISC) le nombre d'instructions ncessaires une
opration varie pour chacune d'entre elle. Un processeur CISC excute la
plupart des instructions lmentaires (addition, multiplication, tests, etc..)
en un coup d'horloge alors qu'il faut gnralement quatre coups d'horloge
un processeur RISC pour obtenir le mme rsultat. Enfin, soit le nombre
ncessaire doprations pour rsoudre un algorithme N pour convertir N en
secondes, il faudrait connaitre le temps dexcution lmentaire dune
opration par le processeur. Nous pouvons dduire ce temps lmentaire
depuis la capacit de traitement dun processeur exprim selon deux
units de mesure : le million d'instructions par seconde MIPS et les
oprations virgule flottante par seconde FLOPS dans le cas o ces
oprations impliquent des nombres rels. Pour en finir, un processeur qui a
une capacit de cent milles FLOPS excute cent milles oprations par
seconde. Donc, une complexit quasi-linaire O (n*log(n)) doit tre divise
par cent milles pour connaitre son temps dexcution -en pratique-, par un
processeur qui a cette capacit, en secondes.

2
1.8
1.6
1.4
1.2
Temps dexcution en secondes
p.infixe

p.postfixe

1
0.8p.prefixe

p.largeur

n*log(n)/100000

0.6
0.4
0.2
0
10

100

500

1000 2500 5000 7500 10000

Nombre de donnes en entre

Figure 3: Diagramme comparatif du temps d'execution des algorithmes.

Nous remarquons dans le diagramme en dessus que la courbe de la


fonction qui reprsente le parcours infixe suit peu prs le mme
comportement que la courbe de la fonction n*log(n)/100000. Alors que les
autres courbes qui reprsentent les parcours restants savoir parcours
en largeur, parcours postfixe et parcours prfixe- sont plus loignes de
cette dernire.
Donc lissue de cette tude pratique, nous remarquons que le
parcours le plus adquat dans la recherche dun lment dans un arbre
binaire est le parcours infixe puisquil prsenteplus que les autres
algorithmes- un temps dexcution proche du nombre doprations divis
par cent milles.

Conclusion

Notre rapport touche sa fin. Nous avons essay de prsenter une


tude comparative entre les implmentations des diffrents parcours dans
un arbre binaire. Ces parcours se divisent en deux types : parcours en

largeur et parcours en profondeur. Nous avons ainsi suivi un itinraire


assez prcis.
En premier lieu, nous avons effectu une tude thorique. Cette
tude a comport une prsentation de la structure de donnes qui a t
larbre binaire de faon rigoureuse et les diverses notions quil offre.
Ensuite, une prsentation un un des diffrents algorithmes de parcours
de cette structure en pseudocode et de leur comportement. Les
algorithmes prsents dans cette tude taient les trois cas spciaux du
parcours en profondeur (infixe, postfixe et prfixe) et le parcours en
largeur.
En second lieu, nous avons entam une tude pratique en
prsentant les diffrentes implmentations de larbre binaire et ses
algorithmes de parcours permettant la recherche dun lment. Ensuite,
nous nous sommes penchs vers lexcution de ces implmentations
suivant diffrentes approches. Ces approches reprsentaient les cas o on
calculait le temps dexcution : meilleur cas possible, cas moyen et pire
des cas. Le calcul du temps dexcution variait aussi suivant la taille
dentre ou plutt le nombre de nuds de larbre donn en paramtre.
Puis nous avons donn une comparaison entre les temps dexcution des
algorithmes travers un diagramme qui met en vedette lvolution de ce
temps par rapport la taille dentre.
A la fin de ce rapport, nous tenons appuyer la puissance des arbres
par rapport aux listes chanes puisquils permettent un parcours plus
rapide de la racine jusqu une feuille donne. Comme nous avons pu
constater, les arbres binaires sont des structures trs puissantes,
permettant un stockage ordonn et logique des donnes. Elles permettent
l'application d'algorithmes souvent en complexit logarithmique (tels les
parcours). Il existe plusieurs types darbres qui permettent des
manipulations plus volues et complexes tels les arbres AVL et les
arbres rouge-noir.

Rfrences
Articles de Wikipedia.org (consults le 17/02/2015) :

http://fr.wikipedia.org/wiki/Arbre_enracin%C3%A9
http://fr.wikipedia.org/wiki/Algorithme_de_parcours_en_largeur
http://fr.wikipedia.org/wiki/Algorithme_de_parcours_en_profondeur
http://fr.wikipedia.org/wiki/Arbre_binaire
http://fr.wikipedia.org/wiki/Arbre_(graphe)
http://fr.wikipedia.org/wiki/Complexit%C3%A9_en_temps
http://fr.wikipedia.org/wiki/Analyse_de_la_complexit
%C3%A9_des_algorithmes
http://fr.wikipedia.org/wiki/Complexit
%C3%A9_en_moyenne_des_algorithmes
http://fr.wikipedia.org/wiki/Th%C3%A9orie_de_la_complexit
%C3%A9_(informatique_th%C3%A9orique)
http://en.wikipedia.org/wiki/C_date_and_time_functions
http://fr.wikipedia.org/wiki/Time.h
http://en.wikipedia.org/wiki/CPU_time
http://fr.wikiversity.org/wiki/Fonctions_de_base_en_langage_C/time.h

Cours depuis Openclassrooms.com :

Consult le 16 /02/2015 : http://openclassrooms.com/courses/time-het-ses-fonctions


Consult
le
17/02/2015
:
http://openclassrooms.com/courses/algorithmique-pour-l-apprentiprogrammeur/arbres
Consult
le
4/02/2015 :
http://openclassrooms.com/courses/apprenez-a-programmer-enc/lire-et-ecrire-dans-des-fichiers

Cours depuis Developpez.com :

Consult le 17/02/2015 : http://algo.developpez.com/sources/?


page=tree
Consult le 17/02/2015 : http://algo.developpez.com/sources/?
page=graphe
Consult le 16/02/2015 : http://chgi.developpez.com/arbre/binaire/

Complexit des algorithmes consult le 17/02/2015 depuis Laboratoire


d'informatique
de
Paris
Nord :
http://lipn.univparis13.fr/~banderier/P13/Algo/cours_complexite.pdf
C. Prodhon, P. Lacomme et R. Libo. Comment mesurer les temps de calcul
de vos programmes ? consult le 16/02/2015 depuis Institut Suprieur
dInformatique,
de
Modlisation
et
de
leurs
Application:
http://www.isima.fr/~lacomme/temps/Temps_de_calcul.pdf

L. Blin. Institut Suprieur dInformatique, de Modlisation et de leurs


Applications
consult
le
17/02/2015 :
http://wwwnpa.lip6.fr/~blin/Enseignement_files/INAL/INAL_5.pdf