🗄️ Tables de Hachage et Fonctions de Hachage

Les tables de hachage sont des structures de données puissantes permettant un accès rapide aux données grâce à des fonctions de hachage. Elles sont essentielles pour des opérations efficaces d'insertion, de recherche et de suppression.

📚 Qu'est-ce qu'une Table de Hachage ?

Une table de hachage est une structure de données qui stocke des paires clé-valeur. Elle utilise une fonction de hachage pour convertir une clé en un index dans un tableau, permettant un accès quasi constant aux données.

Illustration d'une Table de Hachage

🔑 Propriétés des Fonctions de Hachage

Une fonction de hachage efficace doit respecter les propriétés suivantes :

  • Uniformité : Les clés doivent être réparties de manière uniforme pour minimiser les collisions.
  • Déterminisme : La même clé doit toujours produire le même index.
  • Performance : Le calcul doit être rapide pour des opérations efficaces.

⚠️ Gestion des Collisions

Les collisions se produisent lorsque deux clés différentes produisent le même index. Il existe deux méthodes principales pour les résoudre :

Separate Chaining (Chaînage Séparé)

Chaque emplacement de la table pointe vers une liste qui stocke toutes les paires clé-valeur ayant le même index.

Open Addressing (Adressage Ouvert)

Au lieu d'utiliser des listes, on cherche une autre case libre dans la table pour insérer la nouvelle paire. Les techniques incluent le sondage linéaire, quadratique et le double hachage.

💻 Implémentation du Chaînage Séparé en Python

class HashTableSeparateChaining:
    def __init__(self, taille=10):
        self.table = [[] for _ in range(taille)]

    def _hash_function(self, cle):
        return hash(cle) % len(self.table)

    def inserer(self, cle, valeur):
        index = self._hash_function(cle)
        for i, (k, v) in enumerate(self.table[index]):
            if k == cle:
                self.table[index][i] = (cle, valeur)
                return
        self.table[index].append((cle, valeur))

    def rechercher(self, cle):
        index = self._hash_function(cle)
        for k, v in self.table[index]:
            if k == cle:
                return v
        return None

    def supprimer(self, cle):
        index = self._hash_function(cle)
        for i, (k, v) in enumerate(self.table[index]):
            if k == cle:
                del self.table[index][i]
                return True
        return False

Explication du Code : Cette implémentation utilise une liste de listes pour gérer les collisions. Chaque index de la table contient une liste de paires clé-valeur.

💻 Implémentation de l'Adressage Ouvert avec Sondage Linéaire

class HashTableLinearProbing:
    def __init__(self, taille=10):
        self.table = [None] * taille

    def _hash_function(self, cle):
        return hash(cle) % len(self.table)

    def inserer(self, cle, valeur):
        index = self._hash_function(cle)
        while self.table[index] is not None:
            if self.table[index][0] == cle:
                self.table[index] = (cle, valeur)
                return
            index = (index + 1) % len(self.table)
        self.table[index] = (cle, valeur)

    def rechercher(self, cle):
        index = self._hash_function(cle)
        while self.table[index] is not None:
            if self.table[index][0] == cle:
                return self.table[index][1]
            index = (index + 1) % len(self.table)
        return None

    def supprimer(self, cle):
        index = self._hash_function(cle)
        while self.table[index] is not None:
            if self.table[index][0] == cle:
                self.table[index] = None
                return True
            index = (index + 1) % len(self.table)
        return False

Explication du Code : Cette implémentation utilise un tableau où, en cas de collision, on cherche séquentiellement le prochain emplacement libre.

📊 Analyse de Complexité

Pour une table de hachage bien équilibrée :

OpérationComplexité MoyenneComplexité Pire Cas
InsertionO(1)O(n)
RechercheO(1)O(n)
SuppressionO(1)O(n)

💪 Exercices

Testez vos connaissances avec ces exercices :

# Exercices :

# 1. Implémentez une table de hachage en utilisant le sondage quadratique pour l'adressage ouvert.

# 2. Écrivez une fonction pour redimensionner automatiquement la table de hachage lorsque le taux de remplissage dépasse un certain seuil.

# 3. Créez une fonction de hachage personnalisée pour une table de hachage qui stocke des objets complexes.

# 4. Implémentez une méthode pour gérer les collisions en utilisant le double hachage.

# 5. Écrivez un programme pour analyser les performances de différentes méthodes de résolution des collisions.

🎉 Conclusion

Les tables de hachage sont des structures de données essentielles pour des opérations de recherche, d'insertion et de suppression rapides. Comprendre les différentes méthodes de gestion des collisions vous permettra de choisir la meilleure approche pour vos applications.