分类目录:《算法设计与分析》总目录
我们在《字典树(前缀树、Trie树)》这一篇文章中详细介绍了Trie树,本文将利用Python语言实现它。
我们以Trie
来命名我们的Trie树类,它实例化后代表了我们Trie树中的每一个节点。每个节点包含以下两个字段:
-
children
:指向子节点的指针数组,其长度为字符数,本文以不区分大小写的26个因为字母作为例子,构建了一个长度为26的数组children
,其下标i代表着第i+1个英文字母(不区分大小写),比如children
第0个位置代表着字母Aa,第1个位置代表着字母Bb等等。在实际过程中可以采用长度为52的数组来代表区分大小写的英文字母序列。 -
isEnd
:布尔字段,表示该节点是否为字符串的结尾。
插入字符串
我们从字典树的根开始,插入字符串。对于当前字符对应的子节点,有两种情况:
- 子节点存在。沿着指针移动到子节点,继续处理下一个字符。
- 子节点不存在。创建一个新的子节点,记录在
children
数组的对应位置上,然后沿着指针移动到子节点,继续搜索下一个字符。
重复以上步骤,直到处理字符串的最后一个字符,然后将当前节点标记为字符串的结尾。
查找前缀
我们从Trie树的根开始,查找前缀。对于当前字符对应的子节点,有两种情况:
- 子节点存在。沿着指针移动到子节点,继续搜索下一个字符。
- 子节点不存在。说明字典树中不包含该前缀,返回空指针。
重复以上步骤,直到返回空指针或搜索完前缀的最后一个字符。若搜索到了前缀的末尾,就说明字典树中存在该前缀。此外,若前缀末尾对应节点的isEnd
为真,则说明字典树中存在该字符串。
下面是完整的代码:
class Trie:
def __init__(self):
self.children = [None] * 26
self.isEnd = False
def searchPrefix(self, prefix: str) -> "Trie":
node = self
for ch in prefix:
ch = ord(ch) - ord("a")
if not node.children[ch]:
return None
node = node.children[ch]
return node
def insert(self, word: str) -> None:
node = self
for ch in word:
ch = ord(ch) - ord("a")
if not node.children[ch]:
node.children[ch] = Trie()
node = node.children[ch]
node.isEnd = True
def search(self, word: str) -> bool:
node = self.searchPrefix(word)
return node is not None and node.isEnd
def startsWith(self, prefix: str) -> bool:
return self.searchPrefix(prefix) is not None