• Aucun résultat trouvé

m´ethode stockage recherche insertion modif. suppr.

adressage direct Θ(m) Θ(1) Θ(1) Θ(1) Θ(1)

recherche s´equentielle Θ(n) Θ(n) Θ(1) Θ(n) Θ(n)

recherche dichotomique Θ(n) Θ(log(n)) Θ(n) Θ(n) Θ(n)

recherche par interpolation Θ(n) Θ(log log(n)) Θ(log log(n)) Θ(n) Θ(n) tables de hachage Θ(m+n) Θ(mn) Θ(1) Θ(mn) Θ(mn)

avec m≃n Θ(n) Θ(1) Θ(1) Θ(1) Θ(1)

Note : les complexit´es ci-dessus sont celles dans le pire cas, sauf celles suivies de pour lesquelles il s’agit du cas moyen.

On constate qu’une table de hachage de taille bien adapt´ee et munie d’une bonne fonction de hachage peut donc ˆetre tr`es efficace. Cependant cela demande d’avoir une bonne id´ee de la quantit´e de donn´ees `a g´erer `a l’avance.

Chapitre 5 Arbres

La notion d’arbre mod´elise, au niveau des structures de donn´ees, la notion de r´ecursivit´e pour les fonctions. Il est `a noter que la repr´esentation par arbre est tr`es courante dans la vie quotidienne : arbres g´en´ealogiques, organisation de comp´etitions sportives, organi-gramme d’une entreprise... Dans ce chapitre, apr`es avoir introduit la terminologie et les principales propri´et´es des arbres, nous illustrons leur utilisation `a travers trois exemples fondamentaux en informatique : l’´evaluation d’expressions, la recherche d’information, et l’impl´ementation des files de priorit´e. Nous terminons par la notion d’arbre ´equilibr´e, dont la structure permet de garantir une complexit´e algorithmique optimale quelle que soit la distribution de l’entr´ee.

5.1 Pr´ eliminaires

5.1.1 efinitions et terminologie

Un arbre est une collection (´eventuellement vide) de nœuds et d’arˆetes assujettis `a certaines conditions : un nœud peut porter un nom et un certain nombre d’informations pertinentes (les donn´ees contenues dans l’arbre) ; une arˆete est un lien entre deux nœuds.

Une branche (ou chemin) de l’arbre est une suite de nœuds distincts, dans laquelle deux nœuds successifs sont reli´es par une arˆete. La longueur d’une branche est le nombre de ses arˆetes (ou encore le nombre de nœuds moins un). Un nœud est sp´ecifiquement d´esign´e comme ´etant la racine de l’arbre1. La propri´et´e fondamentale d´efinissant un arbre est alors que tout nœud est reli´e `a la racine par une et une seule branche2 (i.e. il existe un unique chemin d’un nœud donn´e `a la racine).

Comme on peut le voir sur la Figure 5.1, chaque nœud poss`ede un lien (descendant, selon la repr´esentation graphique) vers chacun de ses fils (oudescendants), ´eventuellement un lien vers le vide, ou pas de lien si le nœud n’a pas de fils ; inversement, tout nœud - sauf

1. Si la racine n’est pas sp´ecifi´ee, on parle plutˆot d’arborescence.

2. Dans le cas ou certains nœuds sont reli´es par plus d’une branche (ou pas de branche du tout) `a la racine on parle alors degraphe.

§ 5.1 Pr´eliminaires ENSTA – cours IN101

= Nœud

= Arête Racine

Feuilles Nœuds internes

Figure 5.1 – Repr´esentation d’un arbre. On place toujours la racine en haut.

la racine - poss`ede un p`ere (ou ancˆetre) et un seul, qui est le nœud imm´ediatement au-dessus de lui dans la repr´esentation graphique. Les nœuds sans descendance sont appel´es feuilles, les nœuds avec descendance ´etant des nœuds internes. Tout nœud est la racine du sous-arbre constitu´e par sa descendance et lui-mˆeme.

Voici une liste du vocabulaire couramment utilis´e pour les arbres : – Une clef est une information contenue dans un nœud.

– Un ensemble d’arbres est une forˆet.

– Un arbre est ordonn´e si l’ordre des fils de chacun de ses nœuds est sp´ecifi´e. C’est g´en´eralement le cas dans les arbres que l’on va consid´erer dans la suite.

