字典树是多叉树,通常用于处理字符串,如存储单词等
字典树的实现
1. 基本类的实现
public class Trie {
private class Node{
//指向子结点
public TreeMap<Character,Node> next;
public boolean isWord;
public Node(boolean isWord) {
this.isWord = isWord;
next= new TreeMap<>();
}
public Node() {
this(false);
}
}
private Node root; //Trie树的根结点
private int size; //树中结点个数
public Trie() {
root = new Node();
size = 0;
}
public int getSize() {
return size;
}
}
2. 向字典树中添加单词
//向字典树中添加单词
public void add(String str) {
Node current = root;
//依次添加str的每一个字母
for(int i = 0; i < str.length(); ++i) {
char ch = str.charAt(i);
//映射中不包含键值为ch的条目,则将键值为ch的条目插入其中
if(current.next.get(ch) == null) {
current.next.put(ch,new Node());
}
//将current指向当前结点的满足条件(键值为ch)的孩子结点
current = current.next.get(ch);
}
/*
* 更新size大小时需要考虑到前缀问题
* 1. 当遍历完传入的单词str时,可能并为到达树中一个单词的结尾
* 如 str = "pan",Trie中存的是 "panda"
* 2. 如果current执行的结点的isWord为false,说明树中还没有存入
* pan这个单词,此时应将n结点的isWord更改为true,并更新size
* 3. size指的是树中单词的个数(前缀单词也是单词:pan 和 panda是两个单词)
*/
if(!current.isWord) {
current.isWord = true;
size++;
}
}
3. 查询某一单词是否在字典树中
/*
* 判断某一单词是否在字典树中
* 方法:1. 依次获取单词的每一个字母,作为键值去映射中查找是否有
* 与之对应的条目,若有则进行下一个字母的比对,没有则返回false
* 直至最后一个字母。
* 2. 若对单词str遍历完成未发现不匹配的条目,则对current结点的
* isWord进行判断,若其值为true,说明这是一个前缀单词,且已经
* 存入到当前字典树中,返回true,反之返回false。
*/
public boolean contains(String str) {
Node current = root;
for(int i = 0; i < str.length(); ++i) {
char ch = str.charAt(i);
if(current.next.get(ch) == null)
return false;
current = current.next.get(ch);
}
return current.isWord;
}
4. 判断某一字符串是否为字典树中单词的前缀
/*
* 判断某一字符串时候是单词的前缀(不要求prefix是单词)
* 方法(大致思路和contains一致):
* 1. 依次获取字符串prefix的每一个字母,作为键值去映射中查找是否有
* 与之对应的条目,若有则进行下一个字母的比对,没有则返回false
* 直至最后一个字母。
* 2. 如果循环比对之后为发现不匹配的条目,说明prefix是一个前缀,返回true
*/
public boolean isPrefix(String prefix) {
Node current = root;
for(int i = 0; i < prefix.length(); ++i) {
char ch = prefix.charAt(i);
if(current.next.get(ch) == null)
return false;
current = current.next.get(ch);
}
return true;
}