Sunteți pe pagina 1din 13

17/03/2017 ArbresAlgorithmiquepourl'apprentiprogrammeur

Bienvenue sur OpenClassrooms ! En poursuivant votre navigation, vous acceptez l'utilisation de cookies. En savoir OK
plus

S'inscrire Se connecter

Accueil Cours Algorithmique pour l'apprenti programmeur Arbres

Algorithmique pour l'apprenti programmeur


Licence

Facile

Arbres

Connectez-vous ou inscrivez-vous pour bnficier de toutes les fonctionnalits de ce cours !

Les structures de donnes que nous avons vu jusqu'ici (tableaux, listes, piles, files) sont linaires, dans le sens o
elles stockents les lments les uns la suite des autres : on peut les reprsenter comme des lments placs sur
une ligne, ou des oiseaux sur un fil lectrique.

Au bout d'un moment, les oiseaux se lassent de leur fil lectrique : chaque oiseau a deux voisins, et c'est assez
ennuyeux, pas pratique pour discuter. Ils peuvent s'envoler vers des structures plus complexes, commencer par
les arbres.

Dfinition

Un arbre est une structure constitue de noeuds, qui peuvent avoir des enfants (qui sont d'autres noeuds). Sur
l'exemple, le noeud B a pour enfant les noeuds D et E, et est lui-mme l'enfant du noeud A.

https://openclassrooms.com/courses/algorithmiquepourlapprentiprogrammeur/arbres 1/13
17/03/2017 ArbresAlgorithmiquepourl'apprentiprogrammeur

Deux types de noeuds ont un statut particulier : les noeuds qui n'ont aucun enfant, qu'on appelle des feuilles, et un
noeud qui n'est l'enfant d'aucun autre noeud, qu'on appelle la racine. Il n'y a forcment qu'une seule racine, sinon
cela ferait plusieurs arbres disjoints. Sur l'exemple, A est la racine et D, E, G, H, I sont les feuilles.

Bien sr, on ne s'intresse en gnral pas seulement la structure de l'arbre (quelle est la racine, o sont les
feuilles, combien tel noeud a d'enfants, etc.), mais on veut en gnral y stocker des informations. On considrera
donc des arbres dont chaque noeud contient une valeur (par exemple un entier, ou tout autre valeur reprsentable
par votre langage de programmation prfr).

Comme pour les listes, on peut dfinir les arbres rcursivement : "un arbre est constitu d'une valeur et d'une liste
d'arbre (ses enfants)". Vous pouvez remarquer qu'avec cette description, le concept d'"arbre vide" n'existe pas :
chaque arbre contient au moins une valeur. C'est un dtail, et vous pouvez choisir une autre reprsentation
permettant les arbres vides, de toute manire ce ne sont pas les plus intressants pour stocker de l'information

Exercice : essayer de reprsenter l'arbre donn en exemple dans le langage de votre choix. Vous aurez peut-tre
besoin de dfinir une structure ou un type pour les arbres.

Solutions :
Solution en C :
c
1 #include<stdlib.h>
2
3 typedefstructarbreArbre;
4 typedefstructlistList;
5
6 structarbre
7 {
8 intval;
9 List*enfants;

https://openclassrooms.com/courses/algorithmiquepourlapprentiprogrammeur/arbres 2/13
17/03/2017 ArbresAlgorithmiquepourl'apprentiprogrammeur
10 };
11
12 structlist
13 {
14 Arbre*node;
15 List*next;
16 };
17
18 List*cons(Arbre*arbre,List*liste)
19 {
20 List*elem;
21 if((elem=malloc(sizeof*elem))==NULL)
22 returnNULL;
23 elem>node=arbre;
24 elem>next=liste;
25 returnelem;
26 }
27
28 intmain(void)
29 {
30 ArbreG={'G',NULL},H={'H',NULL},I={'I',NULL};
31 ArbreF={'F',cons(&G,cons(&H,cons(&I,NULL)))};
32 ArbreD={'D',NULL},E={'E',NULL};
33 ArbreC={'C',cons(&F,NULL)};
34 ArbreB={'B',cons(&D,cons(&E,NULL))};
35 ArbreA={'A',cons(&B,cons(&C,NULL))};
36 return0;
37 }
38

L'utilisation de la liste n'est pas trs pratique ici : les cons allouent de la mmoire, qu'il faudrait librer ensuite.

Pour simplifier la situation (les listes chanes ne sont pas trs agrables manipuler), les programmeurs C
utilisent en gnral une reprsentation dirente. Au lieu de donner chaque noeud la liste de ses enfants, on lie
les enfants entre eux : chaque enfant a un lien vers son frre, et un noeud a donc juste un lien vers le premier de ses
fils. Pour parcourir les autres, il suit ensuite de passer de frre en frre.
c
1 typedefstructarbreArbre;
2 structarbre
3 {
4 intval;
5 Arbre*frere;
6 Arbre*enfant;
7 };
8
9 intmain(void)
10 {
11 ArbreI={'I',NULL,NULL};
12 ArbreH={'H',&I,NULL};
13 ArbreG={'G',&H,NULL};
14 ArbreF={'F',NULL,&G};
15 ArbreE={'E',NULL,NULL};
16 ArbreD={'D',&E,NULL};
17 ArbreC={'C',NULL,&F};
18 ArbreB={'B',&C,&D};
19 ArbreA={'A',NULL,&B};
20 return0;
21 }
22

C'est une manire d'intgrer la liste chaine au sein des noeuds de l'arbre qui la rend plus facile manipuler en C.
Solution en Caml :
ocaml
1 type'aarbre=Arbreof'a*'aarbrelist
2
3 letexemple=
4 letfeuillelettre=Arbre(lettre,[])in
5 Arbre("A",
6 [Arbre("B",[feuille"D";feuille"E"]);
7 Arbre("C",[Arbre("F",[feuille"G";feuille"H";feuille"I"])])])
https://openclassrooms.com/courses/algorithmiquepourlapprentiprogrammeur/arbres 3/13
17/03/2017 ArbresAlgorithmiquepourl'apprentiprogrammeur
8

Solution en PHP :
html+php
1 <?php
2 functionarbre($val,$enfants)
3 {
4 returnarray('val'=>$val,'enfants'=>$enfants);
5 }
6
7 $arbre=
8 arbre('A',array(
9 arbre('B',array(
10 arbre('D',array()),
11 arbre('E',array()))),
12 arbre('C',array(
13 arbre('F',array(
14 arbre('G',array()),
15 arbre('H',array()),
16 arbre('I',array())))))));
17 ?>
18

Vous pouvez remarquer qu'on a choisi ici d'utiliser un tableau pour stocker les enfants. Dans ce chapitre, nous
manipulerons les arbres comme des structures statiques, sans ajouter ou enlever d'enfants un noeud particulier,
donc a ne sera pas un problme.

Solution en Java :
java
1 classTree<T>{
2 Tval;
3 Tree<T>[]enfants;
4
5 Tree(Tval){
6 this.val=val;
7 this.enfants=newTree[0];
8 }
9
10 Tree(Tval,Tree<T>[]enfants){
11 this.val=val;
12 this.enfants=enfants;
13 }
14
15 publicstaticvoidmain(String[]args){
16 Treed=newTree('D');
17 Treee=newTree('E');
18 Treeg=newTree('G');
19 Treeh=newTree('H');
20 Treei=newTree('I');
21
22 Tree[]enfants_de_f={g,h,i};
23 Treef=newTree('F',enfants_de_f);
24
25 Tree[]enfants_de_b={d,e};
26 Treeb=newTree('B',enfants_de_b);
27
28 Tree[]enfants_de_c={f};
29 Treec=newTree('C',enfants_de_c);
30
31 Tree[]enfants_de_a={b,c};
32 Treea=newTree('A',enfants_de_a);
33
34 System.out.println(a.taille());
35 }
36 }
37

Vous pouvez remarquer qu'on a choisi ici d'utiliser un tableau pour stocker les enfants. Dans ce chapitre, nous
manipulerons les arbres comme des structures statiques, sans ajouter ou enlever d'enfants un noeud particulier,

https://openclassrooms.com/courses/algorithmiquepourlapprentiprogrammeur/arbres 4/13
17/03/2017 ArbresAlgorithmiquepourl'apprentiprogrammeur

donc a ne sera pas un problme.

Remarque : on utilise trs souvent en informatique des arbres comportant des restrictions supplmentaires :
nombre d'enfants, lien entre les enfants et les parents, etc. En particulier les arbres binaires, o chaque noeud a
deux enfants au plus, sont trs courants. Pour faire la dirence on parle parfois d'arbres n-aires pour les arbres
gnraux que je prsente ici, mais le nom n'est pas trs bon et je prfre garder "arbre".

Quelques algorithmes sur les arbres


Pour s'habituer cette nouvelle structure, on va essayer de formuler quelques algorithmes rpondant des
questions simples que l'on peut se poser sur des arbres.

Taille

On cherche savoir combien un arbre contient de noeuds. Le raisonnement est trs simple : un arbre, c'est un
noeud et la liste de ses fils, donc sa taille est un (le noeud), plus la taille des arbre partant de chaque fils :

taille(arbre)=
1+lasommedelatailledesfils

Voici quelques implmentations de cette fonction dans dirents langages. N'hsitez pas essayer de la coder
vous-mme avant de regarder une solution !

C:
c
1 inttaille(Arbre*noeud)
2 {
3 List*enfants;
4 intcompteur=1;
5 for(enfants=noeud>enfants;enfants!=NULL;enfants=enfants>next)
6 compteur+=taille(enfants>node);
7 returncompteur;
8 }
9

Ou bien, avec les liens frre-frre :


c
1 inttaille(Arbre*noeud)
2 {
3 Arbre*enfant;
4 intcompteur=1;
5 for(enfant=noeud>enfant;enfant!=NULL;enfant=enfant>frere)
6 compteur+=taille(enfant);
7 returncompteur;
8 }
9

OCaml : ocaml
https://openclassrooms.com/courses/algorithmiquepourlapprentiprogrammeur/arbres 5/13
17/03/2017 ArbresAlgorithmiquepourl'apprentiprogrammeur

1 letrectaille(Arbre(_,enfants))=
2 List.fold_left(+)1(List.maptailleenfants)
3

PHP :
html+php
1 <?php
2 functiontaille($arbre)
3 {
4 $count=1;
5 foreach($arbre['enfants']as$enfant)
6 $count+=taille($enfant);
7 return$count;
8 }?>
9

Java :
Mthode rajouter la classe Tree
java
1 publicinttaille(){
2 intcompteur=1;
3 for(Tree<?>enfant:enfants)
4 compteur+=enfant.taille();
5 returncompteur;
6 }
7

Hauteur

On voudrait maintenant connatre la hauteur de l'arbre. La hauteur d'une arbre est la plus grande distance qui
spare un noeud de la racine. La distance d'un noeud la racine (la hauteur de ce noeud) est le nombre de noeuds
sur le chemin entre les deux.

On a l'algorithme suivant :

hauteur(arbre)=
1+laplusgrandedeshauteursdesfils(ou0s'iln'yenapas)

Remarque : avec cette dfinition, la hauteur d'un arbre un seul lment (juste la racine) est 1; cela ne colle pas
vraiment notre dfinition de "distance entre le noeud et la racine", puisque la distance de la racine la racine est
logiquement 0. C'est un dtail de la dfinition qui peut changer selon les gens, et qui n'est pas vraiment important
de toute faon : on ne fait pas dans la dentelle.

Remarque : on parle parfois de profondeur plutt que de hauteur : cela dpend de si vous imaginez les arbres avec
la racine en haut et les feuilles en bas, ou (ce qui est plus courant dans la nature) la racine en bas et les branches
vers le haut.

Liste des lments

Une dernire question se poser est "quels sont les lments prsents dans mon arbre ?". Si vous tes tombs
amoureux des listes et des tableaux, vous aimeriez peut-tre avoir accs ces lments sous forme de liste ou de
tableau. Un tableau ne serait pas trs pratique ici, parce qu'il faudrait commencer par calculer la taille de l'arbre; je
vais plutt vous demander d'crire ici l'algorithme pour obtenir la liste des lments d'un arbre.

Indice : Vous pouvez utiliser deux fonctions sur les listes :

reunir_listes(LL) , qui prend une liste de listes et forme une seule liste, la runion de toutes les petites
listes. Par exemple reunir_listes([[1;3];[];[2];[5;1;6]])=[1;3;2;5;1;6] . Pour coder

https://openclassrooms.com/courses/algorithmiquepourlapprentiprogrammeur/arbres 6/13
17/03/2017 ArbresAlgorithmiquepourl'apprentiprogrammeur

reunir_liste , la fonction concat(L1,L2) du chapitre prcdent, qui met deux listes bout bout, vous sera
utile.
si votre langage le permet, une autre fonction trs utile est map(F,L) , qui applique la fonction F tous
les lments de la liste L et renvoie la liste rsultat; par exemple map(ajoute_1,[1;5])=[2;6] . Sinon,
si votre langage ne permet pas de passer des fonctions en argument d'une autre fonction, ou si vous ne
savez pas le faire, vous n'aurez qu' le faire la main.

Remarque : Il existe plusieurs manires de construire la liste des lments de l'arbre, et on peut obtenir plusieurs
listes direntes, avec les mmes lments mais placs dans un ordre dirent.

Correction : Voici un schma d'algorithme :

liste_elements(arbre)=
soitelements_enfants=map(liste_elements,enfants)
renvoyercons(element,reunir_listes(elements_enfants))

Parcours en profondeur


Les trois algorithmes prcdents visitent l'arbre : ils rpondent en interrogeant chaque noeud, un par un. Ils ont un
point commun, l'ordre dans lequel ils visitent les noeuds de l'arbre est le mme chaque fois. Cet ordre
correspond une mthode de parcours de l'arbre qu'on appelle le parcours en profondeur; pour chaque noeud :

on fait quelque chose avec (demander sa valeur, par exemple)


on parcourt chacun de ses enfants, rcursivement
on fait quelque chose pour runir les rsultats aprs le parcours (somme, maximum, reunir_listes )

Pourquoi parle-t-on de parcours en profondeur ? Cela vient de l'ordre dans lequel sont parcourus les noeuds.
Imaginons un de ces parcours sur l'arbre ci-dessous : on l'appelle sur la racine, A, qui lance le parcours sur chacun
de ses enfants, en commenant par B (on suppose que l'ordre des enfants dans la liste est l'ordre de gauche
droite sur le dessin). Pour fournir un rsultat, B doit interroger ses propres enfants, donc il commence par lancer le
parcours sur son premier fils, D. Ainsi, on voit que le parcours va "en profondeur" en commenant par descendre
dans l'arbre le plus possible.

Pour visualiser tout le parcours, on peut numroter les noeuds dans l'ordre dans lequel ils sont parcourus :

https://openclassrooms.com/courses/algorithmiquepourlapprentiprogrammeur/arbres 7/13
17/03/2017 ArbresAlgorithmiquepourl'apprentiprogrammeur

Parcours en largeur


La mthode de parcours en profondeur est simple, mais l'ordre dans lequel les noeuds sont parcourus n'est pas
forcment trs intuitif. En faisait un peu attention (par exemple en essayant de suivre le parcours du doigt), vous
serez capable de vous y habituer, mais on pourrait esprer faire quelque chose qui paraisse plus "naturel" un
humain. Et si, par exemple, on voulait parcourir notre arbre dans l'ordre alphabtique : A, B, C, D, E.. ?

Si cet ordre vous parat "logique", c'est parce que j'ai nomm mes sommets par "couche" : on commence par la
racine (A), puis on donne un nom tous les noeuds de "premire gnration" (les enfants de la racine) B et C, puis
tous les noeuds de "deuxime gnration" (les enfants des enfants de la racine), etc.

Remarque : l'algorithme de parcours en largeur est un peu plus compliqu que les algorithmes que j'ai prsent
jusqu'ici. Si vous avez des diicults comprendre ce qui suit, c'est normal. Essayez de bien faire les exercices, de
bien relire les parties qui vous posent problme, et n'hsitez pas aller demander sur les forums d'aide si vous
pensez avoir un vrai problme de comprhension. Vous y arriverez, c'est ce qui compte.

En mettant des couches

Je cherche maintenant un algorithme qui permet de parcourir les noeuds "par couche" de la mme manire. On
appelle a le parcours en largeur : on parcourt couche par couche, et dans chaque couche on parcourt toute la
"largeur" de l'arbre.

https://openclassrooms.com/courses/algorithmiquepourlapprentiprogrammeur/arbres 8/13
17/03/2017 ArbresAlgorithmiquepourl'apprentiprogrammeur

On va partir de l'ide suivante : pour parcourir l'arbre "par couche", il faut essayer de stocker les noeuds dans des
couches. Plus prcisment, on va maintenir pendant le parcours deux couches : la "couche courante", qui contient
les noeuds que l'on est en train de parcourir, et la "couche des enfants", o on met les enfants de la couche
courante.

Un peu plus prcisment, on a l'algorithme suivant :

au dpart, on met la racine dans la couche courante, on prend une liste vide pour la couche des enfants
ensuite, on parcours les noeuds de la couche courante, en ajoutant leurs enfants dans la couche des enfants

quand on a termin le parcours, on change les couches : on prend la couche des enfants comme
nouvelle couche courante, et on recommence le parcours.

Quand, la fin du parcours de la couche courante, on obtient une couche des enfants vide, l'algorithme s'arrte.
En eet, s'il n'y a pas d'enfants dans la couche des enfants, cela veut dire qu'aucun des noeuds de la couche qui
vient d'tre parcourue n'avaient d'enfants : ce n'tait que des feuilles, donc on est arriv la fin de l'arbre (dans
notre exemple la couche G, H, I).

Remarque : j'ai parl d'utiliser des "listes" pour reprsenter les couches. En ralit, on n'utilise vraiment que deux
oprations : ajouter un noeud dans une couche, retirer un noeud de la couche (pour le parcours). Les files et les
piles sont donc des structures adaptes pour ces oprations (si vous utilisez une simple liste, a se comportera
comme une pile). Le choix d'une file ou d'une pile va changer l'ordre dans lequel les sommets sont parcourus, mais
la proprit du parcours en largeur est videmment conserve dans les deux cas : les noeuds prs de la racine sont
toujours parcourus avant les noeuds plus loin de la racine, et c'est ce qui est important ici.

Exercice : mettre en place l'algorithme avec le noeud donn en exemple (mettre la lettre 'A' comme valeur du
noeud A, et ainsi de suite) : parcourir l'arbre en largeur, en aichant la valeur de chaque noeud rencontr. Essayer
avec des files et des piles pour reprsenter les couches : quelle est la dirence ? Vrifier que l'ordre des couches
est toujours respect.

