字典树(Trie)可以保存一些字符串->值的对应关系。基本上,它跟 Java 的 HashMap 功能相同,都是 key-value 映射,只不过 Trie 的 key 只能是字符串。
Trie 的强大之处就在于它的时间复杂度。它的插入和查询时间复杂度都为 O(k) ,其中 k 为 key 的长度,与 Trie 中保存了多少个元素无关。Hash 表号称是 O(1) 的,但在计算 hash 的时候就肯定会是 O(k) ,而且还有碰撞之类的问题;Trie 的缺点是空间消耗很高。
至于Trie树的实现,可以用数组,也可以用指针动态分配,我做题时为了方便就用了数组,静态分配空间。
Trie树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高。
Trie的核心思想是空间换时间。利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。
import java.util.*;
public class Trie {
private class Node{
private TreeMap<Character,Node> next;
private Boolean isWorld;
public Node(){
next = new TreeMap<>();
isWorld = false;
}
}
private Node root;
private int size;
public Trie(){
root = new Node();
}
public int getSize(){
return size;
}
/**
* 新增一个单词
* @param world
*/
public void addNode(String world){
Node cur = root;
for(int i=0;i<world.length();i++){
char c = world.charAt(i);
Node node = cur.next.get(c);
if(node==null){
node = new Node();
cur.next.put(c,node);
}
cur = node;
}
if(!cur.isWorld){
cur.isWorld=true;
size++;
}
}
/**
* 判断一个单词是否存在
* @param world
* @return
*/
public Boolean contains(String world){
Node cur = root;
for(int i=0;i<world.length();i++){
char c = world.charAt(i);
Node node = cur.next.get(c);
if(node==null){
return false;
}
cur = node;
}
return cur.isWorld;
}
//遍历前缀树所有元素
public List<String> printWorld(){
List<String> list = new ArrayList<>();
printWorld(root,"",list);
return list;
}
public void printWorld(Node node,String str,List<String> list){
if (node==null){
return ;
}
for(Map.Entry<Character,Node> entry : node.next.entrySet()){
StringBuffer sb = new StringBuffer(str);
sb.append(entry.getKey());
if(entry.getValue().isWorld){
list.add(sb.toString());
}
printWorld(entry.getValue(),sb.toString(),list);
}
}
public static void main(String[] args) {
Trie trie = new Trie();
trie.addNode("cat");
trie.addNode("catehw");
trie.addNode("line");
trie.addNode("life");
List<String> list = trie.printWorld();
for (String str:list){
System.out.println(str);
}
}
}