• Aucun résultat trouvé

Ajout dans un arbre ordonné équilibré

Les arbres

3.4 LES ARBRES BINAIRES ORDONNÉS ÉQUILIBRÉS

3.4.2 Ajout dans un arbre ordonné équilibré

Une réorganisation doit avoir lieu si la valeur absolue de la différence de hauteurs entre la plus longue branche du SAD et celle du SAG d’un nœud devient > 1 à la suite d’une insertion. Il y a quatre cas de réorganisations de l’arbre à envisager : le déséquilibre vient du SAG du SAG (noté GG), du SAD du SAD (noté DD), du SAD du SAG (noté GD), du SAG du SAD (noté DG). Les deux premiers et deux derniers cas sont symétriques. Le facteur d’équilibre (hauteur du sous-arbre droit moins hauteur du sous-arbre gauche) est donné entre parenthèses sur les figures qui suivent.

3.4.2.a 1° cas : type GG

Le déséquilibre vient de la Gauche du sous-arbre Gauche. a, b sont des nœuds (a<b) ; SA1, SA2, SA3 sont des sous-arbres équilibrés. Suite à l’insertion dans SA1, le nœud a a un facteur d’équilibre de –1 ; le nœud b devrait avoir un facteur

d’équi-15

18

20

25 Figure 84 Arbre ordonné dégénéré.

04Chap_03 Page 168 Samedi, 17. janvier 2004 10:37 10

3.4 • Les arbres binaires ordonnés équilibrés 169

© Dunod – La photocopie non autorisée est un délit.

libre de –2, ce qui est inacceptable. Il faut réorganiser a et b comme l’indique la Figure 85.

L’insertion de 1, sans réorganisation, à une place imposée par le critère d’ordre, déséquilibrerait l’arbre comme l’indique la Figure 86. La branche en gras indique le chemin suivi par les différents appels récursifs pour atteindre le point d’insertion qui est toujours une feuille. L’intérêt de la méthode réside dans le fait que seule cette branche est affectée par une éventuelle réorganisation de l’arbre pour respecter le critère d’ordre. La réorganisation se fait au retour de l’appel récursif, lors de la remontée de la feuille vers la racine de l’arbre. La feuille insérée (ici 1) est équilibrée.

Le retour au nœud 3 trouve un facteur d’équilibre de 0 avant insertion qui devient –1 après insertion. On remonte au nœud 6 qui passe de même de 0 à –1. Le nœud 15 a un facteur d’équilibre de –1 avant l’insertion qui a accentué le déséquilibre à gauche.

Il faut réorganiser les nœuds 6 et 15. 6 devient racine du sous-arbre à la place de 15 qui glisse à droite de 6. Le sous-arbre 9 est rattaché comme SAG de 15. Après ces modifications, les nœuds 6 et 15 ont un facteur d’équilibre de 0. Les autres nœuds, en amont des nœuds réorganisés, examinés lors de la remontée ne sont pas touchés ; il n’y a aucun traitement à faire lors de la remontée après l’appel récursif ; sur l’exemple, le nœud 25 garde donc son facteur d’équilibre de –1. Les autres parties de l’arbre (branche droite de 25 par exemple) ne sont pas concernées par cette réorganisation.

a (0)

Figure 85 Principe de la réorganisation GG (Rotation Droite).

25 (–1)

Figure 86 Arbre déséquilibré par l'insertion de 1.

04Chap_03 Page 169 Samedi, 17. janvier 2004 10:37 10

170 3 Les arbres

L’arbre peut être réorganisé comme l’indique la Figure 87 (nœud a:6; nœud b:15), le nœud a:6 devenant la nouvelle racine du sous-arbre.

Le détail des modifications de pointeurs sur les différents sous-arbres des nœuds concernés par une réorganisation GG est donné sur la Figure 88 et la Figure 89. Quand on exécute la fonction pour le nœud 15, ce qui a été passé lors de l’appel récursif est l’adresse pracine du pointeur sur ce nœud. Après réorganisation, le pointeur à l’adresse pracine pointe sur 6 au lieu de 15. Tout se passe comme s’il y avait eu une rotation à droite des nœuds 6 et 15 ; 6 a pris la place de 15 ; 15 descend à droite de 6 ; 9 se rattache à gauche de 15. La fonction rd (pracine) réalise cette permutation des 3 pointeurs.

25 (–1)

30 (–1)

