快乐学算法之:三分查找树ternary search tree

三分查找树是一种优化的字典树结构,通过每个节点拥有三个子节点来节省空间。在插入和查找过程中,根据字符大小关系决定插入位置。文章介绍了三分查找树的构建过程,代码实现以及在查找共同前缀字符串上的应用,适合实现搜索引擎的自动填充功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

之前我们介绍了tire字典树,tire字典树的优点就是插入和查找比较快速,但是它的缺点就是占用的空间比较大。假如我们要存放一个英文字典(全都是小写字母),那么每个节点将会有26个子节点,用来保存所有可能字符。

trie树既然这么占用空间,有没有比较好的办法来减少空间的占用或者提高空间的使用率呢?有的,这就是今天我们需要讲到的ternary search tree,中文叫做三分查找树。

三分查找树的结构

在讲三分查找树之前,我们先看一个trie树的结构:

上面的trie树中我们存储了三个单词,分别是quan,qun和lian。 我们在每个节点中同时保存了该节点是否是单词结尾的标记,其中1表示是单词的结尾,0表示不是单词的结尾。

这样做的好处是可以在一条树的路径上存储多个单词。

同时trie树的根节点是个不存任何数据的节点,所有的数据都是接在这个根节点下面的。

我们先看下三分查找树的结构:

首先三分查找树的每个节点都有三个子节点,这也是三分查找树的名字的由来。然后我们给每个节点也添加一个是否是单词结尾的标记,用0和

