TD 4 Arbres de priorité équilibrés

Transcription

TD 4 Arbres de priorité équilibrés
Université de Provence
Mi2 - Sémantique et Programmation Fonctionnelle
sera codé par:
2003 – 2004
TD 4
Solange Coupet-Grimal
Attention: toute définition de fonction Caml doit être accompagnée de son type
Arbres de priorité équilibrés
Node
(3, Node (8, Nil, Node (10, Nil, Nil)),
Node (6, Node (12, Nil, Nil), Node (7, Nil, Nil)))
Question 1 Ecrire une fonction verif qui prend en argument un arbre binaire et renvoie un
booléen indiquant si cet arbre est un APE ou non. Cette fonction ne devra parcourir l’arbre
qu’une seule fois.
On se propose maintenant d’implanter les opérations suivantes sur les APE.
On considère des arbres binaires étiquetés par des éléments d’un ensemble E totalement ordonné.
Parmi ces arbres, on définit l’ensemble des arbres de priorité équilibrés (APE) comme le plus petit
ensemble contenant l’arbre vide et vérifiant les 3 propriétés suivantes :
• insertion : on donne un APE A et une étiquette x, former un nouvel APE B contenant
toutes les étiquettes figurant dans A et l’étiquette x. Si A comporte des répétitions, B devra
comporter les mêmes répétitions, donc taille(B) = taille(A) + 1.
1. L’étiquette de la racine d’un APE non vide est inférieure ou égale aux étiquettes de ses
sous-arbres gauche et droit, s’ils ne sont pas vides.
• union : on donne une étiquette x et deux APE G, D tels que taille(G) ≤ taille(D) ≤
taille(G) + 1, former un APE A contenant toutes les étiquettes de G, de D et l’étiquette x
(donc taille(A) = taille(G) + taille(D) + 1).
2. Les sous-arbres gauche et droit d’un APE non vide sont des APE.
3. Si G et D sont respectivement le sous-arbre gauche et le sous-arbre sous-arbre droit d’un
APE alors :
taille(G) ≤ taille(D) ≤ taille(G) + 1.
(La taille d’un arbre est le nombre de ses nœuds).
Il résulte de ces propriétés que l’on peut trouver la plus petite étiquette d’un APE en temps
constant, c’est ce qui fait l’intérêt premier des arbres de priorité. Les propriétés 2 et 3 garantissent
qu’un APE est “équilibré” dans le sens où les deux sous-arbres issus de chaque nœud ont même
taille à une unité près, et en cas de différence, c’est le sous-arbre droit qui comporte un nœud de
plus. On peut démontrer, par récurrence sur n, que la hauteur d’un APE à n nœuds est majorée
par log2 (n), donc les opérations d’insertion et suppression sur un APE décrites ci-après ont une
complexité O(ln n) lorsque l’arbre considéré est de taille n.
Les APE sont utilisés en informatique pour stocker des tâches à accomplir, chaque tâche ayant un
certain niveau de priorité (les tâches prioritaires ont des niveaux de priorité inférieurs aux tâches
moins prioritaires), de sorte qu’on puisse extraire efficacement l’une des tâches les plus prioritaires
à accomplir, et qu’on puisse insérer efficacement de nouvelles tâches dans l’APE. On se limitera à
des arbres à étiquettes entières ou réelles, la valeur d’une étiquette codant son niveau de priorité.
On utilisera le type suivant:
type ’a btree = Nil | Node of ’a*’a btree*’a btree;;
• extraction de la racine : on donne un APE non vide A, retourner l’étiquette x de la
racine et un APE B contenant toutes les étiquettes présentes dans A sauf celle extraite (donc
taille(B) = taille(A) − 1).
Algorithme d’insertion : le cas où A = ∅ est trivial. Pour A 6= ∅, comparer l’étiquette x à
insérer à celle de la racine de A : y. Placer la plus petite des deux étiquettes à la racine de B,
insérer la plus grande dans le sous-arbre gauche de A et permuter le nouveau sous-arbre droit et
le sous-arbre gauche de A pour former les sous-arbres de B.
insertion si x ≤ y
insertion si x > y
y
x
y
y
→
→
y
x
D
G D
G D
D
... ...
... ...
Le but de la permutation des sous-arbres droit et gauche entre A et B est de maintenir la propriété 3 des APE : si taille(D) = taille(G) alors le sous-arbre droit de B comporte un nœud de
plus que son sous-arbre gauche, et si taille(D) = taille(G) + 1 alors les deux sous-arbres de B ont
même taille.
Algorithme d’extraction de la racine : le cas où l’un au moins des sous-arbres de A est vide
est trivial. Voici un algorithme pour calculer l’arbre B obtenu après extraction de la racine, dans
le cas où ces deux sous-arbres sont non vides:
Par exemple, l’arbre
3
/
8
\
\
6
/ \
10
• extraction à droite : on donne un APE non vide A, retourner l’étiquette x la plus à
droite dans A et un APE B contenant toutes les étiquettes de A sauf celle extraite (donc
taille(B) = taille(A) − 1).
12
7
Soient G et D les sous-arbres gauche et droit de A ; extraire de D l’étiquette la plus à droite,
soit x cette étiquette et D0 l’arbre formé des étiquettes de D restantes. Former l’arbre B =
union(x, D0, G).
Questions 2, 3, 4 et 5 Ecrire les fonctions insertion, union, extrait droite, extraire racine
décrites ci-dessus. Les fonctions d’extraction retourneront un couple constitué de l’étiquette extraite et de l’arbre des étiquettes restantes.
Ces fonctions peuvent être supposées connues dans la suite du problème, même si
elles n’ont pas été écrites.
Question 6 La fonction random int est prédéfinie. Etant donné un entier x, elle renvoie un
entier aléatoire inférieur ou égal à x. Utiliser cette fonction pour créer un APE à n nœuds dont
les étiquettes sont des entiers aléatoires compris entre 2 valeurs a et b passées en paramètres.
On se propose d’obtenir automatiquement le nombre moyen de comparaisons effectuées par la fonction extraire racine. On définit un compteur qui est augmenté d’une unité à chaque fois qu’une
comparaison est effectuée :
let cmp = ref 0;;
let
let
let
let
lt
le
gt
ge
=
=
=
=
prefix
prefix
prefix
prefix
let
let
let
let
prefix
prefix
prefix
prefix
<
<=
>
>=
a
a
a
a
<
<=
>
>=
b
b
b
b
(* compteur de comparaisons *)
;;
;;
;;
;;
=
=
=
=
incr
incr
incr
incr
(* on renomme les operations de *)
(* comparaison usuelles
*)
cmp;
cmp;
cmp;
cmp;
lt
le
gt
ge
a
a
a
a
b
b
b
b
;; (* et on les redefinit *)
;;
;;
;;‘
On suppose que ces déclarations ont été saisies avant celles de la fonction extraire racine par
exemple, de sorte que cette fonction utilise les nouvelles versions des opérateurs ≤, ≥, <, >.
Question 7 Ecrire une fonction nb comp moyen qui prend deux entiers n et p en arguments,
et qui retourne le nombre moyen de comparaisons effectuées par la fonction extraire racine , la
moyenne étant calculée sur p APE aléatoires de taille n.
Une application des APE : la suite de HAMMING
Un nombre entier n ∈ N ∗ est appelé nombre de Hamming si ses seuls diviseurs premiers éventuels
sont 2, 3, 5. La suite de Hamming est la suite des nombres de Hamming classée par ordre croissant.
On remarque que si x est un nombre de Hamming alors 2x, 3x, 5x le sont aussi, et que tous les
nombres de Hamming à part 1 s’obtiennent en multipliant par 2 ou 3 ou 5 un nombre de Hamming
plus petit, ce qui donne l’algorithme suivant pour générer la liste des n premiers nombres de
Hamming :
1. Initialiser un APE avec le nombre 1 et initialiser la liste résultat à ∅.
2. Extraire la racine de l’APE, x.
3. Si x n’a pas déjà été vu : le placer dans la liste résultat et insérer 2x, 3x, 5x dans l’APE.
4. Recommencer les étapes 2 et 3 jusqu’à avoir obtenu n nombres.
Question 8
Programmer cet algorithme.