28 (0) 15 (0)

3 ( –1)

9 ( 0)

1 (0) 20 (0)

6 (0)

Figure 87 Arbre après rééquilibrage GG de 6 et 15.

25

15

6 SA3

SA2 SA1

p

pracine

racine

Figure 88 Arbre avant réorganisation GG.

04Chap_03 Page 170 Samedi, 17. janvier 2004 10:37 10

3.4 • Les arbres binaires ordonnés équilibrés 171

© Dunod – La photocopie non autorisée est un délit.

3.4.2.b 2° cas : type DD (symétrique du cas 1)

Le déséquilibre vient de la droite du sous-arbre droit. L’insertion a provoqué un déséquilibre dans le SAD du SAD. La réorganisation se fait comme indiqué sur la Figure 90, qui est symétrique de la réorganisation GG de la Figure 85.

La Figure 91 présente un exemple simple de réorganisation DD. L’insertion de 30 déséquilibre l’arbre. Lors de la remontée, le facteur d’équilibre du nœud 20 passe de 0 à 1 ; celui de 10 qui devrait passer à 2, valeur interdite, provoque une réorganisa-tion DD. Le principe est rigoureusement identique à celui de la réorganisaréorganisa-tion GG à la symétrie près. On parle de rotation gauche. Sur l’exemple, b:20 prend la place de 10, a:10 descend à gauche selon le principe de la Figure 90. Les facteurs d’équilibre de b:20 et a:10 sont alors de 0.

3.4.2.c 3° cas : type GD

Le déséquilibre vient de la Droite du sous-arbre Gauche (type GD). De même que précédemment a, b, c sont des nœuds (a<b<c) ; SA1, SA2, SA3, SA4 sont des

sous-25

15

6 SA3

SA2 SA1

p

pracine

racine

Figure 89 Arbre après réorganisation GG (Rotation Droite).

a (1 DD)

b (1) S A1

S A3 S A2

devient

b (0)

a (0) SA3

SA1 SA2

Figure 90 Principe de la réorganisation DD (Rotation Gauche).

04Chap_03 Page 171 Samedi, 17. janvier 2004 10:37 10

172 3 Les arbres

arbres équilibrés. Le principe de la réorganisation est donné ci-dessous ; c’est b, la valeur moyenne qui devient racine du sous-arbre à la place de c.

L’insertion de 8 à la place imposée par le critère d’ordre déséquilibre l’arbre comme indiqué sur la Figure 93. La branche en gras indique le chemin des appels récursifs qui a conduit à l’insertion de la feuille 8. La réorganisation se fait lors de la remontée, donc avec une séquence d’instructions qui suit l’appel récursif. La feuille 8 est équilibrée. Le nœud 9 voit son facteur d’équilibre passer de 0 à –1 (on remonte par la gauche ; l’insertion a eu lieu dans le SAG de 9). Le nœud 6 passe de 0 à 1 (on remonte par la droite, l’insertion a eu lieu dans le SAD de 6). Le facteur d’équilibre du nœud 15 (-1) devrait passer à –2 car l’insertion a eu lieu dans le SAG de 15.

Il faut donc réorganiser. Le déséquilibre vient du SAD du SAG de 15. Les nœuds c:15, a:6 et b:9 sont réorganisés conformément à la Figure 92. b:9 devient racine du sous-arbre à la place de c:15 qui glisse à droite du nœud b:9. Le nœud b:9 est devenu équilibré et les autres nœuds en amont (25 sur l’exemple) ne sont plus concernés par ce rééquilibrage. Dans le cas de l’insertion de 8, le facteur d’équilibre pour a:6 est de 0 et celui de c:15 de 1. Dans ce rééquilibrage GD, il y a trois cas à considérer du point de vue des facteurs d’équilibre.

10 (1

DD)

20 (0 1)

30 (0)

20 (0)

10 (0) 30 (0) 10 (1)

20 (0)

Figure 91 Exemple de réorganisation DD (Rotation Gauche).

a (1) SA4

SA1 b (-1, 1 ou 0)

SA2 SA3

c a

SA3 SA4 SA2 SA1

c (–1 GD) b(0)

Figure 92 Principe de la réorganisation GD.

04Chap_03 Page 172 Samedi, 17. janvier 2004 10:37 10

3.4 • Les arbres binaires ordonnés équilibrés 173

© Dunod – La photocopie non autorisée est un délit.

