Présentation de la table de hachage simple
En guise de rappel, une table de hachage est un moyen de stocker une valeur sous une clé spécifique dans une structure de données. Par exemple, je pourrais stocker de la valeur "a"
sous la clé 1
, puis la récupérer plus tard en recherchant la clé 1
dans la table de hachage.
L'exemple le plus simple d'une table de hachage à laquelle je peux penser du haut de ma tête est une table de hachage qui ne peut stocker que des entiers, où la clé de l'entrée de la table de hachage est également la valeur stockée. Disons que votre table est de taille 8, et c'est essentiellement un tableau en mémoire:
---------------------------------
| | | | | | | | |
---------------------------------
0 1 2 3 4 5 6 7
Fonction de hachage
Les fonctions de hachage vous donnent un index sur l'endroit où stocker votre valeur. Une fonction de hachage assez simple pour cette table serait d'ajouter 1 à la valeur que vous souhaitez stocker, puis de la modifier de 8 (la taille de la table). En d'autres termes, votre fonction de hachage est (n+1)%8
, où n
est l'entier que vous souhaitez stocker.
Inserts
Si vous souhaitez insérer une valeur dans cette table de hachage, vous appelez votre fonction de hachage (dans ce cas (n+1)%8
) sur la valeur que vous souhaitez insérer pour vous donner un index. Par exemple, si nous voulons insérer 14, nous appelons (14 + 1) % 8
et récupérons index 7
, nous insérons donc la valeur dans index 7
.
---------------------------------
| | | | | | | |14 |
---------------------------------
0 1 2 3 4 5 6 7
De même, nous pouvons insérer 33, 82 et 191 comme ceci:
---------------------------------
|191| |33 |82 | | | |14 |
---------------------------------
0 1 2 3 4 5 6 7
Collisions
Mais que se passe-t-il si nous essayons d'insérer quelque chose qui entrerait en collision avec une entrée? 2 devrait aller dans l'index 3
, mais il est pris par 82. Il existe plusieurs façons de résoudre ce problème, la plus simple est d'appeler notre fonction de hachage à plusieurs reprises jusqu'à ce que nous trouvions un espace vide.
La logique est donc la suivante:
- (2 + 1)% 8 = 3
- L'index 3 est plein
- Rebranchez 3 dans notre fonction de hachage. ( 3 + 1)% 8 = 4 , qui est vide.
- Placez notre valeur dans l'index 4 .
Maintenant, la table de hachage ressemble à ceci, avec la valeur 2 stockée à l'index 4
.
---------------------------------
|191| |33 |82 |2 | | |14 |
---------------------------------
0 1 2 3 4 5 6 7
L'inconvénient de cette solution est que très bientôt, notre table sera pleine! Si vous savez que la taille de vos données est limitée, cela ne devrait pas être un problème tant que votre table est suffisamment grande pour contenir toutes les valeurs possibles. Si vous voulez pouvoir en tenir plus, vous pouvez gérer les collisions différemment. Revenons à l'endroit où nous en étions avant d'insérer 2.
---------------------------------
|191| |33 |82 | | | |14 |
---------------------------------
0 1 2 3 4 5 6 7
Si vous vous souvenez, (2+1)%8
donne-nous l'indice 3
, qui est pris. Si vous ne voulez pas que votre table de hachage se remplisse, vous pouvez utiliser chaque index de table en tant que liste liée et l'ajouter à la liste à cet index. Ainsi, au lieu d'appeler à nouveau la fonction de hachage, nous ajouterons simplement à la liste à l'index 3
:
-----
| 2 |
---------------------------------
|191| |33 |82 | | | |14 |
---------------------------------
0 1 2 3 4 5 6 7
Cette liste peut alors s'allonger autant que la mémoire le permet. Je peux insérer 18, et il sera simplement ajouté à 2:
-----
|18 |
-----
| 2 |
---------------------------------
|191| |33 |82 | | | |14 |
---------------------------------
0 1 2 3 4 5 6 7
Recherches
La recherche de valeurs dans votre table de hachage est rapide, étant donné que votre table de hachage est d'une taille assez grande. Vous appelez simplement votre fonction de hachage et obtenez l'index. Disons que vous voulez voir si 82 est dans votre table. La fonction de recherche appelle (82+1)%8
= 3
et examine l'élément dans l'index 3
et le renvoie pour vous. Si vous avez recherché 16, la fonction de recherche regarderait dans l'index 1
et verrait qu'elle n'existe pas.
Les recherches doivent également gérer les collisions!
Si vous essayez de rechercher la valeur 2, votre table de hachage devra utiliser la même logique de collision utilisée pour stocker les données que pour récupérer les données. Selon le fonctionnement de votre table de hachage, vous devez soit hacher la clé à plusieurs reprises jusqu'à ce que vous trouviez l'entrée que vous recherchez (ou trouver un espace vide), soit vous parcourrez votre liste de liens jusqu'à ce que vous trouviez l'élément (ou arrivé à la fin de la liste)
Sommaire
Les tables de hachage sont donc un bon moyen de stocker et d'accéder rapidement aux paires clé-valeur. Dans cet exemple, nous avons utilisé la même clé que la valeur, mais dans les tables de hachage du monde réel, les clés ne sont pas si limitées. Les fonctions de hachage fonctionneront sur les clés pour générer un index, puis la clé / valeur peut être stockée dans cet index. Les tables de hachage ne sont pas vraiment destinées à être itérées, bien qu'il soit possible de le faire. Comme vous pouvez le voir, les tables de hachage peuvent avoir beaucoup d'espaces vides, et leur itération serait une perte de temps. Même si la table de hachage a une logique pour ignorer les recherches d'espace vide dans son itérateur, vous seriez mieux adapté en utilisant une structure de données conçue pour les itérateurs, comme les listes chaînées.