欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

前缀树结构

程序员文章站 2022-05-20 08:30:04
...

/*实现一个前缀树*/
什么是前缀树?优点?缺点?一般用来做什么?
数据结构:
包括根节点+儿子节点

前缀树的性质:

1.每一层节点上面的值都不相同;

2.根节点不存储值;除根节点外每一个节点都只包含一个字符。

3. 如果字符的种数为n,则每个结点的出度为n,这也是空间换时间的体现,浪费了很多的空间。 
4. 插入查找的复杂度为O(n),n为字符串长度。

典型应用是 
1. 用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。 
2. 用于前缀匹配,比如我们在搜索引擎中输入待搜索的字词时,搜索引擎会给予提示有哪些前缀。 
它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高。缺点就是空间开销大。
1、前缀匹配 
2、字符串检索 
3、词频统计 
4、字符串排序
1.插入
            从树的根节点开始;定义他的子树节点;26个英文单词;
            判断根的子节点中是否包含了要插入字符串的首字符;如果有;查找字符串的下一个字符;如果没有;则新建一个节点;插入该字符串的字符。
2.查找
            从树的根节点开始;定义他的子树节点;26个英文单词;
            判断根的子节点中是否包含了要插入字符串的首字符;如果有;查找字符串的下一个字符;如果没有;返回false;
3.判断是否是前缀树
        包含两步:
        3.1:树是否是该字符串的前缀词典
        3.2: 该字符串是否是树的前缀词典

class Trie {
    //1.定义数据结构
    public class Node{
        Node[] childs=new Node[26];
        boolean isLeaf;
    }
    //2.定义根节点
    private Node root=new Node();
    
    /** Initialize your data structure here. */
    //3.空参构造器
    public Trie() {
        
    }
    //4.插入字符串
    /** Inserts a word into the trie. */
    public void insert(String word) {
         insert(word,root);
    }
    
    public void insert(String word,Node node){
        //如果根节点为空;越界;因为前缀树的根节点不为空;而且字符是从跟节点的子树开始插入
        if(node==null) return;
        //如果字符串长度为0;也归为越界条件
        if(word.length()==0){
            node.isLeaf=true;
            return;                           
        }
        //从字符串的第一个节点开始;以数组索引表示字符是否存在
        int index=isLeafIndex(word.charAt(0));
        //如果字符不存在于树结构中,新建一个树节点
        if(node.childs[index]==null){
            node.childs[index]=new Node();   
        }
        //如果存在;进行下一步判断,字符串的第二个字符开始插入;
        //前缀树的特点;同一层节点上面的两个值不相同。因此当查找到第一个字符存在时;
        //应该从当前的树节点往下插入!
        insert(word.substring(1),node.childs[index]);
    }
    /** Returns if the word is in the trie. */
    public boolean search(String word) {
       return  search(word,root);
    }
    public boolean search(String word,Node node){
        if(node==null) return false;
        if(word.length()==0) return node.isLeaf;
        int index=isLeafIndex(word.charAt(0));
        return search( word.substring(1), node.childs[index]);
    }
    
    
    /** Returns if there is any word in the trie that starts with the given prefix. */
    public boolean startsWith(String prefix) {
        return startsWith(prefix,root);
    }
    
    public boolean startsWith(String prefix, Node node){
        if(node==null) return false;
        if(prefix.length()==0) return true;
        int index=isLeafIndex(prefix.charAt(0));
        return startsWith( prefix.substring(1), node.childs[index]);
    }
    
    public int isLeafIndex(char c){
        return  c-'a';
    }
}

/**
 * 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);
 */