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.