1.01 Trie
Trie,又称字典树、单词查找树或键树,是一种树形结构,是一种哈希树的变种。
典型应用:是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。
它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。
1.Trie的核心思想:
是空间换时间,利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。
2.Trie的理解:
3.Trie的基本性质:
根节点不包含字符,除根节点外每一个节点都只包含一个字符。
从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
每个节点的所有子节点包含的字符都不相同。
4.Trie的应用:
-
串的快速检索
给定N个互不相同的仅由一个单词构成的英文名,让你将他们按字典序从小到大 输出,用字典树进行排序,采用链表的方式创建字典树,这棵树的每个结点的所有 儿子很显然地按照其字母大小排序。对这棵树进行先序遍历即可。
-
“串”排序
对所有串建立字典树,对于两个串的最长公共前缀的长度即他们所在的结点 的公共祖先个数,于是,问题就转化为当时公共祖先问题。
-
最长公共前缀
字典树把要查找的关键词看作 一个字符序列,并根据构成关键词字符的先后 顺序构造用于检索的树结构。一棵n度的字典树或者为空,或者由n棵n度的字典树 构成。 在进行查找字符的时候是按照树结构广度遍历的方式来遍历树中每一个结点数据信息。
-
典树拼法检查算法
(1)对关键词拼法检查,总是在字典树的根结点开始,且树的根结 点为空。 (2)扫描第一层各个结点获得查找关键词的第一个字符,并根据 关键词的第二个 字符选择对应的子树并转到该子树继续进行检索所在 层各个结点信息,如果查找 成功则转到;否则,继续选择对应的子树进行搜索。 (3)关键词的所有字符已被扫描完毕,则读取附在该结点上的数 据信息,即完成 对关键词的扫描过程,匹配结束。如果扫描后,没有匹 配的字符,则匹配失败,输出可能字符串。
1.02 Trie类的定义
- 定义类
public class Trie //无需定义泛型 本身就是对字符串数据处理
- 定义内部类结点
private class Node{
public boolean isWord; //当前为止 是否已经组成一个单词
public TreeMap<Character,Node> next; //当前之后的字母以及其映射的结点
public Node(boolean isWord){
this.isWord=isWord;
next=new TreeMap<Character,Node>();
}
public Node(){
this(false);
}
}
- 定义成员变量
private Node root; //根节点
private int size; //单词的个数
- 定义构造函数
public Trie(){
root=new Node();
size=0;
}
- 定义功能
//向Trie中添加一个新的单词word
public void add(String word){
Node cur=root; //cur指针从根节点开始
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);
}
if(!cur.isWord){ //如果是单词
cur.isWord=true;
size++;
}
}
//查询单词word是否存放在Trie中
public boolean contains(String word){
Node cur=root;
for(int i=0;i<word.lenght();i++){
char c=word.charAt(i);
if(cur.next.get(c)==null){ //如果树中没有这个字母
return false;
}
cur=cur.next.get(c);
}
return cur.isWord;
}
//查询是否在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.next.get(c)==null){
return false;
}
cur=cur.next.get(c);
}
return true;
}