今天刷LeetCode碰到一题前缀树的题目,想不出来,就顺着学习下Trie树的数据结构了
Trie树又称字典树,前缀树
放上一张偷来的前缀树结构图:
可以看到,前缀树是一种多叉树结构,上面这张图表示了关键字集合{"and","as","at","cn","com" },那么前缀树的前缀体现在哪里?可以看出,前缀树的关键字一般是字符串,而每一个节点则是一个字符,从根节点root到叶子节点的一条路径上所经过的节点则组成一个关键字,而当两个存在前缀字符的字符串,所走的路径是部分相同的,所以叫前缀树
前缀树的特点:
- 根节点不包含数据
- 从根节点到某一个节点经过的路径的字符连接起来,为该节点对应的字符串
- 每个节点的所有子节点包含的字符互不相同
看一下代码实现:
-
前缀树的结构实现:
这里以小写字符串的前缀树为例,即所有输入都是由小写字母a-z构成
class Trie {
private class TrieNode{
private boolean isEnd;//表示该节点是否已经是需要查询的字符串的末尾,即是否为关键字
private TrieNode[] next;//每个节点有26个不同的小写字母
public TrieNode(){
isEnd = false;
next = new TrieNode[26];
}
}
private TrieNode root;
public Trie() {
root = new TrieNode();
}
//插入数据
public void insert(String word) {
//根节点不存放任何数据
TrieNode cur = root;
for(int i = 0,len = word.length(),ch ; i< len;i++){
ch = word.charAt(i) - 'a';//计算下标
if(cur.next[ch] == null){//如果节点为空,则创建
cur.next[ch] = new TrieNode();
}
cur = cur.next[ch];//迭代,进入下一层
}
cur.isEnd = true;//该节点已经结束
}
//判断字符串word是否在前缀树中
public boolean search(String word) {
TrieNode cur = root;
for(int i = 0,len = word.length(),ch;i< len;i++){
ch = word.charAt(i) - 'a';
if(cur.next[ch] == null){
return false;
}
cur = cur.next[ch];//迭代,进入下一次
}
return cur.isEnd;
}
//判断部分前缀是否在前缀树中
public boolean startsWith(String prefix) {
TrieNode cur = root;
for(int i = 0,len = prefix.length(),ch;i< len;i++){
ch = prefix.charAt(i) - 'a';
if(cur.next[ch] == null){//prefix还没检索完,遇到路径不全,则直接返回false,前缀不存在
return false;
}
cur = cur.next[ch];//迭代,进入下一次
}
return true;
}
}