Les tables
Transcription
Les tables
Quelques structures de données utiles Listes; Tables: tables de hachage, arbres équilibrés, hash-tries; 1 Les listes En Caml, la liste [1; 2; 3] est juste la paire formée de et de (la paire formée de 2 et de (la paire formée de 3 et de la liste vide nil)). (* [1; 2; 3] = cons (1, cons (2, cons (3, nil))) *) type ’a list = nil | cons of ’a * ’a list;; let hd x = match x with cons (y, _) -> y;; let tl x = match x with cons (_, l) -> l;; let isnull x = match x with nil -> true | _ -> false;; nil 1 2 3 2 Les tables But: représenter des fonctions partielles. Par exemple, une table qui à chaque nom de variable associe le code qu’il faut compiler pour obtenir sa valeur. On veut donc: type key type val type table (* = table key -> val *);; exception Not_found;; val find : key -> table -> val (* lance Not_found si pas dans le domaine *);; val add : key -> val -> table -> table;; val empty : table; ... 3 Tables: 1. Listes d’associations type table = (key * val) list;; let rec find k t = match t with nil -> raise Not_found | cons ((k’, v’), r) -> if k=k’ then v’ else find k r;; let rec add k v t = (k, v)::t;; let empty = [];; Facile... mais peu efficace. Exercice: quelle est la complexité de find? 4 Tables: 2. Tables de hachage Idée: (son hash-code); 1. calculer pour chaque clé (key) un numéro de à 2. faire un tableau de listes d’associations, une pour chaque hash-code. Par ex: let rec hash (s : string) (n : int) : int = let h = ref 0 in for i = 0 to String.length s-1 do h := !h + Char.code (String.get s i) done; !h mod n;; 5 nil nil nil nil nil nil nil nil 9 nil valeur "abc" nil nil nil 17 valeur "toto" 6 Complexité de find: toujours , où ... mais la constante mulfois moins grande que tiplicative est pour les listes d’associations. Exercice: écrire les fonctions find, add, empty. Noter que add modifie la table de hachage, contrairement à la spécification de départ, qui demandait de construire une nouvelle table. Note: il y a bien d’autres algorithmes de hachage, cf. D. Knuth, The Art of Computer Programming, vol.1. En OCaml, utiliser le module Hashtbl. nil Tables: 3. Arbres équilibrés Précurseur: les arbres AVL (Avelson, Vel’skii, Landis). Bien d’autres: arbres rouge-noir, B, B*, etc. Avantages: purement applicatifs: add ne modifie pas la table, mais en crée une nouvelle — comme spécifié. Prérequis: nécessite un ordre total sur les clés key. Note: réalisés dans le module Caml Map. 7 Les arbres équilibrés: idée générale La complexité de find est proportionnelle à la hauteur de l’arbre. Pour un arbre binaire, la hauteur de l’arbre où est le cardinal de la est table. Les arbres AVL maintiennent la hauteur de , ce qui est essenl’arbre à tiellement optimal. 8 "abc" nil "toto" Les arbres AVL: structure Les paires (clé, valeur) sont stockées aux nœuds, pas juste aux feuilles. Chaque nœud contient une clé, une valeur, un sous-arbre gauche, un sous-arbre droit. , toute clé de est , et Invariant: dans tout nœud toute clé de . De plus, on maintient dans chaque nœud la différence entre les hauteurs des deux sous-arbres. On va définir une opération d’équilibrage, qui ramène ces différences entre et , tout en préservant l’invariant. type avl = VIDE | AVL of key * val * avl * avl * int;; 9 Équilibrage des arbres AVL: rotation simple 2 1 1 C B A 2 A B C Exercice: en supposant que l’arbre de gauche n’est pas équilibré, au sens où le sous-arbre de gauche ( , , ) a une hauteur supérieure ou égale à plus la hauteur de , sous quelles conditions la réécriture ci-dessus fait-elle diminuer le défaut d’équilibrage? 10 Équilibrage des arbres AVL: rotation double 2 1 1 A 3 B C 3 A 2 D B D C Exercice: montrer que lorsque la rotation simple ne fait pas diminuer le défaut d’équilibrage, la rotation double (ci-dessus) le fait. , où 11 Exercice: en déduire comment coder find, add, en temps est le cardinal de la table. Tables: 4. les arbres “hash-trie” Beaucoup plus simples! Couples clés, valeurs stockés aux feuilles, pas aux nœuds. complexité pas bornée! Pas équilibrés en moyenne. Par contre, complexité de find de hachage parfaite Petit inconvénient: nécessite une fonction ). ( type trie = VIDE | SINGLETON of key * val | BRANCH of trie * trie;; 12 Les hash-tries: normalisation Pour find k t, calculer k , l’écrire en binaire; descendre à gauche pour chaque bit à , à droite pour chaque bit à . 1 Invariant: tout sous-nœud BRANCH conSINGLETON tient au moins deux clés. 1 "toto" Exercice: montrer que la représentation hash−code 00110101 VIDE de fonctions de domaine fini sous forme de hash-tries est canonique si l’invariant est respecté: il existe un hash-trie exactement ( étant fixé) représentant une table donnée. 0 BRANCH 0 SINGLETON "abc" hash−code 01101000 13 BRANCH Les hash-tries: complexité Exercice: en supposant que k est une suite de bits uniformément distribuée, montrer que la hauteur moyenne d’un hash-trie représentant une plus une petite constante. table de cardinal est Montrer que la taille de cette hash-trie est . Exercice: coder find, add. Montrer que la complexité moyenne est . De quel ordre est l’écart-type de la complexité? (Indication: il est extrêmement faible.) 14