Tables de hachage Tables de hachage: Idée et exemples Fonctions de hachage: Génération d’adresses : code de hachage + fonction de compression Résolution des collisions: Chaînage Sondage linéaire Sondage quadratique Hachage double CSI2510 CSI2510
Idée Les tables de hachage sont des exemples du TAD MAP Combine les avantages des tableaux et des listes chaînées On accède aux données emmagasinées à partir de leurs clés Les clés sont emmagasinées, mais ne sont pas triées ! CSI2510 CSI2510
Révision - Le TAD Map: méthodes findElement(k): si il y a un item avec clé k, retourner son élément, autrement retourner l'élément spécial NO_SUCH_KEY insertItem(k, o): insérer un item (k, o) removeElement(k): si il y a un item avec clé k, enlever-le et retourner son élément, autrement retourner l'élément spécial NO_SUCH_KEY size(), isEmpty() keys(), Elements() findAllElements(k), removeAllElements(k) CSI2510 CSI2510
Exemple Les rapports des étudiants sont emmagasinés dans un tableau utilisant les 7 chiffres d’identification (ID) des étudiants comme indices. Si l’ID est utilisé sans altération, le tableau doit avoir assez d’espace pour loger les données des 10,000,000 étudiants. Alternative: les IDs des étudiants sont hachés pour produire un entier (entre par exemple 1 et 10,000) qui servira comme indice dans le tableau. 1 2 3 4 9997 9998 9999 … 2290004 1010002 7519998 6120001 CSI2510 CSI2510
Problème Puisque un nombre possible de 10,000,000 d’entrées peuvent être insérées dans un tableau de seulement 10,000 emplacements, comment peut on garantir que 2 IDs ne soient pas emmagasinés dans un même endroit? CSI2510 CSI2510
Principe du hachage Problème 1 : Génération des adresses Construction d’une fonction de hachage h(ki) qui associe une adresse à une clé: Simple à calculer Distribue uniformément les éléments dans le tableau Problème 2 : Résolution des collisions Quelle stratégie à adopter lorsque la fonction de hachage attribue la même adresse à deux clés différentes CSI2510 CSI2510
L’ idée: Pour toute clé ki : h ( ki ) = la position de ki dans le tableau h ( ki ) = pos avec pos: entier h ( ki ) h ( kg ) pour i g T 1 2 3 4 5 6 Chercher la clé ki O( 1 ) ! Insertion CSI2510 CSI2510
Exemple d’une table de hachage Hypothèse: toutes les clés ont des premières lettres différentes CAT, ELEPHANT, FOX, SKUNK, ZEBRA h (CAT) = 2 h (ELEPHANT) = 4 h (FOX) = 5 1 CAT 2 3 ELEPHANT 4 FOX 5 6 7 8 SKUNK ZEBRA CSI2510 CSI2510
Exemple d’une table de hachage Si nous voulons insérer deux clés qui ont la même première lettre COLLISION 1 CAT 2 3 ELEPHANT 4 FOX 5 6 7 8 SKUNK ZEBRA CSI2510 CSI2510
Exemple d’une table de hachage Si nous voulons insérer deux clés qui ont la même première lettre COLLISION 1 CAT 2 3 ELEPHANT 4 FOX 5 6 7 8 SKUNK ZEBRA nous voulons insérer: CRICKET h (CRICKET) = 2 position 2 est occupée CSI2510 CSI2510
Fonction de hachage Une bonne fonction de hachage doit être facile et rapide à calculer et doit minimiser le risque de collision La fonction de hachage est la composition de deux fonctions: Le code de hachage h1 (Hash code map): h1: clé entier La fonction de compression h2 (Compression map): h2: entier [0, Taille du tableau - 1] On applique le code de hachage puis la fonction de compression: h(ki)=h2(h1(ki)) CSI2510 CSI2510
Code de hachage Le code de hachage réinterprète la clé comme un entier Un bon code de hachage : Déterministe: pour une même clé k on a toujours le même code h1(k) Doit fournir une bonne distribution : Le hachage des éléments similaires est discriminant; les clés similaires sont distribuées dans des cellules d’indices éloignés CSI2510 CSI2510
Code de hachage - Exemples Adresse mémoire: Nous réinterprétons l'adresse mémoire (ou une autre propriété) de l'objet clé comme un entier (le code de hachage par défaut de tous les objets Java – int 32bits). Cette valeur doit être mémorisée si elle est appelée à changer en cours d’exécution. Integer cast (ex. byte, short, int, char) : Nous réinterprétons la clé comme un entier Somme des composantes (ex. long, double) : Nous représentons les bits de la clé dans avec des composantes de longueurs fixes (par ex., 16 ou 32 bits) et nous additionnons ces composantes (en négligeant les overflow) CSI2510 CSI2510
Code de hachage - Exemples Accumulation polynômiale : Nous divisons les bits de la clé en une séquence de composantes de longueurs fixes (par ex., 8, 16 ou 32 bits) a0 a1 … an-1 Nous évaluons le polynôme : p(z) = a0 + a1 z + a2 z2 + … + an-1zn-1 pour une valeur fixe z (en négligeant les surplus) Surtout convenable pour les chaînes de caractères (strings) (par ex., le choix z = 33 donne au plus 6 collisions par case sur une série de 50.000 mots anglais) CSI2510 CSI2510
La fonction de compression Le nombre des codes de hachage possibles peut dépasser la taille du tableau La fonction de compression transforme le résultat du code de hachage en le compressant dans la zone désirée La fonction de compression doit aussi être déterministe La fonction de compression doit maximiser la “distribution” et ainsi minimiser les collisions CSI2510 CSI2510
La fonction de compression - Exemples Division: h2 (y) = y mod N Le taille N du tableau de hachage est d'habitude choisie comme un nombre premier CSI2510 CSI2510
La fonction de compression - Exemples Multiplier, ajouter et diviser (MAD): h2 (y) = (ay + b) mod N a et b sont des nombres entiers non-négatifs tel que a mod N 0 Autrement, h2 (y) = (ay + b) mod N = b CSI2510 CSI2510
Fonction de hachage exemples … CSI2510 CSI2510
Fonction de hachage – Exemple a N = la taille de la table r = log N 000000000 000000001 111111111 111111110 N = 29 r = 9 29 Pour représenter 29 nombres on a besoin de 9 bits CSI2510 CSI2510
Fonction de hachage – Exemple a h1(x): changement de type à entier a) h2(h1(x)): = sous-ensemble ( de r bits ) de h1(x) a.1) les r bits les moins significatifs a.2) les r bits les plus significatifs a.3) les r bits central Simple à calculer Ne garantit pas une distribution aléatoire CSI2510 CSI2510
Fonction de hachage – Exemple a Le codage de lettres A 000001 N = 29 r = 9 B 000010 C 000011 29 H 001000 CHAT-- T 010010 - 100000 Mot de 6 caractères (seulement pour cet exemple) h(0000011001000000001010010100000100000) = C H A T - - CSI2510 CSI2510
les r bits les plus significatifs Exemple a.1: les r bits les plus significatifs (r = 9) h(000011001000000001010010100000100000) = 000011001 Tous les animaux qui commence avec “CH” hachent a la même place. CSI2510 CSI2510
les r bits les moins significatifs Exemple a.2: les r bits les moins significatifs (r = 9) h(000011001000000001010010100000100000) = 000100000 Tous les animaux de 4 (ou moins) caractères hachent a la même place. CSI2510 CSI2510
Fonction de hachage – Exemple b h1(x): changement au type entier b) h2(h1(x)): la somme des sous-ensembles de bits de h1(x) Simple à calculer Distribution plus aléatoire que a) CSI2510 CSI2510
} —Exemple — Code pour les lettres N = 29 ⌴ r = 9 29 CHAT-- 000001 B 000010 C 000011 H 001000 T 010010 ⌴ 100000 } N = 29 r = 9 29 CHAT-- h(000011001000000001010010100000100000) = b) 000011001 plus significatifs 000101001 centraux 000100000 moins significatifs XOR 000010000 CSI2510 CSI2510
Fonction de hachage – Exemple c h1(x): changement au type entier c) h2(h1(x)): sous-ensembles (de r bits) de h1(x)2 La multiplication est impliquée Distribution plus aléatoire que a) et b) CSI2510 CSI2510
Fonction de hachage – Exemple d d) h2(h1(x)): = h1(x) MOD N La division est impliquée Distribution complètement aléatoire (surtout si N impair) CSI2510 CSI2510
Résolution de collision CSI2510 CSI2510
Résolution des collisions Le facteur de charge d’une table de hachage est la proportion des cases utilisées dans cette table: α =n/N n = nb. des cases occupées N = capacité du tableau Indicateur des performances de la table de hachage Deux approches: Chaînage Adressage ouvert (sondage lineaire, quadratique et double hachage) CSI2510 CSI2510
Résolution de collision Chaînage 1 2 3 CAT 4 DOG 5 ELEPHANT 6 FOX 7 8 9 10 ZEBRA Ex: cricket, cccc CRICKET COYOTE findElement(k) removeElement(k) insertItem(k,o) Idéalement avec une excellente fonction de hachage chaque liste chaînée est de taille n/N O(n/N) CSI2510 CSI2510
Résolution des collisions – Adressage ouvert La collision est résolue en trouvant une place libre dans le tableau pour y insérer la nouvelle entrée. Cette nouvelle place est obtenue en ‘sondant’ les cases du tableau On utilise une fonction de sondage s qu’on compose avec la fonction de hachage h(k) pour trouver le nouveau indice (case) à vérifier; s(h(k),j) où {j=0..N et s(h(k),0)=h(k)} Le facteur de charge α dans ce cas est <1; A partir de α=75% on dit que la table de hachage est saturée et les collisions deviennent inévitables CSI2510 CSI2510
Résolution de collision (exemples) Adressage ouvert Sondage linéaire CRICKET 1 2 3 CAT 4 5 ELEPHANT 6 FOX 7 8 9 10 ZEBRA CRICKET h (CRICKET) = 3 OCCUPÉE Nous considérons 4 LIBRE! CSI2510 CSI2510
Résolution de collision (exemples) Adressage ouvert Sondage linéaire COYOTE 1 2 3 CAT 4 CRICKET 5 ELEPHANT 6 FOX 7 8 9 10 ZEBRA h (COYOTE) = 3 OCCUPÉE Nous considérons 4 OCCUPÉE COYOTE Nous considérons 5 OCCUPÉE “ 6 OCCUPÉE “ 7 LIBRE! Les clés sont stockées dans des cellules contigües CSI2510 CSI2510
Résolution de collision (1) Sondage linéaire h ( Ki ), h ( Ki ) + 1, h ( Ki ) + 2, h ( Ki ) + 3 …. h0 ( Ki ) h1 ( Ki ) h2 ( Ki ) h3 ( Ki ) Soit h0 ( ki ) = h ( ki ) s(h(ki),j) = hj(ki) =( h ( ki ) + j ) mod N CSI2510 CSI2510
Recherche avec un sondage linéaire Algorithm findElement(k) i h(k) p 0 repeat c A[i] if c = return NO_SUCH_KEY else if c.key () = k return c.element() else i (i + 1) mod N p p + 1 until p = N Considérons un tableau A de hachage qui utilise le sondage linéaire findElement(k) Nous commençons à la cellule h(k) Nous sondons les emplacements consécutifs jusqu'à ce que: Une entrée avec la clé k est trouvée, ou Une cellule vide est trouvée, ou N cellules ont été sondées sans succès CSI2510 CSI2510
Les mises à jour avec un sondage linéaire Pour contrôler les insertions et les suppressions, nous introduisons un objet spécial, appelé DISPONIBLE, qui remplace les éléments enlevés removeElement(k) Nous cherchons un item avec la clé k Si un tel élément (k, o) est trouvé, nous le remplaçons avec l’objet spécial DISPONIBLE et nous retournons l'élément o Sinon, nous retournons NO_SUCH_KEY insert Item(k, o) Nous lançons une exception si la table est pleine Nous commençons à la cellule h(k) Nous sondons les cellules consécutives jusqu'à ce que: Une cellule i qui est vide ou emmagasine DISPONIBLE est trouvée, ou N cellules ont été infructueusement sondées Nous emmagasinons l’item (k, o) dans la cellule i CSI2510 CSI2510
Performance du Sondage Linéaire Recherche: Le nombre moyen de sondages…. C() Les résultats expérimentaux pour un tableau de hachage avec le facteur de chargement =n/N C( ) 0.1 (10%) 1.06 0.5 (50%) 1.50 0.75 (75%) 2.50 0.9 (90%) 5.50 CSI2510 CSI2510
Exemple de sondage linéaire hj(ki) = [h(ki) + j] mod N Insérer les clés 13,15,5,28,1,14,2 dans cet ordre 1 2 3 4 5 6 7 8 9 10 11 12 13 1 15 28 14 5 2 1 2 3 4 5 6 7 8 9 10 11 12
Problème avec Sondage Linéaire : REGROUPEMENT PRIMAIRE (création de cellules contigües) 3 CAT 4 CRICKET 5 ELEPHANT 6 FOX 7 CCC 8 h (COUGAR) = 3 h1 (COUGAR) = 4 h2 = 5 h3 = 6 h4 = 7 h5 = 8 ! Idée: Utiliser un sondage non linéaire Ici nous utilisons comme fonction de hachage l’entier correspondant à la première lettre CSI2510 CSI2510
Résolution de collision (2) Sondage Quadratique h(ki), h(ki)+1, h(ki)+4, h(ki)+9, … h0(ki) h1(ki) s(h(ki),j) = hj(ki) =( h ( ki ) + j2) mod N N: nombre premier CSI2510 CSI2510
Exemple de sondage Quadratique hj(ki) = [h(ki) + j2] mod N Insertion des clés 13,15,5,28,1,14,2 1 2 3 4 5 6 7 8 9 10 11 12 13 1 15 28 5 2 14 1 2 3 4 5 6 7 8 9 10 11 12
13 1 15 28 - 5 2 - - - 14 - - h0(14) = 14 mod 13 = 1 Rechercher 14: 13 1 15 28 - 5 2 - - - 14 - - 0 1 2 3 4 5 6 7 8 9 10 11 12 h0(14) = 14 mod 13 = 1 Rechercher 14: Sonde 1 Sonde 2 Sonde 5 Sonde 10 --- Trouvé!
13 1 15 28 - 5 2 - - - 14 - - Retirer 5: Sonder 5 13 1 15 28 - 5 2 - - - 14 - - 0 1 2 3 4 5 6 7 8 9 10 11 12 Retirer 5: Sonder 5 13 1 15 28 - dispo 2 - - - 14 - - 0 1 2 3 4 5 6 7 8 9 10 11 12
13 1 15 28 - dispo 2 - - - 14 - - Trouver 14: Sonder 1 Sonder 2 0 1 2 3 4 5 6 7 8 9 10 11 12 Trouver 14: Sonder 1 Sonder 2 Sonder 5 ??? Sonder 10
Performance du Sondage Quadratique Les résultats expérimentaux pour un tableau de hachage avec le facteur de chargement recherche = n/N C( ) 0.1 (10%) 1.05 0.5 (50%) 1.44 0.75 (75%) 1.99 0.9 (90%) 2.79 CSI2510 CSI2510
Problème avec Sondage non-linéaire : REGROUPEMENT SECONDAIRE Deux clés qui hachent au même endroit suivent le même chemin de collision Idée: Hachage Double CSI2510 CSI2510
Résolution de collision Adressage ouvert: (3) Hachage Double Ex: h(ki), h(ki)+h'(ki), h(ki)+2h'(ki), h(ki)+3h'(ki), … h0 h1 h2 h3 hj(ki) = [h(ki) + j•h’(ki)] mod N OU Ex: h(ki), h(ki)+h’(ki), h(ki)+4 h’(ki), h(ki)+9 h’(ki), … hJ(ki) = [h(ki) + j2•h’(ki)] mod N CSI2510 CSI2510
Un exemple de Hachage Double h(k) = k mod 13 h’(k) = 7 - k mod 7 Insérer les clés 18, 41, 22, 44, 59, 32, 31, 73, dans cet ordre Note: le modulo c’est le nombre qui doit être ajouté au résultat de la division entière -34 modulo 7 donne 1 car 7*-5 + 1 = -34 1 2 3 4 5 6 7 8 9 10 11 12 31 41 18 32 59 73 22 44 CSI2510 CSI2510
Retirer 22 (22 mod 13 = 9) h(k) = k mod 13 d(k) = 7 - k mod 7 31 41 18 32 59 73 22 44 0 1 2 3 4 5 6 7 8 9 10 11 12 Retirer 22 (22 mod 13 = 9) h(k) = k mod 13 d(k) = 7 - k mod 7
h(k) = k mod 13 d(k) = 7 - k mod 7 Rechercher 31 41 18 32 59 73 Dispo 44 0 1 2 3 4 5 6 7 8 9 10 11 12 Rechercher 31 Fonction de hachage primaire: 31 mod 13 = 5 Espace occupé Fonction de hachage secondaire: 7 - 31 mod 7 = 4. Sonder 5+4=9: Dispo Sonder (9+4) mod 13: Trouvé! h(k) = k mod 13 d(k) = 7 - k mod 7
Autre exemple de Hachage Double h(ki) = ki mod N h’(ki) = ki div N N nombre premier! CSI2510 CSI2510
Performance de Hachage Double Les résultats expérimentaux pour un tableau de hachage avec le facteur de chargement recherche = n/N C( ) 0.1 (10%) 1.05 0.5 (50%) 1.38 0.75 (75%) 1.83 0.9 (90%) 2.55 CSI2510 CSI2510
Chaînage vs Adressage ouvert La méthode de chaînage utilise beaucoup de mémoire Au niveau théorique et expérimental la méthode de chainage est souvent aussi rapide que les méthodes d’adressage ouvert CSI2510 CSI2510
Performance de Hachage: Résumé Dans le pire cas, les recherches, les insertions et les suppressions dans une table de hachage prennent O(n) Le pire cas arrive quand toutes les clés insérées dans le dictionnaire entrent en collision Le facteur de chargement = n/N affecte les performances d’une table de hachage Supposons que les valeurs de hachage sont comme des nombres aléatoires, il peut être montré que le nombre prévu de sondages pour une insertion avec adressage ouvert est 1 / (1 - ) Le temps prévu de toutes les opérations du TAD dictionnaire dans le tableau est O(1) En pratique, le hachage est très rapide si le facteur de chargement n'est pas près de 100% Les applications de tableau de hachage: Petite base de données compilateurs Cache des navigateurs P2P CSI2510 CSI2510