- Trie基本介绍
1.是一种多叉树
2.专门处理字符串
3.查询每个条目的时间复杂度,和字典映射中一共多少条目无关
4.其时间复杂度为O(w),w为所查询单词的长度
5.大多数单词的长度小于10(优势)
- Trie性质
1、根节点不包含字符,除根节点外每一个节点都只包含一个字符。
2、从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
3、每个节点的所有子节点包含的字符都不相同。
应用的场景就是查询字符串,字符串的前缀,词频统计等等。
优点:查询的效率非常高,缺点是利用空间换取时间。
实现原理:利用Trie树节点组织成一棵树,每个节点包含两个值,一个代表该字符的添加次数,另一个代表以该字符结尾的字符串个数。路径上用于存储字符。存储字符可以利用数组指针也可以利用哈希结构实现。
- Trie的实现
package org.yanan.Trie;
import java.util.TreeMap;
public class Trie {
//1.定义内部类
private class Node{
boolean isWord;//当前为止,是否组成一个单词
TreeMap<Character,Node> nexts;//当前之后的字母以及其映射后的结点
public Node(boolean isWord){
this.isWord=isWord;
nexts=new TreeMap<>();
}
public Node(){
this(false);
}
}
//2.定义成员变量和构造函数
private Node root;
private int size;
public Trie(){
root=new Node();
size=0;
}
//3.向Trie中添加一个新的单词
public void add(String word){
Node cur=root;//cur从根开始
for(int i=0;i<word.length();i++){
char c=word.charAt(i);
if(cur.nexts.get(c)==null){//若树中无该字母,cur的映射map中通过c找到的结点为空
cur.nexts.put(c, new Node());//将该字母加入树中
}
cur=cur.nexts.get(c);//更新cur的值
}
//标记此时已经是一个单词了,但为了避免相同单词出现,判断一下
if(!cur.isWord){//在它不是一个单词时,将其改成一个单词
cur.isWord=true;
size++;
}
}
//4.查询单词是否在Trie树中
public boolean contains(String word){
Node cur=root;
for(int i=0;i<word.length();i++){
char c=word.charAt(i);
if(cur.nexts.get(c)==null){
return false;
}
cur=cur.nexts.get(c);
}
return cur.isWord;//如果不是一个单词,只有一个单词的前一部分
}
//5.查询是否在Trie中有单词以prefix为前缀
public boolean isPrefix(String prefix){
Node cur=root;
for(int i=0;i<prefix.length();i++){
char c=prefix.charAt(i);
if(cur.nexts.get(c)==null){
return false;
}
cur=cur.nexts.get(c);
}
return true;//前缀
}
}
==============================Main================================
package org.yanan.Trie;
public class Main {
public static void main(String[] args) {
Trie trie=new Trie();
trie.add("dog");
trie.add("door");
trie.add("does");
trie.add("cat");
trie.add("capacity");
trie.add("can");
trie.add("panada");
System.out.println(trie.contains("do"));
System.out.println(trie.isPrefix("ca"));
}
}
=========================比较速度:Main1============================
package org.yanan.Trie;
import java.util.ArrayList;
import org.openlab.集合与映射.BSTSet;
public class Main2 {
public static void main(String[] args) {
ArrayList<String> words=new ArrayList<>();
FileOperation.readFile("pride-and-prejudice.txt", words);
double time1=testTime(true,words);
double time2=testTime(false,words);
System.out.println("Trie:"+time1);
System.out.println("BSTSet:"+time2);
}
private static double testTime(boolean b, ArrayList<String> words) {
long startTime=System.currentTimeMillis();
if(b){
Trie trie=new Trie();
for(String word:words){
trie.add(word);
}
for(String word:words){
trie.contains(word);
}
}else{
BSTSet<String> set=new BSTSet<>();
for(String word:words){
set.add(word);
}
for(String word:words){
set.contains(word);
}
}
long endTime=System.currentTimeMillis();
return endTime-startTime;
}
}