Avec une file

https://openclassrooms.com/courses/algorithmiquepourlapprentiprogrammeur/arbres 9/13
17/03/2017 ArbresAlgorithmiquepourl'apprentiprogrammeur

Avec notre algorithme, on stocke les noeuds dans deux structures spares : les noeuds appartenant la couche
courante, que l'on va bientt parcourir, et les noeuds de la couche des enfants, que l'on va parcourir plus tard. Est-
il possible de conserver ce sens de parcours, en utilisant une seule structure au lieu de deux ?

On peut obtenir une rponse cette question en considrant les deux structures comme une seule : on considre
qu'un noeud "entre" dans nos structures quand on l'ajoute la couche des enfants, et qu'il en "sort" quand on le
prend dans la couche courante pour le parcourir. Pour que notre parcours soit correct, il faut que l'ordre des
couches soit respect : un noeud d'une couche doit entrer avant les noeuds de la couche suivante, et sortir avant
tous les noeuds de la couche suivante. Cela correspond donc une forme de premier entr, premier sorti :
premire couche entre, premire couche sortie.

a ne vous rappelle pas quelque chose ? Normalement, si : premier entr, premier sorti, c'est le comportement des
files. On peut donc utiliser une file pour stocker les noeuds, car l'ordre de la file respectera l'ordre des couches.

