前缀树:理论知识不做赘述,直接看代码
1-Node节点、
树是由一个个节点组建而来,那前缀树的节点应该包含哪些基本信息呢:
a-以当前节点作为末尾节点的次数
b-以当前节点作为中间节点的次数
c-当前节点的后续节点
代码如下:
class TrieNode{
int path;
int end;
TrieNode [] nexts ;
TrieNode(){
path = 0 ;
end = 0;
nexts = new TrieNode[26];
}
}
当前构建的node节点用来统计单词信息,而字母只有26个,所以nexts可以用长度为26的数组代替。此处根据情况也可以使用HashMap<char,TrieNode>
2-树结构
树结构必须包含的基本信息
a-根节点root
b-插入方法insert
c-搜索方法search,该方法应该返回包含被查找单词的个数
d-前缀计数方法,该方法应该返回以搜索word作为前缀的单词的个数
3-方法
a-insert
将单词转化为charArray,将Array中的每个char元素添加到数中
因为之前使用了长度为26的数组来作为next,所以每个字节的index可以通过index = char[i] - 'a'得到。
将对应位置构建出TrieNode
增加沿途节点的path值和尾节点的end值
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++;
}
b-search
同插入的逻辑基本相同。
给定的word转化为charArray,一次查询每个char的next节点是否存在,如果循环过程中任意一个不存在则返回0,若循环到最后返回最后一个节点的end值。
public int search(String word){
if(word == null){
return 0;
}
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){
return 0;
}
node = node.nexts[index];
}
return node.end;
}
delete和prefixNum同理。代码如下:
public void delete(String word){
if(search(word) != 0 && word == null){
return;
}
char [] chars = word.toCharArray();
int index = 0;
TrieNode node = root;
for(int i = 0; i < chars.length; i++){
index = chars[i] - 'a';
if(--node.nexts[index].path == 0){
node.nexts[index] = null;
return;
}
node = node.nexts[index];
}
node.end--;
}
public int prefixNum(String word){
if(word == null){
return 0;
}
TrieNode node = root;
char [] chars = word.toCharArray();
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;
}