前缀树概述:
前缀树是一种用于存储和检索字符串的数据结构。能够高效的支持字符串的插入、搜索和前缀匹配操作,经常用于搜索引擎、拼写检查、自动完成和单词查找等场景。
前缀树的结构是一个多叉树,每个节点代表一个字符,从根节点到叶子节点的路径表示一个字符串。根节点没有相应的字符,而其他节点表示字符集中的一个字符。每个节点可能有多个子节点,每个节点代表一个字符的可能取值。
核心思想:空间换时间,利用字符串的公共前缀来降低查询时间,不同的公共前缀只保存一份。
我们用 pass 标记当前节点有多少个字符串经过, 用 end 标记当前节点是多少字符串的结束字符。
前缀树Java实现:
class TrieNode{
int pass;
int end;
//用TrieNode数组来存储当前字符的下一个字符,来形成多叉树结构
TrieNode[] nodes = new TrieNode[26];
}
public class TrieTree{
//根节点
private TrieNode root;
public TrieTree(){
root = new TrieNode();
}
//insert
public void insert(String word){
if(word == null){
return ;
}
char[] chars = word.toCharArray();
//通过index来找到每一个字符在nodes的对应位置
int index = 0;
TrieNode node = root;
node.pass++;
for(char achar : chars){
//确定index
index = achar - 'a';
//如果给位置的字符为空,就new一个TrieNode 来填充
if(node.nodes[index] == null){
node.nodes[index] = new TrieNode();
}
//更新node
node = node.nodes[index];
//pass 加一,表示经过该节点的word加一
node.pass++;
}
//将最后一个node的end加一,表示以该node结尾的word加一
node.end++;
}
//searchWord,word若是不存在返回0
public int search(String word){
if(word == null){
return 0;
}
char[] chars = word.toCharArray();
int index = 0;
TrieNode node = root;
for(char achar : chars){
index = achar - 'a';
//当前字符所在位置为空的话,说明该word不在前缀树中,直接返回0
if(node.nodes[index] == null){
return 0;
}
//更新node
node = node.nodes[index];
}
return node.end;
}
//searchPre
public int searchPre(String pre){
if(pre == null){
return 0;
}
char[] chars = pre.toCharArray();
int index = 0;
TrieNode node = root;
for(char achar : chars){
index = achar - 'a';
if(node.nodes[index] == null){
return 0;
}
//更新node
node = node.nodes[index];
}
return node.pass;
}
//delete
public void delete(String word){
if(word == null){
return;
}
//先判断word在不在前缀树中
if(search(word) != 0){
char[] chars = word.toCharArray();
int index = 0;
TrieNode node = root;
node.pass--;
for(char achar : chars){
index = achar - 'a';
//如果当前字符所在的节点的pass值减一后为0,那么当前直接将该节点置null返回即可,没有存在的必要了
if(--node.nodes[index].pass == 0){
node.node.nodes[index] = null;
return;
}
//更新node
node = node.nodes.[index];
}
//将最后一个node的end减一
node.end--;
}
}
}