10 Les arbres

Transcription

10 Les arbres
Licence Maths-Info-SPI, informatique pour les scientifiques : cours 6
responsable de l’UE : Jean Lieber,
10
10.1
année scolaire 2010-2011
Les arbres
Notions théoriques et terminologie des arbres
Arbres binaires, arbres quelconques (et forêts), recherche dans un espace d’états.
Notions de racine, arbre-fils, nœud (ou sommet), feuille, branche, profondeur, rang.
Définition récursive d’un arbre : donnée d’une racine et d’une liste d’arbres.
10.2
Arbres binaires
Un arbre binaire est un arbre tel que tous ses nœuds ont au plus 2 fils.
Type abstrait :
Nom : arbre
Types abstraits importés : booléen, typélt.
Constructeurs :
arbre_vide : −→ arbre
cons : typélt × arbre × arbre −→ arbre
Erreur_arbre : −→ arbre
Accès :
est_vide : arbre −→ booléen
racine : arbre −→ typélt
fils_gauche : arbre −→ arbre
fils_droit : arbre −→ arbre
Jeu d’axiomes :
[Ax-1] est_vide(arbre_vide) = vrai
[Ax-2] est_vide(cons(r, G, D)) = faux
[Ax-3] racine(arbre_vide) = Erreur_typélt
[Ax-4] racine(cons(r, G, D)) = r
[Ax-5] fils_gauche(arbre_vide) = Erreur_arbre
[Ax-6] fils_gauche(cons(r, G, D)) = G
[Ax-7] fils_droit(arbre_vide) = Erreur_arbre
[Ax-8] fils_droit(cons(r, G, D)) = D
Parcours :
– En profondeur :
– préfixé, i.e., selon l’ordre : racine, fils gauche, fils droit.
– infixé, i.e., selon l’ordre : fils gauche, racine, fils droit.
– postfixé, i.e., selon l’ordre : fils gauche, fils droit, racine.
Exemple du parcours préfixé :
procédure parcoursPréfixé (A : arbre)
début
si est_vide (A)
alors retourner /* quitter la procédure */
fsi
traiter racine (A)
parcoursPréfixé (fils_gauche (A))
parcoursPréfixé (fils_droit (A))
fin
– En largeur :
procédure parcoursEnLargeur (A : arbre)
var OUVERTS : file dont les éléments sont de type arbre
courant : arbre
début
OUVERTS := enfiler (A, fileVide)
tant que non (estVide (OUVERTS)) faire
courant := premier (OUVERTS)
OUVERTS := defiler (OUVERTS)
si non (estVide (fils_gauche (courant)))
alors OUVERTS := enfiler (fils_gauche (courant), OUVERTS)
fin-si
si non (estVide (fils_droit (courant)))
alors OUVERTS := enfiler (fils_droit (courant), OUVERTS)
fin-si
traiter racine (courant)
fin-tant que
fin
1
Application à la gestion d’un ensemble de mots. « Arbres binaires de recherche ». On dispose d’une liste de mots L, par exemple,
L = (chat chien arbre chèvre lapin banane ours dindon chameau asticot abricot)
On va construire un arbre binaire qui respecte les règles suivantes :
– L’ensemble des nœuds de cet arbre est l’ensemble des mots de L ;
– Pour tout sous-arbre A de cet arbre, si G = fils_gauche(A) et D = fils_droit(A), alors l’ensemble des mots de G (resp., de
D) précèdent racine(A) (resp., suivent racine(A)).
Par exemple, on obtiendra avec la liste L ci-dessus :
chat
PPP
PPP
chien
arbre
!
"
!
@@
"" @@
!!
abricot
chèvre
banane
#
# @@
lapin
@@
asticot chameau
dindon ours
Permet une structure de dictionnaire plus souple que celle de tableau trié (comparer le temps de calcul pour l’insertion d’un élément
dans l’arbre).
Exercice 1 Pour chacune des opérations suivantes, on demande de suivre la démarche algorithmique : (1) définir le profil, (2) traiter
un ou plusieurs exemples, (3) définir des axiomes, (4) traduire ces axiomes en un algorithme récursif :
Q1 nb_n÷uds(A) est le nombre de nœuds de l’arbre binaire A.
Q2 nb_feuilles(A) est le nombre de feuilles de A (c’est-à-dire, le nombre de nœuds sans fils).
Q3 profondeur(A) est la profondeur de l’arbre binaire A, c’est-à-dire le nombre maximum de liens de filiations pour relier la racine
à un nœud-feuille (c’est aussi le nombre de générations −1).
Q4 égaux(A1 , A2 ) vaut vrai si et seulement si A1 et A2 sont deux arbres égaux.
Q5 clone(A) est un arbre créé de façon à être égal à A.
Q6 symétrique(A) est l’arbre obtenu en inversant les fils dans tout l’arbre A.
Q7 isomorphes(A1 , A2 ) vaut vrai si et seulement si les arbres A1 et A2 sont égaux modulo des permutations entre fils gauches et fils
droits.
Q8 substituer_fils_gauche(A, G) est l’arbre obtenu en substituant au fils gauche de A l’arbre G.
Q9 substituer_fils_droit(A, D) est l’arbre obtenu en substituant au fils droit de A l’arbre D.
Exercice 2 On veut définir des opérations pour la gestion d’un ensemble de mots utilisant des arbres binaires sous la forme d’un type
de nom ensemble qui est le type des arbres binaires dont les éléments sont des chaînes de caractères. Les opérations ont les profils
suivants :
ensemble_vide() retourne ∅
ensemble_vide : −→ ensemble
ajouter : chaîne × ensemble −→ ensemble
ajouter(x, E) retourne E ∪ {x}
est_vide : ensemble −→ booléen
est_vide(E) retourne vrai ssi E est l’ensemble vide
soit : ensemble −→ chaîne
soit(E) retourne un élément (quelconque) de E
supprimer : chaîne × ensemble −→ ensemble
supprimer(x, E) retourne E\{x}
Donner une implantation de ces opérations sous la forme d’algorithmes sur les arbres. Si ch1 et ch2 sont deux chaînes, on notera
ch1 6 ch2 si ch1 précède lexicographiquement ch2 et ch1 = ch2 si elles sont égales. Ainsi, "lapin" 6 "ours" et "chat" = "chat".
Étudier la complexité de ces opérations en fonction de n (le nombre d’éléments de l’arbre) et de p (sa profondeur).
Exercice 3 Les arbres peuvent se représenter de façon similaire aux listes chaînées, mais avec un double chaînage (à gauche et à
droite). Autrement dit, un arbre non vide correspond à un enregistrement à trois champs : un pour la racine, un pour le fils gauche et un
pour le fils droit.
Donner une implantation C du type des arbres de chaînes de caractères.
10.3
Arbres quelconques et forêts
Arbres ternaires : similaires aux arbres binaires (fils numéros 1, 2 et 3).
Arbres quelconques : on n’a pas de majorant a priori du nombre de fils par nœud.
Structure doublement chaînée : racine, « fils aîné », « frère suivant ».
En fait, structure de forêt. Type abstrait équivalent à celui d’arbre binaire (avec renommages : fils_aîné à la place de fils_gauche,
frère_suivant à la place de fils_droit).
Mais pour les opérations non primitives, pas nécessairement les mêmes axiomes : pour nb_n÷uds, c’est pareil ; pour nb_feuilles et
profondeur, c’est différent.
2
Exercice 4 Reprendre l’exercice 1 avec des forêts à la place des arbres binaires.
10.4
Recherche dans un espace d’états
Certains « problèmes de recherche » peuvent être modélisés par :
– Une notion d’état.
– Une fonction successeurs qui à un état e associe un ensemble d’états (les successeurs de e).
– Un problème particulier de ce domaine est un couple (einit , b) où einit est un état (l’état initial) et où b est un but (b est une fonction
qui a un état e associe vrai si e réalise le but b).
– Une solution d’un problème (einit , b) est une liste (e0 e1 . . . eq−1 eq ), où :
– e0 = einit ;
– b(eq ) = vrai (eq réalise le but b) ;
– Pour tout i ∈ {0, 1, . . . q − 1}, on peut aller de ei à ei+1 : ei+1 ∈ successeurs(ei ).
Étant donné un problème de recherche, l’arbre de recherche associé est un arbre qui peut être infini, dont les éléments sont des états,
dont la racine est l’état initial et tel que, pour chaque état e de l’arbre, les fils de e sont les états qu’on peut atteindre à partir de e. La
recherche dans un tel arbre s’arrête quand on trouve un état qui vérifie le but du problème à résoudre.
Si cet arbre est fini, on peut effectuer une recherche en profondeur ou en largeur (avec une préférence pour la recherche en profondeur
qui a l’avantage d’être plus facile à programmer). La recherche en profondeur s’appelle parfois recherche avec « retours arrière » ou
backtracking, en anglais. En revanche, si l’arbre est infini, il est préférable d’utiliser une recherche en largeur.
La complexité de la recherche dans un espace d’états dépend d’une part du facteur de branchement b (à savoir le nombre moyen de
successeurs par état) et de la longueur n de la solution la plus courte. Par exemple, pour une recherche en largeur, on générera environ
bn états.
Enfin, notons qu’il n’est pas nécessaire de représenter informatiquement l’arbre pour effectuer une telle recherche.
Exercice 5 Pour chacune des questions ci-dessous, on demande :
– De modéliser ce problème comme un problème de recherche dans un espace d’états (définir ce qu’est un état, un état initial, un but,
les successeurs d’un état, une solution) ;
– De caractériser l’arbre de recherche pour un tel problème (l’arbre est-il fini ? que peut-on dire sur le facteur de branchement ? quel
est le rang dans cet arbre d’un état réalisant le but ?) ;
– Quel type de recherche est plus appropriée (en largeur, en profondeur, etc.) et pourquoi ;
– comment représenter de façon efficace un état et les successeurs d’un état.
Q1 Comment placer sur un échiquier 8 reines pour qu’aucune ne puisse être prise avec une autre (problème des 8-reines, qui se
généralise en problème des n-reines, on peut aussi chercher toutes les façons de placer ainsi les n reines) ?
Q2 Comment faire parcourir un échiquier par un cavalier, de façon à ce qu’il passe par toutes les cases une fois et une seule ?
Q3 Trouver une solution à l’équation 5x − 3y + 2z = 4 dans IN (variante : trouver deux solutions à cette équation).
Q4 Résoudre un jeu du taquin.
Q5 Résoudre un jeu du cube de Rubik.
Q6 Résoudre le jeu du solitaire.
3