什么是 Trie 树
Trie 树,又称前缀树,字段典树,或单词查找树,是一种树形结构,也是哈希表的变种,它是一种专门处理字段串匹配的数据结构,用来解决在一组字符串集合中快速查找某个字符串的问题,主要被搜索引擎用来做文本词频的统计。
先看一下前辍树的图:

这棵前辍树根节点不存放数据,其他节点保存了 hello,her,hi,how,see,so 等关键词信息,如果查 he 前辍的单词可以很快返回 hello,her。
Trie 树的 Python 实现
一般来讲 trie 要实现这么几个方法
- 插入一个单词 insert (word: str) -> None
- 查找一个单词是否在 trie 中 search (word:str) -> bool
- 查找一个前缀是否在 trie 中 startsWith (prefix:str) -> bool
class Trie:def __init__(self):"""Initialize your data structure here."""self.root = {}self.end_of_word = '#'def insert(self, word: str) -> None:"""Inserts a word into the trie."""node = self.rootfor char in word:node = node.setdefault(char, {})node[self.end_of_word] = self.end_of_worddef search(self, word: str) -> bool:"""Returns if the word is in the trie."""node = self.rootfor char in word:if char not in node:return Falsenode = node[char]return self.end_of_word in nodedef startsWith(self, prefix: str) -> bool:"""Returns if there is any word in the trie that starts with the given prefix."""node = self.rootfor char in prefix:if char not in node:return Falsenode = node[char]return Truedef get_start(self,prefix):'''给出一个前辍,打印出所有匹配的字符串:param prefix::return:'''def get_key(pre,pre_node):result = []if pre_node.get(self.end_of_word):result.append(pre)for key in pre_node.keys():if key != self.end_of_word:result.extend(get_key(pre+key,pre_node.get(key)))return resultif not self.startsWith(prefix):return []else:node = self.rootfor p in prefix:node = node.get(p)else:return get_key(prefix,node)if __name__ == "__main__":trie = Trie()trie.insert("Python")trie.insert("Python 算法")trie.insert("Python web")trie.insert("Python web 开发")trie.insert("Python web 开发 视频教程")trie.insert("Python 算法 源码")trie.insert("Perl 算法 源码")print(trie.search("Perl"))print(trie.search("Perl 算法 源码"))print((trie.get_start('P')))print((trie.get_start('Python web')))print((trie.get_start('Python 算')))print((trie.get_start('P')))print((trie.get_start('Python web')))print((trie.get_start('Python 算')))
代码运行结果如下:
FalseTrue['Python', 'Python 算法', 'Python 算法 源码', 'Python web', 'Python web 开发', 'Python web 开发 视频教程', 'Perl 算法 源码']['Python web', 'Python web 开发', 'Python web 开发 视频教程']['Python 算法', 'Python 算法 源码']
Trie 的时间复杂度
如果要在一组关键词中,频繁地查询某些关键词,用 Trie 树会非常高效。构建 Trie 树的过程,需要扫描所有的关键词,时间复杂度是 O(n)(n 表示所有关键词的长度和)。但是一旦构建成功之后,后续的查询操作会非常高效。
每次查询时,如果要查询的关键词长度是 k,那我们只需要最多比对 k 个节点,就能完成查询操作。跟原本那组关键词的长度和个数没有任何关系。所以说,构建好 Trie 树后,在其中查找关键词的时间复杂度是 O(k),k 表示要查找的关键词的长度。
Trie三方实现库
自己造轮子还要思考,编码,验证,但这是学习提升的最佳方式。如果急于应用没有时间造轮子,至少要学会如何使用轮子,下面的前辍树的轮子是一个日本人写的,大家可以学习应用下。
https://github.com/pytries/marisa-trie
https://marisa-trie.readthedocs.io/en/latest/tutorial.html
