字典树:
又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。
package myclass;
import openlab.day14.AVLTreeMap;
//因为是针对于字符串的字典树,所以不需要泛型
public class Trie {
/**
* 定义节点node有以下功能
* 1.存储当前层的字符 C并且存储该位置字符为 C的所有后续节点的映射
* 2.存储从根节点到该节点是否组成一个单词,如果组成并存储其数量
*/
private class Node{
private boolean isWord;
private int count;
private AVLTreeMap<Character,Node> nexts;
//创建节点时需要对nexts进行初始化,不然进行操作时回空指针
private Node(){
isWord = false;
count = 0;
nexts = new AVLTreeMap<>();
}
}
private Node root;//字典树的根节点
private int size;//字典树中不重复单词的个数
private int total;//字典树中总单词的个数
//创建字典树时需要对根节点进行初始化
public Trie() {
root = new Node();
size = 0;
total = 0;
}
public void add(String word){
if (word == null && "".equals(word)){
return;
}
Node cur = root;
//字典树的每一层对应一个位置的字符
for (int i = 0; i <word.length(); i++) {
char c = word.charAt(i);
//判断当前层是否包含该字符
if (cur.nexts.get(c) == null){
//不包含该字符则需要创建该字符的后续节点
cur.nexts.put(c,new Node());
}
cur = cur.nexts.get(c);
}
//做完循环后,整个单词已经遍历完毕,需要设计单词完结的标记乐
if (cur.isWord){
//原来已经存在这个单词
total++;
cur.count++;
}else {
//原来树中没有这个单词
size++;
total++;
cur.count = 1;
cur.isWord = true;
}
}
//判断字典树中是否包含该单词
public boolean contains(String word){
if (word == null || "".equals(word)){
return false;
}
Node cur = root;
for (int i = 0; i <word.length() ; i++) {
char c = word.charAt(i);
if (cur.nexts.get(c) == null){
//在某一层没有找到该字符,直接返回false
return false;
}
cur = cur.nexts.get(c);
}
//循环遍历完毕后说明所有单词都存在,但是不一定代表字典树中含有这个单词
//还需要判断cur的isWord
return cur.isWord;
}
public int count(String word){
if (word == null || "".equals(word)){
return 0;
}
Node cur = root;
for (int i = 0; i <word.length() ; i++) {
char c = word.charAt(i);
if (cur.nexts.get(c) == null){
//在某一层没有找到该字符,直接返回0
return 0;
}
cur = cur.nexts.get(c);
}
return cur.isWord ? cur.count : 0 ;
}
public int size() {
return size;
}
public int total() {
return total;
}
public boolean isPrefix(String prefix){
if (prefix == null || "".equals(prefix)){
return false;
}
Node cur = root;
for (int i = 0; i <prefix.length() ; i++) {
char c = prefix.charAt(i);
if (cur.nexts.get(c) == null){
//在某一层没有找到该字符,直接返回false
return false;
}
}
return true;
}
}