La présentation est en train de télécharger. S'il vous plaît, attendez

La présentation est en train de télécharger. S'il vous plaît, attendez

Structures de données IFT-2000 Abder Alikacem Semaine 11 Gestion des arbres binaires de tri et de recherche. Les arbres cousus. Les arbres n-aires Département.

Présentations similaires


Présentation au sujet: "Structures de données IFT-2000 Abder Alikacem Semaine 11 Gestion des arbres binaires de tri et de recherche. Les arbres cousus. Les arbres n-aires Département."— Transcription de la présentation:

1

2 Structures de données IFT-2000 Abder Alikacem Semaine 11 Gestion des arbres binaires de tri et de recherche. Les arbres cousus. Les arbres n-aires Département dinformatique et de génie logiciel Édition Septembre 2009

3 Gestion des arbres binaires Algorithmes de gestion dun arbre binaire de tri Les arbres de recherche, arbres AVL Algorithme de balancement dun arbre AVL Les arbres cousus Les arbres n-aires Notez bien. Les exemples de code qui seront montrés dans le cours se trouvent dans la section exemple de la semaine 11 Classe Arbre: une implémentation d'un arbre de tri.

4 Implantation dun arbre binaire par chaînage template class Arbre { public: //.. private: // classe Noeud class Noeud { public: E data; Noeud *gauche; Noeud *droite; int card; int hauteur; Noeud( const E&d ): gauche(0),data( d ),droite(0),hauteur(0) { } }; // Les membres données Noeud * racine;//racine de l'arbre long cpt;// Nombre de noeuds dans l'arbre // Les membres fonctions privés //... };... data Modèle dimplantation par chaînage

5 Implantation dun arbre binaire par chaînage template class Arbre { public: //Constructeurs Arbre(){racine = 0; cpt=0;} Arbre(const Arbre& source) { _auxCopier(source.racine,racine);} //Destructeur ~Arbre() { _auxDetruire(racine);} //Les membres méthodes bool estVide(){ return cpt==0;} long taille() {return cpt;} int hauteur() throw(logic_error); E max() const throw(logic_error); E min()const throw(logic_error); int nbFeuilles()const; int nbNoeuds()const; E parent(const E&) throw(logic_error); E successeur(const E& ) throw(logic_error); bool appartient(const E &); void lister(vector &) const; //.. Linterface publique

6 template E Arbre ::max()const throw (logic_error) { if (cpt==0) throw logic_error("Max: l'arbre est vide!\n"); if (racine->droite == 0) { return racine->data; } Noeud * temp = racine->droite; while (temp->droite!=0) temp = temp->droite; return temp->data; }

7 template E Arbre ::min()const throw (logic_error) { if (cpt==0) throw logic_error("Min: l'arbre est vide!\n"); if (racine->gauche == 0) { return racine->data; } Noeud * temp = racine->gauche; while (temp->gauche!=0) temp = temp->gauche; return temp->data; }

8 template int Arbre :: nbNoeuds() const { return _nbNoeuds(racine); } template int Arbre :: _nbNoeuds(Noeud* arb) const { if (arb==0) return 0; return _nbNoeuds(arb->gauche) + _nbNoeuds(arb->droite) + 1; }

9 template int Arbre ::nbFeuilles() const { return _nbFeuilles(racine); } template int Arbre ::_nbFeuilles(Noeud*arb) const { int nbG (0), nbD(0); if (arb != 0) { if (arb->gauche == 0 && arb->droite == 0) return 1; else { if (arb->gauche != 0) nbG = _nbFeuilles(arb->gauche); if (arb->droite != 0) nbD = _nbFeuilles(arb->droite); } return nbG + nbD; }

10 template int Arbre ::hauteur() throw (logic_error) { if (cpt==0) throw logic_error("Hauteur: l'arbre est vide!\n"); return _hauteurParcours(racine); } template int Arbre ::_hauteurParcours(Noeud * arb) { if (arb==0) return -1; return 1 + _maximum(_hauteur(arb->gauche), _hauteur(arb->droite)); }

11 template bool Arbre :: appartient(const E &data) { return _auxAppartient(racine, data)!=0; } template typename Arbre :: Noeud* Arbre :: _auxAppartient(Noeud* & arbre, const E &data) { if (arbre == 0) return 0; if ( arbre->data == data ) return arbre; if ( arbre->data > data ) return _auxAppartient(arbre->gauche, data); else return _auxAppartient(arbre->droite, data); }

12 template E Arbre :: parent(const E& el) throw(logic_error) { Noeud* noeudDeEl = _auxAppartient(racine, el); Noeud* parentDeEl = _parent(racine, noeudDeEl); return parentDeEl->data; }

13 template typename Arbre :: Noeud* Arbre :: _parent(Noeud* arb, Noeud* sArb) throw(logic_error) { if (arb == 0) throw logic_error("Parent: l'arbre est vide!\n"); if (sArb == 0) throw logic_error("Parent: l'element n'existe pas!\n"); if (sArb == arb) throw logic_error("Parent: Le parent de la racine d'existe pas!\n"); if ( sArb->data data ) { if (arb->gauche == sArb)return arb; elsereturn _parent(arb->gauche, sArb); } else { if (arb->droite == sArb)return arb; elsereturn _parent(arb->droite, sArb); }

14 template E Arbre :: successeur(const E& info) throw(logic_error) { return _successeur(racine, info); } template E Arbre :: _successeur(Noeud* arb, const E& info) throw (logic_error) { if (cpt == 0) throw logic_error("Successeur: l'arbre est vide!\n"); Noeud* sArb = _auxAppartient(racine, info); if (sArb == 0) throw logic_error("Successeur: l'element n'existe pas!\n"); if ( info == _max(arb)) throw logic_error("Successeur: l'element est le max dans l'arbre!\n"); if (sArb->droite != 0) return _min(sArb->droite); else { Noeud * pere = _parent(arb, sArb); while (pere->data data ) pere = _parent(arb,pere); return pere->data; }

15 Implantation dun arbre binaire par chaînage template class Arbre { public: //.. void insererAVL(const E &data) throw(bad_alloc);//..//.. void enleverAVL( const E&) throw(logic_error);//…//… void parcourirPreOrdre(void (* traitement)(E &iteme)) const; //…//… void parcourirEnOrdre(void (* traitement)(E &iteme)) const; void parcourirPostOrdre(void (* traitement)(E &iteme)) const; void parcourirParNiveau(void (* traitement)(E &iteme)) const; //…//… //surcharge d'opérateurs void operator = (const Arbre & a) {…; _auxCopier(a.racine,racine);} bool operator == (const Arbre &a) { return( _auxArbresEgaux(racine,a.racine));} //… private: // classe Nœud // Attributs internes de Arbre // Méthodes privées

16 Ajout déléments dans un arbre de tri 1 2 3 6 8 9 10 11 12 8,3,11,2,1,6,10,9,12,4,5,14

17 1 2 3 6 8 9 10 11 12 4 8,3,11,2,1,6,10,9,12,4,5,14 Ajout déléments dans un arbre de tri

18 1 2 3 6 8 9 10 11 12 4 8,3,11,2,1,6,10,9,12,4,5,14 Ajout déléments dans un arbre de tri

19 1 2 3 6 8 9 10 11 12 4 5 8,3,11,2,1,6,10,9,12,4,5,14 Ajout déléments dans un arbre de tri

20 1 2 3 6 8 9 10 11 12 4 5 8,3,11,2,1,6,10,9,12,4,5,14 Ajout déléments dans un arbre de tri

21 1 2 3 6 8 9 10 11 12 4 5 14 8,3,11,2,1,6,10,9,12,4,5,14 Ajout déléments dans un arbre de tri

22 1 2 3 6 8 9 10 11 12 4 5 14 8,3,11,2,1,6,10,9,12,4,5,14 Ajout déléments dans un arbre de tri

23 1 re séquence dinsertions 1 2 3 6 8 9 10 11 12 4 5 14 8,3,11,2,1,6,10,9,12,4,5,14 O(log n)

24 2 e séquence dinsertions 1 2 1,2,3,4,5,6,8,9,10,11,12,14 3 4 5 6 8 O(n/2)

25 template void Arbre ::inserer(const E &data) throw(bad_alloc) { _auxInserer(racine, data); } template void Arbre ::_auxInserer(Noeud *&arbre, const E &data) { if (arbre == 0) { arbre = new Noeud(data); cpt++; } else if(arbre->data > data ) _auxInserer(arbre->gauche, data); else _auxInserer(arbre->droite, data); } Insertion sans balancement

26 Arbres binaires équilibrés (AVL) Rappel Cest un arbre de recherche binaire tel que pour chaque noeud, les hauteurs des ses sous-arbres gauche et droite sont différentes dau plus k, k étant le critère déquilibre (on attribue comme hauteur la valeur -1 pour un sous-arbre vide). K =1 dans le cas des arbres AVL. Avec cette condition, on est assuré de toujours avoir un arbre dont la profondeur est proportionnelle à log (n). arbres AVL = HB[1] (arbres Adelson-Velski et Landis) arbres HB[k] « Un arbre T est HB[k] si T et tous ses sous-arbres ont la propriété HB[k] qui est : les sous-arbres gauche et droit diffèrent en hauteur dau plus k. »

27 Arbres équilibrés (AVL) 0 00 11 2 Bien équilibré selon la règle AVL 0 10 2 0 01 21 3 0 01 20 3 Mal équilibré selon la règle AVL 0

28 Équilibration : HB[1] 2 cas (~gauche) S1 A B S2 S3 h + 1 h + 2 h + 3 h + 4 N S1 A B S2 S3 h + 1 h + 2 h + 3 h + 4 N

29 Rotation simple S1 A B 2 S3 h + 1 h + 2 h + 3 h + 4 N S1 A B 2 S3 h + 1 h + 2 h + 3 h + 4 N avantaprès S2

30 Rotation simple S1 A B 2 S3 h + 1 h + 2 h + 3 h + 4 N S1 A B 2 S3 h + 1 h + 2 h + 3 h + 4 N avantaprès S2

31 Rotation simple S1 A B 2 S3 h + 1 h + 2 h + 3 h + 4 N S1 A B 2 S3 h + 1 h + 2 h + 3 h + 4 N avantaprès S2

32 S1 A B 2 S3 h + 1 h + 2 h + 3 h + 4 N Rotation simple hauteur initiale vs hauteur finale S1 A B S2 S3 h + 1 h + 2 h + 3 h + 4 N avantaprès S2

33 Rotation double S1 A B S2 S3 h + 1 h + 2 h + 3 h + 4 N S1 A B S2.1 S3 h + 1 h + 2 h + 3 h + 4 N S2.2 C

34 Rotation double S1 A B S2.1 S3 h + 1 h + 2 h + 3 h + 4 N S2.2 C S1 A B S2.1 S3 h + 1 h + 2 h + 3 h + 4 N S2.2 C avantaprès

35 Rotation double S1 A B S2.1 S3 h + 1 h + 2 h + 3 h + 4 N S2.2 C S1 B S2.1 S3 h + 1 h + 2 h + 3 h + 4 N S2.2 C A avantaprès

36 Rotation double S1 B S3 h + 1 h + 2 h + 3 h + 4 N S2.2 C S1 B S3 h + 1 h + 2 h + 3 h + 4 N C A A S2.1 S2.2 avantaprès

37 Rotation double S1 B S3 h + 1 h + 2 h + 3 h + 4 N S2.2 C S1 A B S2.1 S3 h + 1 h + 2 h + 3 h + 4 N S2.2 C hauteur initiale vs hauteur finale A S2.1 avantaprès

38 1 re rotation B S3 h + 1 h + 2 h + 3 h + 4 N S2.2 S1 A B S2.1 S3 h + 1 h + 2 h + 3 h + 4 N S2.2 C S2.1 S1 C A avantaprès

39 2 e rotation B S3 h + 1 h + 2 h + 3 h + 4 N S2.2 S2.1 S1 C A S1 B S3 h + 1 h + 2 h + 3 h + 4 N S2.2 C A S2.1 avantaprès

40 Nœud critique Mais ce nest pas toujours le cas 12 31 4 Ici, le nœud critique du déséquilibre est la racine 1 Quand il y a un déséquilibre, le nœud le plus bas à partir duquel il y a une différence de 2 ou plus est appelé le nœud critique.

41 Nœud critique Il peut parfois y avoir plusieurs nœuds débalancés. Dans ce cas, on soccupe dabord du plus bas de tous, cest le nœud critique.

42 Maintien de léquilibre Quand on implémente un arbre AVL, il faut maintenir son équilibre. Les déséquilibres surviennent soit lors dun ajout, soit lors dune suppression. Le ou les nœuds critiques engendrés, sil y a lieu, sont toujours sur le chemin de lajout ou de la suppression. Nouveau noeud

43 Rééquilibrer un arbre déséquilibré Quand un déséquilibre apparaît, il faut remodeler la partie de larbre dont la racine est le nœud critique. Nouveau noeud

44 Trouver le cas de déséquilibre Il faut dabord identifier le genre de déséquilibre auquel on a affaire. Dabord, il faut voir de quel côté larbre penche à partir du nœud critique. Dans le cas de lexemple ci-bas, cest vers la gauche. Nouveau noeud

45 Trouver le cas de déséquilibre Puis il faut regarder de quel côté penche larbre à partir du nœud sous- critique: il penche vers la droite: deux rotations sont nécessaires. Nous appelons ça un zig-zag. Nœud critique Nœud critique Nœud sous-critique Nœud sous-critique Nouveau noeud

46 Les rotations Nœud critique Nœud critique Nœud sous-critique Nœud sous-critique Nouveau noeud Première rotation (préparatoire à la deuxième).

47 Les rotations Première rotation (préparatoire à la deuxième). Nœud critique Nœud critique Nouveau noeud

48 Les rotations Première rotation (préparatoire à la deuxième). Nœud critique Nœud critique Nouveau noeud

49 Les rotations Première rotation (préparatoire à la deuxième). Nœud critique Nœud critique Ancien nœud sous-critique Nouveau noeud Nœud nouvellement sous-critique Nœud nouvellement sous-critique

50 Les rotations Deuxième rotation. Nœud critique Nœud critique Nouveau noeud

51 Les rotations Deuxième rotation. Nouveau noeud

52 Les rotations Deuxième rotation. Nouveau noeud

53 Les rotations Deuxième rotation. Nouveau noeud

54 Les rotations Les deux rotations sont terminées, nous avons maintenant un arbre AVL équilibré. Nouveau noeud

55 Implémentation : remarques indice de débalancement : tag = hauteur(gauche) - hauteur(droit) valeurs : 2, 1, 0, -1, -2 calcul de hauteur(gauche) - hauteur(droit) au parcours dinsertion + stockage de la hauteur mise à jour un seul rebalancement requis la racine de larbre rebalancé a changé

56 Modèle dimplantation arbre AVL template class Arbre { public: //.. private: // classe Noeud class Noeud { public: E data; Noeud *gauche; Noeud *droite; int card; int hauteur; Noeud( const E&d ): gauche(0),data( d ),droite(0),hauteur(0) { } }; // Les membres données Noeud * racine;//racine de l'arbre //... };... data Modèle dimplantation par chaînage

57 template int Arbre :: _hauteur(Noeud *arb) { if (arb == 0) return -1; return arb->hauteur; } template int Arbre :: _maximum(int ent1, int ent2) { if (ent1 <= ent2) return ent2; else return ent1; } deux méthodes utiles.. Insertion dans un arbre AVL

58 Algorithme insereAvl (Nœud* & T, int x) Début Si T = NULL, alors Début Allocation de mémoire à l'adresse T T.element = x T. filsG = NULL et T. filsD = NULL T.hauteur = 0 Fin Sinon Début Si x < T.element, alors Appel insereAvl(T.filsG, x) Si Hauteur (T.filsG)-Hauteur (T.filsD) = 2 alors Si x < T. filsG.element, alors Appel ZigZigGauche (T) Sinon Appel ZigZagGauche (T) Sinon T.hauteur =Max(Hauteur (T.filsG),Hauteur (T.filsD))+1 Sinon Début /* Cas symétrique pour le sous-arbre droit */ Fin

59 algorithme ZigZigGauche (Nœud* &K2) Début K1 = K2.filsG K2.filsG = K1.filsD K1.filsD = K2 K2.hauteur = Max (Hauteur (K2.filsG), Hauteur (K2.filsD)) +1 K1.hauteur = Max (Hauteur (K1.filsG), K2.hauteur) +1 K2 = K1 Fin + k2 k1 k2 k1

60 algorithme ZigZigDroit (Nœud* &K2) Début K1 = K2.filsD K2.filsD = K1.filsG K1.filsG = K2 K2.hauteur = Max (Hauteur (K2.filsD), Hauteur (K2.filsG)) +1 K1.hauteur = Max (Hauteur (K1.filsD), K2.hauteur) +1 K2 = K1 Fin simple rotation, déséquilibre vers la gauche k2 k1

61 algorithme ZigZagGauche (Nœud * &K3) Début ZigZigDroit (K3.filsG) ZigZigGauche (K3) Fin + k3

62 algorithme ZigZagDroit (Nœud * &K3) Début ZigZigGauche (K3.filsD) ZigZigDroit (K3) Fin + k3

63 template void Arbre :: _zigZigDroit(Noeud * &K2) { Noeud *K1; K1 = K2->droite; K2->droite = K1->gauche; K1->gauche = K2; K2->hauteur = 1 + _maximum(_hauteur(K2->droite), _hauteur(K2->gauche)); K1->hauteur = 1 + _maximum(_hauteur(K1->droite), K2->hauteur); K2 = K1; } Implémentation dune rotation 25 45 8 48 38 36 26 17 40 25 45 8 48 38 36 26 17 40 13 28 13

64 Analyse insertion balancée : trouver le point dinsertion : O(log n) insertion dune feuille : O(1) + vérification et rebalancement: on remonte (suite aux appels récursifs) : O(log n) on vérifie le rebalancement possible : O(1) on rebalance au besoin : O(1) total : O(log n)

65 Enlèvement dans un arbre AVL Pour supprimer un nœud dans un arbre AVL, il y a deux cas simples et un cas compliqué: Premier cas simple: le nœud à supprimer est une feuille. Dans ce cas, il suffit de le supprimer directement. Deuxième cas simple: le nœud à supprimer possède un seul enfant. Dans ce cas, il suffit de le supprimer et de le remplacer par son seul enfant. Cas compliqué: le nœud à supprimer a deux enfants. Dans ce cas, il faut dabord échanger ce nœud avec son successeur, puis le supprimer à son nouvel endroit, ce qui nous mènera nécessairement à lun des deux cas simples. Bien entendu, il faut aussi vérifier les déséquilibres en remontant jusquà la racine. Lalgorithme fonctionne aussi bien si on prend le prédécesseur plutôt que le successeur. Étant donné que la nécessité de retrouver le successeur ne survient que dans le cas où le nœud a deux enfants, alors nous sommes nécessairement toujours en présence du cas simple de recherche du successeur! Ainsi, une simple boucle suffit.

66 Enlèvement dans un arbre AVL une feuille : trivial 48 Analyse : l algorithme de suppression d un nœud présente donc 3 cas : 34 3020 23 5O 45 gauche 48 droit 29 48 34 3020 23 5O 45 29

67 Enlèvement dans un arbre AVL un nœud simple : on le remplace par son unique fils 50 Deuxième cas de nœud à supprimer 34 3020 23 5O 45 gauche 48 droit 29 50 34 3020 23 48 29 45

68 Enlèvement dans un arbre AVL 23 un nœud double : on lui donne la valeur minimale de son sous-arbre droit (ex: 29), et on supprime le nœud qui a cette valeur Troisième cas de nœud à supprimer 34 3020 23 5O 45 gauche 48 droit 29 23 5O 34 302045 48 29

69 68 Exemple denlèvement AVL Supprimons le nœud 36 de cet arbre-ci. Il faut dabord le repérer avec une recherche conventionnelle à partir de la racine. 50 25 70 13 45 85 8 48 28 39 36 60 26 64 90 55 62 17 40 38 37

70 69 Puis, nous établissons quil sagit dun cas compliqué car le nœud à supprimer a deux enfants. 50 25 70 13 45 85 8 48 28 39 36 60 26 64 90 55 62 17 40 38 37 Exemple denlèvement AVL

71 70 Il faut donc dabord retrouver son successeur à laide dune boucle simple (une fois à droite, plein de fois à gauche). 50 25 70 13 45 85 8 48 28 39 36 60 26 64 90 55 62 17 40 38 37 Exemple denlèvement AVL

72 71 Puis on léchange avec. 50 25 70 13 45 85 8 48 28 39 36 60 26 64 90 55 62 17 40 38 37 Exemple denlèvement AVL

73 72 Puis on léchange avec. 50 25 70 13 45 85 8 48 28 39 36 60 26 64 90 55 62 17 40 38 37 Exemple denlèvement AVL

74 73 Puis on léchange avec. 50 25 70 13 45 85 8 48 28 39 36 60 26 64 90 55 62 17 40 38 37 Exemple denlèvement AVL

75 74 Puis on léchange avec. 50 25 70 13 45 85 8 48 28 39 36 60 26 64 90 55 62 17 40 38 37 Exemple denlèvement AVL

76 75 Puis on léchange avec. 50 25 70 13 45 85 8 48 28 39 36 60 26 64 90 55 62 17 40 38 37 Exemple denlèvement AVL

77 76 Remarquez que la règle dordonnancement darbre binaire de recherche est temporairement enfreinte. 50 25 70 13 45 85 8 48 28 39 36 60 26 64 90 55 62 17 40 38 37 Exemple denlèvement AVL

78 77 Ensuite, on continue à descendre récursivement pour supprimer 36, comme si rien nétait. 50 25 70 13 45 85 8 48 28 39 36 60 26 64 90 55 62 17 40 38 37 Exemple denlèvement AVL

79 78 Puis lorsquon retombe sur 36, on arrive nécessairement à lun des deux cas simple. 50 25 70 13 45 85 8 48 28 39 36 60 26 64 90 55 62 17 40 38 37 Exemple denlèvement AVL

80 79 Dans ce cas-ci, il sagit du cas avec un seul enfant. 36 sera donc remplacé par 38. 50 25 70 13 45 85 8 48 28 39 36 60 26 64 90 55 62 17 40 38 37 Exemple denlèvement AVL

81 80 Dans ce cas-ci, il sagit du cas avec un seul enfant. 36 sera donc remplacé par 38. 50 25 70 13 45 85 8 48 28 39 36 60 26 64 90 55 62 17 40 38 37 Exemple denlèvement AVL

82 81 Dans ce cas-ci, il sagit du cas avec un seul enfant. 36 sera donc remplacé par 38. 50 25 70 13 45 85 8 48 28 39 60 26 64 90 55 62 17 40 38 37 Exemple denlèvement AVL

83 82 Puis le nœud 36 est détruit avec « delete ». Ensuite, il faut remonter jusquà la racine pour vérifier léquilibre de larbre. 50 25 70 13 45 85 8 48 28 39 60 26 64 90 55 62 17 40 38 37 00 Exemple denlèvement AVL

84 83 Puis le nœud 36 est détruit avec « delete ». Ensuite, il faut remonter jusquà la racine pour vérifier léquilibre de larbre. 50 25 70 13 45 85 8 48 28 39 60 26 64 90 55 62 17 40 38 37 11 Exemple denlèvement AVL

85 84 Puis le nœud 36 est détruit avec « delete». Ensuite, il faut remonter jusquà la racine pour vérifier léquilibre de larbre. 50 25 70 13 45 85 8 48 28 39 60 26 64 90 55 62 17 40 38 37 21 Exemple denlèvement AVL

86 85 Puis le nœud 36 est détruit avec « delete ». Ensuite, il faut remonter jusquà la racine pour vérifier léquilibre de larbre. 50 25 70 13 45 85 8 48 28 39 60 26 64 90 55 62 17 40 38 37 33 Exemple denlèvement AVL

87 86 Puis le nœud 36 est détruit avec « delete ». Ensuite, il faut remonter jusquà la racine pour vérifier léquilibre de larbre. 50 25 70 13 45 85 8 48 28 39 60 26 64 90 55 62 17 40 38 37 44 Exemple denlèvement AVL

88 template void Arbre ::enlever(const E& data) throw(logic_error) { if( racine == 0 ) throw logic_error("Enlever: l'arbre est vide\n"); if( _auxAppartient(racine, data) == 0 ) throw logic_error("Enlever: l'element nest pas dans l'arbre\n"); _auxEnlever(racine, data); //data est certain dans l'arbre } Enlèvement dans un arbre de tri Enlèvement sans balancement

89 template void Arbre :: _auxEnlever(Noeud * & t, const E & valeur) throw(logic_error) { if( t->data > valeur) _auxEnlever( t->gauche, valeur); else if( t->data < valeur ) _auxEnlever( t->droite, valeur); else if( t->gauche != 0 && t->droite != 0 ) {//Troisième cas //chercher le noeud qui contient la valeur minimale dans le sous-arbre droit Noeud * temp = t->droite; while ( temp->gauche != 0) temp = temp->gauche; t->data = temp->data; _auxRetireMin( t->droite ); // Retirer minimum dans le sous-arbre droit } else { //Premier ou deuxième cas // le noeud n'a aucun enfant ou qu'un seul enfant, il suffit donc de retirer // ce noeud et pointer sur l'éventuel enfant Noeud * vieuxNoeud = t; t = ( t->gauche != 0 ) ? t->gauche : t->droite; delete vieuxNoeud; }

90 template void Arbre :: _auxRetireMin( Noeud* & t) const throw(logic_error) { if (t == 0) throw logic_error("_auxRetireMin: pointeur NULL\n"); else if (t->gauche != 0) _auxRetireMin( t->gauche ); else { Noeud * tmp = t; t = t->droite; delete tmp; }

91 Analyse enlèvement balancé : plusieurs rebalancements possiblement requis la racine de tout arbre rebalancé a changé trouver le nœud à enlever (déjà vu) : O(log n) + vérification et rebalancement: on remonte (suite aux appels récursifs) : O(log n) on vérifie le rebalancement possible : O(1) on rebalance au besoin : O(1) total : O(log n) (mais plus coûteux que linsertion)

92 problèmes : remonter vers les parents : fonction parent à partir dun nœud retour par les appels récursifs espace à gérer : accès par pile : quelle est la taille de la pile ? combien de piles a-t-on besoin ? pour de nombreux usagers = trop despace ! Parcours avec pile

93 Peut-on éliminer les piles ? ajouter un pointeur vers le parent problèmes : ne jamais perdre le parent lors de lajout beaucoup despace perdu complique les rebalancements Parcours avec pile

94 Arbres cousus Peut-on éliminer les piles ? ajouter un pointeur vers le parent ajouter un pointeur vers le succ./préd. problèmes : - complique les ajouts - complique les rebalancements - il faut éviter les cycles

95 Arbres cousus class Noeud { public: E data; /* élément */ Noeud *gauche; /* ptr sur SAG ou prédécesseur */ Noeud *droite; /* ptr sur SAD ou successeur */ bool filGauche;/* indique si gauche est un fil ou non */ bool filDroit;/* indique si droite est un fil ou non */ //… }; Comment reconnaître les cycles ? utiliser un «tag» avec chaque pointeur

96 Arbres n-aires (pour n fixe) critère de branchement multiple exemples ? arbres-B analyse lexicale : 1 re lettre, 2 e lettre, etc. …

97 Arbres n-aires (pour n fixe) template class Arbre { public: //.. private: // classe Noeud class Noeud { public: E data; Noeud ** fils; int card; Noeud(const E&d ) { …} }; // Les membres données Noeud * racine;//racine de l'arbre //... };... data

98 Arbres n-aires (pour n variable) nombre de branchements inconnu au départ nombre de branchements très variable exemples ? structure organisationnelle analyse lexicale autres ?

99 Arbres n-aires variables modèles dimplantation ? tableau dynamique ou liste de pointeurs

100 Arbres n-aires variables modèles dimplantation ? vector ou liste de pointeurs

101 Arbres n-aires variables template class Arbre { public: //.. private: // classe Noeud class Noeud { public: E data; vector fils; int card; Noeud(const E&d ) { …} }; // Les membres données Noeud * racine;//racine de l'arbre //... };... data

102 Arbres n-aires variables modèles dimplantation ? tableau dynamique ou liste de pointeurs 2 types de pointeurs : 1 er fils, frère cadet

103 Arbres n-aires variables modèles dimplantation ? tableau dynamique ou liste de pointeurs 2 types de pointeurs : 1 er fils, frère cadet

104 Arbres n-aires variables modèles dimplantation ? tableau dynamique ou liste de pointeurs 2 types de pointeurs : 1 er fils, frère cadet

105 Arbres n-aires variables modèles dimplantation ? tableau dynamique ou liste de pointeurs 2 types de pointeurs : 1er fils, frère cadet


Télécharger ppt "Structures de données IFT-2000 Abder Alikacem Semaine 11 Gestion des arbres binaires de tri et de recherche. Les arbres cousus. Les arbres n-aires Département."

Présentations similaires


Annonces Google