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

IFT-2000: Structures de Données Les arbres. Arbre Un arbre est une structure dans laquelle on a un nœud qui est une racine, puis chaque nœud a zéro, un.

Présentations similaires


Présentation au sujet: "IFT-2000: Structures de Données Les arbres. Arbre Un arbre est une structure dans laquelle on a un nœud qui est une racine, puis chaque nœud a zéro, un."— Transcription de la présentation:

1 IFT-2000: Structures de Données Les arbres

2 Arbre Un arbre est une structure dans laquelle on a un nœud qui est une racine, puis chaque nœud a zéro, un ou plusieurs enfants. Les nœuds qui nont pas denfants sont appelées des feuilles. Feuille Racine Feuille

3 Arbre binaire Un arbre est dit binaire si chacun de ses nœuds comporte un maximum de deux enfants.

4 Arbre binaire de recherche Un arbre binaire est dit de recherche sil respecte la règle suivante: Pour chaque nœud, tous ses descendants de gauche comportent des valeurs plus petites que lui, et tous ses descendants de droite comportent des valeurs plus grandes que lui

5 Implémentation dune recherche simple typedef struct nœud { float valeur; struct nœud *enfant_de_gauche; // 0 sil ny a pas denfant de gauche. struct nœud *enfant_de_droite; // 0 sil ny a pas denfant de droite. } Noeud; Bool est_present(const Nœud *racine, float nombre) { }

6 Implémentation dune fonction qui compte les noeuds typedef struct nœud { float valeur; struct nœud *enfant_de_gauche; // 0 sil ny a pas denfant de gauche. struct nœud *enfant_de_droite; // 0 sil ny a pas denfant de droite. } Noeud; int nb_noeuds(const Nœud *racine) { }

7 Définitions La hauteur dun arbre est le nombre de rangées quil comporte Hauteur: 3

8 Implémentation de la fonction hauteur typedef struct nœud { float valeur; struct nœud *enfant_de_gauche; // 0 sil ny a pas denfant de gauche. struct nœud *enfant_de_droite; // 0 sil ny a pas denfant de droite. } Noeud; int hauteur(const Nœud *racine) { }

9 Structure pour larbre avec un point dentrée typedef struct nœud { float valeur; struct nœud *enfant_de_gauche; // 0 sil ny a pas denfant de gauche. struct nœud *enfant_de_droite; // 0 sil ny a pas denfant de droite. } Noeud; typedef struct { Nœud *racine; // 0 si larbre est vide. int nb_noeuds; // Ce champ est optionel, mais il permet daccélérer les requêtes sur la taille. } Arbre; Int hauteur(const Nœud *racine) { // … } int hauteur(const Arbre *arbre) { return hauteur(arbre->racine); }

10 Clé de recherche Une clé de recherche doit toujours être choisie, afin détablir la relation dordre qui régit la position des nœuds. Dautres information peut être emmagasinée dans chaque nœud. Dans lexemple ci-bas, la clé de recherche est le prénom, et linformation complémentaire est lâge. La relation dordre utilisée pour déterminer la position relative des nœuds est la comparaison lexicographique (cest-à- dire lordre alphabétique) des prénoms. Claude 55 Jean 40 Dominic 31 Françis 35 Nestor 5

11 Implémentation dune recherche par clé typedef struct nœud { char prenom[100]; int age; struct nœud *enfant_de_gauche; // 0 sil ny a pas denfant de gauche. struct nœud *enfant_de_droite; // 0 sil ny a pas denfant de droite. } Noeud; int trouve_age(const Nœud *racine, const char *prenom) { }

12 Ajout (non équilibré) typedef struct nœud { char prenom[100]; int age; struct nœud *enfant_de_gauche; // 0 sil ny a pas denfant de gauche. struct nœud *enfant_de_droite; // 0 sil ny a pas denfant de droite. } Noeud; Nœud *ajouter(Nœud *racine, const char *prenom, int age) { }

13 Arbre binaire de recherche équilibré Un arbre binaire de recherche est dit équilibré (ou balancé) quand on lui impose un critère sur la position de ses nœuds, et que ce critère permet de maintenir une hauteur de lordre du logarithme du nombre de nœuds quil comporte. Arbre bien équilibréArbre mal équilibré

14 Arbre binaire de recherche AVL Il existe deux façons bien connues déquilibrer les arbres binaires de recherche: Les arbres AVL, et les arbres Rouge-Noir. Pour le cours de Structures de Données, nous ne nous attarderons quaux arbres AVL. Dans un arbre AVL, la règle de léquilibre est la suivante: Pour chaque nœud, la hauteur de son sous- arbre de gauche et celle de son sous-arbre de droite doivent différer dau maximum 1.

15 Équilibre AVL Bien équilibré selon la règle AVL Mal équilibré selon la règle AVL 1

16 Nœud critique Mais ce nest pas toujours le cas 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.

17 Plusieurs nœuds critiques Il peut parfois y avoir plusieurs nœuds critiques. Dans ce cas, on soccupe dabord du plus bas de tous.

18 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

19 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

20 Les quatre 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

21 Les quatre cas de déséquilibre Lenfant immédiat du nœud critique du côté vers lequel larbre penche sappelle le nœud sous-critique. Nœud critique Nœud critique Nœud sous-critique Nœud sous-critique Nouveau noeud

22 Les quatre cas de déséquilibre Puis il faut regarder de quel côté penche larbre à partir du nœud sous-critique. Larbre sous-critique na pas besoin dêtre déséquilibré pour quon considère quil penche. Une différence de 1 suffit pour identifier le cas (contrairement à la vérification quon faisait au départ pour vérifier sil y avait déséquilibre). Dans lexemple ci-bas, larbre sous-critique penche vers la droite. Nœud critique Nœud critique Nœud sous-critique Nœud sous-critique Nouveau noeud

23 Les quatre cas de déséquilibre Nous avons donc, dans cet exemple-ci, un déséquilibre vers la gauche, avec un arbre sous-critique qui penche vers la droite. Quand le sens du déséquilibre principal est différent du sens dans lequel larbre sous-critique penche, alors deux rotations sont nécessaires. Nous appelons ça un zig-zag. Quand le sens du déséquilibre principal est le même que le sens dans lequel larbre sous-critique penche, ou bien que larbre sous-critique ne penche pas dutout, alors une seule rotation est nécessaire, et il sagit dun zig-zig. Dans notre exemple, nous aurons donc à faire deux rotations. Nœud critique Nœud critique Nœud sous-critique Nœud sous-critique Nouveau noeud

24 Les rotations Quand nous nous retrouvons dans le cas où il faut faire deux rotations, la première sert finalement à faire pencher larbre sous- critique dans le même sens que larbre critique, de façon à nous retrouver dans le cas simple dune seule rotation. Nœud critique Nœud critique Nœud sous-critique Nœud sous-critique Nouveau noeud

25 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).

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

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

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

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

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

31 Les rotations Nœud critique Nœud critique Ancien nœud sous-critique Nouveau noeud Nœud nouvellement sous-critique Nœud nouvellement sous-critique La première rotation est terminée. Grâce à cette première rotation, nous avons retrouvé un cas de rotation simple, car larbre sous-critique penche maintenant dans le même sens que le déséquilibre au nœud critique.

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

33 Les rotations Nouveau noeud Deuxième rotation.

34 Les rotations Nouveau noeud Deuxième rotation.

35 Les rotations Nouveau noeud Deuxième rotation.

36 Les rotations Nouveau noeud Deuxième rotation.

37 Les rotations Nouveau noeud Deuxième rotation.

38 Les rotations Nouveau noeud Deuxième rotation.

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

40 Les rotations Voici un autre exemple dajout. Celui-ci engendre un cas simple de déséquilibre, car larbre sous-critique penche dans le même sens que le déséquilibre au nœud critique. Supposons que nous ajoutons un nœud avec la valeur de clé 40 à larbre ci-bas. 40

41 Les rotations < Ajout de

42 Les rotations < Ajout de

43 Les rotations < Ajout de

44 Les rotations 50 > Ajout de

45 Les rotations 50 > Ajout de

46 Les rotations > Ajout de

47 Les rotations > Ajout de

48 Les rotations < Ajout de

49 Les rotations < Ajout de

50 Les rotations > Ajout de

51 Les rotations > Ajout de

52 Les rotations La position du nouveau nœud 40 a été déterminée. On doit donc, en remontant, vérifier si larbre est déséquilibré. 40

53 Les rotations On vérifie léquilibre nœud par nœud, en remontant le long du chemin parcouru depuis la racine

54 Les rotations On vérifie léquilibre nœud par nœud, en remontant le long du chemin parcouru depuis la racine

55 Les rotations On vérifie léquilibre nœud par nœud, en remontant le long du chemin parcouru depuis la racine

56 Les rotations On vérifie léquilibre nœud par nœud, en remontant le long du chemin parcouru depuis la racine. Un déséquilibre est détecté au nœud

57 Les rotations On vérifie léquilibre nœud par nœud, en remontant le long du chemin parcouru depuis la racine. Un déséquilibre est détecté au nœud 25. Le nœud sous-critique est le nœud

58 Les rotations On constate que larbre sous-critique penche dans le même sens que le déséquilibre au nœud critique. On aura donc une seule rotation à faire. 40

59 Les rotations On a une seule rotation à faire. 40

60 Les rotations On a une seule rotation à faire. 40

61 Les rotations On a une seule rotation à faire. 40

62 Les rotations On a une seule rotation à faire. 40

63 Les rotations On a une seule rotation à faire. 40

64 Les rotations On a une seule rotation à faire. 40

65 Les rotations On a une seule rotation à faire. Nous avons donc rééquilibré larbre à partir du nœud critique que nous avions. Il reste encore à vérifier léquilibre pour le reste du chemin en remontant à la racine, car il pourrait y en avoir dautres. 40

66 Les rotations On a une seule rotation à faire. Nous avons donc rééquilibré larbre à partir du nœud critique que nous avions. Il reste encore à vérifier léquilibre pour le reste du chemin en remontant à la racine, car il pourrait y en avoir dautres. 40

67 Les rotations En loccurrence, il ne reste quà vérifier quil ny a pas de déséquilibre au nœud

68 Les rotations On a une seule rotation à faire. Nous avons donc rééquilibré larbre à partir du nœud critique que nous avions. Il reste encore à vérifier léquilibre pour le reste du chemin en remontant à la racine, car il pourrait y en avoir dautres. 40

69 Implémentation dune rotation Nœud *rotation_gauche(Nœud *racine) { Nœud *nouvelle_racine=racine->droite; racine->droite = nouvelle_racine->gauche; nouvelle_racine->gauche = racine; return nouvelle_racine; }

70 Implémentation dun rééquilibre Nœud *reequilibrer_si_necessaire(Nœud *racine) { int diff; if(!racine) return racine; diff = hauteur(racine->droite)-hauteur(racine->gauche); if(diff>1) { Nœud *sous_critique = racine->droite; int diff_sous_critique = hauteur(sous_critique->droite)-hauteur(sous_critique->gauche); if(diff_sous_critique<0) sous_critique = rotation_droite(sous_critique); racine=rotation_gauche(racine); } else if(diff<-1) { Nœud *sous_critique = racine->gauche; int diff_sous_critique = hauteur(sous_critique->droite)-hauteur(sous_critique->gauche); if(diff_sous_critique>0) sous_critique = rotation_gauche(sous_critique); racine=rotation_droite(racine); } return racine; }

71 Intégration du rééquilibre dans lalgorithme dajout Nœud *ajout(Nœud *racine, float nouvelle_valeur) { if(!racine) { racine = malloc(sizeof(Nœud)); racine->gauche=racine->droite=0; racine->valeur = nouvelle_valeur; } else if(nouvelle_valeur valeur) racine->gauche = ajout(racine->gauche,nouvelle_valeur); else if(nouvelle_valeur>racine->valeur) racine->droite = ajout(racine->droite,nouvelle_valeur); return reequilibrer_si_necessaire(racine); }

72 Algorithme de recherche du successeur Dans un ensemble ordonné, le successeur dune valeur est la valeur qui la suit immédiatement dans lordre. Par exemple, dans lensemble ordonné { 3, 6, 7, 12, 17, 18, 22 }, le successeur de 12 est 17, le successeur de 3 est 7, et 22 na pas de successeur.

73 Algorithme de recherche du successeur Dans un arbre AVL, le successeur peut être découvert en descendant une fois à droite, puis autant de fois que lon peut à gauche. Par exemple, dans cet arbre-ci, le successeur de 50 est

74 Algorithme de recherche du successeur Le successeur de 70 est 85. En effet, on descend une fois à droite, et on va à gauche tant et aussi longtemps quon le peut, mais ça cest bien sil y a un enfant de gauche. Sinon, on a déjà trouvé le successeur

75 Algorithme de recherche du successeur Comment faire pour retrouver le successeur dun nœud qui na pas denfant de droite? Par exemple, comment faire pour trouver le successeur de 28?

76 Algorithme de recherche du successeur Ce quil faut faire, dans ce cas, cest remonter de parent en parent jusquà ce que ce soit vers la droite que se trouve le parent. Dès que lon a remonté une fois vers la droite, alors nous avons le successeur

77 Algorithme de recherche du successeur Si, par ce processus, on aboutit à la racine en nayant jamais remonté à droite, cest alors parce que le nœud na pas de successeur

78 Implémentation de lalgorithme de recherche du successeur Nœud *successeur(Nœud *racine, float valeur) { if(!racine) { ??? (nous aborderons ce cas plus tard) } // Il faut dabord retrouver le nœud dont on cherche le successeur. if(valeur valeur) return successeur(racine->gauche,valeur); else if(valeur>racine->valeur) return successeur(racine->droite,valeur); else if(valeur==racine->valeur) // On a trouvé le nœud dont on cherche le successeur. if(racine->droite) // Cas simple { Nœud *i=racine->droite; //Une fois à droite while(i->gauche) i=i->gauche; // À gauche tant et aussi longtemps quon peut. return i; } else // Cas compliqué { // Comment faire quand le nœud dont on cherche le successeur na pas denfant de droite? }

79 Implémentation de lalgorithme de recherche du successeur Pour résoudre le cas compliqué, lastuce est la suivante: la fonction récursive retourne tout simplement zéro comme réponse! Cela est pour signifier à lappelant que cet appel-ci na pas été capable de trouver le successeur. Puis, à lendroit où la fonction fait un appel récursif sur lenfant de gauche, avant de retourner simplement la réponse reçue, on vérifie si cest zéro qui a été retourné. Si cest le cas, alors le successeur est précisément le nœud « racine »!

80 Implémentation de lalgorithme de recherche du successeur Nœud *successeur(Nœud *racine, float valeur) { if(!racine) { ??? } if(valeur valeur) { Nœud *s = successeur(racine->gauche,valeur); if(s==0) return racine; // Ceci résout le cas compliqué! return s; } else if(valeur>racine->valeur) return successeur(racine->droite,valeur); else if(valeur==racine->valeur) // On a trouvé le nœud dont on cherche le successeur. if(racine->droite) // Cas simple { Nœud *i=racine->droite; while(i->gauche) i=i->gauche; return i; } else return 0; // Cas compliqué: on retourne zéro! }

81 Implémentation de lalgorithme de recherche du successeur Dans le cas où la valeur dont on cherche le successeur nest pas présente dans larbre, on pourrait avoir comme réflexe de retourner un code derreur. Par contre, il faut sauter sur loccasion pour implémenter un algorithme bien plus puissant, puis de retourner quand même le successeur de cette valeur. Pour ce faire, il suffit de retourner zéro, et la même ligne de code qui réglait le cas compliqué retournera la bonne valeur pour le cas où la valeur est introuvable.

82 Implémentation de lalgorithme de recherche du successeur Nœud *successeur(Nœud *racine, float valeur) { if(!racine) return 0; // Ceci sera résolu de la même façon que le cas compliqué. if(valeur valeur) { Nœud *s = successeur(racine->gauche,valeur); if(s==0) return racine; // Ceci résout aussi le cas de la valeur absente dans larbre! return s; } else if(valeur>racine->valeur) return successeur(racine->droite,valeur); else if(valeur==racine->valeur) if(racine->droite) { Nœud *i=racine->droite; //Une fois à droite while(i->gauche) i=i->gauche; return i; } else return 0; }

83 Algorithme du prédécesseur Évidemment, pour implémenter lalgorithme de recherche du prédécesseur, il suffit de faire la même chose, mais en inversant gauche et droite.

84 Algorithme de suppression 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.

85 Exemple de suppression AVL Supprimons le nœud 36 de cet arbre-ci. Il faut dabord le repérer avec une recherche conventionnelle à partir de la racine

86 Exemple de suppression AVL Puis, nous établissons quil sagit dun cas compliqué car le nœud à supprimer a deux enfants

87 Exemple de suppression AVL Il faut donc dabord retrouver son successeur à laide dune boucle simple (une fois à droite, plein de fois à gauche)

88 Exemple de suppression AVL Puis on léchange avec

89 Exemple de suppression AVL Puis on léchange avec

90 Exemple de suppression AVL Puis on léchange avec

91 Exemple de suppression AVL Puis on léchange avec

92 Exemple de suppression AVL Puis on léchange avec

93 Exemple de suppression AVL Puis on léchange avec

94 Exemple de suppression AVL Puis on léchange avec

95 Exemple de suppression AVL Puis on léchange avec

96 Exemple de suppression AVL Puis on léchange avec

97 Exemple de suppression AVL Puis on léchange avec

98 Exemple de suppression AVL Puis on léchange avec

99 Exemple de suppression AVL Puis on léchange avec

100 Exemple de suppression AVL Puis on léchange avec

101 Exemple de suppression AVL Puis on léchange avec

102 Exemple de suppression AVL Puis on léchange avec

103 Exemple de suppression AVL Puis on léchange avec

104 Exemple de suppression AVL Puis on léchange avec

105 Exemple de suppression AVL Remarquez que la règle dordonnancement darbre binaire de recherche est temporairement enfreinte

106 Exemple de suppression AVL Ensuite, on continue à descendre récursivement pour supprimer 36, comme si rien nétait

107 Exemple de suppression AVL Puis lorsquon retombe sur 36, on arrive nécessairement à lun des deux cas simple

108 Exemple de suppression AVL Dans ce cas-ci, il sagit du cas avec un seul enfant. 36 sera donc remplacé par

109 Exemple de suppression AVL Dans ce cas-ci, il sagit du cas avec un seul enfant. 36 sera donc remplacé par

110 Exemple de suppression AVL Dans ce cas-ci, il sagit du cas avec un seul enfant. 36 sera donc remplacé par

111 Exemple de suppression AVL Dans ce cas-ci, il sagit du cas avec un seul enfant. 36 sera donc remplacé par

112 Exemple de suppression AVL Dans ce cas-ci, il sagit du cas avec un seul enfant. 36 sera donc remplacé par

113 Exemple de suppression AVL Dans ce cas-ci, il sagit du cas avec un seul enfant. 36 sera donc remplacé par

114 Exemple de suppression AVL Puis le nœud 36 est détruit avec « free ». Ensuite, il faut remonter jusquà la racine pour vérifier léquilibre de larbre

115 Exemple de suppression AVL Puis le nœud 36 est détruit avec « free ». Ensuite, il faut remonter jusquà la racine pour vérifier léquilibre de larbre

116 Exemple de suppression AVL Puis le nœud 36 est détruit avec « free ». Ensuite, il faut remonter jusquà la racine pour vérifier léquilibre de larbre

117 Exemple de suppression AVL Puis le nœud 36 est détruit avec « free ». Ensuite, il faut remonter jusquà la racine pour vérifier léquilibre de larbre

118 Exemple de suppression AVL Puis le nœud 36 est détruit avec « free ». Ensuite, il faut remonter jusquà la racine pour vérifier léquilibre de larbre

119 Les parcours darbre Parcours symétrique (donne les nœuds en ordre croissant): – Gauche, racine, droite. Parcours anti-symétrique (donne les nœuds en ordre décroissant): – Droite, racine, gauche. Parcours par priorité aux pères (aucune interprétation simple): – Racine, gauche, droite (ou racine, droite, gauche). Parcours par priorité aux fils (aucune interprétation simple): – Gauche, droite, racine (ou droite, gauche, racine). Parcours rangée par rangée: – Ne peut pas simplémenter par une fonction récursive simple. On doit limplémenter comme un parcours de graphe par largeur, donc avec une file.

120 Implémentation de parcours darbre void parcours_symétrique(Nœud *racine) { if(!racine) return; parcours_symétrique(racine->gauche); traitement(racine); // Traitement quelconque. parcours_symétrique(racine->droite); } void parcours_anti_symétrique(Nœud *racine) { if(!racine) return; parcours_anti_symétrique(racine->droite); traitement(racine); parcours_anti_symétrique(racine->gauche); } void parcours_par_priorite_aux_peres(Nœud *racine) { if(!racine) return; traitement(racine); parcours_par_priorite_aux_peres (racine- >gauche); // Ça pourrait être droite avant gauche. parcours_par_priorite_aux_peres (racine->droite); } void parcours_par_priorite_aux_fils(Nœud *racine) { if(!racine) return; parcours_par_priorite_aux_fils (racine->gauche); // Ça pourrait être droite avant gauche. parcours_par_priorite_aux_fils (racine->droite); traitement(racine); }

121 Traces de parcours darbre Soit cet arbre-ci:

122 Traces de parcours darbre Parcours symétrique: 8, 13, 17, 25, 26, 28, 37, 38, 39, 40, 45, 48, 50, 55, 60, 62, 64, 70, 85,

123 Traces de parcours darbre Parcours anti-symétrique: 90, 85, 70, 64, 62, 60, 55, 50, 48, 45, 40, 39, 38, 37, 28, 26, 25, 17, 13,

124 Traces de parcours darbre Parcours par priorité aux pères (gauche avant droite): 50, 37, 25, 13, 8, 17, 28, 26, 45, 39, 38, 40, 48, 70, 60, 55, 64, 62, 85,

125 Traces de parcours darbre Parcours par priorité aux fils (gauche avant droite): 8, 17, 13, 26, 28, 25, 38, 40, 39, 48, 45, 37, 55, 62, 64, 60, 90, 85, 70,


Télécharger ppt "IFT-2000: Structures de Données Les arbres. Arbre Un arbre est une structure dans laquelle on a un nœud qui est une racine, puis chaque nœud a zéro, un."

Présentations similaires


Annonces Google