10.4 Trie字典树前缀查询
Tip:本博客内容是通过学习慕课网bobo老师视频做的笔记总结,不用于任何商业用途,只用于帮助更多技术爱好者。
(1) Trie字典树的Java语言实现案例
// 在Trie树中查找是否存在某个prefix前缀的单词,即实现前缀树
public boolean isPrefix(String prefix)
package com.wwl.trie;
import java.util.TreeMap;
/**
* Trie树性能高于BST(二分搜索树)
* Trie时间复杂度:O(w) 与单词长度有关
* BST时间复杂度:O(logn) 与存储的数据条目有关
*/
public class Trie {
private class Node {
private boolean isWord;
private TreeMap<Character, Node> next;
public Node(boolean isWord) {
this.isWord = isWord;
next = new TreeMap<>();
}
public Node() {
this(false);
}
}
// Trie树根节点定义
private Node root;
// Trie树存储单词数
private int size;
public Trie() {
root = new Node();
this.size = 0;
}
// 获取Trie树存储的单词数
public int getSize() {
return size;
}
// 向Trie树种添加一个新的词汇
public void add(String word) {
// 字符串判空操作
if (word == null) {
return;
}
// 定义当前节点
Node cur = root;
// 对新加入Trie树的词汇进行识别
// 第一:如果新加入的字符不存在,则在当前node节点创建一个新的节点树;
// 第二:如果新加入的字符存在,则找到存在的字符节点,然后赋值给当前节点,继续下一步识别。
for (int i = 0; i < word.length(); i++) {
char c = word.charAt(i);
if (cur.next.get(c) == null) {
cur.next.put(c, new Node());
}
cur = cur.next.get(c);
}
// 第一:如果当前加入的单词不存在,则把isWord标志改成true,表示加入的单词最后一个字符表示单词结尾;
// 第二:如果当前假如的字符存在,则不进行逻辑处理。
if (!cur.isWord) {
cur.isWord = true;
size++;
}
}
// 判断Trie树中是否存在某个单词
public boolean contains(String word) {
if (word == null) {
return false;
}
// 定义当前节点
Node cur = root;
// 第一:如果新加入的字符不存在,则返回false;
for (int i = 0; i < word.length(); i++) {
char c = word.charAt(i);
if (cur.next.get(c) == null) {
return false;
}
cur = cur.next.get(c);
}
// 第二:如果新加入的单词的所有字符都存在,则根据当前node节点的isWord字段判断此单词是否存在。
return cur.isWord;
}
// 在Trie树中查找是否存在某个prefix前缀的单词,即实现前缀树
public boolean isPrefix(String prefix) {
if (prefix == null) {
return false;
}
// 定义当前节点
Node cur = root;
// 第一:如果新加入的字符不存在,则返回false;
for (int i = 0; i < prefix.length(); i++) {
char c = prefix.charAt(i);
if (cur.next.get(c) == null) {
return false;
}
cur = cur.next.get(c);
}
// 第二:如果新加入的单词的所有字符都存在,则表示Trie树中能查找到此prefix前缀。
return true;
}
}
(2) Trie字典树的Java测试代码
package com.wwl.trie;
public class TrieIsPrefixTest {
public static void main(String[] args) {
Trie trie = new Trie();
trie.add("hello");
trie.add("word");
trie.add("dog");
trie.add("cat");
trie.add("beer");
trie.add("honey");
trie.add("co-worker");
trie.add("handsome");
boolean isPrefix = trie.isPrefix("co");
System.out.println("查找的前缀prefix是否存在:" + isPrefix);
isPrefix = trie.contains("co-worker");
System.out.println("查找的前缀prefix是否存在:" + isPrefix);
isPrefix = trie.contains("some");
System.out.println("查找的前缀prefix是否存在:" + isPrefix);
isPrefix = trie.contains("handsome");
System.out.println("查找的前缀prefix是否存在:" + isPrefix);
}
}
程序运行结果如下:
查找的前缀prefix是否存在:true
查找的前缀prefix是否存在:true
查找的前缀prefix是否存在:false
查找的前缀prefix是否存在:true
(3) Leetcode实现Trie(前缀树)
https://leetcode-cn.com/problemset/all/?search=Trie%E5%89%8D%E7%BC%80%E6%A0%91
class Trie {
private class Node {
private boolean isWord;
private TreeMap<Character, Node> next;
public Node(boolean isWord) {
this.isWord = isWord;
next = new TreeMap<>();
}
public Node() {
this(false);
}
}
// Trie树根节点定义
private Node root;
// Trie树存储单词数
private int size;
/** Initialize your data structure here. */
public Trie() {
root = new Node();
this.size = 0;
}
/** Inserts a word into the trie. */
public void insert(String word) {
// 字符串判空操作
if (word == null) {
return;
}
// 定义当前节点
Node cur = root;
// 对新加入Trie树的词汇进行识别
// 第一:如果新加入的字符不存在,则在当前node节点创建一个新的节点树;
// 第二:如果新加入的字符存在,则找到存在的字符节点,然后赋值给当前节点,继续下一步识别。
for (int i = 0; i < word.length(); i++) {
char c = word.charAt(i);
if (cur.next.get(c) == null) {
cur.next.put(c, new Node());
}
cur = cur.next.get(c);
}
// 第一:如果当前加入的单词不存在,则把isWord标志改成true,表示加入的单词最后一个字符表示单词结尾;
// 第二:如果当前假如的字符存在,则不进行逻辑处理。
if (!cur.isWord) {
cur.isWord = true;
size++;
}
}
/** Returns if the word is in the trie. */
public boolean search(String word) {
if (word == null) {
return false;
}
// 定义当前节点
Node cur = root;
// 第一:如果新加入的字符不存在,则返回false;
for (int i = 0; i < word.length(); i++) {
char c = word.charAt(i);
if (cur.next.get(c) == null) {
return false;
}
cur = cur.next.get(c);
}
// 第二:如果新加入的单词的所有字符都存在,则根据当前node节点的isWord字段判断此单词是否存在。
return cur.isWord;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
public boolean startsWith(String prefix) {
if (prefix == null) {
return false;
}
// 定义当前节点
Node cur = root;
// 第一:如果新加入的字符不存在,则返回false;
for (int i = 0; i < prefix.length(); i++) {
char c = prefix.charAt(i);
if (cur.next.get(c) == null) {
return false;
}
cur = cur.next.get(c);
}
// 第二:如果新加入的单词的所有字符都存在,则表示Trie树中能查找到此prefix前缀。
return true;
}
}
/**
* Your Trie object will be instantiated and called as such:
* Trie obj = new Trie();
* obj.insert(word);
* boolean param_2 = obj.search(word);
* boolean param_3 = obj.startsWith(prefix);
*/
如果感兴趣的童鞋,可以观看我下一篇博客:10.5 Trie字典树和简单模式匹配