• Nenhum resultado encontrado

A Tables de hachage « Coucou »

A.1 Introduction

Le trait caractéristique de toute méthode de hachage est la manière dont elle gère la collision des clés, c’est-à-dire le cas où la fonction de hachage attribue à des clés différentes la même case de la table de hachage. Les solutions les plus connues au problème des collisions consistent à utiliser soit la méthode de chaînage en associant à chaque case une liste de clés qui ont la même image par la fonction de hachage, soit la méthode d’adressage ouvert en stockant les valeurs de hachage dans des cases contiguës.

Contrairement à ces méthodes, l’approche connue dans la littérature anglophone sous le nom de « cuckoo hashing », introduite par Pagh et Rodler [1], gère les collisions en mettant en jeu plusieurs tables de hachage simultanément.

Dans cette annexe, nous illustrons comment le système de types avec régions que nous avons présenté dans le chapitre 3permet de vérifier une implémentation de « cu- ckoo hashing ».

Notre étude de cas est organisée de la manière suivante. Nous commençons par décrire brièvement l’approche, en suivant la présentation de Pagh et Rodler. Puis, nous présentons notre réalisation de cette approche en Why3 en donnant le code et la spécification de chaque fonction. Enfin, nous analysons notre implémentation du point de vue du typage et expliquons en quoi elle présente un cas d’étude intéressant et non trivial pour le système de types en question.

invariant est que le test d’appartenance se fait en temps constant. De la même manière, la suppression d’un élément est faite en temps constant, si l’on ignore le coût possible de amincissement des tableaux au cas où ils deviennent épars.

Supposons maintenant que l’on veuille ajouter un nouvel élément x dans la table de hachage H. Considérons d’abord le cas où l’ajout ne nécessite pas de rédimension- nement des tableauxT1 etT2, c’est-à-dire que, en choisissant un entierµpour fixer la charge maximale de remplissage, on a :

1 + nombre d’éléments de H Æ ¸ µ

L’insertion se passe de la façon suivante : on commence par regarder si la caseT1[h1(x)]

est disponible, auquel cas il suffit de faire l’affectation T1[h1(x)]Ωx. Sinon, T1[h1(x)]

correspond à un certain élément y différent de x (car on a supposé que x était un nouvel élément vis-à-vis de H) et avec lequel x rentre donc en collision. Dans ce cas- là, on effectue toujours l’affectation T1[h1(x)] Ω x, mais en « dénichant » cette fois l’élément y (d’où l’image de « coucou » de l’approche).

Bien entendu, on doit remettre l’élément y dans H et c’est là que l’on utilise le tableau T2, en ramenant le problème de l’insertion de x dans le tableau T1 à celui de l’insertion de y dans le tableau T2. Or, la case T2[h2(y)] peut être elle-même occupée par un autre élément z qui, délogé par y, doit à son tour être réinséré à la table H dans le tableau T1, et ainsi de suite, jusqu’à ce que chaque élément trouve son nid.

Bien entendu, ce processus migratoire peut ne pas terminer. Le dessin de la figureA.1 illustre un exemple simple d’une telle situation. Comme on le voit sur le dessin, si l’on

s t

y

z

x

T1 T2

h1(x) h2(x)

FigureA.1 – L’insertion d’un élément engendrant un cycle.

suppose que les élémentsy,z,s,t, qui appartiennent à la tableH, vérifient les égalités suivantes :

h1(y) =h1(z), h1(s) = h1(t) h2(y) =h2(z), h2(s) = h2(t),

alors, si x vérifie les égalités h1(x) = h1(y) et h2(x) =h2(t), l’insertion de x dans H ne termine pas. Notons que dans l’exemple de la figure A.1 les deux cycles sont de la même longueur égale à trois. En général, de tels cycles peuvent, bien sûr, avoir des longueurs différentes et aussi longues que le nombre d’éléments stockés dans H.

Pour éviter qu’un tel cycle se produise pour une paire de fonctions de hachage donnée une solution possible est de borner le nombre maximal d’itérations par une constantecutofflaquelle, une fois atteinte, requiert un remplacement des fonctions de hachageh1 eth2 par une nouvelle paire de fonctions hÕ1,hÕ2 pour ensuite redémarrer le processus d’insertion. Une autre solution serait de remplacer les fonctions de hachage, non pas en bornant le nombre maximal d’itérations, mais en détectant la présence d’un cycle engendré par l’insertion.

Néanmoins il reste toujours possible que, même pour les nouvelles fonctions de hachagehÕ1 ethÕ2, l’insertion engendre un nouveau cycle (ou qu’elle atteigne simplement la constantecutoffselon l’approche choisie). En général, l’insertion d’un élément dans la table peut, au moins du point de vue théorique, échouer dans l’approche « cuckoo hashing ». Nous invitons le lecteur à consulter l’article de Pagh et Rodler qui expliquent les raisons pour lesquelles cette situation est peu probable et, plus généralement, qui montrent que « cuckoo hashing » est une méthode de hachage très efficace de point de vue de complexité des opérations de base.

Enfin, il se peut que l’ajout de x dans H nécessite de redimensionner les tableaux T1 etT2. Dans ce cas-là, le redimensionnement peut être fait en temps constant amorti par rapport à l’opération d’ajout, en doublant la taille des tableaux à chaque redi- mensionnement. Nous présentons maintenant une implémentation possible de cette approche en Why31.

1. Le lecteur peut trouver l’intégralité du code sur le lien suivant : https://www.lri.fr/~gondelman/cuckoo_hashing.mlw