一、什么是前缀树
前缀树 Trie ,又称为字典树, 是一种树形数据结构,用于高效地 存储和检索字符串数据集中的键 。这一数据结构有相当多的应用情景,例如 自动补完和拼写检查
其结构如下图所示 ,其模拟了将如下字符串插入前缀树的过程 :
[apple, app, ap, ba, baidu]
。
二、前缀树代码实现
- 使用
Trie[]
实现, 利用小写字符和数组下标的关系
class Trie {
private Trie[] children;
private boolean isEnd;
public Trie() {
children = new Trie[26];
isEnd = false;
}
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.children[index];
}
node.isEnd = true;
}
public boolean search(String word) {
Trie node = searchPrefix(word);
return node != null && node.isEnd;
}
public boolean startsWith(String prefix) {
return searchPrefix(prefix) != null;
}
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;
}
}
- 使用
HashMap<Character, Trie>
实现,直接存储字符本身
public class Trie {
Map<Character, Trie> children; // 孩子节点
boolean isEnd; // 结束标志
public Trie() {
children = new HashMap<>();
isEnd = false;
}
public void insert(String word) {
Trie node = this; // 得到根节点
for(Character cur : word.toCharArray()){ // 遍历 word
if(!node.children.containsKey(cur)){ // 加入前缀树中
node.children.put(cur, new Trie());
}
node = node.children.get(cur);
}
node.isEnd = true; // 标志结束
}
public boolean search(String word) {
Trie node = searchPrefix(word);
return node != null && node.isEnd;
}
public boolean startsWith(String prefix) {
return searchPrefix(prefix) != null;
}
// 找到以 prefix 为前缀的前缀树节点,不存在返回 null
public Trie searchPrefix(String prefix) {
Trie node = this;
for(Character cur : prefix.toCharArray()){
if(!node.children.containsKey(cur)){ // 不含当前前缀
return null;
}
node = node.children.get(cur);
}
return node;
}
}