Avant la réorganisation sur le nœud c lors de la remontée récursive, le facteur d’équilibre de c est de –1 ; celui de a vaut +1, et celui de b vaut –1, 1 ou 0 d’où les 3 cas illustrés par le tableau et les exemples suivants.

L’arbre peut être réorganisé comme l’indique la Figure 94 (nœud c:15 ; nœud a:6 ; nœud b:9), le nœud b:9 compris entre a:6 et c:15 devenant la nouvelle racine du sous-arbre.

L’insertion de 10 est schématisé sur la Figure 95 et la Figure 96 et illustre le deuxième cas concernant les facteurs d’équilibre.

La Figure 97 illustre le troisième cas concernant les facteurs d’équilibre dans un rééquilibrage GD.

Avant Après

a b c a b c

1 -1 -1 0 0 1

1 1 -1 -1 0 0

1 0 -1 0 0 0

25 (–1)

15 (-1) 30 (–1)

28 (0) 20 (0)

9 (0) 3 (0)

25 (?)

15 (–1 GD) 30 (–1)

28 (0) 20 (0)

6 (0 + 1)

9 (0 – 1) 3 (0)

8 (0) 6 (0)

Figure 93 Arbre déséquilibré par l'insertion de 8 ; 15, 6 et 9 sont réorganisés.

25 (-1)

9 (0) 30 (–1)

28 (0) 15 (1)

6 (0)

8 (0)

3 (0) 20 (0)

Figure 94 Cas 1 : arbre après rééquilibrage GD; a:6 (0), b:9 (0), c:15 (1).

04Chap_03 Page 173 Samedi, 17. janvier 2004 10:37 10

174 3 Les arbres

Du point de vue des modifications de pointeurs, cette transformation peut être considérée comme une double rotation : rotation gauche sur le nœud a, puis rotation droite sur le nœud c comme le schématise la Figure 98.

25 (–1)

15 (–1) 30 (–1)

28 (0) 20 (0)

6 (0)

9 (0) 3 (0)

15 (–1 GD) 30 (–1)

28 (0) 20 (0)

6 (0 → 1)

9 (0 → 1) 3 (0)

10 (0) 25(?)

Figure 95 Arbre déséquilibré par l'insertion de 10 ; 15, 6 et 9 sont réorganisés.

25 (-1)

9 (0) 30 (-1)

28 (0) 15 (0)

6 (-1)

10 (0)

3 (0) 20 (0)

Figure 96 Cas 2 : arbre après rééquilibrage GD ; a:6 (-1), b:9 (0), c:15 (0).

15 (–1 GD)

6 ( 0→1)

9 (0 ) 6 (0)

9 (0)

6 (0 ) 15 (0)

15 (–1)

Figure 97 Cas 3 : arbre après rééquilibrage GD ; a:6 (0), b:9 (0), c:15 (0).

04Chap_03 Page 174 Samedi, 17. janvier 2004 10:37 10

3.4 • Les arbres binaires ordonnés équilibrés 175

© Dunod – La photocopie non autorisée est un délit.

3.4.2.d 4° cas : type DG (symétrique du cas 3)

Le déséquilibre vient de la gauche du sous-arbre droit (type DG). Si le déséquilibre vient de la gauche du sous-arbre droit, il faut réorganiser comme l’indique la Figure 99. Ceci peut aussi se décomposer en une rotation droite sur c, puis une rotation gauche sur a. Il y a de même trois cas à considérer, pour les facteurs d’équilibre, symétriques des cas GD.

La Figure 100 présente un exemple de réorganisation DG. L’insertion de 15 se fait à gauche de 20. Le facteur d’équilibre de 20 passe de 0 à –1, celui de 10 devrait passer à 2 ; il provoque une réorganisation DG.

c

Figure 98 Réorganisation GD = rotation RG sur a, puis rotation RD sur c.

a (1 DG)

Figure 99 Principe de la réorganisation DG.

10 (1 → DG)

Figure 100 Exemple de réorganisation DG.

04Chap_03 Page 175 Samedi, 17. janvier 2004 10:37 10

176 3 Les arbres

Pour les facteurs d’équilibre, on retrouve les 3 cas du type GD. Le tableau est rigoureusement le même que pour le cas GD car afin d’avoir a, b et c en ordre crois-sant, on a permuté c et a dans la symétrie GD/DG.

Exercice 18 - Facteur d’équilibre

