Dans les microcosmes dans lesquels je suis intégré, les goûts de la structure de données trie n’est pas si populaire. Cet environnement est composé principalement de data scientists et, en plus petit nombre, d’ingénieurs logiciels, travaillant avec le traitement du langage naturel (NLP).
Récemment, je me suis retrouvé dans une discussion intéressante sur le moment où il faut utiliser trie ou table de hachage. Bien qu’il n’y ait rien de nouveau dans cette discussion que je puisse rapporter ici, comme les avantages et les inconvénients de chacune de ces deux structures de données (si vous googlez un peu, vous trouverez de nombreux liens les abordant), ce qui était nouveau pour moi était un type spécial de trie appelé Patricia Trie et, que dans certains scénarios, cette structure de données fonctionne de manière comparable à la fois en temps de traitement et en espace avec la table de hachage, tout en abordant des tâches telles que la liste des chaînes de caractères avec un préfixe commun sans coût supplémentaire.
Avec cela en tête, j’ai cherché une histoire ou un blog pour m’aider à comprendre de manière simple (euphémisme pour la paresse) comment fonctionne l’algorithme PATRICIA, servant spécialement de raccourci pour lire le papier de 21 pages publié en 1968. Malheureusement, je n’ai pas réussi dans cette recherche, me laissant sans alternative pour le lire.
Mon objectif avec cette histoire est de combler la lacune ci-dessus, c’est-à-dire, d’avoir une histoire décrivant en termes profanes l’algorithme à portée de main.
Pour atteindre mon objectif, d’abord, et brièvement, je vais introduire, pour ceux qui ne sont pas familiers avec les essais, cette structure de données. Après cette introduction, je vais énumérer les trie les plus populaires qui existent, ce qui me permettra d’implémenter et de décrire en détail le fonctionnement des trie PATRICIA et pourquoi ils sont si performants. Je terminerai cette histoire en comparant les résultats (performances et consommation d’espace) dans deux applications différentes : la première est un comptage de mots (tuples <WORD, FREQUENCY>) basé sur un texte assez volumineux ; et la seconde construit un tuples <URL, IP>, basé sur une liste de plus de 2 millions d’URL, qui consiste en l’élément central d’un serveur DNS. Les deux applications ont été construites sur la base de Hash Map et de Patricia Trie.
Comme défini par Sedgewick et Wayne de l’Université de Princeton dans leur livre Algorithms – Fourth Edition (éditeur : Addison-Wesley) un trie, ou arbre de préfixe, est « une structure de données construite à partir des caractères de la clé de recherche pour guider la recherche ». Cette « structure de données est composée de nœuds qui contiennent des liens qui sont soit nuls, soit des références à d’autres nœuds. Chaque nœud est pointé par un seul autre nœud, qui est appelé son parent (à l’exception d’un nœud, la racine, qui n’a aucun nœud pointant vers lui), et chaque nœud a S liens, où S est la taille de l’alphabet (ou charset) ».
La figure 1 ci-dessous, suivant la définition ci-dessus, contient un exemple de trie.
Et, enfin, nous insérons le caractère G. Après tous les calculs, nous concluons que le nouveau nœud doit être placé comme enfant droit du nœud F avec diff égal à 8. Le résultat final est dans la figure 14.
Jusqu’à présent nous insérons des chaînes de caractères composées d’un seul caractère. Que se passerait-il si nous essayions d’insérer les chaînes AB et BA ? Le lecteur intéressé peut prendre cette proposition comme un exercice. Deux indices : les deux chaînes diffèrent du nœud B en position 9 ; et le trie final est illustré dans la figure 15.
En réfléchissant à la dernière figure, on peut se poser la question suivante : Pour trouver, par exemple, la chaîne BA on a besoin de 5 comparaisons de bits, tandis que pour calculer le code de hachage de cette chaîne seulement deux itérations sont nécessaires, alors quand est-ce que le Trie PATRICIA devient compétitif ? Imaginez que nous insérions dans cette structure la chaîne ABBABABBBBABABBA (tirée de l’exemple de l’article original de PATRICIA datant de 1968) qui compte 16 caractères ? Cette chaîne serait placée en tant qu’enfant gauche du nœud AB avec diff en position 17. Pour la trouver, nous aurions besoin de 5 comparaisons de bits, tandis que pour calculer le code de hachage, il faudrait 16 itérations, une pour chaque caractère, ceci étant la raison pour laquelle les Trie PATRICIA sont si compétitifs lors de la recherche de longues chaînes.
Trie PATRICIA vs Hash Map
Dans cette dernière section, je vais comparer Hash Map et Trie PATRICIA dans deux applications. La première est un comptage de mots sur leipzig1m.txt contenant 1 million de phrases aléatoires et la seconde consiste à peupler une table de symboles avec plus de 2,3 millions d’URL du projet DMOZ (fermé en 2017) téléchargé ici.
Le code que j’ai développé et utilisé à la fois pour mettre en œuvre le pseudocode ci-dessus et comparer les performances de PATRICIA Trie avec la table de hachage peut être trouvé sur mon GitHub.
Ces comparaisons ont été exécutées dans ma boîte Ubuntu 18.04. Configurantion peut être trouvée dans la figure 16
.