Trie即前缀树,又称为字典树或者单词查找树。Trie典型的应用是搜索引擎系统用于文本词频统计。Trie的优点是利用字符串的公共前缀,来减少查询的时间,最大限度减少无谓的字符串比较,查询效率很高。如图所示:
image.png
上面这个Trie中包含的字符串的集合为:
{"abc","abd","b","ba","cb","cd"}
一个完整的字典树,应该包含的信息如上所示,root节点下每个节点存储着path变量,path变量代表在插入一个节点过程中该路径共经过了多少次;每个节点存储着end变量,end变量代表一个字符串的结尾,只需要这些信息,我们就可以还原出整棵树。
除了对字典树进行添加删除操作外,字典树还可以快速查询某个字符串是否在字典树中,也可以快速查询字典树中是否有以某个前缀为开头的字符串。
字典树结构如下:
public class TrieTree {
public static class TrieNode{
public int path;
public int end;
public TrieNode[] nexts;
public TrieNode(){
path = 0;
end = 0;
nexts = new TrieNode[26];
}
}
public static class Trie{
private TrieNode root;
public Trie(){
root = new TrieNode();
}
public void insert(String word){
if(word == null)
return;
char[] chars = word.toCharArray();
TrieNode node = root;
int index = 0;
for(int i = 0;i < chars.length;i++){
index = chars[i] - 'a';
if(node.nexts[index] == null){
node.nexts[index] = new TrieNode();
}
node = node.nexts[index];
node.path++;
}
node.end++;
}
// search:在字典树中是否存在某个字符串 返回具体的个数,如果不存在返回 0
public int search(String word){
if(word == null)
return 0;
char[] chars = word.toCharArray();
TrieNode node = root;
int index = 0;
int res = 0;
for(int i = 0;i < chars.length;i++){
index = chars[i] - 'a';
if(node.nexts[index] == null){
return 0;
}
node = node.nexts[index];
}
return node.end;
}
// delete
public void delete(String word){
if(search(word) > 0){
char[] chars = word.toCharArray();
TrieNode node = root;
int index = 0;
for(int i = 0;i < chars.length;i++){
index = chars[i] - 'a';
node = node.nexts[index];
if(--node.path == 0){
node = null;
return;
}
}
node.end--;
}
}
// 在Trie中有多少个以pre为前缀的字符串
public int prefixNumber(String pre){
if(pre == null)
return 0;
char[] chars = pre.toCharArray();
TrieNode node = root;
int index = 0;
for(int i = 0;i < chars.length;i++){
index = chars[i] - 'a';
if(node.nexts[index] == null){
return 0;
}
node = node.nexts[index];
}
return node.path;
}
}
}