字典树(Trie),也叫前缀树,是一个比较简单的数据结构,用来存储和查询字符串。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较。例如,hello
,hi
,haha
,ha
,ga
这几个单词可以用以下方式存储:
基本思想
字典树的核心思想是空间换时间。利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。前缀树的性质:
- 根节点不包含字符,除根节点外每一个节点都只包含一个字符。
- 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
- 每个节点的所有子节点包含的字符都不相同。
字典树查询和哈希查询之间的区别:
- 字典树的查询时间复杂度是 O ( L ) O(L) O(L),L是字符串的长度。哈希查询的时间复杂度为 O ( 1 ) O(1) O(1)。因此,在查询一整个单词的时候,哈希查询比较快。
- 哈希查询不支持动态查询,即查看单词时不能查找单词的一部分。
代码实现
其核心代码为:
public class Template {
class TreeNode {
int count = 0;
int prefix = 0;
TreeNode[] chd = new TreeNode[26];
}
/**
* 插入单词
*
* @param node
* @param word
*/
public void insert(TreeNode node, String word) {
if (word == null || word.length() == 0) return;
int len = word.length();
for (int i = 0; i < len; i++) {
int pos = word.charAt(i) - 'a';
if (node.chd[pos] == null) node.chd[pos] = new TreeNode();
node = node.chd[pos];
node.prefix++;
}
node.count++;
}
/**
* 查找对应的结点
*
* @param node
* @param word
* @return
*/
public TreeNode searchNode(TreeNode node, String word) {
if (word == null || word.length() == 0) return null;
int len = word.length();
for (int i = 0; i < len; i++) {
int pos = word.charAt(i) - 'a';
if (node.chd[pos] == null) return null;
node = node.chd[pos];
}
return node;
}
/**
* 查找单词
*
* @param node
* @param word
* @return
*/
public int searchWord(TreeNode node, String word) {
TreeNode target = searchNode(node, word);
if (target == null) return 0;
return target.count;
}
/**
* 查看前缀
*
* @param node
* @param word
* @return
*/
public int searchPrefix(TreeNode node, String word) {
TreeNode target = searchNode(node, word);
if (target == null) return 0;
return target.prefix;
}
public static void main(String[] args) {
Template temp = new Template();
TreeNode node = temp.new TreeNode();
temp.insert(node, "hello");
temp.insert(node, "hi");
temp.insert(node, "haha");
temp.insert(node, "ha");
System.out.println(temp.searchPrefix(node, "h"));
System.out.println(temp.searchWord(node, "ha"));
}
}
参考文献: