建树,数据存储在路径上
可以查询 是否包含前缀为 xx 的字符串
例如 查询前缀是否包含 be 的字符串,可以查到
但是无法查询确定的字符串,例如查询字符串是否含有 be,无法查询,那么需要改进
也即,可以在节点位置上添加一条信息,这条信息保存了 有多少个字符串以当前字母结尾的
例如 在插入 bef 字符串的时候,b路径的尾端节点置 0 ,因为没有任何一个字符串以 b 结尾
同样,e 尾端节点也是0,但是 f 的尾端节点是 1 ,因为有一个字符串 bef 是以 f 结尾的
这样,我们就可以精确的知道,哪个字符串是存在的
我们可以再在节点处加一个数据项,来表示经过某节点多少次,例如 abd 串 中的 b 节点,每到达一次 b 节点,我们就让 这个数据项 + 1,这样,我们就能知道 以 ab 为前缀的字符串有多少个
package 前缀树;
public class TrieTree {
private TrieNode root;
public TrieTree() {
root = new TrieNode();
}
/**
* 插入
*
* @param word
*/
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++) {
// 例如 当前节点 是a 那么 index = 0
//如果当前节点 是 z 那么 index = 25
index = chars[i] - 'a';
//如果 当前节点的 nexts[index] 不存在,那么说明没有这条路,则建路
if(node.nexts[index] == null) {
node.nexts[index] = new TrieNode();
}
node = node.nexts[index];
node.path++;
}
node.end++;
}
/**
* 查询插入了几次
*
* @param word
* @return
*/
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++) {
// 例如 当前节点 是a 那么 index = 0
//如果当前节点 是 z 那么 index = 25
index = chars[i] - 'a';
//如果 当前节点的 nexts[index] 不存在,那么说明没有这条路,则建路
if(node.nexts[index] == null) {
return 0;
}
node = node.nexts[index];
}
return node.end;
}
/**
* 查找 前缀出现了机次
*
* @param pre
* @return
*/
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];
}
//path 是到达了机次 即前缀的数量
return node.path;
}
/**
* 删除
*
* @param word
*/
public void delete(String word) {
if(search(word) == 0) return;
char[] chars = word.toCharArray();
TrieNode node = root;
int index = 0;
for(int i=0;i<chars.length;i++) {
index = chars[i] - 'a';
//如果 node 的path 已经是 0 了 就说明 这个节点下面的链 只出现过一次,那么直接可以把下面的节点删除
if(node.nexts[index].path == 0) {
node.nexts[index] = null;
return;
}
node = node.nexts[index];
}
node.end--;
}
}
class TrieNode {
//有多少节点到达过这个节点
int path;
//有多少节点以当前节点结尾
int end;
//表示 当前节点共 多少条路
//本类 默认 路最多有 26条,也就是说 一个节点 的下面的路 最多由 a,b,c,…,z组成 共26条
TrieNode[] nexts;
public TrieNode() {
path = 0;
end = 0;
nexts = new TrieNode[26];
}
}