← 返回题目列表

三叉搜索树 TST 是什么?它和 Trie 有什么区别?

困难 第 25 / 26 题 更新于 2026/07/30
TrieTST字符串搜索

简化版

TST,全称 Ternary Search Tree,三叉搜索树,是 Trie 和二叉搜索树思想的结合。

每个节点存一个字符,并有 3 条指针:小于当前字符、等于当前字符、大于当前字符。等于分支表示继续匹配下一个字符,小于和大于分支用于在同一层做字符搜索。

它比普通 Trie 更省孩子指针空间,但查找时多了字符比较和分支判断。

详细版

普通 Trie 的一个节点通常保存多个孩子,比如 a-z

TST 节点只保存一个字符:

char c
left   -> 当前字符更小
middle -> 当前字符相等,匹配下一个字符
right  -> 当前字符更大
结构孩子表示
Trie一个节点有多个字符孩子
TST一个节点 3 个指针,像 BST 一样比较字符

TST 适合字符集较大、普通 Trie 孩子数组太浪费,但又希望保留前缀搜索能力的场景。

完整版教学

1. 为什么会有 TST

普通 Trie 对前缀搜索很友好,但节点孩子结构可能很占空间。

如果每个节点都有 children[256],而真实孩子只有几个,空间浪费明显。

TST 想做一件事:保留 Trie 的逐字符匹配能力,同时把每个节点的孩子指针数量控制在 3 个。

2. TST 节点结构长什么样

一个 TST 节点通常包含:

char c
Node left
Node mid
Node right
boolean end

含义是:

指针含义
left当前要匹配的字符小于 c
mid当前字符等于 c,进入下一个字符
right当前要匹配的字符大于 c

它有点像每一层都挂了一棵字符二叉搜索树。

3. 查找过程怎么走

查找单词 cat 时,拿当前字符和节点字符比较。

if ch < node.c: go left
if ch > node.c: go right
if ch == node.c:
  if 是最后一个字符: 看 end
  else: go mid and match next char

只有走 mid 时,才会消费字符串的下一个字符。

TST 最容易混淆的点是:left/right 仍然比较同一个字符,mid 才进入下一个字符。

4. 和普通 Trie 的核心区别

普通 Trie 通过下标或 Map 直接找到某个字符孩子。

TST 则通过比较当前字符,在 left/right/mid 中导航。

维度普通 TrieTST
单节点孩子多个3 个
查找字符数组或 Map 定位比较字符
空间可能较大通常更省
实现理解更直接稍绕

如果字符集大而稀疏,TST 会更有吸引力。

5. TST 是否支持前缀搜索

支持。

先查找到前缀最后一个字符对应的节点,然后从它的 mid 子树开始收集后续字符串。

如果前缀本身也是单词,还要先输出前缀。

例如前缀 ca

找到 a 节点
如果 a.end 输出 ca
遍历 a.mid 输出 cat, car ...

6. 复杂度怎么回答

TST 的查找复杂度和树形有关。

如果同层字符搜索比较平衡,查找接近:

O(L log A)

其中 L 是字符串长度,A 是字符集分支规模。实际实现中也常说与字符串长度和字符比较路径有关。

普通数组 Trie 则更接近 O(L),但空间常数大。

7. 它适合什么场景

TST 适合:

  1. 字符集较大;
  2. 数据集较稀疏;
  3. 需要前缀搜索;
  4. 希望比 Map Trie 更紧凑;
  5. 能接受稍复杂的查找逻辑。

工程中它不如普通 Trie 常见,但作为数据结构面试扩展点很有价值。

8. 常见误区与追问

  • 误区:TST 是三叉堆或三叉树。 它是用于字符串搜索的三叉搜索树,不是堆结构。
  • 误区:left/right 会消费下一个字符。 只有 mid 分支表示当前字符匹配成功并进入下一个字符。
  • 误区:TST 不支持前缀匹配。 它支持,只是遍历入口和普通 Trie 稍有不同。
  • 追问:TST 为什么省空间? 每个节点固定 3 个指针,不需要为完整字符集准备孩子槽。
  • 追问:它比 Trie 更快吗? 不一定,它通常省空间,但字符比较路径可能更长。