– Un arbre est de plusnum´erot´esi chacun de ses fils est num´erot´e par un entier strictement positif (deux nœuds ne poss´edant pas le mˆeme num´ero).

– Les nœuds d’un arbre se r´epartissent en niveaux. Le niveau d’un nœud est la longueur de la branche qui le relie `a la racine.

– Lahauteurd’un arbre est le niveau maximum de l’arbre (i.e.plus grande distance d’un nœud `a la racine).

– La longueur totale d’un arbre est la somme des longueurs de tous les chemins menant des nœuds `a la racine.

– Le degr´ed’un nœud est le nombre de fils qu’il poss`ede.

– L’arit´e d’un arbre est le degr´e maximal de ses nœuds.

– Lorsque l’on a un arbre dont les fils de chaque nœud sont num´erot´es par des entiers tous compris dans l’intervalle [1, . . . , k], on parle d’arbrek-aire. Un arbrek-aire est donc un arbre num´erot´e, d’arit´e inf´erieure ou ´egale `a k.

– Comme avec les sentinelles pour les listes, on peut d´efinir un type particulier de nœud ditnœud vide: c’est un nœudfacticedans le sens o`u il ne contient pas d’information ; il peut juste servir `a remplir la descendance des nœuds qui contiennent moins dek fils.

– L’exemple le plus important d’arbre m-aire est l’arbre binaire. Chaque nœud poss`ede deux fils et on parle alors de fils gauche et de fils droit d’un nœud interne. On peut

´

egalement d´efinir la notion de fils gauche et fils droit d’une feuille : il suffit de repr´esenter chacun d’eux par le nœud vide. De cette mani`ere, tout nœud non vide peut ˆetre consid´er´e comme un nœud interne.

– Un arbre binaire est complet si les nœuds remplissent compl`etement tous les niveaux, sauf ´eventuellement le dernier, pour lequel les nœuds apparaissent alors tous le plus `a gauche possible (notez que l’arbre binaire de hauteur 0 est complet).

5.1.2 Premi` eres propri´ et´ es

La meilleure d´efinition des arbres est sans doute r´ecursive : un arbre est soit l’arbre vide, soit un nœud appel´e racine reli´e `a un ensemble (´eventuellement vide) d’arbres appel´es ses fils.

Cette d´efinition r´ecursive se particularise trivialement au cas des arbres binaires comme suit : un arbre binaire est soit l’arbre vide, soit un nœud racine reli´e `a un arbre binaire gauche (appel´e sous-arbre gauche) et un arbre binaire droit (appel´e sous-arbre droit).

Un arbre binaire est ´evidemment un arbre ; mais r´eciproquement, tout arbre peut ˆetre repr´esent´e par un arbre binaire (cf. plus loin la repr´esentation des arbres). Cette vision r´ecursive des arbres nous permet de d´emontrer les propri´et´es suivantes.

Propri´et´e 5.1.1. Il existe une branche unique reliant deux nœuds quelconques d’un arbre.

Propri´et´e 5.1.2. Un arbre de N nœuds contient N 1 arˆetes.

Preuve. C’est une cons´equence directe du fait que tout nœud, sauf la racine, poss`ede un p`ere et un seul, et que chaque arˆete relie un nœud `a son p`ere. Il y a donc autant d’arˆetes que de nœuds ayant un p`ere, soitN 1.

Propri´et´e 5.1.3. Un arbre binaire complet poss´edant N nœuds internes contient N + 1 feuilles.

Preuve. Pour un arbre binaire complet A, notons f(A), son nombre de feuilles et n(A), son nombre de nœuds internes. On doit montrer que f(A) = n(A) + 1. Le r´esultat est vrai pour l’arbre binaire de hauteur 0 (il est r´eduit `a une feuille). Consid´erons un arbre binaire complet A = (r, Ag, Ad), r d´esignant la racine de l’arbre, et Ag et Ad ses sous-arbres gauche et droit respectivement. Les feuilles de A ´etant celles de Ag et de Ad, on a f(A) =f(Ag) +f(Ad) ; les nœuds internes de A sont ceux de Ag, ceux de Ad, et r, d’o`u n(A) = n(Ag) +n(Ad) + 1. Ag et Ad ´etant des arbres complets, la r´ecurrence s’applique, et f(Ag) = n(Ag) + 1, f(Ad) = n(Ad) + 1. On obtient donc f(A) = f(Ag) +f(Ad) = n(Ag) + 1 +n(Ad) + 1 =n(A) + 1.

Propri´et´e 5.1.4. La hauteur h d’un arbre binaire contenant N nœuds v´erifie h+ 1 log2(N + 1).

Preuve. Un arbre binaire contient au plus 2 nœuds au premier niveau, 22 nœuds au deuxi`eme niveau,..., 2h nœuds au niveau h. Le nombre maximal de nœuds pour un arbre binaire de hauteur h est donc 1 + 2 +. . .+ 2h = 2h+11, i.e. N + 12h+1.

