Détente Il est essentiellement vrai qu'il existe de nombreuses façons différentes d'implémenter un trie ; et pour un trie important et évolutif, les dictionnaires imbriqués peuvent devenir encombrants -- ou au moins inefficaces en termes d'espace. Mais puisque vous débutez, je pense que c'est l'approche la plus simple ; vous pourriez coder un simple trie
en quelques lignes seulement. D'abord, une fonction pour construire le trie :
>>> _end = '_end_'
>>>
>>> def make_trie(*words):
... root = dict()
... for word in words:
... current_dict = root
... for letter in word:
... current_dict = current_dict.setdefault(letter, {})
... current_dict[_end] = _end
... return root
...
>>> make_trie('foo', 'bar', 'baz', 'barz')
{'b': {'a': {'r': {'_end_': '_end_', 'z': {'_end_': '_end_'}},
'z': {'_end_': '_end_'}}},
'f': {'o': {'o': {'_end_': '_end_'}}}}
Si vous n'êtes pas familier avec setdefault
il cherche simplement une clé dans le dictionnaire (ici, letter
o _end
). Si la clé est présente, il renvoie la valeur associée ; sinon, il attribue une valeur par défaut à cette clé et renvoie cette valeur ( {}
o _end
). (C'est comme une version de get
qui met également à jour le dictionnaire).
Ensuite, une fonction pour tester si le mot est dans le tri :
>>> def in_trie(trie, word):
... current_dict = trie
... for letter in word:
... if letter not in current_dict:
... return False
... current_dict = current_dict[letter]
... return _end in current_dict
...
>>> in_trie(make_trie('foo', 'bar', 'baz', 'barz'), 'baz')
True
>>> in_trie(make_trie('foo', 'bar', 'baz', 'barz'), 'barz')
True
>>> in_trie(make_trie('foo', 'bar', 'baz', 'barz'), 'barzz')
False
>>> in_trie(make_trie('foo', 'bar', 'baz', 'barz'), 'bart')
False
>>> in_trie(make_trie('foo', 'bar', 'baz', 'barz'), 'ba')
False
Je vous laisse l'insertion et le retrait comme exercice.
Bien sûr, la suggestion de Unwind ne serait pas beaucoup plus difficile. Il pourrait y avoir un léger désavantage en termes de vitesse, car trouver le bon sous-nœud nécessiterait une recherche linéaire. Mais la recherche serait limitée au nombre de caractères possibles -- 27 si nous incluons _end
. De plus, il n'y a rien à gagner à créer une liste massive de nœuds et à y accéder par index comme il le suggère ; vous pourriez tout aussi bien imbriquer les listes.
Enfin, j'ajouterai que la création d'un graphe de mots acyclique dirigé (DAWG) serait un peu plus complexe, car vous devez détecter les situations dans lesquelles votre mot actuel partage un suffixe avec un autre mot de la structure. En fait, cela peut devenir assez complexe, selon la façon dont vous voulez structurer le DAWG ! Vous devrez peut-être apprendre des choses sur Levenshtein distance pour bien faire les choses.
7 votes
Lire kmike.ru/python-data-structures pour un aperçu des structures de données exotiques en Python