Python 字典树的变体:压缩字典树、三分搜索树等
压缩字典树(Trie-树)
Trie-树是一种特殊的字典树,它以空间换时间的方式,将相同前缀的节点进行压缩,从而减少存储空间。在 Trie-树中,每个节点表示一个字符串的前缀,每条边表示一个字符,从根节点到叶子节点的路径表示一个完整的字符串。
以下是 Trie-树的实现:
class TrieNode:
def init(self):
self.children = {}
self.is_end = False
class Trie:
def init(self):
self.root = TrieNode()
def insert(self, word: str) -> None:
current = self.root
for ch in word:
if ch not in current.children:
current.children[ch] = TrieNode()
current = current.children[ch]
current.is_end = True
def search(self, word: str) -> bool:
current = self.root
for ch in word:
if ch not in current.children:
return False
current = current.children[ch]
return current.is_end
def startsWith(self, prefix: str) -> bool:
current = self.root
for ch in prefix:
if ch not in current.children:
return False
current = current.children[ch]
return True
注意,此实现并没有进行压缩操作,而是使用普通的 Trie-树实现。如果需要实现压缩 Trie-树,可以在每个节点中添加一个计数器,表示以该节点为结尾的单词数量。当计数器为 1 时,就可以合并该节点与其父节点。
三分搜索树
三分搜索树是一种特殊的字典树,它的每个节点有三个指针,分别指向小于、等于、大于当前节点的元素。在三分搜索树中,每个节点表示一个字符,从根节点到叶子节点的路径表示一个完整的字符串。
以下是三分搜索树的实现:
class TSTNode:
def init(self, val: str):
self.val = val
self.left = None
self.mid = None
self.right = None
self.is_end = False
class TST:
def init(self):
self.root = None
def insert(self, word: str) -> None:
def _insert(node: TSTNode, i: int) -> TSTNode:
if not node:
node = TSTNode(word[i])
if word[i] < node.val:
node.left = _insert(node.left, i)
elif word[i] > node.val:
node.right = _insert(node.right, i)
elif i < len(word) - 1:
node.mid = _insert(node.mid, i + 1)
else:
node.is_end = True
return node
self.root = _insert(self.root, 0)
def search(self, word: str) -> bool:
def _search(node: TSTNode, i: int) -> bool:
if not node:
return False
if word[i] < node.val:
return _search(node.left, i)
elif word[i] > node.val:
return _search(node.right, i)
elif i == len(word) - 1:
return node.is_end
else:
return _search(node.mid, i + 1)
return _search(self.root, 0)
def startsWith(self, prefix: str) -> bool:
def _startsWith(node: TSTNode, i: int) -> bool:
if not node:
return False
if prefix[i] < node.val:
return _startsWith(node.left, i)
elif prefix[i] > node.val:
return _startsWith(node.right, i)
elif i == len(prefix) - 1:
return True
else:
return _startsWith(node.mid, i + 1)
return _startsWith(self.root, 0)
注意,由于每个节点有三个指针,因此在插入和搜索时需要对字符进行比较,比较顺序为左、中、右。
相关文章