分类目录:​​《算法设计与分析》总目录​


我们在​​《字典树(前缀树、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