### 字典(Trie)原理 字典(Trie),又称为前缀,是一种有序结构,用于存储一组字符串,其中每个节点代表一个字符。从根节点到某一节点路径上的字符组成的字符串即为该节点所代表的字符串。字典的一个显著特点是共享前缀的字符串可以共用的前缀路径,从而节省存储空间并提高查找效率。字典通常采用链表或数组的方式实现节点的子节点集合。 字典的基本操作包括插入、查找和删除: - **插入**:将一个字符串插入到字典中,从根节点开始逐字符查找,若字符对应的节点不存在则创建新节点。 - **查找**:判断一个字符串是否存在于字典中,同样从根节点出发,逐字符匹配。 - **删除**:移除字典中的某个字符串,需要考虑删除后是否影响其他字符串的前缀。 字典的核心优势在于其高效的字符串处理能力,特别是在处理具有公共前缀的字符串集合时表现尤为出色。通过字典,可以快速完成字符串的检索、排序、前缀统计等操作。字典的时间复杂度为 $O(L)$,其中 $L$ 是字符串的最大长度,这使得它在字符串处理方面具有较高的效率。 ### 字典的应用场景 字典因其高效的字符串处理能力,在多个领域得到了广泛应用,主要包括以下几个方面: 1. **搜索引擎**:字典常用于搜索引擎中的自动补全功能,能够快速响应用户的输入建议,提供高效的前缀匹配能力。 2. **路由查找**:在网络路由中,字典可用于IP地址的最长前缀匹配,提高路由查找的效率。 3. **拼写检查**:字典可用于实现拼写检查功能,通过构建词典来快速判断输入单词是否正确。 4. **电话簿管理**:字典适用于电话簿等需要频繁进行字符串查询的应用场景,能够快速完成联系人的查找。 5. **文本压缩**:在某些文本压缩算法中,字典被用来构建编码表,提高压缩效率。 6. **自然语言处理**:字典在自然语言处理领域也有应用,如词性标注、命名实体识别等任务中,用于快速查找词汇表中的词语。 ### 字典的变种 字典有许多变种,其中较为常见的包括 **Ternary Search Tree (TST)** 和 **Radix Tree**(也称 **Patricia Tree**)。 #### Ternary Search Tree (TST) Ternary Search Tree三元搜索树)是字典的一种变体,结合了二叉搜索树和字典的优点。每个节点包含三个分支:左子、中间子和右子,分别对应小于、等于和大于当前字符的情况。TST 的搜索效率与字符串的长度成正比,但由于每次比较可以将搜索范围缩小到三分之一,因此在处理大量字符串或长字符串时,其效率优于传统字典。 #### Radix Tree Radix Tree(基数),又称为压缩字典,是对传统字典的优化。它通过合并单子节点的路径来减少的高度,从而减少内存占用并提高查找效率。Radix Tree 在字典的基础上进行了优化,适用于需要高效查找的场景,例如 Redis 中存储 Slot 对应的 Key 信息、内核中使用 Radix Tree 管理数据结构、大多数 HTTP 的 Router 通过 Radix Tree 管理路由等。 ### 字典的代码实现 以下是一个简单的 Python 实现字典的示例: ```python class TrieNode: def __init__(self): self.children = {} self.is_end_of_word = False class Trie: def __init__(self): self.root = TrieNode() def insert(self, word): node = self.root for char in word: if char not in node.children: node.children[char] = TrieNode() node = node.children[char] node.is_end_of_word = True def search(self, word): node = self.root for char in word: if char not in node.children: return False node = node.children[char] return node.is_end_of_word def starts_with(self, prefix): node = self.root for char in prefix: if char not in node.children: return False node = node.children[char] return True ``` 上述代码定义了一个 `TrieNode` 类作为字典的节点,每个节点包含一个字典 `children` 来存储子节点以及一个布尔值 `is_end_of_word` 来标记该节点是否为某个单词的结尾。`Trie` 类提供了插入、查找和前缀检查的方法。 ### 字典的优缺点 #### 优点 1. **高效查找**:字典的查找时间复杂度为 $O(L)$,其中 $L$ 是字符串的最大长度,相较于哈希表的 $O(1)$,虽然时间复杂度略高,但字典在处理前缀匹配时具有明显优势。 2. **前缀匹配**:字典非常适合处理前缀匹配问题,能够快速找到所有以特定前缀开头的字符串。 3. **节省空间**:对于具有公共前缀的字符串集合,字典可以通过共享前缀路径来节省存储空间。 #### 缺点 1. **内存占用**:字典在某些情况下可能会占用较多的内存,尤其是在字符串集合中没有太多公共前缀的情况下。 2. **插入和删除操作较复杂**:相比于其他数据结构,字典的插入和删除操作较为复杂,需要维护的结构。 ### 字典与其他数据结构的比较 | 数据结构 | 插入时间复杂度 | 查找时间复杂度 | 前缀匹配 | 内存占用 | |---------|----------------|----------------|----------|----------| | 字典 | $O(L)$ | $O(L)$ | 支持 | 中等 | | 哈希表 | $O(1)$ | $O(1)$ | 不支持 | 较低 | | 平衡二叉搜索树 | $O(\log N)$ | $O(\log N)$ | 不支持 | 较低 | 从上表可以看出,字典在处理字符串时具有独特的优势,尤其是在前缀匹配方面,而哈希表和平衡二叉搜索树则在插入和查找效率上各有特点。 ### 字典的扩展应用 除了上述应用场景外,字典还可以应用于以下领域: 1. **IP 地址查找**:在路由表中,字典可用于实现最长前缀匹配,提高 IP 地址查找的效率。 2. **词频统计**:字典可以用于统计文本中单词出现的频率,通过在每个节点记录单词出现的次数来实现。 3. **字符串排序**:字典可以用于对字符串集合进行排序,通过遍历字典即可得到按字典序排列的字符串集合。 ### 字典的优化 为了进一步提高字典的性能,可以采取以下优化措施: 1. **压缩路径**:通过合并单子节点的路径来减少的高度,从而减少内存占用并提高查找效率,这就是 Radix Tree 的核心思想。 2. **使用数组代替字典**:在某些情况下,可以使用固定大小的数组来代替字典来存储子节点,以提高访问速度。 3. **多线程支持**:为了支持并发操作,可以在字典的基础上添加锁机制或使用无锁编程技术来实现线程安全。 ### 字典的挑战 尽管字典在字符串处理方面具有诸多优势,但在实际应用中仍面临一些挑战: 1. **内存限制**:在处理大规模字符串集合时,字典可能会占用大量内存,尤其是在字符串集合中没有太多公共前缀的情况下。 2. **动态更新**:字典的插入和删除操作较为复杂,需要维护的结构,这在某些动态更新频繁的场景下可能会影响性能。 3. **可扩展性**:随着数据量的增长,字典的可扩展性成为一个挑战,需要设计更高效的存储和访问机制。 ### 字典的发展趋势 随着大数据和人工智能技术的发展,字典的应用前景更加广阔。未来,字典可能会在以下几个方面得到进一步发展: 1. **分布式字典**:为了支持大规模数据处理,可以将字典扩展为分布式版本,利用分布式计算框架来提高处理能力。 2. **内存优化**:通过引入更高效的存储结构和压缩算法,进一步降低字典的内存占用。 3. **智能索引**:结合机器习和深度习技术,开发智能索引机制,提高字典的查询效率和适应性。 ### 总结 字典是一种高效的字符串处理数据结构,广泛应用于搜索引擎、路由查找、拼写检查等领域。通过共享前缀路径,字典能够在字符串集合中实现高效的查找和前缀匹配。字典的变种如 Ternary Search Tree 和 Radix Tree 进一步优化了其性能,使其在不同场景下更具竞争力。尽管字典在内存占用和动态更新方面存在一定挑战,但通过合理的优化措施,可以有效克服这些问题,拓展其应用范围。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

flydean程序那些事

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值