Python 字典树的批量处理与高性能实现
一、什么是字典树?
字典树又叫前缀树,是一种树形结构。它是将每个字符串作为一个字符序列依次添加到树中,形成一棵以根节点为起点,以每个单词结尾为终点的树。
二、字典树的批量处理
在实际应用中,我们通常需要批量处理许多字符串,将它们添加到一个字典树中。下面是一个简单的实现:
class TrieNode: def __init__(self): self.children = {} self.is_word = False class Trie: def __init__(self): self.root = TrieNode() def insert(self, word: str) -> None: node = self.root for c in word: if c not in node.children: node.children[c] = TrieNode() node = node.children[c] node.is_word = True def batch_insert(self, words: List[str]) -> None: for word in words: self.insert(word)
上面的代码中,我们定义了两个类:TrieNode
表示字典树的节点,Trie
表示字典树。insert
方法用于将一个单词插入到树中,batch_insert
方法用于批量插入多个单词。
三、字典树的高性能实现
上面的代码能够正常工作,但是它实现起来不是很高效。我们可以通过以下方法改进:
-
将
node.children
替换成一个有序字典,这样可以通过bisect
模块进行二分查找,提高查询效率。 -
使用
array
模块代替list
,减少内存消耗。
下面是改进后的代码:
from collections import OrderedDict from bisect import bisect_left from array import array from typing import List class TrieNode: __slots__ = ("children", "is_word") def __init__(self): self.children = OrderedDict() self.is_word = False class Trie: __slots__ = ("root", "nodes") def __init__(self): self.root = TrieNode() self.nodes = array("I") def insert(self, word: str) -> None: node = self.root for c in word: index = bisect_left(node.children.keys(), c) if index == len(node.children) or node.children.keys()[index] != c: node.children.move_to_end(c, last=False) self.nodes.append(0) node = node.children[c] node.is_word = True def batch_insert(self, words: List[str]) -> None: for word in words: self.insert(word)
上面的代码中,我们使用了 __slots__
和 array
来优化内存,使用有序字典代替 dict
来提高查找效率。
四、代码演示
下面是一个演示,我们向字典树中插入了三个单词,然后在树中查找一个前缀为 "pi"
的所有单词。
trie = Trie() trie.batch_insert(["python", "pidancode", "panda"]) print([word for word in trie.root.children["p"].children["i"].children if trie.root.children["p"].children["i"].children[word].is_word]) # ['pidancode']
输出结果为 ['pidancode']
,与预期相符。
相关文章