On obtient donc l'algorithme suivant :

au dpart, on commence avec une file vide, dans laquelle on ajoute la racine
tant que la file n'est pas vide, on enlve le premier noeud de la file, on le parcourt et on ajoute tous ses
enfants dans la file.

Exercice : implmenter cet algorithme de parcours, et vrifier que la proprit de parcours en largeur est bien
respecte.

Comparaison des mthodes de parcours


Remarque : les programmeurs utilisent souvent la terminologie anglosaxonne pour dcrire ces parcours : on parle
de DFS (Depth First Search, parcours en profondeur d'abord) et de BFS (Breadth first search, parcours en largeur
d'abord).

Une symtrie assez surprenante

Vous avez srement remarqu que les files et les piles sont des structures trs proches, qui proposent le mme
genre d'oprations (ajouter et enlever des lments). Il est donc naturel de se demander : que se passe-t-il quand,
dans l'algorithme de parcours en largeur avec une file, on remplace la file par une pile ?

On passe alors d'un rgime premier entr, premier sorti un rgime dernier entr, premier sorti. Imaginez qu'on
vient de parcourir un noeud : on a ajout tous ses enfants la pile, et maintenant on passe au noeud suivant
parcourir. Quel est le noeud suivant qui sera pris ? C'est le dernier noeud entr sur la pile, donc un des enfants du
noeud prcdent.
On se retrouve avec un parcours o, quand on a parcouru un noeud, on parcourt ensuite ses enfants. a ne vous
rappelle rien ? Si (ou alors vous n'avez pas t asssez attentif) : c'est le parcours en profondeur !

On peut donc implmenter le parcours en profondeur exactement comme le parcours en largeur, en remplaant la
file par une pile. Cela montre que les deux parcours sont trs proches, et qu'il y a des liens trs forts entre les
algorithmes et les structures de donnes.

Choix de l'implmentation

Nous avons donc vu deux implmentations de chaque parcours : le parcours en profondeur rcursif, le parcours en
largeur avec deux couches, le parcours en largeur avec une file et le parcours en profondeur avec une pile. En
gnral, on choisit les algorithmes les plus pratiques : quand on veut faire un parcours en profondeur, on utilise la
https://openclassrooms.com/courses/algorithmiquepourlapprentiprogrammeur/arbres 10/13
17/03/2017 ArbresAlgorithmiquepourl'apprentiprogrammeur

mthode rcursive (qui est plus simple concevoir et mettre en oeuvre), et quand on veut faire un parcours en
largeur on utilise la mthode avec une file (parce qu'une structure, c'est plus simple que deux). Quand les gens
parlent du "parcours en largeur", ils font (quasiment) toujours rfrence l'implmentation avec une file.

Il est quand mme utile de connatre les autres implmentations. Tout d'abord, la symtrie entre le parcours en
largeur file et le parcours en profondeur pile est trs jolie (obtenir deux algorithmes dirents en changeant
juste deux fonctions, c'est quand mme assez fort). Ensuite, certains langages (dont je pense le plus grand mal) ne
supportent pas bien la rcursion, dans ce cas le parcours en profondeur avec une pile peut tre un bon choix
d'implmentation.
Enfin, la mthode de parcours en largeur avec deux couches a un avantage : il est facile de savoir quelle couche
appartient un lment, et donc de mesurer sa "distance" au noeud facilement et eicacement. Quand on utilise
une file, la distinction entre les deux couches se brouille (on sait que tout arrive dans le bon ordre, mais on ne sait
plus exactement o est la coupure entre les couches), et si on a besoin de cette information il faut la maintenir par
d'autres mthodes (par exemple en la stockant dans la file avec le noeud, ou dans une structure part).

Exercice : Implmenter un algorithme de parcours en largeur qui aiche la valeur de chaque noeud, ainsi que la
distance de ce noeud la racine.

Analyse de complexit

Les deux parcours ont une complexit en temps linaire en la taille de l'arbre (son nombre de noeuds) : en eet, on
parcourt chaque noeud une seule fois, et on eectue avant et aprs quelques oprations (entre et sortie d'une
structure) qui sont en temps constant. Si on a N noeuds dans l'arbre c'est donc du O(N).

Pour ce qui est de la complexit mmoire, il faut faire un peu plus attention. Le parcours en profondeur conserve
les chemins par lequel il est "en train de passer". J'ai donn l'exemple du dbut du parcours o on passe par les
noeuds A, C puis D. Vers la fin du parcours, on sera en train de passer par les noeuds A, C, F puis I. Ces noeuds sont
bien prsents en mmoire : c'est facile voir dans la version avec une pile, c'est juste le contenu de la pile; c'est
aussi le cas dans la version rcursive, car chaque paramtre pass un appel rcursif de la fonction doit tre
conserv quelque part (pour en savoir plus, vous pouvez lire la description de la pile d'appel dans le tutoriel sur la
rcursivit, mais ce n'est pas un point important ici). La complexit mmoire du parcours en profondeur est donc
en O(H), o H est la profondeur maximale des noeuds de l'arbre, c'est dire la hauteur de l'arbre.

Pour le parcours en largeur, c'est un peu dirent : un instant donn on stocke une partie de la couche courante
(ceux qui n'ont pas encore t parcourus), et une partie de la couche des enfants (ceux qui ont dj t ajouts).
Cela se voit bien dans la version avec deux couches, mais on stocke exactement la mme quantit de noeuds dans
la version avec pile. La complexit mmoire est donc en O(L) o L est la plus grande largeur d'une couche de
l'arbre.

Je parle de O(H) et O(L) ici, mais a ne vous apporte pas grand chose : un arbre N lments, c'est parlant, mais
comment avoir une ide des valeurs de H et L ? Si vous ne connaissez pas les arbres qu'on va vous donner, c'est
diicile de le savoir. Une approximation pessimiste est de se dire que H et L sont toujours infrieurs N, le nombre
de noeuds de l'arbre. En eet, dans le "pire cas" pour H, chaque noeud a un seul enfant, et sa hauteur est donc N
(vous pouvez remarquer que cela correspond exactement une liste). Dans le "pire cas" pour H, la racine a N-1
enfants, donc H = N-1 = O(N).

On peut donc dire que les complexits mmoires des parcours d'arbres sont en O(N). Si j'ai tenu vous parler de H
et L, c'est parce que dans la plupart des cas on peut avoir des estimations plus prcises de leurs valeurs. En
particulier, on verra plus tard que H est souvent nettement plus petit que N.

https://openclassrooms.com/courses/algorithmiquepourlapprentiprogrammeur/arbres 11/13
17/03/2017 ArbresAlgorithmiquepourl'apprentiprogrammeur

Utilisation en pratique

Dans quels cas utiliser plutt un parcours ou l'autre ? Le parcours en profondeur est le plus simple implmenter
(par la rcursivit), donc si vous avez besoin de parcourir tout l'arbre c'est un bon choix; par exemple, on peut
coder la fonction "taille d'un arbre" en utilisant un parcours en largeur (il suit d'incrmenter un compteur
chaque noeud parcouru), mais c'est nettement plus compliqu (et donc sans doute un peu plus lent) et a
n'apporte rien.

De mme, si on veut trouver "tous les noeuds qui vrifient la proprit donne" (par exemple "leur valeur est
suprieure 100" ou "ils reprsentent une salle du labyrinthe qui contient un trsor"), les deux mthodes de
parcours sont aussi bien, et il vaut mieux utiliser le parcours en profondeur qui est plus simple. Si on cherche "un
noeud qui vrifie la proprit donne", les deux parcours sont tous les deux aussi bien.

Il y a un cas cependant o le parcours en largeur est le bon choix : quand on a besoin de la proprit de "distance
la racine" du parcours en largeur. Pour dvelopper mon exemple prcdent, imaginez que l'arbre dcrit le plan
d'un labyrinthe : l'entre est la racine, et quand vous tes dans la salle correspondant un noeud, vous pouvez
vous rendre dans les salles enfant (ou remonter dans la salle parent). Certains noeuds contiennent des trsors;
vous voulez que votre algorithme vous donne, pas la liste des trsors, pas une seule salle qui contient un trsor,
mais le trsor le plus proche de l'entre (qui est aussi la sortie).
Alors il faut utiliser un parcours en largeur : il va visiter les cases les plus proches de la racine en premier. Ds que
vous aurez trouv un trsor, vous savez que c'est le trsor le plus proche de l'entre, ou en tout cas un des trsors
les plus proches : il y a peut-tre d'autres trsors dans la mme couche. Un parcours en profondeur ne permet pas
cela : le premier trsor qu'il trouve peut tre trs profond dans l'arbre, trs loin dans la racine (imaginez sur notre
exemple qu'il y a un trsor en E et en C).

Pour rsumer, le parcours en profondeur est trs bien pour rpondre aux questions du style "le nombre total de ...",
"la liste des ...", "le plus long chemin qui ...", et le parcours en largeur pour les questions du style "le plus court
chemin qui ..", "le noeud le plus proche qui ...", "la liste des .. en ordre de distance croissante".

Ce n'est pas fini !

Comme vous l'avez peut-tre devin, le tutoriel est encore en cours de rdaction.

Pour vous tenir en haleine, voici les deux principaux constituants de la troisime partie (en cours d'criture) :
arbres et graphes. Vous y verrez un autre tri optimal, plus eicace, direntes mthodes de recherche de sortie
d'un labyrinthe, etc.

Post Scriptum (t 2011) : en raison de l'absence de modification visible depuis maintenant assez longtemps, on
nous demande rgulirement si le tutoriel est abandonn. La rponse est non, mais la prparation de nouveaux
chapitres progresse lentement. En attendant, nous continuons eectuer de petites mises jour pour apporter
des amliorations ou des clarifications, suite aux retours des lecteurs, qui nous sont donc fort utiles.

Piles et files

Les auteurs Dcouvrez aussi ce cours en...


lastsseldon
https://openclassrooms.com/courses/algorithmiquepourlapprentiprogrammeur/arbres 12/13
17/03/2017 ArbresAlgorithmiquepourl'apprentiprogrammeur

lastsseldon

PDF

Cygal

bluestorm

OpenClassrooms Professionnels En plus Suivez-nous


Qui sommes-nous ? Ailiation Crer un cours Le blog OpenClassrooms
Fonctionnement de nos coursPartenaires CourseLab
Recrutement Conditions Gnrales d'Utilisation
Nous contacter

English Espaol

https://openclassrooms.com/courses/algorithmiquepourlapprentiprogrammeur/arbres 13/13

S-ar putea să vă placă și