如有错误,希望大家批评指正,日拱一卒,功不唐捐。
一、字典树是什么
字典树,顾名思义,就是通过树(多叉树)的结构来存储类似字典的内容,主要是存储字符串中的字符,利用字符串的公共前缀来减少查询的时间,也就是常说的空间换时间。根节点不包含任何字符,也可以理解为 ‘/’(类似Linux文件系统中的根目录),从根节点到某一节点可以唯一确定一个字符串。在实际使用中,主要用来查找公共前缀的字符串。
图片来源参考自:https://segmentfault.com/a/1190000022597367
二、字典树的实现
假设字符串中只包含小写字符,即每个节点最多有26个子节点(实际情况中可以根据实际情况增加或减少)。
类中比较重要的成员变量就是children和isEnd,children是代表每个节点的子节点,isEnd则代表是否结束,比如一棵树中存在 abc, abcd,则在b的子节点c中,isEnd值为true,这样可以准确获取树种的字符串。
class Trie{
private Trie[] children;
//是否是结尾
private boolean isEnd;
public Trie() {
children = new Trie[26];
isEnd = false;
}
/**
* 插入一个单词到树种
* @param word
*/
public void insert(String word) {
Trie node = this;
//根据单词遍历子节点
for (int i = 0; i < word.length(); i++) {
char ch = word.charAt(i);
int index = ch - 'a';
//如果当前字符对应的子节点不存在 则新建
if (node.children[index] == null) {
node.children[index] = new Trie();
}
//重新赋值node
node = node.children[index];
}
node.isEnd = true;
}
/**
* 查找单词
* @param word
* @return
*/
public boolean search(String word) {
Trie node = searchPrefix(word);
return node != null && node.isEnd;
}
/**
* 查找以前缀开头的单词
* @param prefix
* @return
*/
public boolean startsWith(String prefix) {
return searchPrefix(prefix) != null;
}
/**
* 核心实现逻辑
* @param prefix
* @return
*/
private Trie searchPrefix(String prefix) {
Trie node = this;
for (int i = 0; i < prefix.length(); i++) {
char ch = prefix.charAt(i);
int index = ch - 'a';
if (node.children[index] == null) {
return null;
}
node = node.children[index];
}
return node;
}
}
总结
字典树这个数据结构整体比较简单, 熟悉一下就可以。