【树】前缀树
作者:互联网
前缀树,又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。
trie树常用于搜索提示。如当输入一个网址,可以自动搜索出可能的选择。当没有完全匹配的搜索结果,可以返回前缀最相似的可能。
举例:假如现在有 abc、adc、bc、bca、cde 4个字符串,构建的trie树如下
前缀树的实现
//节点结构
public static class TrieNode {
public int pass; //经过该节点的单词数量
public int end; //以该节点为尾的单词数量
/*
当字符很多时,可以考虑
HashMap<Character, TrieNode> nexts;
或
TreeMap<Character, TrieNode> nexts;
*/
public TrieNode[] nexts;
public TrieNode() {
pass = 0;
end = 0;
//26个英文字母
//nexts[0] != null 代表 a
//nexts[1] != null 代表 b
//nexts[2] != null 代表 c
//nexts[3] != null 代表 d
//nexts[4] != null 代表 e
//……
nexts = new TrieNode[26];
}
}
下图基于该节点结构
//前缀树的实现以及操作
public static class Trie {
private TrieNode root; //根节点
public Trie() {
root = new TrieNode();
}
//插入word字符串
public void insert(String word) {
if (word == null) {
return;
}
char[] chs = word.toCharArray();
TrieNode node = root;
node.pass++;
int index = 0;
for (char ch : chs) {
index = ch - 'a'; //得到ch字符的位置
if (node.nexts[index] == null) { //如果该字符为空就创建
node.nexts[index] = new TrieNode();
}
node = node.nexts[index]; //取出ch字符所属节点
node.pass++;
}
node.end++;
}
//word之前加入过几次
public int search(String word) {
if (word == null) {
return 0;
}
char[] chs = word.toCharArray();
TrieNode node = root;
int index = 0;
for (char ch : chs) {
index = ch - 'a';//得到ch字符的位置
if (node.nexts[index] == null) { //如果该位置为空表示word字串还没插入到前缀树中
return 0;
}
node = node.nexts[index];
}
return node.end;
}
//所有加入的字符串中,有几个是以pre这个字符串作为前缀的
public int prefixNumber(String pre) {
if (pre == null) {
return 0;
}
char[] chs = pre.toCharArray();
TrieNode node = root;
int index = 0;
for (char ch : chs) {
index = ch - 'a';//得到ch字符的位置
if (node.nexts[index] == null) { //如果该位置为空表示前缀树中无以pre为前缀的字符串
return 0;
}
node = node.nexts[index];
}
return node.pass;
}
//删除word
public void delete(String word) {
if (search(word) != 0) { //确定前缀树中确实加入过word,才删除
char[] chs = word.toCharArray();
TrieNode node = root;
node.pass--;
int index = 0;
for (char ch : chs) {
index = ch - 'a';//得到ch字符的位置
//如果pass变为0表示前缀树中已经无从root到node.nexts[index]的字符串
//需要释放node.nexts[index]的空间
if (--node.nexts[index].pass == 0) {
node.nexts[index] = null;
return;
}
node = node.nexts[index];
}
node.end--;
}
}
}
标签:node,index,ch,word,前缀,nexts,null 来源: https://www.cnblogs.com/hzyuan/p/15848154.html