1.定义
字典树,即 Trie 树,又称单词查找树或键树,是一种树形结构 。典型应用是用于统计和排序大量的字符串(但不仅限于字符串), 所以经常被搜索引擎系统用于文本词频统计。
它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高。(空间换时间)
思考
我们能够使用平衡树或哈希表在字符串数据集中搜索单词。为什么我们还需要 Trie 树呢?
尽管哈希表可以在 O(1) 时间内寻找键值,却无法高效的完成:
- 找到具有同一前缀的全部键值
- 按词典序枚举字符串的数据集
- 随着哈希表大小的增加,更容易产生冲突
Trie树在存储多个具有相同的前缀的键值时可以使用较少的空间。此时Trie树只需要o(m)的时间复杂度,其中m为键长。而在平衡树中查找键值需要O(mlogn) 时间复杂度。
Trie树图片
2.基本性质
- 节点本身不存在完整的单词 。
- 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
- 每个节点的所有子节点路径代表的字符都不相同。
3.场景应用
1.自动补全
2.拼写检查
3. IP 路由 (最长前缀匹配)
4.核心思想
- Trie树的核心思想是空间换时间
- 利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。
5.代码实现
public class Trie {
private TrieNode root;
/**
* Initialize your data structure here.
*/
public Trie() {
root = new TrieNode();
}
/**
* Inserts a word into the trie.
*/
public void insert(String word) {
TrieNode node = root;
for (int i = 0; i < word.length(); i++) {
char key = word.charAt(i);
if (!node.containKey(key)) {
node.put(key, new TrieNode());
}
node = node.get(key);
}
node.setEnd();
}
public TrieNode searchPrefix(String word) {
TrieNode node = root;
for (int i = 0; i < word.length(); i++) {
char key = word.charAt(i);
if (node.containKey(key)) {
node = node.get(key);
} else {
return null;
}
}
return node;
}
/**
* Returns if the word is in the trie.
*/
public boolean search(String word) {
TrieNode node = searchPrefix(word);
return node != null && node.isEnd();
}
/**
* Returns if there is any word in the trie that starts with the given prefix.
*/
public boolean startsWith(String prefix) {
TrieNode node = searchPrefix(prefix);
return node != null;
}
}
class TrieNode {
private TrieNode[] trieNodes;
private final int number = 26;
private boolean isEnd;
public TrieNode() {
trieNodes = new TrieNode[number];
}
public boolean containKey(char key) {
return trieNodes[key - 'a'] != null;
}
public void put(char key, TrieNode trieNode) {
trieNodes[key - 'a'] = trieNode;
}
public TrieNode get(char key) {
return trieNodes[key - 'a'];
}
public void setEnd() {
isEnd = true;
}
public boolean isEnd() {
return isEnd;
}
}