ARBRES exercices

publicité
ARBRES
exercices
Ex 1 Dans cet exercice, on considère des graphes dont l’ensemble des sommets est S = {0, 1, . . . , n−1}.
On suppose de plus que n ≥ 3.
1. Soit G = (S, A) un arbre. Montrer que G possède un sommet de degré 1 et que le graphe obtenu
en supprimant un tel sommet et l’arête associée est encore un arbre.
2. A un arbre G = (S, A) on peut alors associer un n − 2 uplet d’éléments de [|0, n − 1|] par
l’algorithme suivant
On part d’un uplet L vide
Pour k de 1 à n-2, faire
Noter i le plus petit sommet de degré 1
Ajouter au uplet L le voisin de i
Supprimer i de G
Renvoyer L
Donner le 6-uplet associé à l’arbre
4k
6k
0k
A
A
A
2k
5k
7k
1k
3k
3. Justifier l’injectivité de l’application qui à l’arbre associe le n − 2-uplet.
4. Justifier la bijectivité en donnant un algorithme permettant de reconstruire l’arbre à partir du
n − 2-uplet (on ne demande pas de preuve). Appliquer au uplet (1, 1, 0, 2, 2, 0, 3, 3).
5. Implémenter les deux algorithmes précédents en Caml. On représentera les graphes par une
matrice d’adjacence et les uplets par des tableaux.
6. Déterminer le nombre des arbres dont l’ensemble des sommets est S.
Ex 2 Soit G = (S, A) un graphe connexe. Pour construire un arbre couvrant ce graphe, on peut partir
d’un graphe sans arête. On choisit arbitrairement un sommet. On ajoute alors une arête issue de ce
sommet (il en existe une). On a alors deux sommets “couverts”. On ajoute alors une arête entre un
sommet couvert et un autre non couvert (il en existe une par connexité). On poursuit le processus
jusqu’à couvrir tous les sommets. On a alors ajouté n − 1 arêtes et on a un sous-graphe qui est un
arbre.
On choisit de représenter les graphes en Caml grâce au type suivant :
type arete == int*int ;;
type graphe = {N : int ; A : arete list} ;;
Le champ N nous donne le nombre des sommets. Le champ A donne la liste des arêtes, une arête étant
ici un couple (x, y) avec x < y.
Ecrire une fonction arbrecouvrant : graphe → graphe mettant en oeuvre l’algorithme précédent.
1
Ex 3 On veut compter le nombre Cn d’arbres différents de sommets 0, . . . , n − 1 (on parle ici d’arbres
non orientés ; le calcul a été effectué d’une autre manière en exercice 1). Pour cela, on va transiter par
des arbres orientés (et donc aussi enracinés). Pour construire un tel arbre orienté, on doit choisir n − 1
arêtes orientées. On appelle construction un n − 1 uplet d’arêtes orientées donnant un arbre. Notez que
deux constructions peuvent donner le même arbre et que tout n − 1 uplet n’est pas une construction
(le choix des arêtes pouvant ne pas mener à un arbre orienté). On note Dn le nombre de constructions
dans le cas de n sommets (on compte donc le nombre de uplets et pas le nombre d’arbres orientés).
1. Dans un premier compte, on choisit l’un des Cn arbres non orientés. Choisir une racine oriente
chaque arête et il reste à choisir l’ordre de ces arêtes dans le uplet. En utilisant ce raisonnement,
montrer que Dn = n!Cn .
2. Dans un second temps, on part du graphe vide et on ajoute une arête orientée puis une seconde
puis une troisième etc. Initialement, on a n composantes connexes formant une forêt de n arbres
réduits à leurs racines. L’ajout de chaque arête orientée fusionne deux composantes. Quel est
le nombre de choix possibles pour la k-ième arête (lors de ce choix, on a n − k + 1 composantes
connexes formées d’arbres orientés et on doit en fusionner deux en gardant des arbres orientés) ?
En déduire la valeur de Dn .
3. Conclure que Cn = nn−2 .
Ex 4 Ecrire une fonction arbreDFS : graphe → int → graphe qui à partir d’un graphe non orienté
et d’un numéro de sommet renvoie l’arbre orienté de parcours en profondeur à partir du sommet argument. On représente ici les graphes par le tableau des listes d’adjacence.
Ex 5 Ecrire une fonction compteF : arbre → int renvoyant le nombre de feuilles d’un arbre.
Ex 6 On choisit ici la définition des arbres binaires sans l’arbre vide. Dans un arbre binaire t,
on note i(t) la somme des profondeurs des noeuds internes et e(t) celle des profondeurs des feuilles.
Démontrer que dans un arbre binaire t à n(t) noeuds internes on a
e(t) = i(t) + 2n(t)
Ex 7 Si a est un arbre non vide, on appelle déséquilibre de a la différence des hauteurs du fils gauche
et du fils droit de a (d(a) = h(g) − h(d)). On définit récursivement les arbres AVL par
- l’arbre vide est un arbre AVL
- a = Noeud(g, c, d) est un arbre AVL si g et d sont des arbres AVL et si d(a) ∈ {−1, 0, +1}.
1. Montrer qu’un arbre AVL est équilibré.
2. Ecrire une fonction testant si un arbre possède la propriété AVL. On ne devra parcourir qu’une
unique fois chaque noeud de l’arbre.
Ex 8 On appelle arbre 0-1 un arbre binaire dont les étiquettes valent 0 ou 1 et qui vérifie les conditions
suivantes :
- la racine (si l’arbre est non vide) est d’étiquette 0 ;
- le parent d’un noeud d’étiquette 1 est d’étiquette 0 ;
- pour chaque noeud, tout les chemins de ce noeud à une feuille contiennent le même nombre de
noeuds d’étiquette 0.
1. Montrer que le squelette d’arbre ci-dessous peut être étiqueté afin de devenir un arbre 0-1.
2
HH
HH
HH
H
@
@
@
@
@
@
A
A
A
A
A A
A
A
A
A
A
A
2. Donner un exemple de squelette d’arbre ne pouvant être étiqueté en un arbre 0-1.
3. Si a est un arbre 0-1, on note z(a) le nombre de noeuds d’étiquette 0 sur le chemin de la racine
à une feuille (ce nombre ne dépend pas de la feuille). Montrer que
z(a) ≤ h(a) + 1 ≤ 2z(a) et |a| ≥ 2z(a) − 1
En déduire que les arbres 0-1 sont équilibrés.
4. Ecrire une fonction testant en temps linéaire en fonction du nombre de noeuds si un arbre
d’étiquettes dans {0, 1} est un arbre 0-1.
Ex 9 Ecrire une fonction prenant en argument un arbre binaire et renvoyant la liste des étiquettes de
l’arbre dans l’ordre préfixe (par exemple). On essayera d’écrire une fonction n’utilisant que l’opérateur ::
de consage et pas celui de concaténation @.
Ex 10 Implémenter l’algorithme d’affichage des noeuds d’un arbre dans un parcours en largeur (on
supposera les étiquettes entières). On représentera une file à l’aide de deux listes (selon le cours de
première année) ; on écrira donc une fonction auxiliaire récursive qui prendra en argument ces deux
listes.
Ex 11 Comment, à l’aide d’un parcours en profondeur, vérifier la structure d’ABR ?
Ex 12 Ecrire une fonction efficace de création d’un abr à partir d’un tableau trié. Justifier les choix
faits (en quoi est-ce efficace ?) et donner la complexité de la fonction.
Ex 13 On peut utiliser une technique d’insertion dans un abr autre que celle d’insertion aux feuilles
vue en cours. La méthode consiste à insérer l’étiquette x à la racine du nouvel arbre. Pour cela, on
découpe l’arbre initial en deux arbres dont les étiquettes sont respectivement plus petites et plus
grandes que x et à rassembler ces arbres sous une nouvelle racine.
a. Ecrire une fonction Caml mettant en oeuvre cette méthode (on convient de ne pas ajouter x
s’il est déjà présent).
b. Quelle est la complexité de la fonction précédente.
3
Ex 14 Proposer une structure permettant de gérer des tas dont les éléments ne sont plus forcément
des entiers.
Ex 15
1. Ecrire une fonction arbre to vect prenant en argument un arbre parfait (pas forcément un
APO) et renvoyant un tableau représentant cet arbre.
2. Ecrire la fonction réciproque vect to arbre.
Ex 16 Ecrire une fonction d’insertion d’un élément dans un tas (insere : int → tas → unit).
Ex 17 Ecrire une fonction supprime : tas → int qui prend en argument un tas non vide et en
supprime l’élément à la racine et renvoie l’élément supprimé.
Ex 18 Ecrire une fonction tri : int list → int list qui prend en argument une liste et en
renvoie une version triée. On utilisera un tas comme file de priorité et la stratégie de tri décrite dans
le cours. On commencera sans doute par une fonction créant un tas à partir d’une liste. Préciser la
complexité de cette fonction.
4
Téléchargement