# solutions exercices arbres binaires et arbres binaires de recherche # (mercredi 8 juillet, matin) # à toutes fins utiles, on redonne la classe Noeud class Noeud: def __init__(self, g, v, d): self.gauche = g self.valeur = v self.droit = d ### exercice 1 ############################################################ # Il y a 5 arbres binaires possédant 3 noeuds # et 14 arbres binaires possédant 4 noeuds ### exercice 2 ############################################################ # Pour les dénombrer, on considère le noeud à la racine puis on # répartit les quatre noeuds restants entre le sous-arbre gauche et # le sous-arbre droit. Par exemple, on peut mettre un noeud dans # le sous-arbre gauche et trois dans le sous-arbre droit. Au total, il # y a cinq façons différentes de répartir les noeuds (0+4, 1+3, # 2+2, 3+1, 4+0). Pour chacune, on connaît le # nombre de sous-arbres possibles, ce qui donne la somme # # 1*14 + 1*5 + 2*2 + 5*1 + 14*1 # # soit un total de 42 arbres binaires possédant 5 noeuds. ### exercice 3 ############################################################ def affiche(a): if a is None: return print("(", end="") affiche(a.gauche) print(a.valeur, end="") affiche(a.droit) print(")", end="") ### exercice 4 ############################################################ # On peut le faire au choix avec une fonction récursive ou avec une # boucle. On choisit ici la seconde solution : def peigne_gauche(h): """construit un peigne gauche de hauteur h""" a = None while h > 0: a = Noeud(a, h, None) h -= 1 return a # Il est intéressant de noter que les noeuds de l'arbre sont ici # construits de bas en haut. C'est ce qui nous permet notamment de # l'écrire facilement avec une boucle. ### exercice 5 ############################################################ # On reprend les cinq arbres de l'exercice 1 et on les # étiquette correctement à chaque fois (il n'y a qu'une seule façon de le # faire à chaque fois. ### exercice 6 ############################################################ # C'est exactement la même réponse que celle de l'exercice précédent ! ### exercice 7 ############################################################ # par définition d'un ARB, le plus petit élément se trouve en bas à # gauche de l'arbre. def minimum(a): if a is None: return None if a.gauche is None: return a.valeur else: return minimum(a.gauche) ### exercice 8 ############################################################ def ajoute(x, a): if a is None: return Noeud(None, x, None) if x < a.valeur: return Noeud(ajoute(x, a.gauche), a.valeur, a.droit) elif x > a.valeur: return Noeud(a.gauche, a.valeur, ajoute(x, a.droit)) else: return a # x est dans a ### exercice 9 ############################################################ def compte(x, a): if a is None: return 0 if x < a.valeur: return compte(x, a.gauche) elif x > a.valeur: return compte(x, a.droit) else: return 1 + compte(x, a.gauche) + compte(x, a.droit) ### exercice 10 ############################################################ # C'est un cas particulier de parcours infixe def remplir(a, t): if a is None: return remplir(a.gauche, t) t.append(a.valeur) remplir(a.droit, t) # Pour la méthode lister, on crée un nouveau tableau, que l'on # remplit avec la fonction remplir # (à faire dans la classe ABR, bien entendu) def lister(self): t = [] remplir(self.racine, t) return t ### exercice 11 ############################################################ # L'idée est d'ajouter tous les éléments du tableau t dans un # ABR, puis d'utiliser la méthode lister de l'exercice précédent. def trier(t): a = ABR() for x in t: a.ajouter(x) return a.lister() # L'efficacité de ce tri dépend fortement de la répartition des # éléments dans le tableau initial. Si par exemple les éléments sont # déjà triés dans le tableau initial, alors l'arbre sera un peigne et # le coût de la construction de l'ABR sera donc quadratique.