§ 5.1 Pr´eliminaires ENSTA – cours IN101

Pour un arbre binaire complet de hauteurh contenantN nœuds, tous les niveaux (sauf le dernier sont compl`etement remplis. On a donc N 1 + 2 +. . .+ 2h1 = 2h 1 , i.e.

log2(N + 1) ≥h. La hauteur d’un arbre binaire complet `a N nœuds est donc toujours de l’ordre de log2(N).

5.1.3 Repr´ esentation des arbres

Arbres binaires. Pour repr´esenter un arbre binaire, on utilise une structure similaire `a celle d’une liste chaˆın´ee, mais avec deux pointeurs au lieu d’un : l’un vers le fils gauche, l’autre vers le fils droit. On d´efinit alors un nœud par :

1 struct node {

2 int key;

3 type_info info;

4 node* left;

5 node* right;

6 };

7 typedef node* binary_tree;

Arbres k-aires. On peut construire un arbrek-aire de fa¸con tr`es similaire (o`uk est un entier fix´e une fois pour toute dans le programme) :

1 struct node {

2 int key;

3 type_info info;

4 node sons[k];

5 };

6 typedef node* k_ary_tree;

Arbres g´en´eraux. Dans le cas d’un arbre g´en´eral il n’y a pas de limite sur le nombre de fils d’un nœud. Il faut donc utiliser une structure dynamique pour stocker tous les fils d’un mˆeme nœud. Pour cela on utilise une liste chaˆın´ee. Chaque nœud contient donc un pointeur vers son fils le plus `a gauche (le premier ´el´ement de la liste), qui lui contient un pointeur vers sont fr`ere juste `a sa droite (la queue de la liste). Chaque nœud contient donc un pointeur vers un fils et un pointeur vers un fr`ere. On obtient une structure de la forme :

1 struct node {

2 int key;

3 type_info info;

4 node* brother;

5 node* son;

6 };

7 typedef node* tree;

= Nœud

= Fils

= Frère

=NULL

= Arête

Figure5.2 –Arbre g´en´eral : on acc`ede aux fils d’un nœud en suivant une liste chaˆın´ee.

Dans cette repr´esentation, on voit que tout nœud poss`ede deux liens : elle est donc identique `a la repr´esentation d’un arbre binaire. Ainsi, on peut voir un arbre quelconque comme un arbre binaire (avec, pour tout nœud, le lien gauche pointant sur son fils le plus

`

a gauche, le lien droit vers son fr`ere imm´ediatement `a droite). Nous verrons cependant les modifications `a apporter lors du parcours des arbres g´en´eraux.

Remonter dans un arbre

Dans les applications o`u il est seulement n´ecessaire de remonter dans l’arbre, et pas de descendre, la repr´esentation par lien-p`ere d’un arbre est suffisante. Cette repr´esentation consiste `a stocker, pour chaque nœud, un lien vers son p`ere. On peut alors utiliser deux tableaux pour repr´esenter un tel arbre : on prend soin d’´etiqueter les nœuds de l’arbre au pr´ealable (de 1 `a k s’il y a k nœuds). Le premier tableau tab info de taille k contiendra l’information contenue dans chaque nœud (tab info[i] = info du nœud i), le deuxi`eme tableau tab father de taille k lui aussi contiendra les liens p`ere, de telle sorte que tab father[i]= clef du p`ere du nœud i. L’information relative au p`ere du nœud i se trouve alors dans tab info[tab father[i]].

Lorsqu’on doit juste remonter dans l’arbre, une repr´esentation par tableaux est donc suffisante. On pourrait aussi utiliser une liste de tous les nœud dans laquelle chaque nœud contiendrait en plus un lien vers son p`ere.