Retrouver du point de vue des facteurs d’équilibre, les 3 cas de rééquilibrage DG en insérant dans un arbre vide :

50, 40, 70, 80, 60, 58 50, 40, 70, 80, 60, 65 10, 20, 15

3.4.2.e Insertion dans un arbre binaire équilibré

Les paragraphes 3.4.2.a, b, c et d ont présenté les quatre réorganisations de l’arbre.

Il n’y a pas réorganisation à chaque ajout d’un élément dans l’arbre ordonné (en moyenne, une réorganisation pour 2 ajouts). Dans certains cas, l’insertion améliore l’équilibre de l’arbre comme sur la Figure 101 et la Figure 102.

Les notations concernant les arbres équilibrés sont celles décrites pour les arbres binaires dans arbre.h. Toutefois, il convient d’ajouter le champ facteur d’équilibre factEq pour chaque nœud de l’arbre. factEq vaut -1, 0 ou 1 ; c’est la différence de hauteur entre le SAD et le SAG. Comme pour les arbres ordonnés, la clé peut être numérique ou alphanumérique.

// ********** ARBRES EQUILIBRES

// permuter p1, p2, p3 : p2 = p1, p3 = p2, p1 = p3

static void permut (Noeud** p1, Noeud** p2, Noeud** p3) { Noeud* temp;

10 (1)

20 (0)

10 (1 0)

20 (0) 5 (0)

Figure 101 L'insertion de 5 dans le SAG améliore l'équilibre du nœud 10.

20 (-1)

10 (0)

20 (-1 → 0)

10 (0) 30 (0)

Figure 102 L'insertion de 30 en SAD améliore l'équilibre du nœud 20.

04Chap_03 Page 176 Samedi, 17. janvier 2004 10:37 10

3.4 • Les arbres binaires ordonnés équilibrés 177

© Dunod – La photocopie non autorisée est un délit.

temp = *p3;

static void rd (Noeud** pracine) { Noeud* racine = *pracine;

Noeud* p = racine->gauche;

permut (pracine, &p->droite, &racine->gauche);

}

// rotation gauche

static void rg (Noeud** pracine) { Noeud* racine = *pracine;

Noeud* p = racine->droite;

permut (pracine, &p->gauche, &racine->droite);

}

// - insérer objet dans l'arbre d'adresse de racine "pracine";

// - req à vrai indique qu'il se peut qu'un rééquilibrage // soit nécessaire en amont du noeud en cours

static void insererArbreEquilibre (Noeud** pracine, Objet* objet,

booleen* req, char* (toString) (Objet*), int (*comparer) (Objet*, Objet*) ) { int resu;

Noeud* racine = *pracine;

if (racine == NULL) {

racine = cNd (objet);

racine->factEq = 0;

*req = vrai;

*pracine = racine;

} else if ( (resu=comparer (objet, racine->reference)) < 0) {

insererArbreEquilibre (&racine->gauche, objet, req, toString, comparer);

if (*req) {

// L'insertion a eu lieu dans le SAG de racine switch (racine->factEq) {

case 1: // 1 -> 0

fprintf (stderr, "%s 1 -> 0\n", toString (racine->reference));

racine->factEq = 0;

*req = faux;

break;

case 0: // 0 -> -1 racine->factEq = -1;

fprintf (stderr, "%s 0 -> -1\n", toString (racine->reference));

break;

04Chap_03 Page 177 Samedi, 17. janvier 2004 10:37 10

178 3 Les arbres

insererArbreEquilibre (&racine->droite, objet, req, toString,

comparer);

if (*req) {

// L'insertion a eu lieu dans le SAD de racine switch (racine->factEq) {

case -1: // -1 -> 0

fprintf (stderr, "%s -1 -> 0\n", toString (racine->reference));

racine->factEq = 0;

*req = faux;

break;

case 0: // 0 -> 1 racine->factEq = 1;

fprintf (stderr, "%s 0 -> 1\n", toString (racine->reference));

break;

void insererArbreEquilibre (Arbre* arbre, Objet* objet) { booleen req;

insererArbreEquilibre (&arbre->racine, objet, &req, arbre->toString, arbre->comparer);

}

04Chap_03 Page 178 Samedi, 17. janvier 2004 10:37 10

3.4 • Les arbres binaires ordonnés équilibrés 179

© Dunod – La photocopie non autorisée est un délit.